Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Aug 2011 23:48:31 +0000 (13:48 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Aug 2011 23:48:31 +0000 (13:48 -1000)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  xfs: Fix build breakage in xfs_iops.c when CONFIG_FS_POSIX_ACL is not set
  VFS: Reorganise shrink_dcache_for_umount_subtree() after demise of dcache_lock
  VFS: Remove dentry->d_lock locking from shrink_dcache_for_umount_subtree()
  VFS: Remove detached-dentry counter from shrink_dcache_for_umount_subtree()
  switch posix_acl_chmod() to umode_t
  switch posix_acl_from_mode() to umode_t
  switch posix_acl_equiv_mode() to umode_t *
  switch posix_acl_create() to umode_t *
  block: initialise bd_super in bdget()
  vfs: avoid call to inode_lru_list_del() if possible
  vfs: avoid taking inode_hash_lock on pipes and sockets
  vfs: conditionally call inode_wb_list_del()
  VFS: Fix automount for negative autofs dentries
  Btrfs: load the key from the dir item in readdir into a fake dentry
  devtmpfs: missing initialialization in never-hit case
  hppfs: missing include

31 files changed:
drivers/base/devtmpfs.c
fs/9p/acl.c
fs/9p/acl.h
fs/9p/vfs_inode_dotl.c
fs/block_dev.c
fs/btrfs/acl.c
fs/btrfs/inode.c
fs/dcache.c
fs/ext2/acl.c
fs/ext3/acl.c
fs/ext4/acl.c
fs/generic_acl.c
fs/gfs2/acl.c
fs/hppfs/hppfs.c
fs/inode.c
fs/jffs2/acl.c
fs/jffs2/acl.h
fs/jffs2/fs.c
fs/jffs2/os-linux.h
fs/jfs/acl.c
fs/jfs/xattr.c
fs/namei.c
fs/nfs/nfs3acl.c
fs/nfs/nfs3proc.c
fs/ocfs2/acl.c
fs/posix_acl.c
fs/reiserfs/xattr_acl.c
fs/xfs/linux-2.6/xfs_acl.c
include/linux/fs.h
include/linux/nfs_fs.h
include/linux/posix_acl.h

index b89fffc..33e1bed 100644 (file)
@@ -166,7 +166,7 @@ static int create_path(const char *nodepath)
 {
        char *path;
        char *s;
-       int err;
+       int err = 0;
 
        /* parent directories do not exist, create them */
        path = kstrdup(nodepath, GFP_KERNEL);
index e9cb57f..9a1d426 100644 (file)
@@ -182,11 +182,11 @@ int v9fs_set_create_acl(struct dentry *dentry,
        return 0;
 }
 
-int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+int v9fs_acl_mode(struct inode *dir, umode_t *modep,
                  struct posix_acl **dpacl, struct posix_acl **pacl)
 {
        int retval = 0;
-       mode_t mode = *modep;
+       umode_t mode = *modep;
        struct posix_acl *acl = NULL;
 
        if (!S_ISLNK(mode)) {
@@ -319,7 +319,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
        case ACL_TYPE_ACCESS:
                name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
+                       umode_t mode = inode->i_mode;
                        retval = posix_acl_equiv_mode(acl, &mode);
                        if (retval < 0)
                                goto err_out;
index ddb7ae1..5595564 100644 (file)
@@ -20,7 +20,7 @@ extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type);
 extern int v9fs_acl_chmod(struct dentry *);
 extern int v9fs_set_create_acl(struct dentry *,
                               struct posix_acl **, struct posix_acl **);
-extern int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+extern int v9fs_acl_mode(struct inode *dir, umode_t *modep,
                         struct posix_acl **dpacl, struct posix_acl **pacl);
 #else
 #define v9fs_iop_get_acl NULL
@@ -38,7 +38,7 @@ static inline int v9fs_set_create_acl(struct dentry *dentry,
 {
        return 0;
 }
-static inline int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+static inline int v9fs_acl_mode(struct inode *dir, umode_t *modep,
                                struct posix_acl **dpacl,
                                struct posix_acl **pacl)
 {
index 9a26dce..b6c8ed2 100644 (file)
@@ -206,7 +206,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
        int err = 0;
        gid_t gid;
        int flags;
-       mode_t mode;
+       umode_t mode;
        char *name = NULL;
        struct file *filp;
        struct p9_qid qid;
@@ -348,7 +348,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
        struct p9_fid *fid = NULL, *dfid = NULL;
        gid_t gid;
        char *name;
-       mode_t mode;
+       umode_t mode;
        struct inode *inode;
        struct p9_qid qid;
        struct dentry *dir_dentry;
@@ -751,7 +751,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
        int err;
        gid_t gid;
        char *name;
-       mode_t mode;
+       umode_t mode;
        struct v9fs_session_info *v9ses;
        struct p9_fid *fid = NULL, *dfid = NULL;
        struct inode *inode;
index f55aad4..f286805 100644 (file)
@@ -552,6 +552,7 @@ struct block_device *bdget(dev_t dev)
 
        if (inode->i_state & I_NEW) {
                bdev->bd_contains = NULL;
+               bdev->bd_super = NULL;
                bdev->bd_inode = inode;
                bdev->bd_block_size = (1 << inode->i_blkbits);
                bdev->bd_part_count = 0;
index 65a735d..4cc5c01 100644 (file)
@@ -111,7 +111,6 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,
        int ret, size = 0;
        const char *name;
        char *value = NULL;
-       mode_t mode;
 
        if (acl) {
                ret = posix_acl_valid(acl);
@@ -122,13 +121,11 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,
 
        switch (type) {
        case ACL_TYPE_ACCESS:
-               mode = inode->i_mode;
                name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
-                       ret = posix_acl_equiv_mode(acl, &mode);
+                       ret = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (ret < 0)
                                return ret;
-                       inode->i_mode = mode;
                }
                ret = 0;
                break;
@@ -222,19 +219,16 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans,
        }
 
        if (IS_POSIXACL(dir) && acl) {
-               mode_t mode = inode->i_mode;
-
                if (S_ISDIR(inode->i_mode)) {
                        ret = btrfs_set_acl(trans, inode, acl,
                                            ACL_TYPE_DEFAULT);
                        if (ret)
                                goto failed;
                }
-               ret = posix_acl_create(&acl, GFP_NOFS, &mode);
+               ret = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (ret < 0)
                        return ret;
 
-               inode->i_mode = mode;
                if (ret > 0) {
                        /* we need an acl */
                        ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
index 13e6255..ae762da 100644 (file)
@@ -3993,12 +3993,19 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
        struct btrfs_root *sub_root = root;
        struct btrfs_key location;
        int index;
-       int ret;
+       int ret = 0;
 
        if (dentry->d_name.len > BTRFS_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       ret = btrfs_inode_by_name(dir, dentry, &location);
+       if (unlikely(d_need_lookup(dentry))) {
+               memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
+               kfree(dentry->d_fsdata);
+               dentry->d_fsdata = NULL;
+               d_clear_need_lookup(dentry);
+       } else {
+               ret = btrfs_inode_by_name(dir, dentry, &location);
+       }
 
        if (ret < 0)
                return ERR_PTR(ret);
@@ -4053,6 +4060,12 @@ static int btrfs_dentry_delete(const struct dentry *dentry)
        return 0;
 }
 
+static void btrfs_dentry_release(struct dentry *dentry)
+{
+       if (dentry->d_fsdata)
+               kfree(dentry->d_fsdata);
+}
+
 static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
                                   struct nameidata *nd)
 {
@@ -4075,6 +4088,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
        struct btrfs_path *path;
        struct list_head ins_list;
        struct list_head del_list;
+       struct qstr q;
        int ret;
        struct extent_buffer *leaf;
        int slot;
@@ -4164,6 +4178,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
 
                while (di_cur < di_total) {
                        struct btrfs_key location;
+                       struct dentry *tmp;
 
                        if (verify_dir_item(root, leaf, di))
                                break;
@@ -4184,6 +4199,33 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
                        d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
                        btrfs_dir_item_key_to_cpu(leaf, di, &location);
 
+                       q.name = name_ptr;
+                       q.len = name_len;
+                       q.hash = full_name_hash(q.name, q.len);
+                       tmp = d_lookup(filp->f_dentry, &q);
+                       if (!tmp) {
+                               struct btrfs_key *newkey;
+
+                               newkey = kzalloc(sizeof(struct btrfs_key),
+                                                GFP_NOFS);
+                               if (!newkey)
+                                       goto no_dentry;
+                               tmp = d_alloc(filp->f_dentry, &q);
+                               if (!tmp) {
+                                       kfree(newkey);
+                                       dput(tmp);
+                                       goto no_dentry;
+                               }
+                               memcpy(newkey, &location,
+                                      sizeof(struct btrfs_key));
+                               tmp->d_fsdata = newkey;
+                               tmp->d_flags |= DCACHE_NEED_LOOKUP;
+                               d_rehash(tmp);
+                               dput(tmp);
+                       } else {
+                               dput(tmp);
+                       }
+no_dentry:
                        /* is this a reference to our own snapshot? If so
                         * skip it
                         */
@@ -7430,4 +7472,5 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
 
 const struct dentry_operations btrfs_dentry_operations = {
        .d_delete       = btrfs_dentry_delete,
+       .d_release      = btrfs_dentry_release,
 };
index b05aac3..2347cdb 100644 (file)
@@ -301,6 +301,27 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
        return parent;
 }
 
+/*
+ * Unhash a dentry without inserting an RCU walk barrier or checking that
+ * dentry->d_lock is locked.  The caller must take care of that, if
+ * appropriate.
+ */
+static void __d_shrink(struct dentry *dentry)
+{
+       if (!d_unhashed(dentry)) {
+               struct hlist_bl_head *b;
+               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
+                       b = &dentry->d_sb->s_anon;
+               else
+                       b = d_hash(dentry->d_parent, dentry->d_name.hash);
+
+               hlist_bl_lock(b);
+               __hlist_bl_del(&dentry->d_hash);
+               dentry->d_hash.pprev = NULL;
+               hlist_bl_unlock(b);
+       }
+}
+
 /**
  * d_drop - drop a dentry
  * @dentry: dentry to drop
@@ -319,17 +340,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
 void __d_drop(struct dentry *dentry)
 {
        if (!d_unhashed(dentry)) {
-               struct hlist_bl_head *b;
-               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
-                       b = &dentry->d_sb->s_anon;
-               else
-                       b = d_hash(dentry->d_parent, dentry->d_name.hash);
-
-               hlist_bl_lock(b);
-               __hlist_bl_del(&dentry->d_hash);
-               dentry->d_hash.pprev = NULL;
-               hlist_bl_unlock(b);
-
+               __d_shrink(dentry);
                dentry_rcuwalk_barrier(dentry);
        }
 }
@@ -828,44 +839,24 @@ EXPORT_SYMBOL(shrink_dcache_sb);
 static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 {
        struct dentry *parent;
-       unsigned detached = 0;
 
        BUG_ON(!IS_ROOT(dentry));
 
-       /* detach this root from the system */
-       spin_lock(&dentry->d_lock);
-       dentry_lru_del(dentry);
-       __d_drop(dentry);
-       spin_unlock(&dentry->d_lock);
-
        for (;;) {
                /* descend to the first leaf in the current subtree */
-               while (!list_empty(&dentry->d_subdirs)) {
-                       struct dentry *loop;
-
-                       /* this is a branch with children - detach all of them
-                        * from the system in one go */
-                       spin_lock(&dentry->d_lock);
-                       list_for_each_entry(loop, &dentry->d_subdirs,
-                                           d_u.d_child) {
-                               spin_lock_nested(&loop->d_lock,
-                                               DENTRY_D_LOCK_NESTED);
-                               dentry_lru_del(loop);
-                               __d_drop(loop);
-                               spin_unlock(&loop->d_lock);
-                       }
-                       spin_unlock(&dentry->d_lock);
-
-                       /* move to the first child */
+               while (!list_empty(&dentry->d_subdirs))
                        dentry = list_entry(dentry->d_subdirs.next,
                                            struct dentry, d_u.d_child);
-               }
 
                /* consume the dentries from this leaf up through its parents
                 * until we find one with children or run out altogether */
                do {
                        struct inode *inode;
 
+                       /* detach from the system */
+                       dentry_lru_del(dentry);
+                       __d_shrink(dentry);
+
                        if (dentry->d_count != 0) {
                                printk(KERN_ERR
                                       "BUG: Dentry %p{i=%lx,n=%s}"
@@ -886,14 +877,10 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                                list_del(&dentry->d_u.d_child);
                        } else {
                                parent = dentry->d_parent;
-                               spin_lock(&parent->d_lock);
                                parent->d_count--;
                                list_del(&dentry->d_u.d_child);
-                               spin_unlock(&parent->d_lock);
                        }
 
-                       detached++;
-
                        inode = dentry->d_inode;
                        if (inode) {
                                dentry->d_inode = NULL;
@@ -938,9 +925,7 @@ void shrink_dcache_for_umount(struct super_block *sb)
 
        dentry = sb->s_root;
        sb->s_root = NULL;
-       spin_lock(&dentry->d_lock);
        dentry->d_count--;
-       spin_unlock(&dentry->d_lock);
        shrink_dcache_for_umount_subtree(dentry);
 
        while (!hlist_bl_empty(&sb->s_anon)) {
index 52c0537..35d6a3c 100644 (file)
@@ -194,12 +194,10 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
                case ACL_TYPE_ACCESS:
                        name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
                        if (acl) {
-                               mode_t mode = inode->i_mode;
-                               error = posix_acl_equiv_mode(acl, &mode);
+                               error = posix_acl_equiv_mode(acl, &inode->i_mode);
                                if (error < 0)
                                        return error;
                                else {
-                                       inode->i_mode = mode;
                                        inode->i_ctime = CURRENT_TIME_SEC;
                                        mark_inode_dirty(inode);
                                        if (error == 0)
@@ -253,16 +251,14 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
                        inode->i_mode &= ~current_umask();
        }
        if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               mode_t mode = inode->i_mode;
                if (S_ISDIR(inode->i_mode)) {
                        error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
                        if (error)
                                goto cleanup;
                }
-               error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+               error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
                if (error < 0)
                        return error;
-               inode->i_mode = mode;
                if (error > 0) {
                        /* This is an extended ACL */
                        error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
index 6c29bf0..3091f62 100644 (file)
@@ -199,12 +199,10 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
                case ACL_TYPE_ACCESS:
                        name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
                        if (acl) {
-                               mode_t mode = inode->i_mode;
-                               error = posix_acl_equiv_mode(acl, &mode);
+                               error = posix_acl_equiv_mode(acl, &inode->i_mode);
                                if (error < 0)
                                        return error;
                                else {
-                                       inode->i_mode = mode;
                                        inode->i_ctime = CURRENT_TIME_SEC;
                                        ext3_mark_inode_dirty(handle, inode);
                                        if (error == 0)
@@ -261,19 +259,16 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
                        inode->i_mode &= ~current_umask();
        }
        if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               mode_t mode = inode->i_mode;
-
                if (S_ISDIR(inode->i_mode)) {
                        error = ext3_set_acl(handle, inode,
                                             ACL_TYPE_DEFAULT, acl);
                        if (error)
                                goto cleanup;
                }
-               error = posix_acl_create(&acl, GFP_NOFS, &mode);
+               error = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (error < 0)
                        return error;
 
-               inode->i_mode = mode;
                if (error > 0) {
                        /* This is an extended ACL */
                        error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
index dca2d1d..a5c29bb 100644 (file)
@@ -198,12 +198,10 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
        case ACL_TYPE_ACCESS:
                name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
-                       error = posix_acl_equiv_mode(acl, &mode);
+                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (error < 0)
                                return error;
                        else {
-                               inode->i_mode = mode;
                                inode->i_ctime = ext4_current_time(inode);
                                ext4_mark_inode_dirty(handle, inode);
                                if (error == 0)
@@ -259,19 +257,16 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
                        inode->i_mode &= ~current_umask();
        }
        if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               mode_t mode = inode->i_mode;
-
                if (S_ISDIR(inode->i_mode)) {
                        error = ext4_set_acl(handle, inode,
                                             ACL_TYPE_DEFAULT, acl);
                        if (error)
                                goto cleanup;
                }
-               error = posix_acl_create(&acl, GFP_NOFS, &mode);
+               error = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (error < 0)
                        return error;
 
-               inode->i_mode = mode;
                if (error > 0) {
                        /* This is an extended ACL */
                        error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
index d5e33a0..d0dddac 100644 (file)
@@ -82,18 +82,14 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value,
                        return PTR_ERR(acl);
        }
        if (acl) {
-               mode_t mode;
-
                error = posix_acl_valid(acl);
                if (error)
                        goto failed;
                switch (type) {
                case ACL_TYPE_ACCESS:
-                       mode = inode->i_mode;
-                       error = posix_acl_equiv_mode(acl, &mode);
+                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (error < 0)
                                goto failed;
-                       inode->i_mode = mode;
                        inode->i_ctime = CURRENT_TIME;
                        if (error == 0) {
                                posix_acl_release(acl);
@@ -125,21 +121,20 @@ int
 generic_acl_init(struct inode *inode, struct inode *dir)
 {
        struct posix_acl *acl = NULL;
-       mode_t mode = inode->i_mode;
        int error;
 
-       inode->i_mode = mode & ~current_umask();
        if (!S_ISLNK(inode->i_mode))
                acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
        if (acl) {
                if (S_ISDIR(inode->i_mode))
                        set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
-               error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+               error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
                if (error < 0)
                        return error;
-               inode->i_mode = mode;
                if (error > 0)
                        set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
+       } else {
+               inode->i_mode &= ~current_umask();
        }
        error = 0;
 
index 884c9af..34501b6 100644 (file)
@@ -72,7 +72,7 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
        return gfs2_acl_get(GFS2_I(inode), type);
 }
 
-static int gfs2_set_mode(struct inode *inode, mode_t mode)
+static int gfs2_set_mode(struct inode *inode, umode_t mode)
 {
        int error = 0;
 
@@ -117,7 +117,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct posix_acl *acl;
-       mode_t mode = inode->i_mode;
+       umode_t mode = inode->i_mode;
        int error = 0;
 
        if (!sdp->sd_args.ar_posix_acl)
@@ -276,7 +276,7 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
                goto out_release;
 
        if (type == ACL_TYPE_ACCESS) {
-               mode_t mode = inode->i_mode;
+               umode_t mode = inode->i_mode;
                error = posix_acl_equiv_mode(acl, &mode);
 
                if (error <= 0) {
index 8635be5..970ea98 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/statfs.h>
 #include <linux/types.h>
 #include <linux/pid_namespace.h>
+#include <linux/namei.h>
 #include <asm/uaccess.h>
 #include "os.h"
 
index d0c72ff..5aab80d 100644 (file)
@@ -399,12 +399,12 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
 EXPORT_SYMBOL(__insert_inode_hash);
 
 /**
- *     remove_inode_hash - remove an inode from the hash
+ *     __remove_inode_hash - remove an inode from the hash
  *     @inode: inode to unhash
  *
  *     Remove an inode from the superblock.
  */
-void remove_inode_hash(struct inode *inode)
+void __remove_inode_hash(struct inode *inode)
 {
        spin_lock(&inode_hash_lock);
        spin_lock(&inode->i_lock);
@@ -412,7 +412,7 @@ void remove_inode_hash(struct inode *inode)
        spin_unlock(&inode->i_lock);
        spin_unlock(&inode_hash_lock);
 }
-EXPORT_SYMBOL(remove_inode_hash);
+EXPORT_SYMBOL(__remove_inode_hash);
 
 void end_writeback(struct inode *inode)
 {
@@ -454,7 +454,9 @@ static void evict(struct inode *inode)
        BUG_ON(!(inode->i_state & I_FREEING));
        BUG_ON(!list_empty(&inode->i_lru));
 
-       inode_wb_list_del(inode);
+       if (!list_empty(&inode->i_wb_list))
+               inode_wb_list_del(inode);
+
        inode_sb_list_del(inode);
 
        if (op->evict_inode) {
@@ -1328,7 +1330,8 @@ static void iput_final(struct inode *inode)
        }
 
        inode->i_state |= I_FREEING;
-       inode_lru_list_del(inode);
+       if (!list_empty(&inode->i_lru))
+               inode_lru_list_del(inode);
        spin_unlock(&inode->i_lock);
 
        evict(inode);
index 27c511a..926d020 100644 (file)
@@ -227,7 +227,7 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
        case ACL_TYPE_ACCESS:
                xprefix = JFFS2_XPREFIX_ACL_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
+                       umode_t mode = inode->i_mode;
                        rc = posix_acl_equiv_mode(acl, &mode);
                        if (rc < 0)
                                return rc;
@@ -259,7 +259,7 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
        return rc;
 }
 
-int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, mode_t *i_mode)
+int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, umode_t *i_mode)
 {
        struct posix_acl *acl;
        int rc;
index b3421c7..9b47724 100644 (file)
@@ -28,7 +28,7 @@ struct jffs2_acl_header {
 
 struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
 extern int jffs2_acl_chmod(struct inode *);
-extern int jffs2_init_acl_pre(struct inode *, struct inode *, mode_t *);
+extern int jffs2_init_acl_pre(struct inode *, struct inode *, umode_t *);
 extern int jffs2_init_acl_post(struct inode *);
 
 extern const struct xattr_handler jffs2_acl_access_xattr_handler;
index b81b35d..bbcb975 100644 (file)
@@ -406,7 +406,7 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
 
 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
    fill in the raw_inode while you're at it. */
-struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode, struct jffs2_raw_inode *ri)
+struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri)
 {
        struct inode *inode;
        struct super_block *sb = dir_i->i_sb;
index 526979c..6c1755c 100644 (file)
@@ -173,7 +173,7 @@ int jffs2_do_setattr (struct inode *, struct iattr *);
 struct inode *jffs2_iget(struct super_block *, unsigned long);
 void jffs2_evict_inode (struct inode *);
 void jffs2_dirty_inode(struct inode *inode, int flags);
-struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode,
+struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode,
                               struct jffs2_raw_inode *ri);
 int jffs2_statfs (struct dentry *, struct kstatfs *);
 int jffs2_remount_fs (struct super_block *, int *, char *);
index b3a32ca..45559dc 100644 (file)
@@ -127,16 +127,14 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
                return PTR_ERR(acl);
 
        if (acl) {
-               mode_t mode = inode->i_mode;
                if (S_ISDIR(inode->i_mode)) {
                        rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
                        if (rc)
                                goto cleanup;
                }
-               rc = posix_acl_create(&acl, GFP_KERNEL, &mode);
+               rc = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
                if (rc < 0)
                        goto cleanup; /* posix_acl_release(NULL) is no-op */
-               inode->i_mode = mode;
                if (rc > 0)
                        rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 cleanup:
index 24838f1..e87fede 100644 (file)
@@ -693,8 +693,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
                        return rc;
                }
                if (acl) {
-                       mode_t mode = inode->i_mode;
-                       rc = posix_acl_equiv_mode(acl, &mode);
+                       rc = posix_acl_equiv_mode(acl, &inode->i_mode);
                        posix_acl_release(acl);
                        if (rc < 0) {
                                printk(KERN_ERR
@@ -702,7 +701,6 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
                                       rc);
                                return rc;
                        }
-                       inode->i_mode = mode;
                        mark_inode_dirty(inode);
                }
                /*
index f8c69d3..445fd5d 100644 (file)
@@ -716,19 +716,25 @@ static int follow_automount(struct path *path, unsigned flags,
        if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
                return -EISDIR; /* we actually want to stop here */
 
-       /* We want to mount if someone is trying to open/create a file of any
-        * type under the mountpoint, wants to traverse through the mountpoint
-        * or wants to open the mounted directory.
-        *
+       /*
         * We don't want to mount if someone's just doing a stat and they've
         * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
         * appended a '/' to the name.
         */
-       if (!(flags & LOOKUP_FOLLOW) &&
-           !(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
-                      LOOKUP_OPEN | LOOKUP_CREATE)))
-               return -EISDIR;
-
+       if (!(flags & LOOKUP_FOLLOW)) {
+               /* We do, however, want to mount if someone wants to open or
+                * create a file of any type under the mountpoint, wants to
+                * traverse through the mountpoint or wants to open the mounted
+                * directory.
+                * Also, autofs may mark negative dentries as being automount
+                * points.  These will need the attentions of the daemon to
+                * instantiate them before they can be used.
+                */
+               if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
+                            LOOKUP_OPEN | LOOKUP_CREATE)) &&
+                   path->dentry->d_inode)
+                       return -EISDIR;
+       }
        current->total_link_count++;
        if (current->total_link_count >= 40)
                return -ELOOP;
index e49e731..7ef2397 100644 (file)
@@ -415,7 +415,7 @@ fail:
 }
 
 int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-               mode_t mode)
+               umode_t mode)
 {
        struct posix_acl *dfacl, *acl;
        int error = 0;
index 38053d8..85f1690 100644 (file)
@@ -316,7 +316,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                 int flags, struct nfs_open_context *ctx)
 {
        struct nfs3_createdata *data;
-       mode_t mode = sattr->ia_mode;
+       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  create %s\n", dentry->d_name.name);
@@ -562,7 +562,7 @@ static int
 nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 {
        struct nfs3_createdata *data;
-       int mode = sattr->ia_mode;
+       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
@@ -681,7 +681,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                dev_t rdev)
 {
        struct nfs3_createdata *data;
-       mode_t mode = sattr->ia_mode;
+       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  mknod %s %u:%u\n", dentry->d_name.name,
index 783c58d..a721907 100644 (file)
@@ -247,7 +247,7 @@ static int ocfs2_set_acl(handle_t *handle,
        case ACL_TYPE_ACCESS:
                name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
+                       umode_t mode = inode->i_mode;
                        ret = posix_acl_equiv_mode(acl, &mode);
                        if (ret < 0)
                                return ret;
@@ -351,7 +351,7 @@ int ocfs2_init_acl(handle_t *handle,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct posix_acl *acl = NULL;
        int ret = 0, ret2;
-       mode_t mode;
+       umode_t mode;
 
        if (!S_ISLNK(inode->i_mode)) {
                if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
index d43729a..10027b4 100644 (file)
@@ -149,10 +149,10 @@ posix_acl_valid(const struct posix_acl *acl)
  * file mode permission bits, or else 1. Returns -E... on error.
  */
 int
-posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
+posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p)
 {
        const struct posix_acl_entry *pa, *pe;
-       mode_t mode = 0;
+       umode_t mode = 0;
        int not_equiv = 0;
 
        FOREACH_ACL_ENTRY(pa, acl, pe) {
@@ -188,7 +188,7 @@ posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
  * Create an ACL representing the file mode permission bits of an inode.
  */
 struct posix_acl *
-posix_acl_from_mode(mode_t mode, gfp_t flags)
+posix_acl_from_mode(umode_t mode, gfp_t flags)
 {
        struct posix_acl *acl = posix_acl_alloc(3, flags);
        if (!acl)
@@ -279,11 +279,11 @@ check_perm:
  * system calls. All permissions that are not granted by the acl are removed.
  * The permissions in the acl are changed to reflect the mode_p parameter.
  */
-static int posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
+static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
 {
        struct posix_acl_entry *pa, *pe;
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
-       mode_t mode = *mode_p;
+       umode_t mode = *mode_p;
        int not_equiv = 0;
 
        /* assert(atomic_read(acl->a_refcount) == 1); */
@@ -336,7 +336,7 @@ static int posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
 /*
  * Modify the ACL for the chmod syscall.
  */
-static int posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
+static int posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
 {
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
        struct posix_acl_entry *pa, *pe;
@@ -382,7 +382,7 @@ static int posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
 }
 
 int
-posix_acl_create(struct posix_acl **acl, gfp_t gfp, mode_t *mode_p)
+posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
 {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
@@ -400,7 +400,7 @@ posix_acl_create(struct posix_acl **acl, gfp_t gfp, mode_t *mode_p)
 EXPORT_SYMBOL(posix_acl_create);
 
 int
-posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, mode_t mode)
+posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
 {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
index 7362cf4..6da0396 100644 (file)
@@ -272,12 +272,10 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
        case ACL_TYPE_ACCESS:
                name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
-                       mode_t mode = inode->i_mode;
-                       error = posix_acl_equiv_mode(acl, &mode);
+                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (error < 0)
                                return error;
                        else {
-                               inode->i_mode = mode;
                                if (error == 0)
                                        acl = NULL;
                        }
@@ -354,8 +352,6 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
                return PTR_ERR(acl);
 
        if (acl) {
-               mode_t mode = inode->i_mode;
-
                /* Copy the default ACL to the default ACL of a new directory */
                if (S_ISDIR(inode->i_mode)) {
                        err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
@@ -366,12 +362,10 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
 
                /* Now we reconcile the new ACL and the mode,
                   potentially modifying both */
-               err = posix_acl_create(&acl, GFP_NOFS, &mode);
+               err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
                if (err < 0)
                        return err;
 
-               inode->i_mode = mode;
-
                /* If we need an ACL.. */
                if (err > 0)
                        err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl);
index 44ce516..b6c4b37 100644 (file)
@@ -221,7 +221,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 }
 
 static int
-xfs_set_mode(struct inode *inode, mode_t mode)
+xfs_set_mode(struct inode *inode, umode_t mode)
 {
        int error = 0;
 
@@ -267,7 +267,7 @@ posix_acl_default_exists(struct inode *inode)
 int
 xfs_inherit_acl(struct inode *inode, struct posix_acl *acl)
 {
-       mode_t mode = inode->i_mode;
+       umode_t mode = inode->i_mode;
        int error = 0, inherit = 0;
 
        if (S_ISDIR(inode->i_mode)) {
@@ -381,7 +381,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
                goto out_release;
 
        if (type == ACL_TYPE_ACCESS) {
-               mode_t mode = inode->i_mode;
+               umode_t mode = inode->i_mode;
                error = posix_acl_equiv_mode(acl, &mode);
 
                if (error <= 0) {
index f23bcb7..786b3b1 100644 (file)
@@ -2317,11 +2317,18 @@ extern int should_remove_suid(struct dentry *);
 extern int file_remove_suid(struct file *);
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
-extern void remove_inode_hash(struct inode *);
 static inline void insert_inode_hash(struct inode *inode)
 {
        __insert_inode_hash(inode, inode->i_ino);
 }
+
+extern void __remove_inode_hash(struct inode *);
+static inline void remove_inode_hash(struct inode *inode)
+{
+       if (!inode_unhashed(inode))
+               __remove_inode_hash(inode);
+}
+
 extern void inode_sb_list_add(struct inode *inode);
 
 #ifdef CONFIG_BLOCK
index b96fb99..eaac770 100644 (file)
@@ -569,12 +569,12 @@ extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type);
 extern int nfs3_proc_setacl(struct inode *inode, int type,
                            struct posix_acl *acl);
 extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-               mode_t mode);
+               umode_t mode);
 extern void nfs3_forget_cached_acls(struct inode *inode);
 #else
 static inline int nfs3_proc_set_default_acl(struct inode *dir,
                                            struct inode *inode,
-                                           mode_t mode)
+                                           umode_t mode)
 {
        return 0;
 }
index 9a53b99..951bba8 100644 (file)
@@ -75,10 +75,10 @@ extern void posix_acl_init(struct posix_acl *, int);
 extern struct posix_acl *posix_acl_alloc(int, gfp_t);
 extern int posix_acl_valid(const struct posix_acl *);
 extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
-extern struct posix_acl *posix_acl_from_mode(mode_t, gfp_t);
-extern int posix_acl_equiv_mode(const struct posix_acl *, mode_t *);
-extern int posix_acl_create(struct posix_acl **, gfp_t, mode_t *);
-extern int posix_acl_chmod(struct posix_acl **, gfp_t, mode_t);
+extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t);
+extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *);
+extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *);
+extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t);
 
 extern struct posix_acl *get_posix_acl(struct inode *, int);
 extern int set_posix_acl(struct inode *, int, struct posix_acl *);