Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
Linus Torvalds [Wed, 16 Dec 2009 20:04:02 +0000 (12:04 -0800)]
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (38 commits)
  direct I/O fallback sync simplification
  ocfs: stop using do_sync_mapping_range
  cleanup blockdev_direct_IO locking
  make generic_acl slightly more generic
  sanitize xattr handler prototypes
  libfs: move EXPORT_SYMBOL for d_alloc_name
  vfs: force reval of target when following LAST_BIND symlinks (try #7)
  ima: limit imbalance msg
  Untangling ima mess, part 3: kill dead code in ima
  Untangling ima mess, part 2: deal with counters
  Untangling ima mess, part 1: alloc_file()
  O_TRUNC open shouldn't fail after file truncation
  ima: call ima_inode_free ima_inode_free
  IMA: clean up the IMA counts updating code
  ima: only insert at inode creation time
  ima: valid return code from ima_inode_alloc
  fs: move get_empty_filp() deffinition to internal.h
  Sanitize exec_permission_lite()
  Kill cached_lookup() and real_lookup()
  Kill path_lookup_open()
  ...

Trivial conflicts in fs/direct-io.c

81 files changed:
arch/ia64/kernel/perfmon.c
arch/parisc/hpux/sys_hpux.c
arch/x86/include/asm/sys_ia32.h
arch/xtensa/include/asm/syscall.h
arch/xtensa/include/asm/unistd.h
arch/xtensa/kernel/syscall.c
drivers/infiniband/core/uverbs_main.c
drivers/staging/dst/dcore.c
fs/anon_inodes.c
fs/btrfs/acl.c
fs/cachefiles/bind.c
fs/cachefiles/rdwr.c
fs/dcache.c
fs/ecryptfs/main.c
fs/ext2/acl.c
fs/ext2/xattr.c
fs/ext2/xattr_security.c
fs/ext2/xattr_trusted.c
fs/ext2/xattr_user.c
fs/ext3/acl.c
fs/ext3/xattr.c
fs/ext3/xattr_security.c
fs/ext3/xattr_trusted.c
fs/ext3/xattr_user.c
fs/ext4/acl.c
fs/ext4/xattr.c
fs/ext4/xattr_security.c
fs/ext4/xattr_trusted.c
fs/ext4/xattr_user.c
fs/file_table.c
fs/generic_acl.c
fs/gfs2/acl.c
fs/gfs2/inode.c
fs/gfs2/xattr.c
fs/gfs2/xattr.h
fs/hugetlbfs/inode.c
fs/internal.h
fs/jffs2/acl.c
fs/jffs2/security.c
fs/jffs2/xattr.c
fs/jffs2/xattr_trusted.c
fs/jffs2/xattr_user.c
fs/libfs.c
fs/namei.c
fs/namespace.c
fs/nfs/super.c
fs/nfsd/vfs.c
fs/nilfs2/super.c
fs/notify/inotify/inotify_user.c
fs/ocfs2/acl.c
fs/ocfs2/alloc.c
fs/ocfs2/xattr.c
fs/open.c
fs/pipe.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr_acl.c
fs/reiserfs/xattr_security.c
fs/reiserfs/xattr_trusted.c
fs/reiserfs/xattr_user.c
fs/xattr.c
fs/xfs/linux-2.6/xfs_acl.c
fs/xfs/linux-2.6/xfs_xattr.c
fs/xfs/xfs_acl.h
include/linux/file.h
include/linux/fs.h
include/linux/generic_acl.h
include/linux/ima.h
include/linux/mnt_namespace.h
include/linux/shmem_fs.h
include/linux/xattr.h
ipc/mqueue.c
ipc/shm.c
mm/Makefile
mm/filemap.c
mm/shmem.c
mm/shmem_acl.c [deleted file]
net/9p/trans_fd.c
net/socket.c
security/integrity/ima/ima.h
security/integrity/ima/ima_iint.c
security/integrity/ima/ima_main.c

index 599b233..5246285 100644 (file)
@@ -2200,7 +2200,7 @@ pfm_alloc_file(pfm_context_t *ctx)
 {
        struct file *file;
        struct inode *inode;
-       struct dentry *dentry;
+       struct path path;
        char name[32];
        struct qstr this;
 
@@ -2225,18 +2225,19 @@ pfm_alloc_file(pfm_context_t *ctx)
        /*
         * allocate a new dcache entry
         */
-       dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
-       if (!dentry) {
+       path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
+       if (!path.dentry) {
                iput(inode);
                return ERR_PTR(-ENOMEM);
        }
+       path.mnt = mntget(pfmfs_mnt);
 
-       dentry->d_op = &pfmfs_dentry_operations;
-       d_add(dentry, inode);
+       path.dentry->d_op = &pfmfs_dentry_operations;
+       d_add(path.dentry, inode);
 
-       file = alloc_file(pfmfs_mnt, dentry, FMODE_READ, &pfm_file_ops);
+       file = alloc_file(&path, FMODE_READ, &pfm_file_ops);
        if (!file) {
-               dput(dentry);
+               path_put(&path);
                return ERR_PTR(-ENFILE);
        }
 
index 18072e0..92343bd 100644 (file)
@@ -445,12 +445,7 @@ done:
 
 int hpux_pipe(int *kstack_fildes)
 {
-       int error;
-
-       lock_kernel();
-       error = do_pipe_flags(kstack_fildes, 0);
-       unlock_kernel();
-       return error;
+       return do_pipe_flags(kstack_fildes, 0);
 }
 
 /* lies - says it works, but it really didn't lock anything */
index 4a5a089..d5f6904 100644 (file)
@@ -30,7 +30,6 @@ struct mmap_arg_struct;
 asmlinkage long sys32_mmap(struct mmap_arg_struct __user *);
 asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long);
 
-asmlinkage long sys32_pipe(int __user *);
 struct sigaction32;
 struct old_sigaction32;
 asmlinkage long sys32_rt_sigaction(int, struct sigaction32 __user *,
index 4352dbe..efcf33b 100644 (file)
@@ -12,7 +12,6 @@ struct pt_regs;
 struct sigaction;
 asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
 asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
-asmlinkage long xtensa_pipe(int __user *);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
 asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
index fbf318b..528042c 100644 (file)
@@ -94,7 +94,7 @@ __SYSCALL( 35, sys_readlink, 3)
 #define __NR_mknod                              36
 __SYSCALL( 36, sys_mknod, 3)
 #define __NR_pipe                               37
-__SYSCALL( 37, xtensa_pipe, 1)
+__SYSCALL( 37, sys_pipe, 1)
 #define __NR_unlink                             38
 __SYSCALL( 38, sys_unlink, 1)
 #define __NR_rmdir                              39
index 1e67bab..816e6d0 100644 (file)
@@ -39,24 +39,6 @@ syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
 #include <asm/unistd.h>
 };
 
-/*
- * xtensa_pipe() is the normal C calling standard for creating a pipe. It's not
- * the way unix traditional does this, though.
- */
-
-asmlinkage long xtensa_pipe(int __user *userfds)
-{
-       int fd[2];
-       int error;
-
-       error = do_pipe_flags(fd, 0);
-       if (!error) {
-               if (copy_to_user(userfds, fd, 2 * sizeof(int)))
-                       error = -EFAULT;
-       }
-       return error;
-}
-
 asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
 {
        unsigned long ret;
index aec0fbd..5f284ff 100644 (file)
@@ -492,6 +492,7 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
                                        int is_async, int *fd)
 {
        struct ib_uverbs_event_file *ev_file;
+       struct path path;
        struct file *filp;
        int ret;
 
@@ -519,8 +520,10 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
         * system call on a uverbs file, which will already have a
         * module reference.
         */
-       filp = alloc_file(uverbs_event_mnt, dget(uverbs_event_mnt->mnt_root),
-                         FMODE_READ, fops_get(&uverbs_event_fops));
+       path.mnt = uverbs_event_mnt;
+       path.dentry = uverbs_event_mnt->mnt_root;
+       path_get(&path);
+       filp = alloc_file(&path, FMODE_READ, fops_get(&uverbs_event_fops));
        if (!filp) {
                ret = -ENFILE;
                goto err_fd;
@@ -531,6 +534,8 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
        return filp;
 
 err_fd:
+       fops_put(&uverbs_event_fops);
+       path_put(&path);
        put_unused_fd(*fd);
 
 err:
index fd5bd0e..c83ca7e 100644 (file)
@@ -403,7 +403,7 @@ static void dst_node_cleanup(struct dst_node *n)
 
        if (n->bdev) {
                sync_blockdev(n->bdev);
-               blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE);
+               close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
        }
 
        dst_state_lock(st);
@@ -464,37 +464,6 @@ void dst_node_put(struct dst_node *n)
 }
 
 /*
- * This function finds devices major/minor numbers for given pathname.
- */
-static int dst_lookup_device(const char *path, dev_t *dev)
-{
-       int err;
-       struct nameidata nd;
-       struct inode *inode;
-
-       err = path_lookup(path, LOOKUP_FOLLOW, &nd);
-       if (err)
-               return err;
-
-       inode = nd.path.dentry->d_inode;
-       if (!inode) {
-               err = -ENOENT;
-               goto out;
-       }
-
-       if (!S_ISBLK(inode->i_mode)) {
-               err = -ENOTBLK;
-               goto out;
-       }
-
-       *dev = inode->i_rdev;
-
-out:
-       path_put(&nd.path);
-       return err;
-}
-
-/*
  * Setting up export device: lookup by the name, get its size
  * and setup listening socket, which will accept clients, which
  * will submit IO for given storage.
@@ -503,17 +472,12 @@ static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl,
                struct dst_export_ctl *le)
 {
        int err;
-       dev_t dev = 0; /* gcc likes to scream here */
 
        snprintf(n->info->local, sizeof(n->info->local), "%s", le->device);
 
-       err = dst_lookup_device(le->device, &dev);
-       if (err)
-               return err;
-
-       n->bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
-       if (!n->bdev)
-               return -ENODEV;
+       n->bdev = open_bdev_exclusive(le->device, FMODE_READ|FMODE_WRITE, NULL);
+       if (IS_ERR(n->bdev))
+               return PTR_ERR(n->bdev);
 
        if (n->size != 0)
                n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size);
@@ -528,7 +492,7 @@ static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl,
        return 0;
 
 err_out_cleanup:
-       blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE);
+       close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
        n->bdev = NULL;
 
        return err;
index 2ca7a7c..94f5110 100644 (file)
@@ -88,7 +88,7 @@ struct file *anon_inode_getfile(const char *name,
                                void *priv, int flags)
 {
        struct qstr this;
-       struct dentry *dentry;
+       struct path path;
        struct file *file;
        int error;
 
@@ -106,10 +106,11 @@ struct file *anon_inode_getfile(const char *name,
        this.name = name;
        this.len = strlen(name);
        this.hash = 0;
-       dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
-       if (!dentry)
+       path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
+       if (!path.dentry)
                goto err_module;
 
+       path.mnt = mntget(anon_inode_mnt);
        /*
         * We know the anon_inode inode count is always greater than zero,
         * so we can avoid doing an igrab() and we can use an open-coded
@@ -117,14 +118,13 @@ struct file *anon_inode_getfile(const char *name,
         */
        atomic_inc(&anon_inode_inode->i_count);
 
-       dentry->d_op = &anon_inodefs_dentry_operations;
+       path.dentry->d_op = &anon_inodefs_dentry_operations;
        /* Do not publish this dentry inside the global dentry hash table */
-       dentry->d_flags &= ~DCACHE_UNHASHED;
-       d_instantiate(dentry, anon_inode_inode);
+       path.dentry->d_flags &= ~DCACHE_UNHASHED;
+       d_instantiate(path.dentry, anon_inode_inode);
 
        error = -ENFILE;
-       file = alloc_file(anon_inode_mnt, dentry,
-                         FMODE_READ | FMODE_WRITE, fops);
+       file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
        if (!file)
                goto err_dput;
        file->f_mapping = anon_inode_inode->i_mapping;
@@ -137,7 +137,7 @@ struct file *anon_inode_getfile(const char *name,
        return file;
 
 err_dput:
-       dput(dentry);
+       path_put(&path);
 err_module:
        module_put(fops->owner);
        return ERR_PTR(error);
index 3616042..52cbe47 100644 (file)
@@ -73,13 +73,13 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
        return acl;
 }
 
-static int btrfs_xattr_get_acl(struct inode *inode, int type,
-                              void *value, size_t size)
+static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name,
+               void *value, size_t size, int type)
 {
        struct posix_acl *acl;
        int ret = 0;
 
-       acl = btrfs_get_acl(inode, type);
+       acl = btrfs_get_acl(dentry->d_inode, type);
 
        if (IS_ERR(acl))
                return PTR_ERR(acl);
@@ -151,8 +151,8 @@ out:
        return ret;
 }
 
-static int btrfs_xattr_set_acl(struct inode *inode, int type,
-                              const void *value, size_t size)
+static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        int ret = 0;
        struct posix_acl *acl = NULL;
@@ -167,38 +167,13 @@ static int btrfs_xattr_set_acl(struct inode *inode, int type,
                }
        }
 
-       ret = btrfs_set_acl(inode, acl, type);
+       ret = btrfs_set_acl(dentry->d_inode, acl, type);
 
        posix_acl_release(acl);
 
        return ret;
 }
 
-
-static int btrfs_xattr_acl_access_get(struct inode *inode, const char *name,
-                                     void *value, size_t size)
-{
-       return btrfs_xattr_get_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int btrfs_xattr_acl_access_set(struct inode *inode, const char *name,
-                                     const void *value, size_t size, int flags)
-{
-       return btrfs_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int btrfs_xattr_acl_default_get(struct inode *inode, const char *name,
-                                      void *value, size_t size)
-{
-       return btrfs_xattr_get_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
-static int btrfs_xattr_acl_default_set(struct inode *inode, const char *name,
-                              const void *value, size_t size, int flags)
-{
-       return btrfs_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 int btrfs_check_acl(struct inode *inode, int mask)
 {
        struct posix_acl *acl;
@@ -303,14 +278,16 @@ int btrfs_acl_chmod(struct inode *inode)
 
 struct xattr_handler btrfs_xattr_acl_default_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .get    = btrfs_xattr_acl_default_get,
-       .set    = btrfs_xattr_acl_default_set,
+       .flags  = ACL_TYPE_DEFAULT,
+       .get    = btrfs_xattr_acl_get,
+       .set    = btrfs_xattr_acl_set,
 };
 
 struct xattr_handler btrfs_xattr_acl_access_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
-       .get    = btrfs_xattr_acl_access_get,
-       .set    = btrfs_xattr_acl_access_set,
+       .flags  = ACL_TYPE_ACCESS,
+       .get    = btrfs_xattr_acl_get,
+       .set    = btrfs_xattr_acl_set,
 };
 
 #else /* CONFIG_BTRFS_FS_POSIX_ACL */
index 3797e00..2906077 100644 (file)
@@ -84,7 +84,7 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
 static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 {
        struct cachefiles_object *fsdef;
-       struct nameidata nd;
+       struct path path;
        struct kstatfs stats;
        struct dentry *graveyard, *cachedir, *root;
        const struct cred *saved_cred;
@@ -114,15 +114,12 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
        _debug("- fsdef %p", fsdef);
 
        /* look up the directory at the root of the cache */
-       memset(&nd, 0, sizeof(nd));
-
-       ret = path_lookup(cache->rootdirname, LOOKUP_DIRECTORY, &nd);
+       ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path);
        if (ret < 0)
                goto error_open_root;
 
-       cache->mnt = mntget(nd.path.mnt);
-       root = dget(nd.path.dentry);
-       path_put(&nd.path);
+       cache->mnt = path.mnt;
+       root = path.dentry;
 
        /* check parameters */
        ret = -EOPNOTSUPP;
index a6c8c6f..1d83325 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/mount.h>
 #include <linux/file.h>
-#include <linux/ima.h>
 #include "internal.h"
 
 /*
@@ -923,7 +922,6 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
        if (IS_ERR(file)) {
                ret = PTR_ERR(file);
        } else {
-               ima_counts_get(file);
                ret = -EIO;
                if (file->f_op->write) {
                        pos = (loff_t) page->index << PAGE_SHIFT;
index a100fa3..953173a 100644 (file)
@@ -978,6 +978,7 @@ struct dentry *d_alloc_name(struct dentry *parent, const char *name)
        q.hash = full_name_hash(q.name, q.len);
        return d_alloc(parent, &q);
 }
+EXPORT_SYMBOL(d_alloc_name);
 
 /* the caller must hold dcache_lock */
 static void __d_instantiate(struct dentry *dentry, struct inode *inode)
index c6ac85d..101fe4c 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/key.h>
 #include <linux/parser.h>
 #include <linux/fs_stack.h>
-#include <linux/ima.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -119,7 +118,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
        const struct cred *cred = current_cred();
        struct ecryptfs_inode_info *inode_info =
                ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
-       int opened_lower_file = 0;
        int rc = 0;
 
        mutex_lock(&inode_info->lower_file_mutex);
@@ -136,12 +134,9 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
                               "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
                               "rc = [%d]\n", lower_dentry, lower_mnt, rc);
                        inode_info->lower_file = NULL;
-               } else
-                       opened_lower_file = 1;
+               }
        }
        mutex_unlock(&inode_info->lower_file_mutex);
-       if (opened_lower_file)
-               ima_counts_get(inode_info->lower_file);
        return rc;
 }
 
index a63d442..a99e543 100644 (file)
@@ -339,12 +339,12 @@ ext2_acl_chmod(struct inode *inode)
  * Extended attribut handlers
  */
 static size_t
-ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
-                          const char *name, size_t name_len)
+ext2_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_size,
+                          const char *name, size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return 0;
        if (list && size <= list_size)
                memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -352,12 +352,12 @@ ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
 }
 
 static size_t
-ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
-                           const char *name, size_t name_len)
+ext2_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_size,
+                           const char *name, size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return 0;
        if (list && size <= list_size)
                memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -365,15 +365,18 @@ ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+ext2_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
+                  size_t size, int type)
 {
        struct posix_acl *acl;
        int error;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return -EOPNOTSUPP;
 
-       acl = ext2_get_acl(inode, type);
+       acl = ext2_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -385,33 +388,17 @@ ext2_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
 }
 
 static int
-ext2_xattr_get_acl_access(struct inode *inode, const char *name,
-                         void *buffer, size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-ext2_xattr_get_acl_default(struct inode *inode, const char *name,
-                          void *buffer, size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
-                  size_t size)
+ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+                  size_t size, int flags, int type)
 {
        struct posix_acl *acl;
        int error;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return -EOPNOTSUPP;
-       if (!is_owner_or_cap(inode))
+       if (!is_owner_or_cap(dentry->d_inode))
                return -EPERM;
 
        if (value) {
@@ -426,41 +413,25 @@ ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
        } else
                acl = NULL;
 
-       error = ext2_set_acl(inode, type, acl);
+       error = ext2_set_acl(dentry->d_inode, type, acl);
 
 release_and_out:
        posix_acl_release(acl);
        return error;
 }
 
-static int
-ext2_xattr_set_acl_access(struct inode *inode, const char *name,
-                         const void *value, size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int
-ext2_xattr_set_acl_default(struct inode *inode, const char *name,
-                          const void *value, size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ext2_xattr_acl_access_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags  = ACL_TYPE_ACCESS,
        .list   = ext2_xattr_list_acl_access,
-       .get    = ext2_xattr_get_acl_access,
-       .set    = ext2_xattr_set_acl_access,
+       .get    = ext2_xattr_get_acl,
+       .set    = ext2_xattr_set_acl,
 };
 
 struct xattr_handler ext2_xattr_acl_default_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags  = ACL_TYPE_DEFAULT,
        .list   = ext2_xattr_list_acl_default,
-       .get    = ext2_xattr_get_acl_default,
-       .set    = ext2_xattr_set_acl_default,
+       .get    = ext2_xattr_get_acl,
+       .set    = ext2_xattr_set_acl,
 };
index 7913531..904f006 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/mbcache.h>
 #include <linux/quotaops.h>
 #include <linux/rwsem.h>
+#include <linux/security.h>
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -249,8 +250,9 @@ cleanup:
  * used / required on success.
  */
 static int
-ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+       struct inode *inode = dentry->d_inode;
        struct buffer_head *bh = NULL;
        struct ext2_xattr_entry *entry;
        char *end;
@@ -300,9 +302,10 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
                        ext2_xattr_handler(entry->e_name_index);
 
                if (handler) {
-                       size_t size = handler->list(inode, buffer, rest,
+                       size_t size = handler->list(dentry, buffer, rest,
                                                    entry->e_name,
-                                                   entry->e_name_len);
+                                                   entry->e_name_len,
+                                                   handler->flags);
                        if (buffer) {
                                if (size > rest) {
                                        error = -ERANGE;
@@ -330,7 +333,7 @@ cleanup:
 ssize_t
 ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       return ext2_xattr_list(dentry->d_inode, buffer, size);
+       return ext2_xattr_list(dentry, buffer, size);
 }
 
 /*
index 70c0dbd..c815584 100644 (file)
@@ -11,8 +11,8 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-                        const char *name, size_t name_len)
+ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+                        const char *name, size_t name_len, int type)
 {
        const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -26,22 +26,22 @@ ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_security_get(struct inode *inode, const char *name,
-                      void *buffer, size_t size)
+ext2_xattr_security_get(struct dentry *dentry, const char *name,
+                      void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
+       return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
                              buffer, size);
 }
 
 static int
-ext2_xattr_security_set(struct inode *inode, const char *name,
-                      const void *value, size_t size, int flags)
+ext2_xattr_security_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
+       return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
                              value, size, flags);
 }
 
index e8219f8..2a26d71 100644 (file)
@@ -13,8 +13,8 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-                       const char *name, size_t name_len)
+ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
 {
        const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -31,22 +31,22 @@ ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_trusted_get(struct inode *inode, const char *name,
-                      void *buffer, size_t size)
+ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+       return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
                              buffer, size);
 }
 
 static int
-ext2_xattr_trusted_set(struct inode *inode, const char *name,
-                      const void *value, size_t size, int flags)
+ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+       return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
                              value, size, flags);
 }
 
index 92495d2..3f6caf3 100644 (file)
 #include "xattr.h"
 
 static size_t
-ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-                    const char *name, size_t name_len)
+ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return 0;
 
        if (list && total_len <= list_size) {
@@ -30,27 +30,28 @@ ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_user_get(struct inode *inode, const char *name,
-                   void *buffer, size_t size)
+ext2_xattr_user_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, buffer, size);
+       return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_USER,
+                             name, buffer, size);
 }
 
 static int
-ext2_xattr_user_set(struct inode *inode, const char *name,
-                   const void *value, size_t size, int flags)
+ext2_xattr_user_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
 
-       return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
-                             value, size, flags);
+       return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_USER,
+                             name, value, size, flags);
 }
 
 struct xattr_handler ext2_xattr_user_handler = {
index c9b0df3..82ba341 100644 (file)
@@ -366,12 +366,12 @@ out:
  * Extended attribute handlers
  */
 static size_t
-ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
-                          const char *name, size_t name_len)
+ext3_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
+                          const char *name, size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return 0;
        if (list && size <= list_len)
                memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -379,12 +379,12 @@ ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
 }
 
 static size_t
-ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
-                           const char *name, size_t name_len)
+ext3_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
+                           const char *name, size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return 0;
        if (list && size <= list_len)
                memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -392,15 +392,18 @@ ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
 }
 
 static int
-ext3_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+ext3_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
+                  size_t size, int type)
 {
        struct posix_acl *acl;
        int error;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return -EOPNOTSUPP;
 
-       acl = ext3_get_acl(inode, type);
+       acl = ext3_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -412,31 +415,16 @@ ext3_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
 }
 
 static int
-ext3_xattr_get_acl_access(struct inode *inode, const char *name,
-                         void *buffer, size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext3_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-ext3_xattr_get_acl_default(struct inode *inode, const char *name,
-                          void *buffer, size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext3_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
-                  size_t size)
+ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+                  size_t size, int flags, int type)
 {
+       struct inode *inode = dentry->d_inode;
        handle_t *handle;
        struct posix_acl *acl;
        int error, retries = 0;
 
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
        if (!test_opt(inode->i_sb, POSIX_ACL))
                return -EOPNOTSUPP;
        if (!is_owner_or_cap(inode))
@@ -468,34 +456,18 @@ release_and_out:
        return error;
 }
 
-static int
-ext3_xattr_set_acl_access(struct inode *inode, const char *name,
-                         const void *value, size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext3_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int
-ext3_xattr_set_acl_default(struct inode *inode, const char *name,
-                          const void *value, size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext3_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ext3_xattr_acl_access_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags  = ACL_TYPE_ACCESS,
        .list   = ext3_xattr_list_acl_access,
-       .get    = ext3_xattr_get_acl_access,
-       .set    = ext3_xattr_set_acl_access,
+       .get    = ext3_xattr_get_acl,
+       .set    = ext3_xattr_set_acl,
 };
 
 struct xattr_handler ext3_xattr_acl_default_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags  = ACL_TYPE_DEFAULT,
        .list   = ext3_xattr_list_acl_default,
-       .get    = ext3_xattr_get_acl_default,
-       .set    = ext3_xattr_set_acl_default,
+       .get    = ext3_xattr_get_acl,
+       .set    = ext3_xattr_set_acl,
 };
index 387d92d..66895cc 100644 (file)
@@ -99,7 +99,7 @@ static struct buffer_head *ext3_xattr_cache_find(struct inode *,
                                                 struct mb_cache_entry **);
 static void ext3_xattr_rehash(struct ext3_xattr_header *,
                              struct ext3_xattr_entry *);
-static int ext3_xattr_list(struct inode *inode, char *buffer,
+static int ext3_xattr_list(struct dentry *dentry, char *buffer,
                           size_t buffer_size);
 
 static struct mb_cache *ext3_xattr_cache;
@@ -147,7 +147,7 @@ ext3_xattr_handler(int name_index)
 ssize_t
 ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       return ext3_xattr_list(dentry->d_inode, buffer, size);
+       return ext3_xattr_list(dentry, buffer, size);
 }
 
 static int
@@ -332,7 +332,7 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
 }
 
 static int
-ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
+ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
                        char *buffer, size_t buffer_size)
 {
        size_t rest = buffer_size;
@@ -342,9 +342,10 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
                        ext3_xattr_handler(entry->e_name_index);
 
                if (handler) {
-                       size_t size = handler->list(inode, buffer, rest,
+                       size_t size = handler->list(dentry, buffer, rest,
                                                    entry->e_name,
-                                                   entry->e_name_len);
+                                                   entry->e_name_len,
+                                                   handler->flags);
                        if (buffer) {
                                if (size > rest)
                                        return -ERANGE;
@@ -357,8 +358,9 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
 }
 
 static int
-ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+       struct inode *inode = dentry->d_inode;
        struct buffer_head *bh = NULL;
        int error;
 
@@ -383,7 +385,7 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
                goto cleanup;
        }
        ext3_xattr_cache_insert(bh);
-       error = ext3_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
+       error = ext3_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
 
 cleanup:
        brelse(bh);
@@ -392,8 +394,9 @@ cleanup:
 }
 
 static int
-ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+       struct inode *inode = dentry->d_inode;
        struct ext3_xattr_ibody_header *header;
        struct ext3_inode *raw_inode;
        struct ext3_iloc iloc;
@@ -411,7 +414,7 @@ ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
        error = ext3_xattr_check_names(IFIRST(header), end);
        if (error)
                goto cleanup;
-       error = ext3_xattr_list_entries(inode, IFIRST(header),
+       error = ext3_xattr_list_entries(dentry, IFIRST(header),
                                        buffer, buffer_size);
 
 cleanup:
@@ -430,12 +433,12 @@ cleanup:
  * used / required on success.
  */
 static int
-ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
        int i_error, b_error;
 
-       down_read(&EXT3_I(inode)->xattr_sem);
-       i_error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
+       down_read(&EXT3_I(dentry->d_inode)->xattr_sem);
+       i_error = ext3_xattr_ibody_list(dentry, buffer, buffer_size);
        if (i_error < 0) {
                b_error = 0;
        } else {
@@ -443,11 +446,11 @@ ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
                        buffer += i_error;
                        buffer_size -= i_error;
                }
-               b_error = ext3_xattr_block_list(inode, buffer, buffer_size);
+               b_error = ext3_xattr_block_list(dentry, buffer, buffer_size);
                if (b_error < 0)
                        i_error = 0;
        }
-       up_read(&EXT3_I(inode)->xattr_sem);
+       up_read(&EXT3_I(dentry->d_inode)->xattr_sem);
        return i_error + b_error;
 }
 
index 37b8109..4743487 100644 (file)
@@ -12,8 +12,8 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-                        const char *name, size_t name_len)
+ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+                        const char *name, size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -28,23 +28,23 @@ ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_security_get(struct inode *inode, const char *name,
-                      void *buffer, size_t size)
+ext3_xattr_security_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY, name,
-                             buffer, size);
+       return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
+                             name, buffer, size);
 }
 
 static int
-ext3_xattr_security_set(struct inode *inode, const char *name,
-                      const void *value, size_t size, int flags)
+ext3_xattr_security_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name,
-                             value, size, flags);
+       return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
+                             name, value, size, flags);
 }
 
 int
index c7c41a4..e556284 100644 (file)
@@ -14,8 +14,8 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-                       const char *name, size_t name_len)
+ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -32,22 +32,22 @@ ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_trusted_get(struct inode *inode, const char *name,
-                      void *buffer, size_t size)
+ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
+                      void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
-                             buffer, size);
+       return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED,
+                             name, buffer, size);
 }
 
 static int
-ext3_xattr_trusted_set(struct inode *inode, const char *name,
-                      const void *value, size_t size, int flags)
+ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
+       return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED, name,
                              value, size, flags);
 }
 
index 430fe63..3bcfe9e 100644 (file)
 #include "xattr.h"
 
 static size_t
-ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-                    const char *name, size_t name_len)
+ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return 0;
 
        if (list && total_len <= list_size) {
@@ -31,26 +31,27 @@ ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_user_get(struct inode *inode, const char *name,
-                   void *buffer, size_t size)
+ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
+               size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, buffer, size);
+       return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_USER,
+                             name, buffer, size);
 }
 
 static int
-ext3_xattr_user_set(struct inode *inode, const char *name,
-                   const void *value, size_t size, int flags)
+ext3_xattr_user_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
-                             value, size, flags);
+       return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_USER,
+                             name, value, size, flags);
 }
 
 struct xattr_handler ext3_xattr_user_handler = {
index 0df88b2..8a2a29d 100644 (file)
@@ -364,12 +364,12 @@ out:
  * Extended attribute handlers
  */
 static size_t
-ext4_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
-                          const char *name, size_t name_len)
+ext4_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
+                          const char *name, size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return 0;
        if (list && size <= list_len)
                memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -377,12 +377,12 @@ ext4_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
 }
 
 static size_t
-ext4_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
-                           const char *name, size_t name_len)
+ext4_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
+                           const char *name, size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return 0;
        if (list && size <= list_len)
                memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -390,15 +390,18 @@ ext4_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
 }
 
 static int
-ext4_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+ext4_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
+                  size_t size, int type)
 {
        struct posix_acl *acl;
        int error;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       if (!test_opt(dentry->d_sb, POSIX_ACL))
                return -EOPNOTSUPP;
 
-       acl = ext4_get_acl(inode, type);
+       acl = ext4_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -410,31 +413,16 @@ ext4_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
 }
 
 static int
-ext4_xattr_get_acl_access(struct inode *inode, const char *name,
-                         void *buffer, size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext4_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-ext4_xattr_get_acl_default(struct inode *inode, const char *name,
-                          void *buffer, size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext4_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-ext4_xattr_set_acl(struct inode *inode, int type, const void *value,
-                  size_t size)
+ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+                  size_t size, int flags, int type)
 {
+       struct inode *inode = dentry->d_inode;
        handle_t *handle;
        struct posix_acl *acl;
        int error, retries = 0;
 
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
        if (!test_opt(inode->i_sb, POSIX_ACL))
                return -EOPNOTSUPP;
        if (!is_owner_or_cap(inode))
@@ -466,34 +454,18 @@ release_and_out:
        return error;
 }
 
-static int
-ext4_xattr_set_acl_access(struct inode *inode, const char *name,
-                         const void *value, size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext4_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int
-ext4_xattr_set_acl_default(struct inode *inode, const char *name,
-                          const void *value, size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ext4_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ext4_xattr_acl_access_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags  = ACL_TYPE_ACCESS,
        .list   = ext4_xattr_list_acl_access,
-       .get    = ext4_xattr_get_acl_access,
-       .set    = ext4_xattr_set_acl_access,
+       .get    = ext4_xattr_get_acl,
+       .set    = ext4_xattr_set_acl,
 };
 
 struct xattr_handler ext4_xattr_acl_default_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags  = ACL_TYPE_DEFAULT,
        .list   = ext4_xattr_list_acl_default,
-       .get    = ext4_xattr_get_acl_default,
-       .set    = ext4_xattr_set_acl_default,
+       .get    = ext4_xattr_get_acl,
+       .set    = ext4_xattr_set_acl,
 };
index 910bf9a..83218be 100644 (file)
@@ -92,7 +92,7 @@ static struct buffer_head *ext4_xattr_cache_find(struct inode *,
                                                 struct mb_cache_entry **);
 static void ext4_xattr_rehash(struct ext4_xattr_header *,
                              struct ext4_xattr_entry *);
-static int ext4_xattr_list(struct inode *inode, char *buffer,
+static int ext4_xattr_list(struct dentry *dentry, char *buffer,
                           size_t buffer_size);
 
 static struct mb_cache *ext4_xattr_cache;
@@ -140,7 +140,7 @@ ext4_xattr_handler(int name_index)
 ssize_t
 ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       return ext4_xattr_list(dentry->d_inode, buffer, size);
+       return ext4_xattr_list(dentry, buffer, size);
 }
 
 static int
@@ -325,7 +325,7 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
 }
 
 static int
-ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
+ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
                        char *buffer, size_t buffer_size)
 {
        size_t rest = buffer_size;
@@ -335,9 +335,10 @@ ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
                        ext4_xattr_handler(entry->e_name_index);
 
                if (handler) {
-                       size_t size = handler->list(inode, buffer, rest,
+                       size_t size = handler->list(dentry, buffer, rest,
                                                    entry->e_name,
-                                                   entry->e_name_len);
+                                                   entry->e_name_len,
+                                                   handler->flags);
                        if (buffer) {
                                if (size > rest)
                                        return -ERANGE;
@@ -350,8 +351,9 @@ ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
 }
 
 static int
-ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+       struct inode *inode = dentry->d_inode;
        struct buffer_head *bh = NULL;
        int error;
 
@@ -376,7 +378,7 @@ ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
                goto cleanup;
        }
        ext4_xattr_cache_insert(bh);
-       error = ext4_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
+       error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
 
 cleanup:
        brelse(bh);
@@ -385,8 +387,9 @@ cleanup:
 }
 
 static int
-ext4_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+       struct inode *inode = dentry->d_inode;
        struct ext4_xattr_ibody_header *header;
        struct ext4_inode *raw_inode;
        struct ext4_iloc iloc;
@@ -404,7 +407,7 @@ ext4_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
        error = ext4_xattr_check_names(IFIRST(header), end);
        if (error)
                goto cleanup;
-       error = ext4_xattr_list_entries(inode, IFIRST(header),
+       error = ext4_xattr_list_entries(dentry, IFIRST(header),
                                        buffer, buffer_size);
 
 cleanup:
@@ -423,12 +426,12 @@ cleanup:
  * used / required on success.
  */
 static int
-ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext4_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
        int i_error, b_error;
 
-       down_read(&EXT4_I(inode)->xattr_sem);
-       i_error = ext4_xattr_ibody_list(inode, buffer, buffer_size);
+       down_read(&EXT4_I(dentry->d_inode)->xattr_sem);
+       i_error = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
        if (i_error < 0) {
                b_error = 0;
        } else {
@@ -436,11 +439,11 @@ ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
                        buffer += i_error;
                        buffer_size -= i_error;
                }
-               b_error = ext4_xattr_block_list(inode, buffer, buffer_size);
+               b_error = ext4_xattr_block_list(dentry, buffer, buffer_size);
                if (b_error < 0)
                        i_error = 0;
        }
-       up_read(&EXT4_I(inode)->xattr_sem);
+       up_read(&EXT4_I(dentry->d_inode)->xattr_sem);
        return i_error + b_error;
 }
 
index ca5f89f..983c253 100644 (file)
@@ -12,8 +12,8 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-                        const char *name, size_t name_len)
+ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
 {
        const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
        const size_t total_len = prefix_len + name_len + 1;
@@ -28,23 +28,23 @@ ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_security_get(struct inode *inode, const char *name,
-                      void *buffer, size_t size)
+ext4_xattr_security_get(struct dentry *dentry, const char *name,
+                      void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY, name,
-                             buffer, size);
+       return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
+                             name, buffer, size);
 }
 
 static int
-ext4_xattr_security_set(struct inode *inode, const char *name,
-                      const void *value, size_t size, int flags)
+ext4_xattr_security_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY, name,
-                             value, size, flags);
+       return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
+                             name, value, size, flags);
 }
 
 int
index ac1a52c..15b50ed 100644 (file)
@@ -14,8 +14,8 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-                       const char *name, size_t name_len)
+ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -32,23 +32,23 @@ ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_trusted_get(struct inode *inode, const char *name,
-                      void *buffer, size_t size)
+ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
+               size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED, name,
-                             buffer, size);
+       return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
+                             name, buffer, size);
 }
 
 static int
-ext4_xattr_trusted_set(struct inode *inode, const char *name,
-                      const void *value, size_t size, int flags)
+ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED, name,
-                             value, size, flags);
+       return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
+                             name, value, size, flags);
 }
 
 struct xattr_handler ext4_xattr_trusted_handler = {
index d91aa61..c4ce057 100644 (file)
 #include "xattr.h"
 
 static size_t
-ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-                    const char *name, size_t name_len)
+ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+                    const char *name, size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
 
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return 0;
 
        if (list && total_len <= list_size) {
@@ -31,26 +31,27 @@ ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_user_get(struct inode *inode, const char *name,
-                   void *buffer, size_t size)
+ext4_xattr_user_get(struct dentry *dentry, const char *name,
+                   void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER, name, buffer, size);
+       return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_USER,
+                             name, buffer, size);
 }
 
 static int
-ext4_xattr_user_set(struct inode *inode, const char *name,
-                   const void *value, size_t size, int flags)
+ext4_xattr_user_set(struct dentry *dentry, const char *name,
+                   const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       if (!test_opt(inode->i_sb, XATTR_USER))
+       if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER, name,
-                             value, size, flags);
+       return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_USER,
+                             name, value, size, flags);
 }
 
 struct xattr_handler ext4_xattr_user_handler = {
index 4bef4c0..17a55b8 100644 (file)
 #include <linux/fsnotify.h>
 #include <linux/sysctl.h>
 #include <linux/percpu_counter.h>
+#include <linux/ima.h>
 
 #include <asm/atomic.h>
 
+#include "internal.h"
+
 /* sysctl tunables... */
 struct files_stat_struct files_stat = {
        .max_files = NR_FILE
@@ -147,8 +150,6 @@ fail:
        return NULL;
 }
 
-EXPORT_SYMBOL(get_empty_filp);
-
 /**
  * alloc_file - allocate and initialize a 'struct file'
  * @mnt: the vfsmount on which the file will reside
@@ -164,8 +165,8 @@ EXPORT_SYMBOL(get_empty_filp);
  * If all the callers of init_file() are eliminated, its
  * code should be moved into this function.
  */
-struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry,
-               fmode_t mode, const struct file_operations *fop)
+struct file *alloc_file(struct path *path, fmode_t mode,
+               const struct file_operations *fop)
 {
        struct file *file;
 
@@ -173,35 +174,8 @@ struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry,
        if (!file)
                return NULL;
 
-       init_file(file, mnt, dentry, mode, fop);
-       return file;
-}
-EXPORT_SYMBOL(alloc_file);
-
-/**
- * init_file - initialize a 'struct file'
- * @file: the already allocated 'struct file' to initialized
- * @mnt: the vfsmount on which the file resides
- * @dentry: the dentry representing this file
- * @mode: the mode the file is opened with
- * @fop: the 'struct file_operations' for this file
- *
- * Use this instead of setting the members directly.  Doing so
- * avoids making mistakes like forgetting the mntget() or
- * forgetting to take a write on the mnt.
- *
- * Note: This is a crappy interface.  It is here to make
- * merging with the existing users of get_empty_filp()
- * who have complex failure logic easier.  All users
- * of this should be moving to alloc_file().
- */
-int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
-          fmode_t mode, const struct file_operations *fop)
-{
-       int error = 0;
-       file->f_path.dentry = dentry;
-       file->f_path.mnt = mntget(mnt);
-       file->f_mapping = dentry->d_inode->i_mapping;
+       file->f_path = *path;
+       file->f_mapping = path->dentry->d_inode->i_mapping;
        file->f_mode = mode;
        file->f_op = fop;
 
@@ -211,14 +185,15 @@ int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
         * visible.  We do this for consistency, and so
         * that we can do debugging checks at __fput()
         */
-       if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
+       if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) {
+               int error = 0;
                file_take_write(file);
-               error = mnt_clone_write(mnt);
+               error = mnt_clone_write(path->mnt);
                WARN_ON(error);
        }
-       return error;
+       ima_counts_get(file);
+       return file;
 }
-EXPORT_SYMBOL(init_file);
 
 void fput(struct file *file)
 {
index e0b53aa..5545803 100644 (file)
@@ -1,62 +1,58 @@
 /*
- * fs/generic_acl.c
- *
  * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
  *
  * This file is released under the GPL.
+ *
+ * Generic ACL support for in-memory filesystems.
  */
 
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/generic_acl.h>
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
 
-/**
- * generic_acl_list  -  Generic xattr_handler->list() operation
- * @ops:       Filesystem specific getacl and setacl callbacks
- */
-size_t
-generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
-                int type, char *list, size_t list_size)
+
+static size_t
+generic_acl_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
 {
        struct posix_acl *acl;
-       const char *name;
+       const char *xname;
        size_t size;
 
-       acl = ops->getacl(inode, type);
+       acl = get_cached_acl(dentry->d_inode, type);
        if (!acl)
                return 0;
        posix_acl_release(acl);
 
-       switch(type) {
-               case ACL_TYPE_ACCESS:
-                       name = POSIX_ACL_XATTR_ACCESS;
-                       break;
-
-               case ACL_TYPE_DEFAULT:
-                       name = POSIX_ACL_XATTR_DEFAULT;
-                       break;
-
-               default:
-                       return 0;
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               xname = POSIX_ACL_XATTR_ACCESS;
+               break;
+       case ACL_TYPE_DEFAULT:
+               xname = POSIX_ACL_XATTR_DEFAULT;
+               break;
+       default:
+               return 0;
        }
-       size = strlen(name) + 1;
+       size = strlen(xname) + 1;
        if (list && size <= list_size)
-               memcpy(list, name, size);
+               memcpy(list, xname, size);
        return size;
 }
 
-/**
- * generic_acl_get  -  Generic xattr_handler->get() operation
- * @ops:       Filesystem specific getacl and setacl callbacks
- */
-int
-generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
-               int type, void *buffer, size_t size)
+static int
+generic_acl_get(struct dentry *dentry, const char *name, void *buffer,
+                    size_t size, int type)
 {
        struct posix_acl *acl;
        int error;
 
-       acl = ops->getacl(inode, type);
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+
+       acl = get_cached_acl(dentry->d_inode, type);
        if (!acl)
                return -ENODATA;
        error = posix_acl_to_xattr(acl, buffer, size);
@@ -65,17 +61,16 @@ generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
        return error;
 }
 
-/**
- * generic_acl_set  -  Generic xattr_handler->set() operation
- * @ops:       Filesystem specific getacl and setacl callbacks
- */
-int
-generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
-               int type, const void *value, size_t size)
+static int
+generic_acl_set(struct dentry *dentry, const char *name, const void *value,
+                    size_t size, int flags, int type)
 {
+       struct inode *inode = dentry->d_inode;
        struct posix_acl *acl = NULL;
        int error;
 
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
        if (!is_owner_or_cap(inode))
@@ -91,28 +86,27 @@ generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
                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);
-                               if (error < 0)
-                                       goto failed;
-                               inode->i_mode = mode;
-                               if (error == 0) {
-                                       posix_acl_release(acl);
-                                       acl = NULL;
-                               }
-                               break;
-
-                       case ACL_TYPE_DEFAULT:
-                               if (!S_ISDIR(inode->i_mode)) {
-                                       error = -EINVAL;
-                                       goto failed;
-                               }
-                               break;
+               switch (type) {
+               case ACL_TYPE_ACCESS:
+                       mode = inode->i_mode;
+                       error = posix_acl_equiv_mode(acl, &mode);
+                       if (error < 0)
+                               goto failed;
+                       inode->i_mode = mode;
+                       if (error == 0) {
+                               posix_acl_release(acl);
+                               acl = NULL;
+                       }
+                       break;
+               case ACL_TYPE_DEFAULT:
+                       if (!S_ISDIR(inode->i_mode)) {
+                               error = -EINVAL;
+                               goto failed;
+                       }
+                       break;
                }
        }
-       ops->setacl(inode, type, acl);
+       set_cached_acl(inode, type, acl);
        error = 0;
 failed:
        posix_acl_release(acl);
@@ -121,14 +115,12 @@ failed:
 
 /**
  * generic_acl_init  -  Take care of acl inheritance at @inode create time
- * @ops:       Filesystem specific getacl and setacl callbacks
  *
  * Files created inside a directory with a default ACL inherit the
  * directory's default ACL.
  */
 int
-generic_acl_init(struct inode *inode, struct inode *dir,
-                struct generic_acl_operations *ops)
+generic_acl_init(struct inode *inode, struct inode *dir)
 {
        struct posix_acl *acl = NULL;
        mode_t mode = inode->i_mode;
@@ -136,7 +128,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
 
        inode->i_mode = mode & ~current_umask();
        if (!S_ISLNK(inode->i_mode))
-               acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
+               acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
        if (acl) {
                struct posix_acl *clone;
 
@@ -145,7 +137,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
                        error = -ENOMEM;
                        if (!clone)
                                goto cleanup;
-                       ops->setacl(inode, ACL_TYPE_DEFAULT, clone);
+                       set_cached_acl(inode, ACL_TYPE_DEFAULT, clone);
                        posix_acl_release(clone);
                }
                clone = posix_acl_clone(acl, GFP_KERNEL);
@@ -156,7 +148,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
                if (error >= 0) {
                        inode->i_mode = mode;
                        if (error > 0)
-                               ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+                               set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
                }
                posix_acl_release(clone);
        }
@@ -169,20 +161,19 @@ cleanup:
 
 /**
  * generic_acl_chmod  -  change the access acl of @inode upon chmod()
- * @ops:       FIlesystem specific getacl and setacl callbacks
  *
  * A chmod also changes the permissions of the owner, group/mask, and
  * other ACL entries.
  */
 int
-generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
+generic_acl_chmod(struct inode *inode)
 {
        struct posix_acl *acl, *clone;
        int error = 0;
 
        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
-       acl = ops->getacl(inode, ACL_TYPE_ACCESS);
+       acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
        if (acl) {
                clone = posix_acl_clone(acl, GFP_KERNEL);
                posix_acl_release(acl);
@@ -190,8 +181,37 @@ generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
                        return -ENOMEM;
                error = posix_acl_chmod_masq(clone, inode->i_mode);
                if (!error)
-                       ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+                       set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
                posix_acl_release(clone);
        }
        return error;
 }
+
+int
+generic_check_acl(struct inode *inode, int mask)
+{
+       struct posix_acl *acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
+
+       if (acl) {
+               int error = posix_acl_permission(inode, acl, mask);
+               posix_acl_release(acl);
+               return error;
+       }
+       return -EAGAIN;
+}
+
+struct xattr_handler generic_acl_access_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags  = ACL_TYPE_ACCESS,
+       .list   = generic_acl_list,
+       .get    = generic_acl_get,
+       .set    = generic_acl_set,
+};
+
+struct xattr_handler generic_acl_default_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags  = ACL_TYPE_DEFAULT,
+       .list   = generic_acl_list,
+       .get    = generic_acl_get,
+       .set    = generic_acl_set,
+};
index 3eb1ea8..87ee309 100644 (file)
@@ -126,7 +126,7 @@ static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
        error = posix_acl_to_xattr(acl, data, len);
        if (error < 0)
                goto out;
-       error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, data, len, 0);
+       error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
        if (!error)
                set_cached_acl(inode, type, acl);
 out:
@@ -232,9 +232,10 @@ static int gfs2_acl_type(const char *name)
        return -EINVAL;
 }
 
-static int gfs2_xattr_system_get(struct inode *inode, const char *name,
-                                void *buffer, size_t size)
+static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
+                                void *buffer, size_t size, int xtype)
 {
+       struct inode *inode = dentry->d_inode;
        struct posix_acl *acl;
        int type;
        int error;
@@ -255,9 +256,11 @@ static int gfs2_xattr_system_get(struct inode *inode, const char *name,
        return error;
 }
 
-static int gfs2_xattr_system_set(struct inode *inode, const char *name,
-                                const void *value, size_t size, int flags)
+static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
+                                const void *value, size_t size, int flags,
+                                int xtype)
 {
+       struct inode *inode = dentry->d_inode;
        struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct posix_acl *acl = NULL;
        int error = 0, type;
@@ -319,7 +322,7 @@ static int gfs2_xattr_system_set(struct inode *inode, const char *name,
        }
 
 set_acl:
-       error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, 0);
+       error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
        if (!error) {
                if (acl)
                        set_cached_acl(inode, type, acl);
@@ -334,6 +337,7 @@ out:
 
 struct xattr_handler gfs2_xattr_system_handler = {
        .prefix = XATTR_SYSTEM_PREFIX,
+       .flags  = GFS2_EATYPE_SYS,
        .get    = gfs2_xattr_system_get,
        .set    = gfs2_xattr_system_set,
 };
index 26ba2a4..3ff32fa 100644 (file)
@@ -801,7 +801,8 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip)
                return err;
        }
 
-       err = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SECURITY, name, value, len, 0);
+       err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0,
+                              GFS2_EATYPE_SECURITY);
        kfree(value);
        kfree(name);
 
index 912f5cb..8a04108 100644 (file)
@@ -567,18 +567,17 @@ out:
 /**
  * gfs2_xattr_get - Get a GFS2 extended attribute
  * @inode: The inode
- * @type: The type of extended attribute
  * @name: The name of the extended attribute
  * @buffer: The buffer to write the result into
  * @size: The size of the buffer
+ * @type: The type of extended attribute
  *
  * Returns: actual size of data on success, -errno on error
  */
-
-int gfs2_xattr_get(struct inode *inode, int type, const char *name,
-                  void *buffer, size_t size)
+static int gfs2_xattr_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
-       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
        struct gfs2_ea_location el;
        int error;
 
@@ -1119,7 +1118,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
 
 /**
  * gfs2_xattr_remove - Remove a GFS2 extended attribute
- * @inode: The inode
+ * @ip: The inode
  * @type: The type of the extended attribute
  * @name: The name of the extended attribute
  *
@@ -1130,9 +1129,8 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
  * Returns: 0, or errno on failure
  */
 
-static int gfs2_xattr_remove(struct inode *inode, int type, const char *name)
+static int gfs2_xattr_remove(struct gfs2_inode *ip, int type, const char *name)
 {
-       struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_ea_location el;
        int error;
 
@@ -1156,24 +1154,24 @@ static int gfs2_xattr_remove(struct inode *inode, int type, const char *name)
 }
 
 /**
- * gfs2_xattr_set - Set (or remove) a GFS2 extended attribute
- * @inode: The inode
- * @type: The type of the extended attribute
+ * __gfs2_xattr_set - Set (or remove) a GFS2 extended attribute
+ * @ip: The inode
  * @name: The name of the extended attribute
  * @value: The value of the extended attribute (NULL for remove)
  * @size: The size of the @value argument
  * @flags: Create or Replace
+ * @type: The type of the extended attribute
  *
  * See gfs2_xattr_remove() for details of the removal of xattrs.
  *
  * Returns: 0 or errno on failure
  */
 
-int gfs2_xattr_set(struct inode *inode, int type, const char *name,
-                  const void *value, size_t size, int flags)
+int __gfs2_xattr_set(struct inode *inode, const char *name,
+                  const void *value, size_t size, int flags, int type)
 {
-       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct gfs2_ea_location el;
        unsigned int namel = strlen(name);
        int error;
@@ -1184,7 +1182,7 @@ int gfs2_xattr_set(struct inode *inode, int type, const char *name,
                return -ERANGE;
 
        if (value == NULL)
-               return gfs2_xattr_remove(inode, type, name);
+               return gfs2_xattr_remove(ip, type, name);
 
        if (ea_check_size(sdp, namel, size))
                return -ERANGE;
@@ -1224,6 +1222,13 @@ int gfs2_xattr_set(struct inode *inode, int type, const char *name,
        return error;
 }
 
+static int gfs2_xattr_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
+{
+       return __gfs2_xattr_set(dentry->d_inode, name, value,
+                               size, flags, type);
+}
+
 static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
                                  struct gfs2_ea_header *ea, char *data)
 {
@@ -1529,40 +1534,18 @@ out_alloc:
        return error;
 }
 
-static int gfs2_xattr_user_get(struct inode *inode, const char *name,
-                              void *buffer, size_t size)
-{
-       return gfs2_xattr_get(inode, GFS2_EATYPE_USR, name, buffer, size);
-}
-
-static int gfs2_xattr_user_set(struct inode *inode, const char *name,
-                              const void *value, size_t size, int flags)
-{
-       return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags);
-}
-
-static int gfs2_xattr_security_get(struct inode *inode, const char *name,
-                                  void *buffer, size_t size)
-{
-       return gfs2_xattr_get(inode, GFS2_EATYPE_SECURITY, name, buffer, size);
-}
-
-static int gfs2_xattr_security_set(struct inode *inode, const char *name,
-                                  const void *value, size_t size, int flags)
-{
-       return gfs2_xattr_set(inode, GFS2_EATYPE_SECURITY, name, value, size, flags);
-}
-
 static struct xattr_handler gfs2_xattr_user_handler = {
        .prefix = XATTR_USER_PREFIX,
-       .get    = gfs2_xattr_user_get,
-       .set    = gfs2_xattr_user_set,
+       .flags  = GFS2_EATYPE_USR,
+       .get    = gfs2_xattr_get,
+       .set    = gfs2_xattr_set,
 };
 
 static struct xattr_handler gfs2_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
-       .get    = gfs2_xattr_security_get,
-       .set    = gfs2_xattr_security_set,
+       .flags  = GFS2_EATYPE_SECURITY,
+       .get    = gfs2_xattr_get,
+       .set    = gfs2_xattr_set,
 };
 
 struct xattr_handler *gfs2_xattr_handlers[] = {
index 8d6ae58..d392f83 100644 (file)
@@ -53,10 +53,9 @@ struct gfs2_ea_location {
        struct gfs2_ea_header *el_prev;
 };
 
-extern int gfs2_xattr_get(struct inode *inode, int type, const char *name,
-                         void *buffer, size_t size);
-extern int gfs2_xattr_set(struct inode *inode, int type, const char *name,
-                         const void *value, size_t size, int flags);
+extern int __gfs2_xattr_set(struct inode *inode, const char *name,
+                           const void *value, size_t size,
+                           int flags, int type);
 extern ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size);
 extern int gfs2_ea_dealloc(struct gfs2_inode *ip);
 
index 87a1258..a0bbd3d 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/dnotify.h>
 #include <linux/statfs.h>
 #include <linux/security.h>
-#include <linux/ima.h>
 #include <linux/magic.h>
 
 #include <asm/uaccess.h>
@@ -922,7 +921,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
        int error = -ENOMEM;
        struct file *file;
        struct inode *inode;
-       struct dentry *dentry, *root;
+       struct path path;
+       struct dentry *root;
        struct qstr quick_string;
 
        *user = NULL;
@@ -944,10 +944,11 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
        quick_string.name = name;
        quick_string.len = strlen(quick_string.name);
        quick_string.hash = 0;
-       dentry = d_alloc(root, &quick_string);
-       if (!dentry)
+       path.dentry = d_alloc(root, &quick_string);
+       if (!path.dentry)
                goto out_shm_unlock;
 
+       path.mnt = mntget(hugetlbfs_vfsmount);
        error = -ENOSPC;
        inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(),
                                current_fsgid(), S_IFREG | S_IRWXUGO, 0);
@@ -960,24 +961,22 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
                        acctflag))
                goto out_inode;
 
-       d_instantiate(dentry, inode);
+       d_instantiate(path.dentry, inode);
        inode->i_size = size;
        inode->i_nlink = 0;
 
        error = -ENFILE;
-       file = alloc_file(hugetlbfs_vfsmount, dentry,
-                       FMODE_WRITE | FMODE_READ,
+       file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
                        &hugetlbfs_file_operations);
        if (!file)
                goto out_dentry; /* inode is already attached */
-       ima_counts_get(file);
 
        return file;
 
 out_inode:
        iput(inode);
 out_dentry:
-       dput(dentry);
+       path_put(&path);
 out_shm_unlock:
        if (*user) {
                user_shm_unlock(size, *user);
index 515175b..f67cd14 100644 (file)
@@ -79,6 +79,7 @@ extern void chroot_fs_refs(struct path *, struct path *);
  * file_table.c
  */
 extern void mark_files_ro(struct super_block *);
+extern struct file *get_empty_filp(void);
 
 /*
  * super.c
index 7edb62e..7cdc319 100644 (file)
@@ -350,8 +350,8 @@ int jffs2_acl_chmod(struct inode *inode)
        return rc;
 }
 
-static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
-                                        const char *name, size_t name_len)
+static size_t jffs2_acl_access_listxattr(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
 {
        const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
 
@@ -360,8 +360,8 @@ static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t
        return retlen;
 }
 
-static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
-                                         const char *name, size_t name_len)
+static size_t jffs2_acl_default_listxattr(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
 {
        const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
@@ -370,12 +370,16 @@ static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_
        return retlen;
 }
 
-static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
+static int jffs2_acl_getxattr(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
        struct posix_acl *acl;
        int rc;
 
-       acl = jffs2_get_acl(inode, type);
+       if (name[0] != '\0')
+               return -EINVAL;
+
+       acl = jffs2_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (!acl)
@@ -386,26 +390,15 @@ static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_
        return rc;
 }
 
-static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
-{
-       if (name[0] != '\0')
-               return -EINVAL;
-       return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
-{
-       if (name[0] != '\0')
-               return -EINVAL;
-       return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
+static int jffs2_acl_setxattr(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        struct posix_acl *acl;
        int rc;
 
-       if (!is_owner_or_cap(inode))
+       if (name[0] != '\0')
+               return -EINVAL;
+       if (!is_owner_or_cap(dentry->d_inode))
                return -EPERM;
 
        if (value) {
@@ -420,38 +413,24 @@ static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value,
        } else {
                acl = NULL;
        }
-       rc = jffs2_set_acl(inode, type, acl);
+       rc = jffs2_set_acl(dentry->d_inode, type, acl);
  out:
        posix_acl_release(acl);
        return rc;
 }
 
-static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
-                                    const void *buffer, size_t size, int flags)
-{
-       if (name[0] != '\0')
-               return -EINVAL;
-       return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
-                                     const void *buffer, size_t size, int flags)
-{
-       if (name[0] != '\0')
-               return -EINVAL;
-       return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
 struct xattr_handler jffs2_acl_access_xattr_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags  = ACL_TYPE_DEFAULT,
        .list   = jffs2_acl_access_listxattr,
-       .get    = jffs2_acl_access_getxattr,
-       .set    = jffs2_acl_access_setxattr,
+       .get    = jffs2_acl_getxattr,
+       .set    = jffs2_acl_setxattr,
 };
 
 struct xattr_handler jffs2_acl_default_xattr_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags  = ACL_TYPE_DEFAULT,
        .list   = jffs2_acl_default_listxattr,
-       .get    = jffs2_acl_default_getxattr,
-       .set    = jffs2_acl_default_setxattr,
+       .get    = jffs2_acl_getxattr,
+       .set    = jffs2_acl_setxattr,
 };
index 02c39c6..eaccee0 100644 (file)
@@ -44,26 +44,28 @@ int jffs2_init_security(struct inode *inode, struct inode *dir)
 }
 
 /* ---- XATTR Handler for "security.*" ----------------- */
-static int jffs2_security_getxattr(struct inode *inode, const char *name,
-                                  void *buffer, size_t size)
+static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
+                                  void *buffer, size_t size, int type)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
 
-       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
+       return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
+                                name, buffer, size);
 }
 
-static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
-                                  size_t size, int flags)
+static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
+               const void *buffer, size_t size, int flags, int type)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
 
-       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
+       return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
+                                name, buffer, size, flags);
 }
 
-static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
-                                      const char *name, size_t name_len)
+static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
 {
        size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
 
index 4b10788..9e75c62 100644 (file)
@@ -990,9 +990,11 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
                if (!xhandle)
                        continue;
                if (buffer) {
-                       rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
+                       rc = xhandle->list(dentry, buffer+len, size-len,
+                                          xd->xname, xd->name_len, xd->flags);
                } else {
-                       rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
+                       rc = xhandle->list(dentry, NULL, 0, xd->xname,
+                                          xd->name_len, xd->flags);
                }
                if (rc < 0)
                        goto out;
index 8ec5765..3e5a5e3 100644 (file)
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
-                                 void *buffer, size_t size)
+static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
+       return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
+                                name, buffer, size);
 }
 
-static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
-                                 size_t size, int flags)
+static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
+               const void *buffer, size_t size, int flags, int type)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
+       return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
+                                name, buffer, size, flags);
 }
 
-static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
-                                     const char *name, size_t name_len)
+static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
 {
        size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
 
index 8bbeab9..8544af6 100644 (file)
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_user_getxattr(struct inode *inode, const char *name,
-                              void *buffer, size_t size)
+static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
+                              void *buffer, size_t size, int type)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
+       return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
+                                name, buffer, size);
 }
 
-static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
-                              size_t size, int flags)
+static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
+               const void *buffer, size_t size, int flags, int type)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
+       return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
+                                name, buffer, size, flags);
 }
 
-static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
-                                  const char *name, size_t name_len)
+static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
+               size_t list_size, const char *name, size_t name_len, int type)
 {
        size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
 
index 219576c..6e8d17e 100644 (file)
@@ -848,7 +848,6 @@ EXPORT_SYMBOL(simple_write_end);
 EXPORT_SYMBOL(simple_dir_inode_operations);
 EXPORT_SYMBOL(simple_dir_operations);
 EXPORT_SYMBOL(simple_empty);
-EXPORT_SYMBOL(d_alloc_name);
 EXPORT_SYMBOL(simple_fill_super);
 EXPORT_SYMBOL(simple_getattr);
 EXPORT_SYMBOL(simple_link);
index 87f97ba..d2783c8 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/fs_struct.h>
 #include <asm/uaccess.h>
 
+#include "internal.h"
+
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
 /* [Feb-1997 T. Schoebel-Theuer]
  * any extra contention...
  */
 
-static int __link_path_walk(const char *name, struct nameidata *nd);
-
 /* In order to reduce some races, while at the same time doing additional
  * checking and hopefully speeding things up, we copy filenames to the
  * kernel data space before using them..
@@ -414,36 +414,55 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd)
 }
 
 /*
- * Internal lookup() using the new generic dcache.
- * SMP-safe
+ * force_reval_path - force revalidation of a dentry
+ *
+ * In some situations the path walking code will trust dentries without
+ * revalidating them. This causes problems for filesystems that depend on
+ * d_revalidate to handle file opens (e.g. NFSv4). When FS_REVAL_DOT is set
+ * (which indicates that it's possible for the dentry to go stale), force
+ * a d_revalidate call before proceeding.
+ *
+ * Returns 0 if the revalidation was successful. If the revalidation fails,
+ * either return the error returned by d_revalidate or -ESTALE if the
+ * revalidation it just returned 0. If d_revalidate returns 0, we attempt to
+ * invalidate the dentry. It's up to the caller to handle putting references
+ * to the path if necessary.
  */
-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
+static int
+force_reval_path(struct path *path, struct nameidata *nd)
 {
-       struct dentry * dentry = __d_lookup(parent, name);
+       int status;
+       struct dentry *dentry = path->dentry;
 
-       /* lockess __d_lookup may fail due to concurrent d_move() 
-        * in some unrelated directory, so try with d_lookup
+       /*
+        * only check on filesystems where it's possible for the dentry to
+        * become stale. It's assumed that if this flag is set then the
+        * d_revalidate op will also be defined.
         */
-       if (!dentry)
-               dentry = d_lookup(parent, name);
+       if (!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))
+               return 0;
 
-       if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
-               dentry = do_revalidate(dentry, nd);
+       status = dentry->d_op->d_revalidate(dentry, nd);
+       if (status > 0)
+               return 0;
 
-       return dentry;
+       if (!status) {
+               d_invalidate(dentry);
+               status = -ESTALE;
+       }
+       return status;
 }
 
 /*
- * Short-cut version of permission(), for calling by
- * path_walk(), when dcache lock is held.  Combines parts
- * of permission() and generic_permission(), and tests ONLY for
- * MAY_EXEC permission.
+ * Short-cut version of permission(), for calling on directories
+ * during pathname resolution.  Combines parts of permission()
+ * and generic_permission(), and tests ONLY for MAY_EXEC permission.
  *
  * If appropriate, check DAC only.  If not appropriate, or
- * short-cut DAC fails, then call permission() to do more
+ * short-cut DAC fails, then call ->permission() to do more
  * complete permission check.
  */
-static int exec_permission_lite(struct inode *inode)
+static int exec_permission(struct inode *inode)
 {
        int ret;
 
@@ -465,99 +484,6 @@ ok:
        return security_inode_permission(inode, MAY_EXEC);
 }
 
-/*
- * This is called when everything else fails, and we actually have
- * to go to the low-level filesystem to find out what we should do..
- *
- * We get the directory semaphore, and after getting that we also
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
-{
-       struct dentry * result;
-       struct inode *dir = parent->d_inode;
-
-       mutex_lock(&dir->i_mutex);
-       /*
-        * First re-do the cached lookup just in case it was created
-        * while we waited for the directory semaphore..
-        *
-        * FIXME! This could use version numbering or similar to
-        * avoid unnecessary cache lookups.
-        *
-        * The "dcache_lock" is purely to protect the RCU list walker
-        * from concurrent renames at this point (we mustn't get false
-        * negatives from the RCU list walk here, unlike the optimistic
-        * fast walk).
-        *
-        * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
-        */
-       result = d_lookup(parent, name);
-       if (!result) {
-               struct dentry *dentry;
-
-               /* Don't create child dentry for a dead directory. */
-               result = ERR_PTR(-ENOENT);
-               if (IS_DEADDIR(dir))
-                       goto out_unlock;
-
-               dentry = d_alloc(parent, name);
-               result = ERR_PTR(-ENOMEM);
-               if (dentry) {
-                       result = dir->i_op->lookup(dir, dentry, nd);
-                       if (result)
-                               dput(dentry);
-                       else
-                               result = dentry;
-               }
-out_unlock:
-               mutex_unlock(&dir->i_mutex);
-               return result;
-       }
-
-       /*
-        * Uhhuh! Nasty case: the cache was re-populated while
-        * we waited on the semaphore. Need to revalidate.
-        */
-       mutex_unlock(&dir->i_mutex);
-       if (result->d_op && result->d_op->d_revalidate) {
-               result = do_revalidate(result, nd);
-               if (!result)
-                       result = ERR_PTR(-ENOENT);
-       }
-       return result;
-}
-
-/*
- * Wrapper to retry pathname resolution whenever the underlying
- * file system returns an ESTALE.
- *
- * Retry the whole path once, forcing real lookup requests
- * instead of relying on the dcache.
- */
-static __always_inline int link_path_walk(const char *name, struct nameidata *nd)
-{
-       struct path save = nd->path;
-       int result;
-
-       /* make sure the stuff we saved doesn't go away */
-       path_get(&save);
-
-       result = __link_path_walk(name, nd);
-       if (result == -ESTALE) {
-               /* nd->path had been dropped */
-               nd->path = save;
-               path_get(&nd->path);
-               nd->flags |= LOOKUP_REVAL;
-               result = __link_path_walk(name, nd);
-       }
-
-       path_put(&save);
-
-       return result;
-}
-
 static __always_inline void set_root(struct nameidata *nd)
 {
        if (!nd->root.mnt) {
@@ -569,6 +495,8 @@ static __always_inline void set_root(struct nameidata *nd)
        }
 }
 
+static int link_path_walk(const char *, struct nameidata *);
+
 static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
 {
        int res = 0;
@@ -641,11 +569,14 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
                error = 0;
                if (s)
                        error = __vfs_follow_link(nd, s);
+               else if (nd->last_type == LAST_BIND) {
+                       error = force_reval_path(&nd->path, nd);
+                       if (error)
+                               path_put(&nd->path);
+               }
                if (dentry->d_inode->i_op->put_link)
                        dentry->d_inode->i_op->put_link(dentry, nd, cookie);
        }
-       path_put(path);
-
        return error;
 }
 
@@ -672,6 +603,7 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
        current->total_link_count++;
        nd->depth++;
        err = __do_follow_link(path, nd);
+       path_put(path);
        current->link_count--;
        nd->depth--;
        return err;
@@ -797,8 +729,19 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
                     struct path *path)
 {
        struct vfsmount *mnt = nd->path.mnt;
-       struct dentry *dentry = __d_lookup(nd->path.dentry, name);
+       struct dentry *dentry, *parent;
+       struct inode *dir;
+       /*
+        * See if the low-level filesystem might want
+        * to use its own hash..
+        */
+       if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
+               int err = nd->path.dentry->d_op->d_hash(nd->path.dentry, name);
+               if (err < 0)
+                       return err;
+       }
 
+       dentry = __d_lookup(nd->path.dentry, name);
        if (!dentry)
                goto need_lookup;
        if (dentry->d_op && dentry->d_op->d_revalidate)
@@ -810,7 +753,59 @@ done:
        return 0;
 
 need_lookup:
-       dentry = real_lookup(nd->path.dentry, name, nd);
+       parent = nd->path.dentry;
+       dir = parent->d_inode;
+
+       mutex_lock(&dir->i_mutex);
+       /*
+        * First re-do the cached lookup just in case it was created
+        * while we waited for the directory semaphore..
+        *
+        * FIXME! This could use version numbering or similar to
+        * avoid unnecessary cache lookups.
+        *
+        * The "dcache_lock" is purely to protect the RCU list walker
+        * from concurrent renames at this point (we mustn't get false
+        * negatives from the RCU list walk here, unlike the optimistic
+        * fast walk).
+        *
+        * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
+        */
+       dentry = d_lookup(parent, name);
+       if (!dentry) {
+               struct dentry *new;
+
+               /* Don't create child dentry for a dead directory. */
+               dentry = ERR_PTR(-ENOENT);
+               if (IS_DEADDIR(dir))
+                       goto out_unlock;
+
+               new = d_alloc(parent, name);
+               dentry = ERR_PTR(-ENOMEM);
+               if (new) {
+                       dentry = dir->i_op->lookup(dir, new, nd);
+                       if (dentry)
+                               dput(new);
+                       else
+                               dentry = new;
+               }
+out_unlock:
+               mutex_unlock(&dir->i_mutex);
+               if (IS_ERR(dentry))
+                       goto fail;
+               goto done;
+       }
+
+       /*
+        * Uhhuh! Nasty case: the cache was re-populated while
+        * we waited on the semaphore. Need to revalidate.
+        */
+       mutex_unlock(&dir->i_mutex);
+       if (dentry->d_op && dentry->d_op->d_revalidate) {
+               dentry = do_revalidate(dentry, nd);
+               if (!dentry)
+                       dentry = ERR_PTR(-ENOENT);
+       }
        if (IS_ERR(dentry))
                goto fail;
        goto done;
@@ -835,7 +830,7 @@ fail:
  * Returns 0 and nd will have valid dentry and mnt on success.
  * Returns error and drops reference to input namei data on failure.
  */
-static int __link_path_walk(const char *name, struct nameidata *nd)
+static int link_path_walk(const char *name, struct nameidata *nd)
 {
        struct path next;
        struct inode *inode;
@@ -858,7 +853,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
                unsigned int c;
 
                nd->flags |= LOOKUP_CONTINUE;
-               err = exec_permission_lite(inode);
+               err = exec_permission(inode);
                if (err)
                        break;
 
@@ -898,16 +893,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
                        case 1:
                                continue;
                }
-               /*
-                * See if the low-level filesystem might want
-                * to use its own hash..
-                */
-               if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
-                       err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
-                                                           &this);
-                       if (err < 0)
-                               break;
-               }
                /* This does the actual lookups.. */
                err = do_lookup(nd, &this, &next);
                if (err)
@@ -953,12 +938,6 @@ last_component:
                        case 1:
                                goto return_reval;
                }
-               if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
-                       err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
-                                                           &this);
-                       if (err < 0)
-                               break;
-               }
                err = do_lookup(nd, &this, &next);
                if (err)
                        break;
@@ -1017,8 +996,27 @@ return_err:
 
 static int path_walk(const char *name, struct nameidata *nd)
 {
+       struct path save = nd->path;
+       int result;
+
        current->total_link_count = 0;
-       return link_path_walk(name, nd);
+
+       /* make sure the stuff we saved doesn't go away */
+       path_get(&save);
+
+       result = link_path_walk(name, nd);
+       if (result == -ESTALE) {
+               /* nd->path had been dropped */
+               current->total_link_count = 0;
+               nd->path = save;
+               path_get(&nd->path);
+               nd->flags |= LOOKUP_REVAL;
+               result = link_path_walk(name, nd);
+       }
+
+       path_put(&save);
+
+       return result;
 }
 
 static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
@@ -1141,36 +1139,6 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
        return retval;
 }
 
-/**
- * path_lookup_open - lookup a file path with open intent
- * @dfd: the directory to use as base, or AT_FDCWD
- * @name: pointer to file name
- * @lookup_flags: lookup intent flags
- * @nd: pointer to nameidata
- * @open_flags: open intent flags
- */
-static int path_lookup_open(int dfd, const char *name,
-               unsigned int lookup_flags, struct nameidata *nd, int open_flags)
-{
-       struct file *filp = get_empty_filp();
-       int err;
-
-       if (filp == NULL)
-               return -ENFILE;
-       nd->intent.open.file = filp;
-       nd->intent.open.flags = open_flags;
-       nd->intent.open.create_mode = 0;
-       err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
-       if (IS_ERR(nd->intent.open.file)) {
-               if (err == 0) {
-                       err = PTR_ERR(nd->intent.open.file);
-                       path_put(&nd->path);
-               }
-       } else if (err != 0)
-               release_open_intent(nd);
-       return err;
-}
-
 static struct dentry *__lookup_hash(struct qstr *name,
                struct dentry *base, struct nameidata *nd)
 {
@@ -1191,7 +1159,17 @@ static struct dentry *__lookup_hash(struct qstr *name,
                        goto out;
        }
 
-       dentry = cached_lookup(base, name, nd);
+       dentry = __d_lookup(base, name);
+
+       /* lockess __d_lookup may fail due to concurrent d_move()
+        * in some unrelated directory, so try with d_lookup
+        */
+       if (!dentry)
+               dentry = d_lookup(base, name);
+
+       if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
+               dentry = do_revalidate(dentry, nd);
+
        if (!dentry) {
                struct dentry *new;
 
@@ -1223,7 +1201,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
 {
        int err;
 
-       err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
+       err = exec_permission(nd->path.dentry->d_inode);
        if (err)
                return ERR_PTR(err);
        return __lookup_hash(&nd->last, nd->path.dentry, nd);
@@ -1273,7 +1251,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
        if (err)
                return ERR_PTR(err);
 
-       err = inode_permission(base->d_inode, MAY_EXEC);
+       err = exec_permission(base->d_inode);
        if (err)
                return ERR_PTR(err);
        return __lookup_hash(&this, base, NULL);
@@ -1511,69 +1489,45 @@ int may_open(struct path *path, int acc_mode, int flag)
        if (error)
                return error;
 
-       error = ima_path_check(path, acc_mode ?
-                              acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
-                              ACC_MODE(flag) & (MAY_READ | MAY_WRITE),
-                              IMA_COUNT_UPDATE);
-
-       if (error)
-               return error;
        /*
         * An append-only file must be opened in append mode for writing.
         */
        if (IS_APPEND(inode)) {
-               error = -EPERM;
                if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
-                       goto err_out;
+                       return -EPERM;
                if (flag & O_TRUNC)
-                       goto err_out;
+                       return -EPERM;
        }
 
        /* O_NOATIME can only be set by the owner or superuser */
-       if (flag & O_NOATIME)
-               if (!is_owner_or_cap(inode)) {
-                       error = -EPERM;
-                       goto err_out;
-               }
+       if (flag & O_NOATIME && !is_owner_or_cap(inode))
+               return -EPERM;
 
        /*
         * Ensure there are no outstanding leases on the file.
         */
-       error = break_lease(inode, flag);
-       if (error)
-               goto err_out;
-
-       if (flag & O_TRUNC) {
-               error = get_write_access(inode);
-               if (error)
-                       goto err_out;
-
-               /*
-                * Refuse to truncate files with mandatory locks held on them.
-                */
-               error = locks_verify_locked(inode);
-               if (!error)
-                       error = security_path_truncate(path, 0,
-                                              ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
-               if (!error) {
-                       vfs_dq_init(inode);
-
-                       error = do_truncate(dentry, 0,
-                                           ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
-                                           NULL);
-               }
-               put_write_access(inode);
-               if (error)
-                       goto err_out;
-       } else
-               if (flag & FMODE_WRITE)
-                       vfs_dq_init(inode);
+       return break_lease(inode, flag);
+}
 
-       return 0;
-err_out:
-       ima_counts_put(path, acc_mode ?
-                      acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
-                      ACC_MODE(flag) & (MAY_READ | MAY_WRITE));
+static int handle_truncate(struct path *path)
+{
+       struct inode *inode = path->dentry->d_inode;
+       int error = get_write_access(inode);
+       if (error)
+               return error;
+       /*
+        * Refuse to truncate files with mandatory locks held on them.
+        */
+       error = locks_verify_locked(inode);
+       if (!error)
+               error = security_path_truncate(path, 0,
+                                      ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
+       if (!error) {
+               error = do_truncate(path->dentry, 0,
+                                   ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
+                                   NULL);
+       }
+       put_write_access(inode);
        return error;
 }
 
@@ -1628,7 +1582,7 @@ static inline int open_to_namei_flags(int flag)
        return flag;
 }
 
-static int open_will_write_to_fs(int flag, struct inode *inode)
+static int open_will_truncate(int flag, struct inode *inode)
 {
        /*
         * We'll never write to the fs underlying
@@ -1650,10 +1604,10 @@ struct file *do_filp_open(int dfd, const char *pathname,
        struct file *filp;
        struct nameidata nd;
        int error;
-       struct path path;
+       struct path path, save;
        struct dentry *dir;
        int count = 0;
-       int will_write;
+       int will_truncate;
        int flag = open_to_namei_flags(open_flag);
 
        /*
@@ -1681,8 +1635,22 @@ struct file *do_filp_open(int dfd, const char *pathname,
         * The simplest case - just a plain lookup.
         */
        if (!(flag & O_CREAT)) {
-               error = path_lookup_open(dfd, pathname, lookup_flags(flag),
-                                        &nd, flag);
+               filp = get_empty_filp();
+
+               if (filp == NULL)
+                       return ERR_PTR(-ENFILE);
+               nd.intent.open.file = filp;
+               nd.intent.open.flags = flag;
+               nd.intent.open.create_mode = 0;
+               error = do_path_lookup(dfd, pathname,
+                                       lookup_flags(flag)|LOOKUP_OPEN, &nd);
+               if (IS_ERR(nd.intent.open.file)) {
+                       if (error == 0) {
+                               error = PTR_ERR(nd.intent.open.file);
+                               path_put(&nd.path);
+                       }
+               } else if (error)
+                       release_open_intent(&nd);
                if (error)
                        return ERR_PTR(error);
                goto ok;
@@ -1758,13 +1726,17 @@ do_last:
                        goto exit;
                }
                filp = nameidata_to_filp(&nd, open_flag);
-               if (IS_ERR(filp))
-                       ima_counts_put(&nd.path,
-                                      acc_mode & (MAY_READ | MAY_WRITE |
-                                                  MAY_EXEC));
                mnt_drop_write(nd.path.mnt);
                if (nd.root.mnt)
                        path_put(&nd.root);
+               if (!IS_ERR(filp)) {
+                       error = ima_path_check(&filp->f_path, filp->f_mode &
+                                      (MAY_READ | MAY_WRITE | MAY_EXEC));
+                       if (error) {
+                               fput(filp);
+                               filp = ERR_PTR(error);
+                       }
+               }
                return filp;
        }
 
@@ -1805,28 +1777,45 @@ ok:
         * be avoided. Taking this mnt write here
         * ensures that (2) can not occur.
         */
-       will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode);
-       if (will_write) {
+       will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode);
+       if (will_truncate) {
                error = mnt_want_write(nd.path.mnt);
                if (error)
                        goto exit;
        }
        error = may_open(&nd.path, acc_mode, flag);
        if (error) {
-               if (will_write)
+               if (will_truncate)
                        mnt_drop_write(nd.path.mnt);
                goto exit;
        }
        filp = nameidata_to_filp(&nd, open_flag);
-       if (IS_ERR(filp))
-               ima_counts_put(&nd.path,
-                              acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
+       if (!IS_ERR(filp)) {
+               error = ima_path_check(&filp->f_path, filp->f_mode &
+                              (MAY_READ | MAY_WRITE | MAY_EXEC));
+               if (error) {
+                       fput(filp);
+                       filp = ERR_PTR(error);
+               }
+       }
+       if (!IS_ERR(filp)) {
+               if (acc_mode & MAY_WRITE)
+                       vfs_dq_init(nd.path.dentry->d_inode);
+
+               if (will_truncate) {
+                       error = handle_truncate(&nd.path);
+                       if (error) {
+                               fput(filp);
+                               filp = ERR_PTR(error);
+                       }
+               }
+       }
        /*
         * It is now safe to drop the mnt write
         * because the filp has had a write taken
         * on its behalf.
         */
-       if (will_write)
+       if (will_truncate)
                mnt_drop_write(nd.path.mnt);
        if (nd.root.mnt)
                path_put(&nd.root);
@@ -1863,7 +1852,18 @@ do_link:
        error = security_inode_follow_link(path.dentry, &nd);
        if (error)
                goto exit_dput;
+       save = nd.path;
+       path_get(&save);
        error = __do_follow_link(&path, &nd);
+       if (error == -ESTALE) {
+               /* nd.path had been dropped */
+               nd.path = save;
+               path_get(&nd.path);
+               nd.flags |= LOOKUP_REVAL;
+               error = __do_follow_link(&path, &nd);
+       }
+       path_put(&save);
+       path_put(&path);
        if (error) {
                /* Does someone understand code flow here? Or it is only
                 * me so stupid? Anathema to whoever designed this non-sense
index 7d70d63..faab127 100644 (file)
@@ -2068,7 +2068,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
  * create_mnt_ns - creates a private namespace and adds a root filesystem
  * @mnt: pointer to the new root filesystem mountpoint
  */
-struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
+static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
 {
        struct mnt_namespace *new_ns;
 
@@ -2080,7 +2080,6 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
        }
        return new_ns;
 }
-EXPORT_SYMBOL(create_mnt_ns);
 
 SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
                char __user *, type, unsigned long, flags, void __user *, data)
index ce907ef..d5b112b 100644 (file)
@@ -2648,21 +2648,13 @@ out_freepage:
 static int nfs_follow_remote_path(struct vfsmount *root_mnt,
                const char *export_path, struct vfsmount *mnt_target)
 {
-       struct mnt_namespace *ns_private;
        struct nameidata nd;
        struct super_block *s;
        int ret;
 
-       ns_private = create_mnt_ns(root_mnt);
-       ret = PTR_ERR(ns_private);
-       if (IS_ERR(ns_private))
-               goto out_mntput;
-
        ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
                        export_path, LOOKUP_FOLLOW, &nd);
 
-       put_mnt_ns(ns_private);
-
        if (ret != 0)
                goto out_err;
 
index e3ef3ec..7c2e337 100644 (file)
@@ -752,8 +752,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                            flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
-       else
-               ima_counts_get(*filp);
 out_nfserr:
        err = nfserrno(host_err);
 out:
@@ -2132,8 +2130,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
         */
        path.mnt = exp->ex_path.mnt;
        path.dentry = dentry;
-       err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC),
-                            IMA_COUNT_LEAVE);
+       err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
 nfsd_out:
        return err? nfserrno(err) : 0;
 }
index 5403b3e..8173fae 100644 (file)
@@ -1118,8 +1118,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
        /* Abandoning the newly allocated superblock */
        mutex_unlock(&nilfs->ns_mount_mutex);
        put_nilfs(nilfs);
-       up_write(&s->s_umount);
-       deactivate_super(s);
+       deactivate_locked_super(s);
        /*
         * deactivate_super() invokes close_bdev_exclusive().
         * We must finish all post-cleaning before this call;
index 5ef5f36..8271cf0 100644 (file)
@@ -646,6 +646,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        struct fsnotify_group *group;
        struct user_struct *user;
        struct file *filp;
+       struct path path;
        int fd, ret;
 
        /* Check the IN_* constants for consistency.  */
@@ -659,12 +660,6 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        if (fd < 0)
                return fd;
 
-       filp = get_empty_filp();
-       if (!filp) {
-               ret = -ENFILE;
-               goto out_put_fd;
-       }
-
        user = get_current_user();
        if (unlikely(atomic_read(&user->inotify_devs) >=
                        inotify_max_user_instances)) {
@@ -679,24 +674,28 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
                goto out_free_uid;
        }
 
-       filp->f_op = &inotify_fops;
-       filp->f_path.mnt = mntget(inotify_mnt);
-       filp->f_path.dentry = dget(inotify_mnt->mnt_root);
-       filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
-       filp->f_mode = FMODE_READ;
+       atomic_inc(&user->inotify_devs);
+
+       path.mnt = inotify_mnt;
+       path.dentry = inotify_mnt->mnt_root;
+       path_get(&path);
+       filp = alloc_file(&path, FMODE_READ, &inotify_fops);
+       if (!filp)
+               goto Enfile;
+
        filp->f_flags = O_RDONLY | (flags & O_NONBLOCK);
        filp->private_data = group;
 
-       atomic_inc(&user->inotify_devs);
-
        fd_install(fd, filp);
 
        return fd;
 
+Enfile:
+       ret = -ENFILE;
+       path_put(&path);
+       atomic_dec(&user->inotify_devs);
 out_free_uid:
        free_uid(user);
-       put_filp(filp);
-out_put_fd:
        put_unused_fd(fd);
        return ret;
 }
index fbeaec7..e3e4741 100644 (file)
@@ -331,13 +331,14 @@ cleanup:
        return ret;
 }
 
-static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
+static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry,
                                          char *list,
                                          size_t list_len,
                                          const char *name,
-                                         size_t name_len)
+                                         size_t name_len,
+                                         int type)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
        const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
        if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
@@ -348,13 +349,14 @@ static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
        return size;
 }
 
-static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
+static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry,
                                           char *list,
                                           size_t list_len,
                                           const char *name,
-                                          size_t name_len)
+                                          size_t name_len,
+                                          int type)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
        const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
        if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
@@ -365,19 +367,19 @@ static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
        return size;
 }
 
-static int ocfs2_xattr_get_acl(struct inode *inode,
-                              int type,
-                              void *buffer,
-                              size_t size)
+static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
        struct posix_acl *acl;
        int ret;
 
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
        if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
                return -EOPNOTSUPP;
 
-       acl = ocfs2_get_acl(inode, type);
+       acl = ocfs2_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -388,35 +390,16 @@ static int ocfs2_xattr_get_acl(struct inode *inode,
        return ret;
 }
 
-static int ocfs2_xattr_get_acl_access(struct inode *inode,
-                                     const char *name,
-                                     void *buffer,
-                                     size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ocfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int ocfs2_xattr_get_acl_default(struct inode *inode,
-                                      const char *name,
-                                      void *buffer,
-                                      size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ocfs2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int ocfs2_xattr_set_acl(struct inode *inode,
-                              int type,
-                              const void *value,
-                              size_t size)
+static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
+       struct inode *inode = dentry->d_inode;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct posix_acl *acl;
        int ret = 0;
 
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
        if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
                return -EOPNOTSUPP;
 
@@ -442,38 +425,18 @@ cleanup:
        return ret;
 }
 
-static int ocfs2_xattr_set_acl_access(struct inode *inode,
-                                     const char *name,
-                                     const void *value,
-                                     size_t size,
-                                     int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ocfs2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int ocfs2_xattr_set_acl_default(struct inode *inode,
-                                      const char *name,
-                                      const void *value,
-                                      size_t size,
-                                      int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return ocfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ocfs2_xattr_acl_access_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags  = ACL_TYPE_ACCESS,
        .list   = ocfs2_xattr_list_acl_access,
-       .get    = ocfs2_xattr_get_acl_access,
-       .set    = ocfs2_xattr_set_acl_access,
+       .get    = ocfs2_xattr_get_acl,
+       .set    = ocfs2_xattr_set_acl,
 };
 
 struct xattr_handler ocfs2_xattr_acl_default_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags  = ACL_TYPE_DEFAULT,
        .list   = ocfs2_xattr_list_acl_default,
-       .get    = ocfs2_xattr_get_acl_default,
-       .set    = ocfs2_xattr_set_acl_default,
+       .get    = ocfs2_xattr_get_acl,
+       .set    = ocfs2_xattr_set_acl,
 };
index 7c7198a..fb4e672 100644 (file)
@@ -7190,8 +7190,8 @@ int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
         * wait on them - the truncate_inode_pages() call later will
         * do that for us.
         */
-       ret = do_sync_mapping_range(inode->i_mapping, range_start,
-                                   range_end - 1, SYNC_FILE_RANGE_WRITE);
+       ret = filemap_fdatawrite_range(inode->i_mapping, range_start,
+                                      range_end - 1);
        if (ret)
                mlog_errno(ret);
 
index fe34190..43c1148 100644 (file)
@@ -205,8 +205,6 @@ static int ocfs2_get_xattr_tree_value_root(struct super_block *sb,
                                           int offset,
                                           struct ocfs2_xattr_value_root **xv,
                                           struct buffer_head **bh);
-static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
-                                   const void *value, size_t size, int flags);
 
 static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
 {
@@ -6978,9 +6976,9 @@ int ocfs2_init_security_and_acl(struct inode *dir,
 
        ret = ocfs2_init_security_get(inode, dir, &si);
        if (!ret) {
-               ret = ocfs2_xattr_security_set(inode, si.name,
-                                              si.value, si.value_len,
-                                              XATTR_CREATE);
+               ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
+                                     si.name, si.value, si.value_len,
+                                     XATTR_CREATE);
                if (ret) {
                        mlog_errno(ret);
                        goto leave;
@@ -7008,9 +7006,9 @@ leave:
 /*
  * 'security' attributes support
  */
-static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
+static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
                                        size_t list_size, const char *name,
-                                       size_t name_len)
+                                       size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -7023,23 +7021,23 @@ static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
        return total_len;
 }
 
-static int ocfs2_xattr_security_get(struct inode *inode, const char *name,
-                                   void *buffer, size_t size)
+static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
+                                   void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY, name,
-                              buffer, size);
+       return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
+                              name, buffer, size);
 }
 
-static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
-                                   const void *value, size_t size, int flags)
+static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
 
-       return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, name, value,
-                              size, flags);
+       return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
+                              name, value, size, flags);
 }
 
 int ocfs2_init_security_get(struct inode *inode,
@@ -7076,9 +7074,9 @@ struct xattr_handler ocfs2_xattr_security_handler = {
 /*
  * 'trusted' attributes support
  */
-static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
+static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
                                       size_t list_size, const char *name,
-                                      size_t name_len)
+                                      size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -7091,23 +7089,23 @@ static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
        return total_len;
 }
 
-static int ocfs2_xattr_trusted_get(struct inode *inode, const char *name,
-                                  void *buffer, size_t size)
+static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED, name,
-                              buffer, size);
+       return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
+                              name, buffer, size);
 }
 
-static int ocfs2_xattr_trusted_set(struct inode *inode, const char *name,
-                                  const void *value, size_t size, int flags)
+static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
 
-       return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED, name, value,
-                              size, flags);
+       return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
+                              name, value, size, flags);
 }
 
 struct xattr_handler ocfs2_xattr_trusted_handler = {
@@ -7120,13 +7118,13 @@ struct xattr_handler ocfs2_xattr_trusted_handler = {
 /*
  * 'user' attributes support
  */
-static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
+static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
                                    size_t list_size, const char *name,
-                                   size_t name_len)
+                                   size_t name_len, int type)
 {
        const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
        if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
                return 0;
@@ -7139,31 +7137,31 @@ static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
        return total_len;
 }
 
-static int ocfs2_xattr_user_get(struct inode *inode, const char *name,
-                               void *buffer, size_t size)
+static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int type)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
        if (strcmp(name, "") == 0)
                return -EINVAL;
        if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
                return -EOPNOTSUPP;
-       return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name,
+       return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_USER, name,
                               buffer, size);
 }
 
-static int ocfs2_xattr_user_set(struct inode *inode, const char *name,
-                               const void *value, size_t size, int flags)
+static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
        if (strcmp(name, "") == 0)
                return -EINVAL;
        if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
                return -EOPNOTSUPP;
 
-       return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER, name, value,
-                              size, flags);
+       return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_USER,
+                              name, value, size, flags);
 }
 
 struct xattr_handler ocfs2_xattr_user_handler = {
index b4b31d2..ca69241 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -30,6 +30,9 @@
 #include <linux/audit.h>
 #include <linux/falloc.h>
 #include <linux/fs_struct.h>
+#include <linux/ima.h>
+
+#include "internal.h"
 
 int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
@@ -855,6 +858,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
                if (error)
                        goto cleanup_all;
        }
+       ima_counts_get(f);
 
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
index ae17d02..43d79da 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -974,7 +974,7 @@ struct file *create_write_pipe(int flags)
        int err;
        struct inode *inode;
        struct file *f;
-       struct dentry *dentry;
+       struct path path;
        struct qstr name = { .name = "" };
 
        err = -ENFILE;
@@ -983,21 +983,22 @@ struct file *create_write_pipe(int flags)
                goto err;
 
        err = -ENOMEM;
-       dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
-       if (!dentry)
+       path.dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
+       if (!path.dentry)
                goto err_inode;
+       path.mnt = mntget(pipe_mnt);
 
-       dentry->d_op = &pipefs_dentry_operations;
+       path.dentry->d_op = &pipefs_dentry_operations;
        /*
         * We dont want to publish this dentry into global dentry hash table.
         * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
         * This permits a working /proc/$pid/fd/XXX on pipes
         */
-       dentry->d_flags &= ~DCACHE_UNHASHED;
-       d_instantiate(dentry, inode);
+       path.dentry->d_flags &= ~DCACHE_UNHASHED;
+       d_instantiate(path.dentry, inode);
 
        err = -ENFILE;
-       f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops);
+       f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops);
        if (!f)
                goto err_dentry;
        f->f_mapping = inode->i_mapping;
@@ -1009,7 +1010,7 @@ struct file *create_write_pipe(int flags)
 
  err_dentry:
        free_pipe_info(inode);
-       dput(dentry);
+       path_put(&path);
        return ERR_PTR(err);
 
  err_inode:
@@ -1028,20 +1029,14 @@ void free_write_pipe(struct file *f)
 
 struct file *create_read_pipe(struct file *wrf, int flags)
 {
-       struct file *f = get_empty_filp();
+       /* Grab pipe from the writer */
+       struct file *f = alloc_file(&wrf->f_path, FMODE_READ,
+                                   &read_pipefifo_fops);
        if (!f)
                return ERR_PTR(-ENFILE);
 
-       /* Grab pipe from the writer */
-       f->f_path = wrf->f_path;
        path_get(&wrf->f_path);
-       f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
-
-       f->f_pos = 0;
        f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
-       f->f_op = &read_pipefifo_fops;
-       f->f_mode = FMODE_READ;
-       f->f_version = 0;
 
        return f;
 }
index 58aa8e7..8c7033a 100644 (file)
@@ -48,6 +48,7 @@
 #include <net/checksum.h>
 #include <linux/stat.h>
 #include <linux/quotaops.h>
+#include <linux/security.h>
 
 #define PRIVROOT_NAME ".reiserfs_priv"
 #define XAROOT_NAME   "xattrs"
@@ -726,15 +727,14 @@ ssize_t
 reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
                  size_t size)
 {
-       struct inode *inode = dentry->d_inode;
        struct xattr_handler *handler;
 
-       handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+       handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-       if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
+       if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       return handler->get(inode, name, buffer, size);
+       return handler->get(dentry, name, buffer, size, handler->flags);
 }
 
 /*
@@ -746,15 +746,14 @@ int
 reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                  size_t size, int flags)
 {
-       struct inode *inode = dentry->d_inode;
        struct xattr_handler *handler;
 
-       handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+       handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-       if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
+       if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       return handler->set(inode, name, value, size, flags);
+       return handler->set(dentry, name, value, size, flags, handler->flags);
 }
 
 /*
@@ -764,21 +763,20 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
  */
 int reiserfs_removexattr(struct dentry *dentry, const char *name)
 {
-       struct inode *inode = dentry->d_inode;
        struct xattr_handler *handler;
-       handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+       handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-       if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
+       if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+       return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
 }
 
 struct listxattr_buf {
        size_t size;
        size_t pos;
        char *buf;
-       struct inode *inode;
+       struct dentry *dentry;
 };
 
 static int listxattr_filler(void *buf, const char *name, int namelen,
@@ -789,17 +787,19 @@ static int listxattr_filler(void *buf, const char *name, int namelen,
        if (name[0] != '.' ||
            (namelen != 1 && (name[1] != '.' || namelen != 2))) {
                struct xattr_handler *handler;
-               handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr,
+               handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
                                                    name);
                if (!handler)   /* Unsupported xattr name */
                        return 0;
                if (b->buf) {
-                       size = handler->list(b->inode, b->buf + b->pos,
-                                        b->size, name, namelen);
+                       size = handler->list(b->dentry, b->buf + b->pos,
+                                        b->size, name, namelen,
+                                        handler->flags);
                        if (size > b->size)
                                return -ERANGE;
                } else {
-                       size = handler->list(b->inode, NULL, 0, name, namelen);
+                       size = handler->list(b->dentry, NULL, 0, name,
+                                            namelen, handler->flags);
                }
 
                b->pos += size;
@@ -820,7 +820,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
        int err = 0;
        loff_t pos = 0;
        struct listxattr_buf buf = {
-               .inode = dentry->d_inode,
+               .dentry = dentry,
                .buf = buffer,
                .size = buffer ? size : 0,
        };
index 35d6e67..cc32e6a 100644 (file)
@@ -15,8 +15,10 @@ static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
                            struct posix_acl *acl);
 
 static int
-xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
+posix_acl_set(struct dentry *dentry, const char *name, const void *value,
+               size_t size, int flags, int type)
 {
+       struct inode *inode = dentry->d_inode;
        struct posix_acl *acl;
        int error, error2;
        struct reiserfs_transaction_handle th;
@@ -60,15 +62,16 @@ xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
 }
 
 static int
-xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+posix_acl_get(struct dentry *dentry, const char *name, void *buffer,
+               size_t size, int type)
 {
        struct posix_acl *acl;
        int error;
 
-       if (!reiserfs_posixacl(inode->i_sb))
+       if (!reiserfs_posixacl(dentry->d_sb))
                return -EOPNOTSUPP;
 
-       acl = reiserfs_get_acl(inode, type);
+       acl = reiserfs_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -482,30 +485,12 @@ int reiserfs_acl_chmod(struct inode *inode)
        return error;
 }
 
-static int
-posix_acl_access_get(struct inode *inode, const char *name,
-                    void *buffer, size_t size)
-{
-       if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
-               return -EINVAL;
-       return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-posix_acl_access_set(struct inode *inode, const char *name,
-                    const void *value, size_t size, int flags)
-{
-       if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
-               return -EINVAL;
-       return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static size_t posix_acl_access_list(struct inode *inode, char *list,
+static size_t posix_acl_access_list(struct dentry *dentry, char *list,
                                    size_t list_size, const char *name,
-                                   size_t name_len)
+                                   size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-       if (!reiserfs_posixacl(inode->i_sb))
+       if (!reiserfs_posixacl(dentry->d_sb))
                return 0;
        if (list && size <= list_size)
                memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -514,35 +499,18 @@ static size_t posix_acl_access_list(struct inode *inode, char *list,
 
 struct xattr_handler reiserfs_posix_acl_access_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
-       .get = posix_acl_access_get,
-       .set = posix_acl_access_set,
+       .flags = ACL_TYPE_ACCESS,
+       .get = posix_acl_get,
+       .set = posix_acl_set,
        .list = posix_acl_access_list,
 };
 
-static int
-posix_acl_default_get(struct inode *inode, const char *name,
-                     void *buffer, size_t size)
-{
-       if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
-               return -EINVAL;
-       return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-posix_acl_default_set(struct inode *inode, const char *name,
-                     const void *value, size_t size, int flags)
-{
-       if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
-               return -EINVAL;
-       return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
-static size_t posix_acl_default_list(struct inode *inode, char *list,
+static size_t posix_acl_default_list(struct dentry *dentry, char *list,
                                     size_t list_size, const char *name,
-                                    size_t name_len)
+                                    size_t name_len, int type)
 {
        const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-       if (!reiserfs_posixacl(inode->i_sb))
+       if (!reiserfs_posixacl(dentry->d_sb))
                return 0;
        if (list && size <= list_size)
                memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -551,7 +519,8 @@ static size_t posix_acl_default_list(struct inode *inode, char *list,
 
 struct xattr_handler reiserfs_posix_acl_default_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .get = posix_acl_default_get,
-       .set = posix_acl_default_set,
+       .flags = ACL_TYPE_DEFAULT,
+       .get = posix_acl_get,
+       .set = posix_acl_set,
        .list = posix_acl_default_list,
 };
index a92c879..d8b5bfc 100644 (file)
@@ -8,36 +8,37 @@
 #include <asm/uaccess.h>
 
 static int
-security_get(struct inode *inode, const char *name, void *buffer, size_t size)
+security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+               int handler_flags)
 {
        if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
                return -EINVAL;
 
-       if (IS_PRIVATE(inode))
+       if (IS_PRIVATE(dentry->d_inode))
                return -EPERM;
 
-       return reiserfs_xattr_get(inode, name, buffer, size);
+       return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
 }
 
 static int
-security_set(struct inode *inode, const char *name, const void *buffer,
-            size_t size, int flags)
+security_set(struct dentry *dentry, const char *name, const void *buffer,
+            size_t size, int flags, int handler_flags)
 {
        if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
                return -EINVAL;
 
-       if (IS_PRIVATE(inode))
+       if (IS_PRIVATE(dentry->d_inode))
                return -EPERM;
 
-       return reiserfs_xattr_set(inode, name, buffer, size, flags);
+       return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
 }
 
-static size_t security_list(struct inode *inode, char *list, size_t list_len,
-                           const char *name, size_t namelen)
+static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
+                           const char *name, size_t namelen, int handler_flags)
 {
        const size_t len = namelen + 1;
 
-       if (IS_PRIVATE(inode))
+       if (IS_PRIVATE(dentry->d_inode))
                return 0;
 
        if (list && len <= list_len) {
index a865042..5b08aac 100644 (file)
@@ -8,36 +8,37 @@
 #include <asm/uaccess.h>
 
 static int
-trusted_get(struct inode *inode, const char *name, void *buffer, size_t size)
+trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+           int handler_flags)
 {
        if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
                return -EINVAL;
 
-       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
+       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
                return -EPERM;
 
-       return reiserfs_xattr_get(inode, name, buffer, size);
+       return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
 }
 
 static int
-trusted_set(struct inode *inode, const char *name, const void *buffer,
-           size_t size, int flags)
+trusted_set(struct dentry *dentry, const char *name, const void *buffer,
+           size_t size, int flags, int handler_flags)
 {
        if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
                return -EINVAL;
 
-       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
+       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
                return -EPERM;
 
-       return reiserfs_xattr_set(inode, name, buffer, size, flags);
+       return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
 }
 
-static size_t trusted_list(struct inode *inode, char *list, size_t list_size,
-                          const char *name, size_t name_len)
+static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
+                          const char *name, size_t name_len, int handler_flags)
 {
        const size_t len = name_len + 1;
 
-       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
+       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
                return 0;
 
        if (list && len <= list_size) {
index e3238dc..75d59c4 100644 (file)
@@ -7,34 +7,35 @@
 #include <asm/uaccess.h>
 
 static int
-user_get(struct inode *inode, const char *name, void *buffer, size_t size)
+user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+        int handler_flags)
 {
 
        if (strlen(name) < sizeof(XATTR_USER_PREFIX))
                return -EINVAL;
-       if (!reiserfs_xattrs_user(inode->i_sb))
+       if (!reiserfs_xattrs_user(dentry->d_sb))
                return -EOPNOTSUPP;
-       return reiserfs_xattr_get(inode, name, buffer, size);
+       return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
 }
 
 static int
-user_set(struct inode *inode, const char *name, const void *buffer,
-        size_t size, int flags)
+user_set(struct dentry *dentry, const char *name, const void *buffer,
+        size_t size, int flags, int handler_flags)
 {
        if (strlen(name) < sizeof(XATTR_USER_PREFIX))
                return -EINVAL;
 
-       if (!reiserfs_xattrs_user(inode->i_sb))
+       if (!reiserfs_xattrs_user(dentry->d_sb))
                return -EOPNOTSUPP;
-       return reiserfs_xattr_set(inode, name, buffer, size, flags);
+       return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
 }
 
-static size_t user_list(struct inode *inode, char *list, size_t list_size,
-                       const char *name, size_t name_len)
+static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
+                       const char *name, size_t name_len, int handler_flags)
 {
        const size_t len = name_len + 1;
 
-       if (!reiserfs_xattrs_user(inode->i_sb))
+       if (!reiserfs_xattrs_user(dentry->d_sb))
                return 0;
        if (list && len <= list_size) {
                memcpy(list, name, name_len);
index 6d4f6d3..46f87e8 100644 (file)
@@ -615,12 +615,11 @@ ssize_t
 generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
 {
        struct xattr_handler *handler;
-       struct inode *inode = dentry->d_inode;
 
-       handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+       handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->get(inode, name, buffer, size);
+       return handler->get(dentry, name, buffer, size, handler->flags);
 }
 
 /*
@@ -630,18 +629,20 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
 ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-       struct inode *inode = dentry->d_inode;
-       struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
+       struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
        unsigned int size = 0;
 
        if (!buffer) {
-               for_each_xattr_handler(handlers, handler)
-                       size += handler->list(inode, NULL, 0, NULL, 0);
+               for_each_xattr_handler(handlers, handler) {
+                       size += handler->list(dentry, NULL, 0, NULL, 0,
+                                             handler->flags);
+               }
        } else {
                char *buf = buffer;
 
                for_each_xattr_handler(handlers, handler) {
-                       size = handler->list(inode, buf, buffer_size, NULL, 0);
+                       size = handler->list(dentry, buf, buffer_size,
+                                            NULL, 0, handler->flags);
                        if (size > buffer_size)
                                return -ERANGE;
                        buf += size;
@@ -659,14 +660,13 @@ int
 generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
 {
        struct xattr_handler *handler;
-       struct inode *inode = dentry->d_inode;
 
        if (size == 0)
                value = "";  /* empty EA, do not remove */
-       handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+       handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->set(inode, name, value, size, flags);
+       return handler->set(dentry, name, value, size, 0, handler->flags);
 }
 
 /*
@@ -677,12 +677,12 @@ int
 generic_removexattr(struct dentry *dentry, const char *name)
 {
        struct xattr_handler *handler;
-       struct inode *inode = dentry->d_inode;
 
-       handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+       handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+       return handler->set(dentry, name, NULL, 0,
+                           XATTR_REPLACE, handler->flags);
 }
 
 EXPORT_SYMBOL(generic_getxattr);
index 69e598b..2512125 100644 (file)
@@ -354,37 +354,14 @@ xfs_acl_chmod(struct inode *inode)
        return error;
 }
 
-/*
- * System xattr handlers.
- *
- * Currently Posix ACLs are the only system namespace extended attribute
- * handlers supported by XFS, so we just implement the handlers here.
- * If we ever support other system extended attributes this will need
- * some refactoring.
- */
-
 static int
-xfs_decode_acl(const char *name)
-{
-       if (strcmp(name, "posix_acl_access") == 0)
-               return ACL_TYPE_ACCESS;
-       else if (strcmp(name, "posix_acl_default") == 0)
-               return ACL_TYPE_DEFAULT;
-       return -EINVAL;
-}
-
-static int
-xfs_xattr_system_get(struct inode *inode, const char *name,
-               void *value, size_t size)
+xfs_xattr_acl_get(struct dentry *dentry, const char *name,
+               void *value, size_t size, int type)
 {
        struct posix_acl *acl;
-       int type, error;
-
-       type = xfs_decode_acl(name);
-       if (type < 0)
-               return type;
+       int error;
 
-       acl = xfs_get_acl(inode, type);
+       acl = xfs_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -397,15 +374,13 @@ xfs_xattr_system_get(struct inode *inode, const char *name,
 }
 
 static int
-xfs_xattr_system_set(struct inode *inode, const char *name,
-               const void *value, size_t size, int flags)
+xfs_xattr_acl_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
 {
+       struct inode *inode = dentry->d_inode;
        struct posix_acl *acl = NULL;
-       int error = 0, type;
+       int error = 0;
 
-       type = xfs_decode_acl(name);
-       if (type < 0)
-               return type;
        if (flags & XATTR_CREATE)
                return -EINVAL;
        if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
@@ -462,8 +437,16 @@ xfs_xattr_system_set(struct inode *inode, const char *name,
        return error;
 }
 
-struct xattr_handler xfs_xattr_system_handler = {
-       .prefix = XATTR_SYSTEM_PREFIX,
-       .get    = xfs_xattr_system_get,
-       .set    = xfs_xattr_system_set,
+struct xattr_handler xfs_xattr_acl_access_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags  = ACL_TYPE_ACCESS,
+       .get    = xfs_xattr_acl_get,
+       .set    = xfs_xattr_acl_set,
+};
+
+struct xattr_handler xfs_xattr_acl_default_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags  = ACL_TYPE_DEFAULT,
+       .get    = xfs_xattr_acl_get,
+       .set    = xfs_xattr_acl_set,
 };
index 497c7fb..0b18788 100644 (file)
 
 
 static int
-__xfs_xattr_get(struct inode *inode, const char *name,
+xfs_xattr_get(struct dentry *dentry, const char *name,
                void *value, size_t size, int xflags)
 {
-       struct xfs_inode *ip = XFS_I(inode);
+       struct xfs_inode *ip = XFS_I(dentry->d_inode);
        int error, asize = size;
 
        if (strcmp(name, "") == 0)
@@ -52,10 +52,10 @@ __xfs_xattr_get(struct inode *inode, const char *name,
 }
 
 static int
-__xfs_xattr_set(struct inode *inode, const char *name, const void *value,
+xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
                size_t size, int flags, int xflags)
 {
-       struct xfs_inode *ip = XFS_I(inode);
+       struct xfs_inode *ip = XFS_I(dentry->d_inode);
 
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -71,75 +71,34 @@ __xfs_xattr_set(struct inode *inode, const char *name, const void *value,
        return -xfs_attr_set(ip, name, (void *)value, size, xflags);
 }
 
-static int
-xfs_xattr_user_get(struct inode *inode, const char *name,
-               void *value, size_t size)
-{
-       return __xfs_xattr_get(inode, name, value, size, 0);
-}
-
-static int
-xfs_xattr_user_set(struct inode *inode, const char *name,
-               const void *value, size_t size, int flags)
-{
-       return __xfs_xattr_set(inode, name, value, size, flags, 0);
-}
-
 static struct xattr_handler xfs_xattr_user_handler = {
        .prefix = XATTR_USER_PREFIX,
-       .get    = xfs_xattr_user_get,
-       .set    = xfs_xattr_user_set,
+       .flags  = 0, /* no flags implies user namespace */
+       .get    = xfs_xattr_get,
+       .set    = xfs_xattr_set,
 };
 
-
-static int
-xfs_xattr_trusted_get(struct inode *inode, const char *name,
-               void *value, size_t size)
-{
-       return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT);
-}
-
-static int
-xfs_xattr_trusted_set(struct inode *inode, const char *name,
-               const void *value, size_t size, int flags)
-{
-       return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT);
-}
-
 static struct xattr_handler xfs_xattr_trusted_handler = {
        .prefix = XATTR_TRUSTED_PREFIX,
-       .get    = xfs_xattr_trusted_get,
-       .set    = xfs_xattr_trusted_set,
+       .flags  = ATTR_ROOT,
+       .get    = xfs_xattr_get,
+       .set    = xfs_xattr_set,
 };
 
-
-static int
-xfs_xattr_secure_get(struct inode *inode, const char *name,
-               void *value, size_t size)
-{
-       return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE);
-}
-
-static int
-xfs_xattr_secure_set(struct inode *inode, const char *name,
-               const void *value, size_t size, int flags)
-{
-       return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE);
-}
-
 static struct xattr_handler xfs_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
-       .get    = xfs_xattr_secure_get,
-       .set    = xfs_xattr_secure_set,
+       .flags  = ATTR_SECURE,
+       .get    = xfs_xattr_get,
+       .set    = xfs_xattr_set,
 };
 
-
 struct xattr_handler *xfs_xattr_handlers[] = {
        &xfs_xattr_user_handler,
        &xfs_xattr_trusted_handler,
        &xfs_xattr_security_handler,
 #ifdef CONFIG_XFS_POSIX_ACL
-       &xfs_xattr_system_handler,
+       &xfs_xattr_acl_access_handler,
+       &xfs_xattr_acl_default_handler,
 #endif
        NULL
 };
index 947b150..00fd357 100644 (file)
@@ -49,7 +49,8 @@ extern int xfs_acl_chmod(struct inode *inode);
 extern int posix_acl_access_exists(struct inode *inode);
 extern int posix_acl_default_exists(struct inode *inode);
 
-extern struct xattr_handler xfs_xattr_system_handler;
+extern struct xattr_handler xfs_xattr_acl_access_handler;
+extern struct xattr_handler xfs_xattr_acl_default_handler;
 #else
 # define xfs_check_acl                                 NULL
 # define xfs_get_acl(inode, type)                      NULL
index 335a0a5..5555508 100644 (file)
@@ -18,11 +18,9 @@ extern void drop_file_write_access(struct file *file);
 struct file_operations;
 struct vfsmount;
 struct dentry;
-extern int init_file(struct file *, struct vfsmount *mnt,
-               struct dentry *dentry, fmode_t mode,
-               const struct file_operations *fop);
-extern struct file *alloc_file(struct vfsmount *, struct dentry *dentry,
-               fmode_t mode, const struct file_operations *fop);
+struct path;
+extern struct file *alloc_file(struct path *, fmode_t mode,
+       const struct file_operations *fop);
 
 static inline void fput_light(struct file *file, int fput_needed)
 {
index b23a701..7c8ff12 100644 (file)
@@ -2189,7 +2189,6 @@ static inline void insert_inode_hash(struct inode *inode) {
        __insert_inode_hash(inode, inode->i_ino);
 }
 
-extern struct file * get_empty_filp(void);
 extern void file_move(struct file *f, struct list_head *list);
 extern void file_kill(struct file *f);
 #ifdef CONFIG_BLOCK
index 886f5fa..ca666d1 100644 (file)
@@ -1,36 +1,15 @@
-/*
- * include/linux/generic_acl.h
- *
- * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
- *
- * This file is released under the GPL.
- */
+#ifndef LINUX_GENERIC_ACL_H
+#define LINUX_GENERIC_ACL_H
 
-#ifndef GENERIC_ACL_H
-#define GENERIC_ACL_H
+#include <linux/xattr.h>
 
-#include <linux/posix_acl.h>
-#include <linux/posix_acl_xattr.h>
+struct inode;
 
-/**
- * struct generic_acl_operations  -  filesystem operations
- *
- * Filesystems must make these operations available to the generic
- * operations.
- */
-struct generic_acl_operations {
-       struct posix_acl *(*getacl)(struct inode *, int);
-       void (*setacl)(struct inode *, int, struct posix_acl *);
-};
+extern struct xattr_handler generic_acl_access_handler;
+extern struct xattr_handler generic_acl_default_handler;
 
-size_t generic_acl_list(struct inode *, struct generic_acl_operations *, int,
-                       char *, size_t);
-int generic_acl_get(struct inode *, struct generic_acl_operations *, int,
-                   void *, size_t);
-int generic_acl_set(struct inode *, struct generic_acl_operations *, int,
-                   const void *, size_t);
-int generic_acl_init(struct inode *, struct inode *,
-                    struct generic_acl_operations *);
-int generic_acl_chmod(struct inode *, struct generic_acl_operations *);
+int generic_acl_init(struct inode *, struct inode *);
+int generic_acl_chmod(struct inode *);
+int generic_check_acl(struct inode *inode, int mask);
 
-#endif
+#endif /* LINUX_GENERIC_ACL_H */
index 0e3f2a4..99dc6d5 100644 (file)
 #include <linux/fs.h>
 struct linux_binprm;
 
-#define IMA_COUNT_UPDATE 1
-#define IMA_COUNT_LEAVE 0
-
 #ifdef CONFIG_IMA
 extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_inode_alloc(struct inode *inode);
 extern void ima_inode_free(struct inode *inode);
-extern int ima_path_check(struct path *path, int mask, int update_counts);
+extern int ima_path_check(struct path *path, int mask);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern void ima_counts_get(struct file *file);
-extern void ima_counts_put(struct path *path, int mask);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -42,7 +38,7 @@ static inline void ima_inode_free(struct inode *inode)
        return;
 }
 
-static inline int ima_path_check(struct path *path, int mask, int update_counts)
+static inline int ima_path_check(struct path *path, int mask)
 {
        return 0;
 }
@@ -62,9 +58,5 @@ static inline void ima_counts_get(struct file *file)
        return;
 }
 
-static inline void ima_counts_put(struct path *path, int mask)
-{
-       return;
-}
 #endif /* CONFIG_IMA_H */
 #endif /* _LINUX_IMA_H */
index d74785c..d9ebf10 100644 (file)
@@ -23,7 +23,6 @@ struct proc_mounts {
 
 struct fs_struct;
 
-extern struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt);
 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
                struct fs_struct *);
 extern void put_mnt_ns(struct mnt_namespace *ns);
index deee7af..e164291 100644 (file)
@@ -41,20 +41,4 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
 extern int init_tmpfs(void);
 extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
 
-#ifdef CONFIG_TMPFS_POSIX_ACL
-int shmem_check_acl(struct inode *, int);
-int shmem_acl_init(struct inode *, struct inode *);
-
-extern struct xattr_handler shmem_xattr_acl_access_handler;
-extern struct xattr_handler shmem_xattr_acl_default_handler;
-
-extern struct generic_acl_operations shmem_acl_ops;
-
-#else
-static inline int shmem_acl_init(struct inode *inode, struct inode *dir)
-{
-       return 0;
-}
-#endif  /* CONFIG_TMPFS_POSIX_ACL */
-
 #endif
index 5c84af8..fb9b7e6 100644 (file)
@@ -38,12 +38,13 @@ struct dentry;
 
 struct xattr_handler {
        char *prefix;
-       size_t (*list)(struct inode *inode, char *list, size_t list_size,
-                      const char *name, size_t name_len);
-       int (*get)(struct inode *inode, const char *name, void *buffer,
-                  size_t size);
-       int (*set)(struct inode *inode, const char *name, const void *buffer,
-                  size_t size, int flags);
+       int flags;      /* fs private flags passed back to the handlers */
+       size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
+                      const char *name, size_t name_len, int handler_flags);
+       int (*get)(struct dentry *dentry, const char *name, void *buffer,
+                  size_t size, int handler_flags);
+       int (*set)(struct dentry *dentry, const char *name, const void *buffer,
+                  size_t size, int flags, int handler_flags);
 };
 
 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
index ee9d697..c79bd57 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/nsproxy.h>
 #include <linux/pid.h>
 #include <linux/ipc_namespace.h>
-#include <linux/ima.h>
 
 #include <net/sock.h>
 #include "util.h"
@@ -734,7 +733,6 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
                error = PTR_ERR(filp);
                goto out_putfd;
        }
-       ima_counts_get(filp);
 
        fd_install(fd, filp);
        goto out_upsem;
index e9b039f..92fe923 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -39,7 +39,6 @@
 #include <linux/nsproxy.h>
 #include <linux/mount.h>
 #include <linux/ipc_namespace.h>
-#include <linux/ima.h>
 
 #include <asm/uaccess.h>
 
@@ -879,8 +878,8 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
        if (err)
                goto out_unlock;
 
-       path.dentry = dget(shp->shm_file->f_path.dentry);
-       path.mnt    = shp->shm_file->f_path.mnt;
+       path = shp->shm_file->f_path;
+       path_get(&path);
        shp->shm_nattch++;
        size = i_size_read(path.dentry->d_inode);
        shm_unlock(shp);
@@ -890,13 +889,12 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
        if (!sfd)
                goto out_put_dentry;
 
-       file = alloc_file(path.mnt, path.dentry, f_mode,
-                       is_file_hugepages(shp->shm_file) ?
+       file = alloc_file(&path, f_mode,
+                         is_file_hugepages(shp->shm_file) ?
                                &shm_file_operations_huge :
                                &shm_file_operations);
        if (!file)
                goto out_free;
-       ima_counts_get(file);
 
        file->private_data = sfd;
        file->f_mapping = shp->shm_file->f_mapping;
@@ -951,7 +949,7 @@ out_unlock:
 out_free:
        kfree(sfd);
 out_put_dentry:
-       dput(path.dentry);
+       path_put(&path);
        goto out_nattch;
 }
 
index 82131d0..7a68d2a 100644 (file)
@@ -22,7 +22,6 @@ obj-$(CONFIG_HUGETLBFS)       += hugetlb.o
 obj-$(CONFIG_NUMA)     += mempolicy.o
 obj-$(CONFIG_SPARSEMEM)        += sparse.o
 obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
-obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
 obj-$(CONFIG_SLOB) += slob.o
 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_KSM) += ksm.o
index 8b4d88f..96ac6b0 100644 (file)
@@ -2240,7 +2240,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
                size_t count, ssize_t written)
 {
        struct file *file = iocb->ki_filp;
-       struct address_space *mapping = file->f_mapping;
        ssize_t status;
        struct iov_iter i;
 
@@ -2252,15 +2251,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
                *ppos = pos + status;
        }
        
-       /*
-        * If we get here for O_DIRECT writes then we must have fallen through
-        * to buffered writes (block instantiation inside i_size).  So we sync
-        * the file data here, to try to honour O_DIRECT expectations.
-        */
-       if (unlikely(file->f_flags & O_DIRECT) && written)
-               status = filemap_write_and_wait_range(mapping,
-                                       pos, pos + written - 1);
-
        return written ? written : status;
 }
 EXPORT_SYMBOL(generic_file_buffered_write);
@@ -2359,10 +2349,7 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                 * semantics.
                 */
                endbyte = pos + written_buffered - written - 1;
-               err = do_sync_mapping_range(file->f_mapping, pos, endbyte,
-                                           SYNC_FILE_RANGE_WAIT_BEFORE|
-                                           SYNC_FILE_RANGE_WRITE|
-                                           SYNC_FILE_RANGE_WAIT_AFTER);
+               err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
                if (err == 0) {
                        written = written_buffered;
                        invalidate_mapping_pages(mapping,
index 4fb41c8..f848506 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/swap.h>
-#include <linux/ima.h>
 
 static struct vfsmount *shm_mnt;
 
@@ -42,6 +41,7 @@ static struct vfsmount *shm_mnt;
 
 #include <linux/xattr.h>
 #include <linux/exportfs.h>
+#include <linux/posix_acl.h>
 #include <linux/generic_acl.h>
 #include <linux/mman.h>
 #include <linux/string.h>
@@ -810,7 +810,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
                error = inode_setattr(inode, attr);
 #ifdef CONFIG_TMPFS_POSIX_ACL
        if (!error && (attr->ia_valid & ATTR_MODE))
-               error = generic_acl_chmod(inode, &shmem_acl_ops);
+               error = generic_acl_chmod(inode);
 #endif
        if (page)
                page_cache_release(page);
@@ -1824,11 +1824,13 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
                                return error;
                        }
                }
-               error = shmem_acl_init(inode, dir);
+#ifdef CONFIG_TMPFS_POSIX_ACL
+               error = generic_acl_init(inode, dir);
                if (error) {
                        iput(inode);
                        return error;
                }
+#endif
                if (dir->i_mode & S_ISGID) {
                        inode->i_gid = dir->i_gid;
                        if (S_ISDIR(mode))
@@ -2043,27 +2045,28 @@ static const struct inode_operations shmem_symlink_inode_operations = {
  * filesystem level, though.
  */
 
-static size_t shmem_xattr_security_list(struct inode *inode, char *list,
+static size_t shmem_xattr_security_list(struct dentry *dentry, char *list,
                                        size_t list_len, const char *name,
-                                       size_t name_len)
+                                       size_t name_len, int handler_flags)
 {
-       return security_inode_listsecurity(inode, list, list_len);
+       return security_inode_listsecurity(dentry->d_inode, list, list_len);
 }
 
-static int shmem_xattr_security_get(struct inode *inode, const char *name,
-                                   void *buffer, size_t size)
+static int shmem_xattr_security_get(struct dentry *dentry, const char *name,
+               void *buffer, size_t size, int handler_flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return xattr_getsecurity(inode, name, buffer, size);
+       return xattr_getsecurity(dentry->d_inode, name, buffer, size);
 }
 
-static int shmem_xattr_security_set(struct inode *inode, const char *name,
-                                   const void *value, size_t size, int flags)
+static int shmem_xattr_security_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int handler_flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return security_inode_setsecurity(inode, name, value, size, flags);
+       return security_inode_setsecurity(dentry->d_inode, name, value,
+                                         size, flags);
 }
 
 static struct xattr_handler shmem_xattr_security_handler = {
@@ -2074,8 +2077,8 @@ static struct xattr_handler shmem_xattr_security_handler = {
 };
 
 static struct xattr_handler *shmem_xattr_handlers[] = {
-       &shmem_xattr_acl_access_handler,
-       &shmem_xattr_acl_default_handler,
+       &generic_acl_access_handler,
+       &generic_acl_default_handler,
        &shmem_xattr_security_handler,
        NULL
 };
@@ -2454,7 +2457,7 @@ static const struct inode_operations shmem_inode_operations = {
        .getxattr       = generic_getxattr,
        .listxattr      = generic_listxattr,
        .removexattr    = generic_removexattr,
-       .check_acl      = shmem_check_acl,
+       .check_acl      = generic_check_acl,
 #endif
 
 };
@@ -2477,7 +2480,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
        .getxattr       = generic_getxattr,
        .listxattr      = generic_listxattr,
        .removexattr    = generic_removexattr,
-       .check_acl      = shmem_check_acl,
+       .check_acl      = generic_check_acl,
 #endif
 };
 
@@ -2488,7 +2491,7 @@ static const struct inode_operations shmem_special_inode_operations = {
        .getxattr       = generic_getxattr,
        .listxattr      = generic_listxattr,
        .removexattr    = generic_removexattr,
-       .check_acl      = shmem_check_acl,
+       .check_acl      = generic_check_acl,
 #endif
 };
 
@@ -2626,7 +2629,8 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
        int error;
        struct file *file;
        struct inode *inode;
-       struct dentry *dentry, *root;
+       struct path path;
+       struct dentry *root;
        struct qstr this;
 
        if (IS_ERR(shm_mnt))
@@ -2643,38 +2647,35 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
        this.len = strlen(name);
        this.hash = 0; /* will go */
        root = shm_mnt->mnt_root;
-       dentry = d_alloc(root, &this);
-       if (!dentry)
+       path.dentry = d_alloc(root, &this);
+       if (!path.dentry)
                goto put_memory;
-
-       error = -ENFILE;
-       file = get_empty_filp();
-       if (!file)
-               goto put_dentry;
+       path.mnt = mntget(shm_mnt);
 
        error = -ENOSPC;
        inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags);
        if (!inode)
-               goto close_file;
+               goto put_dentry;
 
-       d_instantiate(dentry, inode);
+       d_instantiate(path.dentry, inode);
        inode->i_size = size;
        inode->i_nlink = 0;     /* It is unlinked */
-       init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
-                 &shmem_file_operations);
-
 #ifndef CONFIG_MMU
        error = ramfs_nommu_expand_for_mapping(inode, size);
        if (error)
-               goto close_file;
+               goto put_dentry;
 #endif
-       ima_counts_get(file);
+
+       error = -ENFILE;
+       file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
+                 &shmem_file_operations);
+       if (!file)
+               goto put_dentry;
+
        return file;
 
-close_file:
-       put_filp(file);
 put_dentry:
-       dput(dentry);
+       path_put(&path);
 put_memory:
        shmem_unacct_size(flags, size);
        return ERR_PTR(error);
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
deleted file mode 100644 (file)
index df2c87f..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * mm/shmem_acl.c
- *
- * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
- *
- * This file is released under the GPL.
- */
-
-#include <linux/fs.h>
-#include <linux/shmem_fs.h>
-#include <linux/xattr.h>
-#include <linux/generic_acl.h>
-
-/**
- * shmem_get_acl  -   generic_acl_operations->getacl() operation
- */
-static struct posix_acl *
-shmem_get_acl(struct inode *inode, int type)
-{
-       struct posix_acl *acl = NULL;
-
-       spin_lock(&inode->i_lock);
-       switch(type) {
-               case ACL_TYPE_ACCESS:
-                       acl = posix_acl_dup(inode->i_acl);
-                       break;
-
-               case ACL_TYPE_DEFAULT:
-                       acl = posix_acl_dup(inode->i_default_acl);
-                       break;
-       }
-       spin_unlock(&inode->i_lock);
-
-       return acl;
-}
-
-/**
- * shmem_set_acl  -   generic_acl_operations->setacl() operation
- */
-static void
-shmem_set_acl(struct inode *inode, int type, struct posix_acl *acl)
-{
-       struct posix_acl *free = NULL;
-
-       spin_lock(&inode->i_lock);
-       switch(type) {
-               case ACL_TYPE_ACCESS:
-                       free = inode->i_acl;
-                       inode->i_acl = posix_acl_dup(acl);
-                       break;
-
-               case ACL_TYPE_DEFAULT:
-                       free = inode->i_default_acl;
-                       inode->i_default_acl = posix_acl_dup(acl);
-                       break;
-       }
-       spin_unlock(&inode->i_lock);
-       posix_acl_release(free);
-}
-
-struct generic_acl_operations shmem_acl_ops = {
-       .getacl = shmem_get_acl,
-       .setacl = shmem_set_acl,
-};
-
-/**
- * shmem_list_acl_access, shmem_get_acl_access, shmem_set_acl_access,
- * shmem_xattr_acl_access_handler  -  plumbing code to implement the
- * system.posix_acl_access xattr using the generic acl functions.
- */
-
-static size_t
-shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
-                     const char *name, size_t name_len)
-{
-       return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_ACCESS,
-                               list, list_size);
-}
-
-static int
-shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
-                    size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, buffer,
-                              size);
-}
-
-static int
-shmem_set_acl_access(struct inode *inode, const char *name, const void *value,
-                    size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, value,
-                              size);
-}
-
-struct xattr_handler shmem_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .list   = shmem_list_acl_access,
-       .get    = shmem_get_acl_access,
-       .set    = shmem_set_acl_access,
-};
-
-/**
- * shmem_list_acl_default, shmem_get_acl_default, shmem_set_acl_default,
- * shmem_xattr_acl_default_handler  -  plumbing code to implement the
- * system.posix_acl_default xattr using the generic acl functions.
- */
-
-static size_t
-shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
-                      const char *name, size_t name_len)
-{
-       return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT,
-                               list, list_size);
-}
-
-static int
-shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
-                     size_t size)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, buffer,
-                              size);
-}
-
-static int
-shmem_set_acl_default(struct inode *inode, const char *name, const void *value,
-                     size_t size, int flags)
-{
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, value,
-                              size);
-}
-
-struct xattr_handler shmem_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .list   = shmem_list_acl_default,
-       .get    = shmem_get_acl_default,
-       .set    = shmem_set_acl_default,
-};
-
-/**
- * shmem_acl_init  -  Inizialize the acl(s) of a new inode
- */
-int
-shmem_acl_init(struct inode *inode, struct inode *dir)
-{
-       return generic_acl_init(inode, dir, &shmem_acl_ops);
-}
-
-/**
- * shmem_check_acl  -  check_acl() callback for generic_permission()
- */
-int
-shmem_check_acl(struct inode *inode, int mask)
-{
-       struct posix_acl *acl = shmem_get_acl(inode, ACL_TYPE_ACCESS);
-
-       if (acl) {
-               int error = posix_acl_permission(inode, acl, mask);
-               posix_acl_release(acl);
-               return error;
-       }
-       return -EAGAIN;
-}
index 4dd873e..be1cb90 100644 (file)
@@ -42,6 +42,8 @@
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
 
+#include <linux/syscalls.h> /* killme */
+
 #define P9_PORT 564
 #define MAX_SOCK_BUF (64*1024)
 #define MAXPOLLWADDR   2
@@ -788,24 +790,41 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
 
 static int p9_socket_open(struct p9_client *client, struct socket *csocket)
 {
-       int fd, ret;
+       struct p9_trans_fd *p;
+       int ret, fd;
+
+       p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
 
        csocket->sk->sk_allocation = GFP_NOIO;
        fd = sock_map_fd(csocket, 0);
        if (fd < 0) {
                P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
+               sock_release(csocket);
+               kfree(p);
                return fd;
        }
 
-       ret = p9_fd_open(client, fd, fd);
-       if (ret < 0) {
-               P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
+       get_file(csocket->file);
+       get_file(csocket->file);
+       p->wr = p->rd = csocket->file;
+       client->trans = p;
+       client->status = Connected;
+
+       sys_close(fd);  /* still racy */
+
+       p->rd->f_flags |= O_NONBLOCK;
+
+       p->conn = p9_conn_create(client);
+       if (IS_ERR(p->conn)) {
+               ret = PTR_ERR(p->conn);
+               p->conn = NULL;
+               kfree(p);
+               sockfd_put(csocket);
                sockfd_put(csocket);
                return ret;
        }
-
-       ((struct p9_trans_fd *)client->trans)->rd->f_flags |= O_NONBLOCK;
-
        return 0;
 }
 
@@ -883,7 +902,6 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
        struct socket *csocket;
        struct sockaddr_in sin_server;
        struct p9_fd_opts opts;
-       struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
 
        err = parse_opts(args, &opts);
        if (err < 0)
@@ -897,12 +915,11 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
        sin_server.sin_family = AF_INET;
        sin_server.sin_addr.s_addr = in_aton(addr);
        sin_server.sin_port = htons(opts.port);
-       sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+       err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
 
-       if (!csocket) {
+       if (err) {
                P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
-               err = -EIO;
-               goto error;
+               return err;
        }
 
        err = csocket->ops->connect(csocket,
@@ -912,30 +929,11 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
                P9_EPRINTK(KERN_ERR,
                        "p9_trans_tcp: problem connecting socket to %s\n",
                        addr);
-               goto error;
-       }
-
-       err = p9_socket_open(client, csocket);
-       if (err < 0)
-               goto error;
-
-       p = (struct p9_trans_fd *) client->trans;
-       p->conn = p9_conn_create(client);
-       if (IS_ERR(p->conn)) {
-               err = PTR_ERR(p->conn);
-               p->conn = NULL;
-               goto error;
-       }
-
-       return 0;
-
-error:
-       if (csocket)
                sock_release(csocket);
+               return err;
+       }
 
-       kfree(p);
-
-       return err;
+       return p9_socket_open(client, csocket);
 }
 
 static int
@@ -944,49 +942,33 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
        int err;
        struct socket *csocket;
        struct sockaddr_un sun_server;
-       struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
 
        csocket = NULL;
 
        if (strlen(addr) > UNIX_PATH_MAX) {
                P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
                        addr);
-               err = -ENAMETOOLONG;
-               goto error;
+               return -ENAMETOOLONG;
        }
 
        sun_server.sun_family = PF_UNIX;
        strcpy(sun_server.sun_path, addr);
-       sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+       err = sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+       if (err < 0) {
+               P9_EPRINTK(KERN_ERR, "p9_trans_unix: problem creating socket\n");
+               return err;
+       }
        err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
                        sizeof(struct sockaddr_un) - 1, 0);
        if (err < 0) {
                P9_EPRINTK(KERN_ERR,
                        "p9_trans_unix: problem connecting socket: %s: %d\n",
                        addr, err);
-               goto error;
-       }
-
-       err = p9_socket_open(client, csocket);
-       if (err < 0)
-               goto error;
-
-       p = (struct p9_trans_fd *) client->trans;
-       p->conn = p9_conn_create(client);
-       if (IS_ERR(p->conn)) {
-               err = PTR_ERR(p->conn);
-               p->conn = NULL;
-               goto error;
-       }
-
-       return 0;
-
-error:
-       if (csocket)
                sock_release(csocket);
+               return err;
+       }
 
-       kfree(p);
-       return err;
+       return p9_socket_open(client, csocket);
 }
 
 static int
@@ -994,7 +976,7 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
 {
        int err;
        struct p9_fd_opts opts;
-       struct p9_trans_fd *p = NULL; /* this get allocated in p9_fd_open */
+       struct p9_trans_fd *p;
 
        parse_opts(args, &opts);
 
@@ -1005,21 +987,19 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
 
        err = p9_fd_open(client, opts.rfd, opts.wfd);
        if (err < 0)
-               goto error;
+               return err;
 
        p = (struct p9_trans_fd *) client->trans;
        p->conn = p9_conn_create(client);
        if (IS_ERR(p->conn)) {
                err = PTR_ERR(p->conn);
                p->conn = NULL;
-               goto error;
+               fput(p->rd);
+               fput(p->wr);
+               return err;
        }
 
        return 0;
-
-error:
-       kfree(p);
-       return err;
 }
 
 static struct p9_trans_module p9_tcp_trans = {
index b94c3dd..dbfdfa9 100644 (file)
@@ -355,68 +355,61 @@ static const struct dentry_operations sockfs_dentry_operations = {
  *     but we take care of internal coherence yet.
  */
 
-static int sock_alloc_fd(struct file **filep, int flags)
+static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
 {
+       struct qstr name = { .name = "" };
+       struct path path;
+       struct file *file;
        int fd;
 
        fd = get_unused_fd_flags(flags);
-       if (likely(fd >= 0)) {
-               struct file *file = get_empty_filp();
-
-               *filep = file;
-               if (unlikely(!file)) {
-                       put_unused_fd(fd);
-                       return -ENFILE;
-               }
-       } else
-               *filep = NULL;
-       return fd;
-}
-
-static int sock_attach_fd(struct socket *sock, struct file *file, int flags)
-{
-       struct dentry *dentry;
-       struct qstr name = { .name = "" };
+       if (unlikely(fd < 0))
+               return fd;
 
-       dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
-       if (unlikely(!dentry))
+       path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
+       if (unlikely(!path.dentry)) {
+               put_unused_fd(fd);
                return -ENOMEM;
+       }
+       path.mnt = mntget(sock_mnt);
 
-       dentry->d_op = &sockfs_dentry_operations;
+       path.dentry->d_op = &sockfs_dentry_operations;
        /*
         * We dont want to push this dentry into global dentry hash table.
         * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
         * This permits a working /proc/$pid/fd/XXX on sockets
         */
-       dentry->d_flags &= ~DCACHE_UNHASHED;
-       d_instantiate(dentry, SOCK_INODE(sock));
+       path.dentry->d_flags &= ~DCACHE_UNHASHED;
+       d_instantiate(path.dentry, SOCK_INODE(sock));
+       SOCK_INODE(sock)->i_fop = &socket_file_ops;
 
-       sock->file = file;
-       init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
+       file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
                  &socket_file_ops);
-       SOCK_INODE(sock)->i_fop = &socket_file_ops;
+       if (unlikely(!file)) {
+               /* drop dentry, keep inode */
+               atomic_inc(&path.dentry->d_inode->i_count);
+               path_put(&path);
+               put_unused_fd(fd);
+               return -ENFILE;
+       }
+
+       sock->file = file;
        file->f_flags = O_RDWR | (flags & O_NONBLOCK);
        file->f_pos = 0;
        file->private_data = sock;
 
-       return 0;
+       *f = file;
+       return fd;
 }
 
 int sock_map_fd(struct socket *sock, int flags)
 {
        struct file *newfile;
-       int fd = sock_alloc_fd(&newfile, flags);
-
-       if (likely(fd >= 0)) {
-               int err = sock_attach_fd(sock, newfile, flags);
+       int fd = sock_alloc_file(sock, &newfile, flags);
 
-               if (unlikely(err < 0)) {
-                       put_filp(newfile);
-                       put_unused_fd(fd);
-                       return err;
-               }
+       if (likely(fd >= 0))
                fd_install(fd, newfile);
-       }
+
        return fd;
 }
 
@@ -1390,29 +1383,19 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
        if (err < 0)
                goto out_release_both;
 
-       fd1 = sock_alloc_fd(&newfile1, flags & O_CLOEXEC);
+       fd1 = sock_alloc_file(sock1, &newfile1, flags);
        if (unlikely(fd1 < 0)) {
                err = fd1;
                goto out_release_both;
        }
 
-       fd2 = sock_alloc_fd(&newfile2, flags & O_CLOEXEC);
+       fd2 = sock_alloc_file(sock2, &newfile2, flags);
        if (unlikely(fd2 < 0)) {
                err = fd2;
-               put_filp(newfile1);
-               put_unused_fd(fd1);
-               goto out_release_both;
-       }
-
-       err = sock_attach_fd(sock1, newfile1, flags & O_NONBLOCK);
-       if (unlikely(err < 0)) {
-               goto out_fd2;
-       }
-
-       err = sock_attach_fd(sock2, newfile2, flags & O_NONBLOCK);
-       if (unlikely(err < 0)) {
                fput(newfile1);
-               goto out_fd1;
+               put_unused_fd(fd1);
+               sock_release(sock2);
+               goto out;
        }
 
        audit_fd_pair(fd1, fd2);
@@ -1438,16 +1421,6 @@ out_release_1:
        sock_release(sock1);
 out:
        return err;
-
-out_fd2:
-       put_filp(newfile1);
-       sock_release(sock1);
-out_fd1:
-       put_filp(newfile2);
-       sock_release(sock2);
-       put_unused_fd(fd1);
-       put_unused_fd(fd2);
-       goto out;
 }
 
 /*
@@ -1551,17 +1524,13 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
         */
        __module_get(newsock->ops->owner);
 
-       newfd = sock_alloc_fd(&newfile, flags & O_CLOEXEC);
+       newfd = sock_alloc_file(newsock, &newfile, flags);
        if (unlikely(newfd < 0)) {
                err = newfd;
                sock_release(newsock);
                goto out_put;
        }
 
-       err = sock_attach_fd(newsock, newfile, flags & O_NONBLOCK);
-       if (err < 0)
-               goto out_fd_simple;
-
        err = security_socket_accept(sock, newsock);
        if (err)
                goto out_fd;
@@ -1591,11 +1560,6 @@ out_put:
        fput_light(sock->file, fput_needed);
 out:
        return err;
-out_fd_simple:
-       sock_release(newsock);
-       put_filp(newfile);
-       put_unused_fd(newfd);
-       goto out_put;
 out_fd:
        fput(newfile);
        put_unused_fd(newfd);
index 165eb53..c41afe6 100644 (file)
@@ -97,7 +97,6 @@ static inline unsigned long ima_hash_key(u8 *digest)
 
 /* iint cache flags */
 #define IMA_MEASURED           1
-#define IMA_IINT_DUMP_STACK    512
 
 /* integrity data associated with an inode */
 struct ima_iint_cache {
@@ -128,8 +127,6 @@ void ima_template_show(struct seq_file *m, void *e,
  */
 struct ima_iint_cache *ima_iint_insert(struct inode *inode);
 struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
-struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode);
-void ima_iint_delete(struct inode *inode);
 void iint_free(struct kref *kref);
 void iint_rcu_free(struct rcu_head *rcu);
 
index a4e2b1d..fa592ff 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/radix-tree.h>
 #include "ima.h"
 
-#define ima_iint_delete ima_inode_free
-
 RADIX_TREE(ima_iint_store, GFP_ATOMIC);
 DEFINE_SPINLOCK(ima_iint_lock);
 
@@ -45,22 +43,21 @@ out:
        return iint;
 }
 
-/* Allocate memory for the iint associated with the inode
- * from the iint_cache slab, initialize the iint, and
- * insert it into the radix tree.
- *
- * On success return a pointer to the iint; on failure return NULL.
+/**
+ * ima_inode_alloc - allocate an iint associated with an inode
+ * @inode: pointer to the inode
  */
-struct ima_iint_cache *ima_iint_insert(struct inode *inode)
+int ima_inode_alloc(struct inode *inode)
 {
        struct ima_iint_cache *iint = NULL;
        int rc = 0;
 
        if (!ima_initialized)
-               return iint;
+               return 0;
+
        iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
        if (!iint)
-               return iint;
+               return -ENOMEM;
 
        rc = radix_tree_preload(GFP_NOFS);
        if (rc < 0)
@@ -70,65 +67,13 @@ struct ima_iint_cache *ima_iint_insert(struct inode *inode)
        rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
        spin_unlock(&ima_iint_lock);
 out:
-       if (rc < 0) {
+       if (rc < 0)
                kmem_cache_free(iint_cache, iint);
-               if (rc == -EEXIST) {
-                       spin_lock(&ima_iint_lock);
-                       iint = radix_tree_lookup(&ima_iint_store,
-                                                (unsigned long)inode);
-                       spin_unlock(&ima_iint_lock);
-               } else
-                       iint = NULL;
-       }
-       radix_tree_preload_end();
-       return iint;
-}
-
-/**
- * ima_inode_alloc - allocate an iint associated with an inode
- * @inode: pointer to the inode
- *
- * Return 0 on success, 1 on failure.
- */
-int ima_inode_alloc(struct inode *inode)
-{
-       struct ima_iint_cache *iint;
-
-       if (!ima_initialized)
-               return 0;
-
-       iint = ima_iint_insert(inode);
-       if (!iint)
-               return 1;
-       return 0;
-}
-
-/* ima_iint_find_insert_get - get the iint associated with an inode
- *
- * Most insertions are done at inode_alloc, except those allocated
- * before late_initcall. When the iint does not exist, allocate it,
- * initialize and insert it, and increment the iint refcount.
- *
- * (Can't initialize at security_initcall before any inodes are
- * allocated, got to wait at least until proc_init.)
- *
- *  Return the iint.
- */
-struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
-{
-       struct ima_iint_cache *iint = NULL;
 
-       iint = ima_iint_find_get(inode);
-       if (iint)
-               return iint;
-
-       iint = ima_iint_insert(inode);
-       if (iint)
-               kref_get(&iint->refcount);
+       radix_tree_preload_end();
 
-       return iint;
+       return rc;
 }
-EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
 
 /* iint_free - called when the iint refcount goes to zero */
 void iint_free(struct kref *kref)
@@ -164,12 +109,12 @@ void iint_rcu_free(struct rcu_head *rcu_head)
 }
 
 /**
- * ima_iint_delete - called on integrity_inode_free
+ * ima_inode_free - called on security_inode_free
  * @inode: pointer to the inode
  *
  * Free the integrity information(iint) associated with an inode.
  */
-void ima_iint_delete(struct inode *inode)
+void ima_inode_free(struct inode *inode)
 {
        struct ima_iint_cache *iint;
 
index b85e61b..a89f44d 100644 (file)
@@ -13,8 +13,8 @@
  * License.
  *
  * File: ima_main.c
- *             implements the IMA hooks: ima_bprm_check, ima_file_mmap,
- *             and ima_path_check.
+ *     implements the IMA hooks: ima_bprm_check, ima_file_mmap,
+ *     and ima_path_check.
  */
 #include <linux/module.h>
 #include <linux/file.h>
@@ -35,6 +35,100 @@ static int __init hash_setup(char *str)
 }
 __setup("ima_hash=", hash_setup);
 
+struct ima_imbalance {
+       struct hlist_node node;
+       unsigned long fsmagic;
+};
+
+/*
+ * ima_limit_imbalance - emit one imbalance message per filesystem type
+ *
+ * Maintain list of filesystem types that do not measure files properly.
+ * Return false if unknown, true if known.
+ */
+static bool ima_limit_imbalance(struct file *file)
+{
+       static DEFINE_SPINLOCK(ima_imbalance_lock);
+       static HLIST_HEAD(ima_imbalance_list);
+
+       struct super_block *sb = file->f_dentry->d_sb;
+       struct ima_imbalance *entry;
+       struct hlist_node *node;
+       bool found = false;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) {
+               if (entry->fsmagic == sb->s_magic) {
+                       found = true;
+                       break;
+               }
+       }
+       rcu_read_unlock();
+       if (found)
+               goto out;
+
+       entry = kmalloc(sizeof(*entry), GFP_NOFS);
+       if (!entry)
+               goto out;
+       entry->fsmagic = sb->s_magic;
+       spin_lock(&ima_imbalance_lock);
+       /*
+        * we could have raced and something else might have added this fs
+        * to the list, but we don't really care
+        */
+       hlist_add_head_rcu(&entry->node, &ima_imbalance_list);
+       spin_unlock(&ima_imbalance_lock);
+       printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n",
+              entry->fsmagic);
+out:
+       return found;
+}
+
+/*
+ * Update the counts given an fmode_t
+ */
+static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
+{
+       BUG_ON(!mutex_is_locked(&iint->mutex));
+
+       iint->opencount++;
+       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+               iint->readcount++;
+       if (mode & FMODE_WRITE)
+               iint->writecount++;
+}
+
+/*
+ * Decrement ima counts
+ */
+static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
+                          struct file *file)
+{
+       mode_t mode = file->f_mode;
+       BUG_ON(!mutex_is_locked(&iint->mutex));
+
+       iint->opencount--;
+       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+               iint->readcount--;
+       if (mode & FMODE_WRITE) {
+               iint->writecount--;
+               if (iint->writecount == 0) {
+                       if (iint->version != inode->i_version)
+                               iint->flags &= ~IMA_MEASURED;
+               }
+       }
+
+       if (((iint->opencount < 0) ||
+            (iint->readcount < 0) ||
+            (iint->writecount < 0)) &&
+           !ima_limit_imbalance(file)) {
+               printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n",
+                      __FUNCTION__, iint->readcount, iint->writecount,
+                      iint->opencount);
+               dump_stack();
+       }
+}
+
 /**
  * ima_file_free - called on __fput()
  * @file: pointer to file structure being freed
@@ -54,29 +148,7 @@ void ima_file_free(struct file *file)
                return;
 
        mutex_lock(&iint->mutex);
-       if (iint->opencount <= 0) {
-               printk(KERN_INFO
-                      "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n",
-                      __FUNCTION__, file->f_dentry->d_name.name,
-                      iint->readcount, iint->writecount,
-                      iint->opencount, atomic_long_read(&file->f_count));
-               if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
-                       dump_stack();
-                       iint->flags |= IMA_IINT_DUMP_STACK;
-               }
-       }
-       iint->opencount--;
-
-       if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-               iint->readcount--;
-
-       if (file->f_mode & FMODE_WRITE) {
-               iint->writecount--;
-               if (iint->writecount == 0) {
-                       if (iint->version != inode->i_version)
-                               iint->flags &= ~IMA_MEASURED;
-               }
-       }
+       ima_dec_counts(iint, inode, file);
        mutex_unlock(&iint->mutex);
        kref_put(&iint->refcount, iint_free);
 }
@@ -116,8 +188,7 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
 {
        int rc = 0;
 
-       iint->opencount++;
-       iint->readcount++;
+       ima_inc_counts(iint, file->f_mode);
 
        rc = ima_collect_measurement(iint, file);
        if (!rc)
@@ -125,15 +196,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
        return rc;
 }
 
-static void ima_update_counts(struct ima_iint_cache *iint, int mask)
-{
-       iint->opencount++;
-       if ((mask & MAY_WRITE) || (mask == 0))
-               iint->writecount++;
-       else if (mask & (MAY_READ | MAY_EXEC))
-               iint->readcount++;
-}
-
 /**
  * ima_path_check - based on policy, collect/store measurement.
  * @path: contains a pointer to the path to be measured
@@ -152,7 +214,7 @@ static void ima_update_counts(struct ima_iint_cache *iint, int mask)
  * Always return 0 and audit dentry_open failures.
  * (Return code will be based upon measurement appraisal.)
  */
-int ima_path_check(struct path *path, int mask, int update_counts)
+int ima_path_check(struct path *path, int mask)
 {
        struct inode *inode = path->dentry->d_inode;
        struct ima_iint_cache *iint;
@@ -161,13 +223,11 @@ int ima_path_check(struct path *path, int mask, int update_counts)
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
                return 0;
-       iint = ima_iint_find_insert_get(inode);
+       iint = ima_iint_find_get(inode);
        if (!iint)
                return 0;
 
        mutex_lock(&iint->mutex);
-       if (update_counts)
-               ima_update_counts(iint, mask);
 
        rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
        if (rc < 0)
@@ -219,7 +279,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
                return 0;
-       iint = ima_iint_find_insert_get(inode);
+       iint = ima_iint_find_get(inode);
        if (!iint)
                return -ENOMEM;
 
@@ -238,39 +298,6 @@ out:
 }
 
 /*
- * ima_counts_put - decrement file counts
- *
- * File counts are incremented in ima_path_check. On file open
- * error, such as ETXTBSY, decrement the counts to prevent
- * unnecessary imbalance messages.
- */
-void ima_counts_put(struct path *path, int mask)
-{
-       struct inode *inode = path->dentry->d_inode;
-       struct ima_iint_cache *iint;
-
-       /* The inode may already have been freed, freeing the iint
-        * with it. Verify the inode is not NULL before dereferencing
-        * it.
-        */
-       if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
-               return;
-       iint = ima_iint_find_insert_get(inode);
-       if (!iint)
-               return;
-
-       mutex_lock(&iint->mutex);
-       iint->opencount--;
-       if ((mask & MAY_WRITE) || (mask == 0))
-               iint->writecount--;
-       else if (mask & (MAY_READ | MAY_EXEC))
-               iint->readcount--;
-       mutex_unlock(&iint->mutex);
-
-       kref_put(&iint->refcount, iint_free);
-}
-
-/*
  * ima_counts_get - increment file counts
  *
  * - for IPC shm and shmat file.
@@ -286,16 +313,11 @@ void ima_counts_get(struct file *file)
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
                return;
-       iint = ima_iint_find_insert_get(inode);
+       iint = ima_iint_find_get(inode);
        if (!iint)
                return;
        mutex_lock(&iint->mutex);
-       iint->opencount++;
-       if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-               iint->readcount++;
-
-       if (file->f_mode & FMODE_WRITE)
-               iint->writecount++;
+       ima_inc_counts(iint, file->f_mode);
        mutex_unlock(&iint->mutex);
 
        kref_put(&iint->refcount, iint_free);