Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / fs / ext3 / namei.c
index bfaf8a4..045f588 100644 (file)
@@ -36,6 +36,9 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
+#include <linux/vserver/xid.h>
+
+#include "namei.h"
 #include "xattr.h"
 #include "acl.h"
 
@@ -610,10 +613,14 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
                de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data;
                if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
                        goto errout;
+               count++;
+       }
+       if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
+               de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data;
                de = ext3_next_entry(de);
-               if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
+               if ((err = ext3_htree_store_dirent(dir_file, 2, 0, de)) != 0)
                        goto errout;
-               count += 2;
+               count++;
        }
 
        while (1) {
@@ -671,6 +678,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
                        map_tail->hash = h.hash;
                        map_tail->offs = (u32) ((char *) de - base);
                        count++;
+                       cond_resched();
                }
                /* XXX: do we need to check rec_len == 0 case? -Chris */
                de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
@@ -927,8 +935,16 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
        struct inode *dir = dentry->d_parent->d_inode;
 
        sb = dir->i_sb;
-       if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
-               return NULL;
+       /* NFS may look up ".." - look at dx_root directory block */
+       if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
+               if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
+                       return NULL;
+       } else {
+               frame = frames;
+               frame->bh = NULL;                       /* for dx_release() */
+               frame->at = (struct dx_entry *)frames;  /* hack for zero entry*/
+               dx_set_block(frame->at, 0);             /* dx_root block is 0 */
+       }
        hash = hinfo.hash;
        do {
                block = dx_get_block(frame->at);
@@ -985,15 +1001,18 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
        if (bh) {
                unsigned long ino = le32_to_cpu(de->inode);
                brelse (bh);
-               inode = iget(dir->i_sb, ino);
+               if (!ext3_valid_inum(dir->i_sb, ino)) {
+                       ext3_error(dir->i_sb, "ext3_lookup",
+                                  "bad inode number: %lu", ino);
+                       inode = NULL;
+               } else
+                       inode = iget(dir->i_sb, ino);
 
                if (!inode)
                        return ERR_PTR(-EACCES);
+               vx_propagate_xid(nd, inode);
        }
-       if (inode)
-               return d_splice_alias(inode, dentry);
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 }
 
 
@@ -1016,7 +1035,13 @@ struct dentry *ext3_get_parent(struct dentry *child)
                return ERR_PTR(-ENOENT);
        ino = le32_to_cpu(de->inode);
        brelse(bh);
-       inode = iget(child->d_inode->i_sb, ino);
+
+       if (!ext3_valid_inum(child->d_inode->i_sb, ino)) {
+               ext3_error(child->d_inode->i_sb, "ext3_get_parent",
+                          "bad inode number: %lu", ino);
+               inode = NULL;
+       } else
+               inode = iget(child->d_inode->i_sb, ino);
 
        if (!inode)
                return ERR_PTR(-EACCES);
@@ -1251,7 +1276,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
         * happen is that the times are slightly out of date
         * and/or different from the directory change time.
         */
-       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+       dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
        ext3_update_dx_flag(dir);
        dir->i_version++;
        ext3_mark_inode_dirty(handle, dir);
@@ -1461,7 +1486,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
                if (levels && (dx_get_count(frames->entries) ==
                               dx_get_limit(frames->entries))) {
                        ext3_warning(sb, __FUNCTION__,
-                                    "Directory index full!\n");
+                                    "Directory index full!");
                        err = -ENOSPC;
                        goto cleanup;
                }
@@ -1632,9 +1657,9 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
        int err, retries = 0;
 
 retry:
-       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS);
+                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1666,9 +1691,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
                return -EINVAL;
 
 retry:
-       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS);
+                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1702,9 +1727,9 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
                return -EMLINK;
 
 retry:
-       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS);
+                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -1993,7 +2018,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
        /* Initialize quotas before so that eventual writes go in
         * separate transaction */
        DQUOT_INIT(dentry->d_inode);
-       handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+       handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -2029,7 +2054,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
         * recovery. */
        inode->i_size = 0;
        ext3_orphan_add(handle, inode);
-       inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        ext3_mark_inode_dirty(handle, inode);
        dir->i_nlink--;
        ext3_update_dx_flag(dir);
@@ -2052,7 +2077,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
        /* Initialize quotas before so that eventual writes go
         * in separate transaction */
        DQUOT_INIT(dentry->d_inode);
-       handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+       handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -2079,7 +2104,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
        retval = ext3_delete_entry(handle, dir, de, bh);
        if (retval)
                goto end_unlink;
-       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        ext3_update_dx_flag(dir);
        ext3_mark_inode_dirty(handle, dir);
        inode->i_nlink--;
@@ -2107,9 +2132,9 @@ static int ext3_symlink (struct inode * dir,
                return -ENAMETOOLONG;
 
 retry:
-       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
-                                       2*EXT3_QUOTA_INIT_BLOCKS);
+                                       2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -2129,7 +2154,8 @@ retry:
                 * We have a transaction open.  All is sweetness.  It also sets
                 * i_size in generic_commit_write().
                 */
-               err = page_symlink(inode, symname, l);
+               err = __page_symlink(inode, symname, l,
+                               mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
                if (err) {
                        ext3_dec_count(handle, inode);
                        ext3_mark_inode_dirty(handle, inode);
@@ -2161,7 +2187,7 @@ static int ext3_link (struct dentry * old_dentry,
                return -EMLINK;
 
 retry:
-       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -2169,7 +2195,7 @@ retry:
        if (IS_DIRSYNC(dir))
                handle->h_sync = 1;
 
-       inode->i_ctime = CURRENT_TIME;
+       inode->i_ctime = CURRENT_TIME_SEC;
        ext3_inc_count(handle, inode);
        atomic_inc(&inode->i_count);
 
@@ -2203,7 +2229,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
         * in separate transaction */
        if (new_dentry->d_inode)
                DQUOT_INIT(new_dentry->d_inode);
-       handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
+       handle = ext3_journal_start(old_dir, 2 *
+                                       EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -2270,7 +2297,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
         * Like most other Unix systems, set the ctime for inodes on a
         * rename.
         */
-       old_inode->i_ctime = CURRENT_TIME;
+       old_inode->i_ctime = CURRENT_TIME_SEC;
        ext3_mark_inode_dirty(handle, old_inode);
 
        /*
@@ -2303,9 +2330,9 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 
        if (new_inode) {
                new_inode->i_nlink--;
-               new_inode->i_ctime = CURRENT_TIME;
+               new_inode->i_ctime = CURRENT_TIME_SEC;
        }
-       old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+       old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
        ext3_update_dx_flag(old_dir);
        if (dir_bh) {
                BUFFER_TRACE(dir_bh, "get_write_access");
@@ -2359,6 +2386,7 @@ struct inode_operations ext3_dir_inode_operations = {
        .removexattr    = generic_removexattr,
 #endif
        .permission     = ext3_permission,
+       .sync_flags     = ext3_sync_flags,
 };
 
 struct inode_operations ext3_special_inode_operations = {
@@ -2370,4 +2398,5 @@ struct inode_operations ext3_special_inode_operations = {
        .removexattr    = generic_removexattr,
 #endif
        .permission     = ext3_permission,
+       .sync_flags     = ext3_sync_flags,
 };