Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Oct 2016 00:11:50 +0000 (17:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Oct 2016 00:11:50 +0000 (17:11 -0700)
Pull vfs xattr updates from Al Viro:
 "xattr stuff from Andreas

  This completes the switch to xattr_handler ->get()/->set() from
  ->getxattr/->setxattr/->removexattr"

* 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  vfs: Remove {get,set,remove}xattr inode operations
  xattr: Stop calling {get,set,remove}xattr inode operations
  vfs: Check for the IOP_XATTR flag in listxattr
  xattr: Add __vfs_{get,set,remove}xattr helpers
  libfs: Use IOP_XATTR flag for empty directory handling
  vfs: Use IOP_XATTR flag for bad-inode handling
  vfs: Add IOP_XATTR inode operations flag
  vfs: Move xattr_resolve_name to the front of fs/xattr.c
  ecryptfs: Switch to generic xattr handlers
  sockfs: Get rid of getxattr iop
  sockfs: getxattr: Fail with -EOPNOTSUPP for invalid attribute names
  kernfs: Switch to generic xattr handlers
  hfs: Switch to generic xattr handlers
  jffs2: Remove jffs2_{get,set,remove}xattr macros
  xattr: Remove unnecessary NULL attribute name check

80 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
drivers/staging/lustre/lustre/llite/file.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/llite/symlink.c
fs/9p/vfs_inode_dotl.c
fs/bad_inode.c
fs/btrfs/inode.c
fs/cachefiles/bind.c
fs/cachefiles/namei.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/cifs/cifsfs.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/inode.c
fs/ecryptfs/main.c
fs/ecryptfs/mmap.c
fs/ext2/file.c
fs/ext2/namei.c
fs/ext2/symlink.c
fs/ext4/file.c
fs/ext4/namei.c
fs/ext4/symlink.c
fs/f2fs/file.c
fs/f2fs/namei.c
fs/fuse/dir.c
fs/gfs2/inode.c
fs/hfs/attr.c
fs/hfs/hfs_fs.h
fs/hfs/inode.c
fs/hfs/super.c
fs/hfsplus/dir.c
fs/hfsplus/inode.c
fs/inode.c
fs/jffs2/dir.c
fs/jffs2/file.c
fs/jffs2/symlink.c
fs/jffs2/xattr.h
fs/jfs/file.c
fs/jfs/namei.c
fs/jfs/symlink.c
fs/kernfs/dir.c
fs/kernfs/inode.c
fs/kernfs/kernfs-internal.h
fs/kernfs/mount.c
fs/kernfs/symlink.c
fs/libfs.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/ocfs2/file.c
fs/ocfs2/namei.c
fs/ocfs2/symlink.c
fs/orangefs/inode.c
fs/orangefs/namei.c
fs/orangefs/symlink.c
fs/orangefs/xattr.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/super.c
fs/reiserfs/file.c
fs/reiserfs/namei.c
fs/squashfs/inode.c
fs/squashfs/namei.c
fs/squashfs/symlink.c
fs/squashfs/xattr.h
fs/ubifs/dir.c
fs/ubifs/file.c
fs/xattr.c
fs/xfs/xfs_iops.c
include/linux/fs.h
include/linux/xattr.h
mm/shmem.c
net/socket.c
security/commoncap.c
security/integrity/evm/evm_crypto.c
security/integrity/evm/evm_main.c
security/integrity/ima/ima_appraise.c
security/selinux/hooks.c
security/smack/smack_lsm.c

index d30fb2c..f56b39e 100644 (file)
@@ -61,10 +61,7 @@ prototypes:
        int (*get_acl)(struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
-       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
-       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
-       int (*removexattr) (struct dentry *, const char *);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
        void (*update_time)(struct inode *, struct timespec *, int);
        int (*atomic_open)(struct inode *, struct dentry *,
@@ -91,15 +88,13 @@ setattr:    yes
 permission:    no (may not block if called in rcu-walk mode)
 get_acl:       no
 getattr:       no
-setxattr:      yes
-getxattr:      no
 listxattr:     no
-removexattr:   yes
 fiemap:                no
 update_time:   no
 atomic_open:   yes
 tmpfile:       no
 
+
        Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
        cross-directory ->rename() and rename2() has (per-superblock)
@@ -108,6 +103,23 @@ victim.
 See Documentation/filesystems/directory-locking for more detailed discussion
 of the locking scheme for directory operations.
 
+----------------------- xattr_handler operations -----------------------
+prototypes:
+       bool (*list)(struct dentry *dentry);
+       int (*get)(const struct xattr_handler *handler, struct dentry *dentry,
+                  struct inode *inode, const char *name, void *buffer,
+                  size_t size);
+       int (*set)(const struct xattr_handler *handler, struct dentry *dentry,
+                  struct inode *inode, const char *name, const void *buffer,
+                  size_t size, int flags);
+
+locking rules:
+       all may block
+               i_mutex(inode)
+list:          no
+get:           no
+set:           yes
+
 --------------------------- super_operations ---------------------------
 prototypes:
        struct inode *(*alloc_inode)(struct super_block *sb);
index cbec006..43ef86c 100644 (file)
@@ -323,6 +323,35 @@ Whoever sets up the inode is responsible for filling in the "i_op" field. This
 is a pointer to a "struct inode_operations" which describes the methods that
 can be performed on individual inodes.
 
+struct xattr_handlers
+---------------------
+
+On filesystems that support extended attributes (xattrs), the s_xattr
+superblock field points to a NULL-terminated array of xattr handlers.  Extended
+attributes are name:value pairs.
+
+  name: Indicates that the handler matches attributes with the specified name
+       (such as "system.posix_acl_access"); the prefix field must be NULL.
+
+  prefix: Indicates that the handler matches all attributes with the specified
+       name prefix (such as "user."); the name field must be NULL.
+
+  list: Determine if attributes matching this xattr handler should be listed
+       for a particular dentry.  Used by some listxattr implementations like
+       generic_listxattr.
+
+  get: Called by the VFS to get the value of a particular extended attribute.
+       This method is called by the getxattr(2) system call.
+
+  set: Called by the VFS to set the value of a particular extended attribute.
+       When the new value is NULL, called to remove a particular extended
+       attribute.  This method is called by the the setxattr(2) and
+       removexattr(2) system calls.
+
+When none of the xattr handlers of a filesystem match the specified attribute
+name or when a filesystem doesn't support extended attributes, the various
+*xattr(2) system calls return -EOPNOTSUPP.
+
 
 The Inode Object
 ================
@@ -356,10 +385,7 @@ struct inode_operations {
        int (*get_acl)(struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
-       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
-       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
-       int (*removexattr) (struct dentry *, const char *);
        void (*update_time)(struct inode *, struct timespec *, int);
        int (*atomic_open)(struct inode *, struct dentry *, struct file *,
                        unsigned open_flag, umode_t create_mode, int *opened);
@@ -463,19 +489,8 @@ otherwise noted.
   getattr: called by the VFS to get attributes of a file. This method
        is called by stat(2) and related system calls.
 
-  setxattr: called by the VFS to set an extended attribute for a file.
-       Extended attribute is a name:value pair associated with an
-       inode. This method is called by setxattr(2) system call.
-
-  getxattr: called by the VFS to retrieve the value of an extended
-       attribute name. This method is called by getxattr(2) function
-       call.
-
   listxattr: called by the VFS to list all extended attributes for a
-       given file. This method is called by listxattr(2) system call.
-
-  removexattr: called by the VFS to remove an extended attribute from
-       a file. This method is called by removexattr(2) system call.
+       given file. This method is called by the listxattr(2) system call.
 
   update_time: called by the VFS to update a specific time or the i_version of
        an inode.  If this is not defined the VFS will update the inode itself
index 65c945d..e1d784b 100644 (file)
@@ -3268,10 +3268,7 @@ const struct inode_operations ll_file_inode_operations = {
        .setattr        = ll_setattr,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ll_listxattr,
-       .removexattr    = generic_removexattr,
        .fiemap         = ll_fiemap,
        .get_acl        = ll_get_acl,
 };
index dfa36d3..ff3ce74 100644 (file)
@@ -1152,10 +1152,7 @@ const struct inode_operations ll_dir_inode_operations = {
        .setattr            = ll_setattr,
        .getattr            = ll_getattr,
        .permission      = ll_inode_permission,
-       .setxattr          = generic_setxattr,
-       .getxattr          = generic_getxattr,
        .listxattr        = ll_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl            = ll_get_acl,
 };
 
@@ -1163,9 +1160,6 @@ const struct inode_operations ll_special_inode_operations = {
        .setattr        = ll_setattr,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ll_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl            = ll_get_acl,
 };
index f8bc7ed..82c7c48 100644 (file)
@@ -154,8 +154,5 @@ const struct inode_operations ll_fast_symlink_inode_operations = {
        .get_link       = ll_get_link,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ll_listxattr,
-       .removexattr    = generic_removexattr,
 };
index 0e6ad30..afaa4b6 100644 (file)
@@ -967,9 +967,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
        .rename = v9fs_vfs_rename,
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = v9fs_listxattr,
        .get_acl = v9fs_iop_get_acl,
 };
@@ -977,9 +974,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
 const struct inode_operations v9fs_file_inode_operations_dotl = {
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = v9fs_listxattr,
        .get_acl = v9fs_iop_get_acl,
 };
@@ -989,8 +983,5 @@ const struct inode_operations v9fs_symlink_inode_operations_dotl = {
        .get_link = v9fs_vfs_get_link_dotl,
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = v9fs_listxattr,
 };
index 3ba385e..7bb153c 100644 (file)
@@ -100,29 +100,12 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
        return -EIO;
 }
 
-static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
-               const char *name, const void *value, size_t size, int flags)
-{
-       return -EIO;
-}
-
-static ssize_t bad_inode_getxattr(struct dentry *dentry, struct inode *inode,
-                       const char *name, void *buffer, size_t size)
-{
-       return -EIO;
-}
-
 static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
                        size_t buffer_size)
 {
        return -EIO;
 }
 
-static int bad_inode_removexattr(struct dentry *dentry, const char *name)
-{
-       return -EIO;
-}
-
 static const struct inode_operations bad_inode_ops =
 {
        .create         = bad_inode_create,
@@ -142,10 +125,7 @@ static const struct inode_operations bad_inode_ops =
        .permission     = bad_inode_permission,
        .getattr        = bad_inode_getattr,
        .setattr        = bad_inode_setattr,
-       .setxattr       = bad_inode_setxattr,
-       .getxattr       = bad_inode_getxattr,
        .listxattr      = bad_inode_listxattr,
-       .removexattr    = bad_inode_removexattr,
 };
 
 
@@ -175,6 +155,7 @@ void make_bad_inode(struct inode *inode)
        inode->i_atime = inode->i_mtime = inode->i_ctime =
                current_fs_time(inode->i_sb);
        inode->i_op = &bad_inode_ops;   
+       inode->i_opflags &= ~IOP_XATTR;
        inode->i_fop = &bad_file_ops;   
 }
 EXPORT_SYMBOL(make_bad_inode);
index a0d3016..994fe5a 100644 (file)
@@ -10556,10 +10556,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
        .symlink        = btrfs_symlink,
        .setattr        = btrfs_setattr,
        .mknod          = btrfs_mknod,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
@@ -10633,10 +10630,7 @@ static const struct address_space_operations btrfs_symlink_aops = {
 static const struct inode_operations btrfs_file_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .fiemap         = btrfs_fiemap,
        .get_acl        = btrfs_get_acl,
@@ -10647,10 +10641,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
@@ -10661,10 +10652,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .update_time    = btrfs_update_time,
 };
 
index 6af790f..3ff867f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mount.h>
 #include <linux/statfs.h>
 #include <linux/ctype.h>
+#include <linux/xattr.h>
 #include "internal.h"
 
 static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
@@ -126,8 +127,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
        if (d_is_negative(root) ||
            !d_backing_inode(root)->i_op->lookup ||
            !d_backing_inode(root)->i_op->mkdir ||
-           !d_backing_inode(root)->i_op->setxattr ||
-           !d_backing_inode(root)->i_op->getxattr ||
+           !(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
            !root->d_sb->s_op->statfs ||
            !root->d_sb->s_op->sync_fs)
                goto error_unsupported;
index c6ee4b5..339c910 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 #include "internal.h"
 
 #define CACHEFILES_KEYBUF_SIZE 512
@@ -799,8 +800,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
        }
 
        ret = -EPERM;
-       if (!d_backing_inode(subdir)->i_op->setxattr ||
-           !d_backing_inode(subdir)->i_op->getxattr ||
+       if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
            !d_backing_inode(subdir)->i_op->lookup ||
            !d_backing_inode(subdir)->i_op->mkdir ||
            !d_backing_inode(subdir)->i_op->create ||
index df4b3e6..e33bd09 100644 (file)
@@ -1486,10 +1486,7 @@ const struct inode_operations ceph_dir_iops = {
        .permission = ceph_permission,
        .getattr = ceph_getattr,
        .setattr = ceph_setattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = ceph_listxattr,
-       .removexattr = generic_removexattr,
        .get_acl = ceph_get_acl,
        .set_acl = ceph_set_acl,
        .mknod = ceph_mknod,
index 082e82d..da00b11 100644 (file)
@@ -94,10 +94,7 @@ const struct inode_operations ceph_file_iops = {
        .permission = ceph_permission,
        .setattr = ceph_setattr,
        .getattr = ceph_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = ceph_listxattr,
-       .removexattr = generic_removexattr,
        .get_acl = ceph_get_acl,
        .set_acl = ceph_set_acl,
 };
@@ -1885,10 +1882,7 @@ static const struct inode_operations ceph_symlink_iops = {
        .get_link = simple_get_link,
        .setattr = ceph_setattr,
        .getattr = ceph_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = ceph_listxattr,
-       .removexattr = generic_removexattr,
 };
 
 int __ceph_setattr(struct inode *inode, struct iattr *attr)
index 14ae4b8..34aac1c 100644 (file)
@@ -901,30 +901,21 @@ const struct inode_operations cifs_dir_inode_ops = {
        .setattr = cifs_setattr,
        .symlink = cifs_symlink,
        .mknod   = cifs_mknod,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = cifs_listxattr,
-       .removexattr = generic_removexattr,
 };
 
 const struct inode_operations cifs_file_inode_ops = {
        .setattr = cifs_setattr,
        .getattr = cifs_getattr,
        .permission = cifs_permission,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = cifs_listxattr,
-       .removexattr = generic_removexattr,
 };
 
 const struct inode_operations cifs_symlink_inode_ops = {
        .readlink = generic_readlink,
        .get_link = cifs_get_link,
        .permission = cifs_permission,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = cifs_listxattr,
-       .removexattr = generic_removexattr,
 };
 
 static int cifs_clone_file_range(struct file *src_file, loff_t off,
index 4ba1547..599a292 100644 (file)
@@ -715,4 +715,6 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
 int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
                       loff_t offset);
 
+extern const struct xattr_handler *ecryptfs_xattr_handlers[];
+
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
index 5ffba18..ddccec3 100644 (file)
@@ -1005,15 +1005,14 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
                  const char *name, const void *value,
                  size_t size, int flags)
 {
-       int rc = 0;
+       int rc;
        struct dentry *lower_dentry;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!d_inode(lower_dentry)->i_op->setxattr) {
+       if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
-
        rc = vfs_setxattr(lower_dentry, name, value, size, flags);
        if (!rc && inode)
                fsstack_copy_attr_all(inode, d_inode(lower_dentry));
@@ -1025,15 +1024,14 @@ ssize_t
 ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
                        const char *name, void *value, size_t size)
 {
-       int rc = 0;
+       int rc;
 
-       if (!lower_inode->i_op->getxattr) {
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
        inode_lock(lower_inode);
-       rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
-                                        name, value, size);
+       rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
        inode_unlock(lower_inode);
 out:
        return rc;
@@ -1066,19 +1064,22 @@ out:
        return rc;
 }
 
-static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
+static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
+                               const char *name)
 {
-       int rc = 0;
+       int rc;
        struct dentry *lower_dentry;
+       struct inode *lower_inode;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!d_inode(lower_dentry)->i_op->removexattr) {
+       lower_inode = ecryptfs_inode_to_lower(inode);
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
-       inode_lock(d_inode(lower_dentry));
-       rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name);
-       inode_unlock(d_inode(lower_dentry));
+       inode_lock(lower_inode);
+       rc = __vfs_removexattr(lower_dentry, name);
+       inode_unlock(lower_inode);
 out:
        return rc;
 }
@@ -1089,10 +1090,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
        .getattr = ecryptfs_getattr_link,
-       .setxattr = ecryptfs_setxattr,
-       .getxattr = ecryptfs_getxattr,
        .listxattr = ecryptfs_listxattr,
-       .removexattr = ecryptfs_removexattr
 };
 
 const struct inode_operations ecryptfs_dir_iops = {
@@ -1107,18 +1105,43 @@ const struct inode_operations ecryptfs_dir_iops = {
        .rename = ecryptfs_rename,
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
-       .setxattr = ecryptfs_setxattr,
-       .getxattr = ecryptfs_getxattr,
        .listxattr = ecryptfs_listxattr,
-       .removexattr = ecryptfs_removexattr
 };
 
 const struct inode_operations ecryptfs_main_iops = {
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
        .getattr = ecryptfs_getattr,
-       .setxattr = ecryptfs_setxattr,
-       .getxattr = ecryptfs_getxattr,
        .listxattr = ecryptfs_listxattr,
-       .removexattr = ecryptfs_removexattr
+};
+
+static int ecryptfs_xattr_get(const struct xattr_handler *handler,
+                             struct dentry *dentry, struct inode *inode,
+                             const char *name, void *buffer, size_t size)
+{
+       return ecryptfs_getxattr(dentry, inode, name, buffer, size);
+}
+
+static int ecryptfs_xattr_set(const struct xattr_handler *handler,
+                             struct dentry *dentry, struct inode *inode,
+                             const char *name, const void *value, size_t size,
+                             int flags)
+{
+       if (value)
+               return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
+       else {
+               BUG_ON(flags != XATTR_REPLACE);
+               return ecryptfs_removexattr(dentry, inode, name);
+       }
+}
+
+const struct xattr_handler ecryptfs_xattr_handler = {
+       .prefix = "",  /* match anything */
+       .get = ecryptfs_xattr_get,
+       .set = ecryptfs_xattr_set,
+};
+
+const struct xattr_handler *ecryptfs_xattr_handlers[] = {
+       &ecryptfs_xattr_handler,
+       NULL
 };
index 6120044..151872d 100644 (file)
@@ -529,6 +529,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
        /* ->kill_sb() will take care of sbi after that point */
        sbi = NULL;
        s->s_op = &ecryptfs_sops;
+       s->s_xattr = ecryptfs_xattr_handlers;
        s->s_d_op = &ecryptfs_dops;
 
        err = "Reading sb failed";
index 9c3437c..1f0c471 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/file.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 #include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
@@ -422,7 +423,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
        struct inode *lower_inode = d_inode(lower_dentry);
        int rc;
 
-       if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                printk(KERN_WARNING
                       "No support for setting xattr in lower filesystem\n");
                rc = -ENOSYS;
@@ -436,15 +437,13 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
                goto out;
        }
        inode_lock(lower_inode);
-       size = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
-                                          ECRYPTFS_XATTR_NAME,
-                                          xattr_virt, PAGE_SIZE);
+       size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+                             xattr_virt, PAGE_SIZE);
        if (size < 0)
                size = 8;
        put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
-       rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
-                                        ECRYPTFS_XATTR_NAME,
-                                        xattr_virt, size, 0);
+       rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+                           xattr_virt, size, 0);
        inode_unlock(lower_inode);
        if (rc)
                printk(KERN_ERR "Error whilst attempting to write inode size "
index 0ca363d..a0e1478 100644 (file)
@@ -241,10 +241,7 @@ const struct file_operations ext2_file_operations = {
 
 const struct inode_operations ext2_file_inode_operations = {
 #ifdef CONFIG_EXT2_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext2_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
        .setattr        = ext2_setattr,
        .get_acl        = ext2_get_acl,
index d446203..ff32ea7 100644 (file)
@@ -428,10 +428,7 @@ const struct inode_operations ext2_dir_inode_operations = {
        .mknod          = ext2_mknod,
        .rename         = ext2_rename,
 #ifdef CONFIG_EXT2_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext2_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
        .setattr        = ext2_setattr,
        .get_acl        = ext2_get_acl,
@@ -441,10 +438,7 @@ const struct inode_operations ext2_dir_inode_operations = {
 
 const struct inode_operations ext2_special_inode_operations = {
 #ifdef CONFIG_EXT2_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext2_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
        .setattr        = ext2_setattr,
        .get_acl        = ext2_get_acl,
index 3495d8a..8437b19 100644 (file)
@@ -25,10 +25,7 @@ const struct inode_operations ext2_symlink_inode_operations = {
        .get_link       = page_get_link,
        .setattr        = ext2_setattr,
 #ifdef CONFIG_EXT2_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext2_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
  
@@ -37,9 +34,6 @@ const struct inode_operations ext2_fast_symlink_inode_operations = {
        .get_link       = simple_get_link,
        .setattr        = ext2_setattr,
 #ifdef CONFIG_EXT2_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext2_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
index 36d49cf..2a822d3 100644 (file)
@@ -706,10 +706,7 @@ const struct file_operations ext4_file_operations = {
 const struct inode_operations ext4_file_inode_operations = {
        .setattr        = ext4_setattr,
        .getattr        = ext4_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
        .set_acl        = ext4_set_acl,
        .fiemap         = ext4_fiemap,
index c344b81..a73a919 100644 (file)
@@ -3880,10 +3880,7 @@ const struct inode_operations ext4_dir_inode_operations = {
        .tmpfile        = ext4_tmpfile,
        .rename2        = ext4_rename2,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
        .set_acl        = ext4_set_acl,
        .fiemap         = ext4_fiemap,
@@ -3891,10 +3888,7 @@ const struct inode_operations ext4_dir_inode_operations = {
 
 const struct inode_operations ext4_special_inode_operations = {
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
        .set_acl        = ext4_set_acl,
 };
index fdf1c61..557b3b0 100644 (file)
@@ -86,28 +86,19 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = ext4_encrypted_get_link,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
 };
 
 const struct inode_operations ext4_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
 };
 
 const struct inode_operations ext4_fast_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = simple_get_link,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
 };
index 9045597..acdf4b9 100644 (file)
@@ -732,10 +732,7 @@ const struct inode_operations f2fs_file_inode_operations = {
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
 #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
        .fiemap         = f2fs_fiemap,
 };
index 5625b87..e80ed03 100644 (file)
@@ -1080,10 +1080,7 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
 #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
 
@@ -1103,10 +1100,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
 #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
 
@@ -1116,10 +1110,7 @@ const struct inode_operations f2fs_symlink_inode_operations = {
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
 #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
 
@@ -1129,9 +1120,6 @@ const struct inode_operations f2fs_special_inode_operations = {
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
 #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
index a430c19..572d124 100644 (file)
@@ -1801,10 +1801,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
        .mknod          = fuse_mknod,
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = fuse_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = fuse_get_acl,
        .set_acl        = fuse_set_acl,
 };
@@ -1824,10 +1821,7 @@ static const struct inode_operations fuse_common_inode_operations = {
        .setattr        = fuse_setattr,
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = fuse_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = fuse_get_acl,
        .set_acl        = fuse_set_acl,
 };
@@ -1837,10 +1831,7 @@ static const struct inode_operations fuse_symlink_inode_operations = {
        .get_link       = fuse_get_link,
        .readlink       = generic_readlink,
        .getattr        = fuse_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = fuse_listxattr,
-       .removexattr    = generic_removexattr,
 };
 
 void fuse_init_common(struct inode *inode)
index 7efd1d1..f6c4f00 100644 (file)
@@ -2040,10 +2040,7 @@ const struct inode_operations gfs2_file_iops = {
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = gfs2_listxattr,
-       .removexattr = generic_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
@@ -2062,10 +2059,7 @@ const struct inode_operations gfs2_dir_iops = {
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = gfs2_listxattr,
-       .removexattr = generic_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
@@ -2078,10 +2072,7 @@ const struct inode_operations gfs2_symlink_iops = {
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = gfs2_listxattr,
-       .removexattr = generic_removexattr,
        .fiemap = gfs2_fiemap,
 };
 
index d9a8691..0933600 100644 (file)
 #include "hfs_fs.h"
 #include "btree.h"
 
-int hfs_setxattr(struct dentry *unused, struct inode *inode,
-                const char *name, const void *value,
-                size_t size, int flags)
+enum hfs_xattr_type {
+       HFS_TYPE,
+       HFS_CREATOR,
+};
+
+static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
+                         const void *value, size_t size, int flags)
 {
        struct hfs_find_data fd;
        hfs_cat_rec rec;
@@ -36,18 +40,22 @@ int hfs_setxattr(struct dentry *unused, struct inode *inode,
                        sizeof(struct hfs_cat_file));
        file = &rec.file;
 
-       if (!strcmp(name, "hfs.type")) {
+       switch (type) {
+       case HFS_TYPE:
                if (size == 4)
                        memcpy(&file->UsrWds.fdType, value, 4);
                else
                        res = -ERANGE;
-       } else if (!strcmp(name, "hfs.creator")) {
+               break;
+
+       case HFS_CREATOR:
                if (size == 4)
                        memcpy(&file->UsrWds.fdCreator, value, 4);
                else
                        res = -ERANGE;
-       } else
-               res = -EOPNOTSUPP;
+               break;
+       }
+
        if (!res)
                hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
                                sizeof(struct hfs_cat_file));
@@ -56,8 +64,8 @@ out:
        return res;
 }
 
-ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
-                    const char *name, void *value, size_t size)
+static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
+                             void *value, size_t size)
 {
        struct hfs_find_data fd;
        hfs_cat_rec rec;
@@ -80,41 +88,64 @@ ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
        }
        file = &rec.file;
 
-       if (!strcmp(name, "hfs.type")) {
+       switch (type) {
+       case HFS_TYPE:
                if (size >= 4) {
                        memcpy(value, &file->UsrWds.fdType, 4);
                        res = 4;
                } else
                        res = size ? -ERANGE : 4;
-       } else if (!strcmp(name, "hfs.creator")) {
+               break;
+
+       case HFS_CREATOR:
                if (size >= 4) {
                        memcpy(value, &file->UsrWds.fdCreator, 4);
                        res = 4;
                } else
                        res = size ? -ERANGE : 4;
-       } else
-               res = -ENODATA;
+               break;
+       }
+
 out:
        if (size)
                hfs_find_exit(&fd);
        return res;
 }
 
-#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
-
-ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+static int hfs_xattr_get(const struct xattr_handler *handler,
+                        struct dentry *unused, struct inode *inode,
+                        const char *name, void *value, size_t size)
 {
-       struct inode *inode = d_inode(dentry);
+       return __hfs_getxattr(inode, handler->flags, value, size);
+}
 
-       if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
+static int hfs_xattr_set(const struct xattr_handler *handler,
+                        struct dentry *unused, struct inode *inode,
+                        const char *name, const void *value, size_t size,
+                        int flags)
+{
+       if (!value)
                return -EOPNOTSUPP;
 
-       if (!buffer || !size)
-               return HFS_ATTRLIST_SIZE;
-       if (size < HFS_ATTRLIST_SIZE)
-               return -ERANGE;
-       strcpy(buffer, "hfs.type");
-       strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
-
-       return HFS_ATTRLIST_SIZE;
+       return __hfs_setxattr(inode, handler->flags, value, size, flags);
 }
+
+static const struct xattr_handler hfs_creator_handler = {
+       .name = "hfs.creator",
+       .flags = HFS_CREATOR,
+       .get = hfs_xattr_get,
+       .set = hfs_xattr_set,
+};
+
+static const struct xattr_handler hfs_type_handler = {
+       .name = "hfs.type",
+       .flags = HFS_TYPE,
+       .get = hfs_xattr_get,
+       .set = hfs_xattr_set,
+};
+
+const struct xattr_handler *hfs_xattr_handlers[] = {
+       &hfs_creator_handler,
+       &hfs_type_handler,
+       NULL
+};
index 16f5172..4cdec5a 100644 (file)
@@ -212,11 +212,7 @@ extern void hfs_evict_inode(struct inode *);
 extern void hfs_delete_inode(struct inode *);
 
 /* attr.c */
-extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
-                       const void *value, size_t size, int flags);
-extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode,
-                           const char *name, void *value, size_t size);
-extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+extern const struct xattr_handler *hfs_xattr_handlers[];
 
 /* mdb.c */
 extern int hfs_mdb_get(struct super_block *);
index 09cce23..ed37326 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mpage.h>
 #include <linux/sched.h>
 #include <linux/uio.h>
+#include <linux/xattr.h>
 
 #include "hfs_fs.h"
 #include "btree.h"
@@ -687,7 +688,5 @@ static const struct file_operations hfs_file_operations = {
 static const struct inode_operations hfs_file_inode_operations = {
        .lookup         = hfs_file_lookup,
        .setattr        = hfs_inode_setattr,
-       .setxattr       = hfs_setxattr,
-       .getxattr       = hfs_getxattr,
-       .listxattr      = hfs_listxattr,
+       .listxattr      = generic_listxattr,
 };
index 1ca95c2..bf6304a 100644 (file)
@@ -406,6 +406,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        sb->s_op = &hfs_super_operations;
+       sb->s_xattr = hfs_xattr_handlers;
        sb->s_flags |= MS_NODIRATIME;
        mutex_init(&sbi->bitmap_lock);
 
index 42e1286..9cbe430 100644 (file)
@@ -562,10 +562,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
        .symlink                = hfsplus_symlink,
        .mknod                  = hfsplus_mknod,
        .rename                 = hfsplus_rename,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
        .listxattr              = hfsplus_listxattr,
-       .removexattr            = generic_removexattr,
 #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
        .get_acl                = hfsplus_get_posix_acl,
        .set_acl                = hfsplus_set_posix_acl,
index c43ef39..10827c9 100644 (file)
@@ -333,10 +333,7 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
 
 static const struct inode_operations hfsplus_file_inode_operations = {
        .setattr        = hfsplus_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = hfsplus_listxattr,
-       .removexattr    = generic_removexattr,
 #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
        .get_acl        = hfsplus_get_posix_acl,
        .set_acl        = hfsplus_set_posix_acl,
index a3c7ba7..7d03759 100644 (file)
@@ -140,6 +140,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        inode->i_fop = &no_open_fops;
        inode->__i_nlink = 1;
        inode->i_opflags = 0;
+       if (sb->s_xattr)
+               inode->i_opflags |= IOP_XATTR;
        i_uid_write(inode, 0);
        i_gid_write(inode, 0);
        atomic_set(&inode->i_writecount, 0);
index 30eb33f..9b24243 100644 (file)
@@ -61,10 +61,7 @@ const struct inode_operations jffs2_dir_inode_operations =
        .get_acl =      jffs2_get_acl,
        .set_acl =      jffs2_set_acl,
        .setattr =      jffs2_setattr,
-       .setxattr =     jffs2_setxattr,
-       .getxattr =     jffs2_getxattr,
        .listxattr =    jffs2_listxattr,
-       .removexattr =  jffs2_removexattr
 };
 
 /***********************************************************************/
index 0e62dec..c12476e 100644 (file)
@@ -66,10 +66,7 @@ const struct inode_operations jffs2_file_inode_operations =
        .get_acl =      jffs2_get_acl,
        .set_acl =      jffs2_set_acl,
        .setattr =      jffs2_setattr,
-       .setxattr =     jffs2_setxattr,
-       .getxattr =     jffs2_getxattr,
        .listxattr =    jffs2_listxattr,
-       .removexattr =  jffs2_removexattr
 };
 
 const struct address_space_operations jffs2_file_address_operations =
index 2cabd64..8f3f085 100644 (file)
@@ -16,8 +16,5 @@ const struct inode_operations jffs2_symlink_inode_operations =
        .readlink =     generic_readlink,
        .get_link =     simple_get_link,
        .setattr =      jffs2_setattr,
-       .setxattr =     jffs2_setxattr,
-       .getxattr =     jffs2_getxattr,
        .listxattr =    jffs2_listxattr,
-       .removexattr =  jffs2_removexattr
 };
index 467ff37..720007b 100644 (file)
@@ -99,9 +99,6 @@ extern const struct xattr_handler jffs2_user_xattr_handler;
 extern const struct xattr_handler jffs2_trusted_xattr_handler;
 
 extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
-#define jffs2_getxattr         generic_getxattr
-#define jffs2_setxattr         generic_setxattr
-#define jffs2_removexattr      generic_removexattr
 
 #else
 
@@ -116,9 +113,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
 
 #define jffs2_xattr_handlers   NULL
 #define jffs2_listxattr                NULL
-#define jffs2_getxattr         NULL
-#define jffs2_setxattr         NULL
-#define jffs2_removexattr      NULL
 
 #endif /* CONFIG_JFFS2_FS_XATTR */
 
index cf62037..739492c 100644 (file)
@@ -140,10 +140,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
 }
 
 const struct inode_operations jfs_file_inode_operations = {
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = jfs_listxattr,
-       .removexattr    = generic_removexattr,
        .setattr        = jfs_setattr,
 #ifdef CONFIG_JFS_POSIX_ACL
        .get_acl        = jfs_get_acl,
index 814b0c5..e420c60 100644 (file)
@@ -1537,10 +1537,7 @@ const struct inode_operations jfs_dir_inode_operations = {
        .rmdir          = jfs_rmdir,
        .mknod          = jfs_mknod,
        .rename         = jfs_rename,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = jfs_listxattr,
-       .removexattr    = generic_removexattr,
        .setattr        = jfs_setattr,
 #ifdef CONFIG_JFS_POSIX_ACL
        .get_acl        = jfs_get_acl,
index c94c7e4..c82404f 100644 (file)
@@ -25,19 +25,13 @@ const struct inode_operations jfs_fast_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = simple_get_link,
        .setattr        = jfs_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = jfs_listxattr,
-       .removexattr    = generic_removexattr,
 };
 
 const struct inode_operations jfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = jfs_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = jfs_listxattr,
-       .removexattr    = generic_removexattr,
 };
 
index e57174d..2b23ad9 100644 (file)
@@ -1126,9 +1126,6 @@ const struct inode_operations kernfs_dir_iops = {
        .permission     = kernfs_iop_permission,
        .setattr        = kernfs_iop_setattr,
        .getattr        = kernfs_iop_getattr,
-       .setxattr       = kernfs_iop_setxattr,
-       .removexattr    = kernfs_iop_removexattr,
-       .getxattr       = kernfs_iop_getxattr,
        .listxattr      = kernfs_iop_listxattr,
 
        .mkdir          = kernfs_iop_mkdir,
index df21f5b..102b6f0 100644 (file)
@@ -28,9 +28,6 @@ static const struct inode_operations kernfs_iops = {
        .permission     = kernfs_iop_permission,
        .setattr        = kernfs_iop_setattr,
        .getattr        = kernfs_iop_getattr,
-       .setxattr       = kernfs_iop_setxattr,
-       .removexattr    = kernfs_iop_removexattr,
-       .getxattr       = kernfs_iop_getxattr,
        .listxattr      = kernfs_iop_listxattr,
 };
 
@@ -138,17 +135,12 @@ out:
        return error;
 }
 
-static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
+static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
                                  u32 *secdata_len)
 {
-       struct kernfs_iattrs *attrs;
        void *old_secdata;
        size_t old_secdata_len;
 
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
-
        old_secdata = attrs->ia_secdata;
        old_secdata_len = attrs->ia_secdata_len;
 
@@ -160,71 +152,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
        return 0;
 }
 
-int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
-                       const char *name, const void *value,
-                       size_t size, int flags)
-{
-       struct kernfs_node *kn = inode->i_private;
-       struct kernfs_iattrs *attrs;
-       void *secdata;
-       int error;
-       u32 secdata_len = 0;
-
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
-
-       if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
-               const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
-               error = security_inode_setsecurity(inode, suffix,
-                                               value, size, flags);
-               if (error)
-                       return error;
-               error = security_inode_getsecctx(inode,
-                                               &secdata, &secdata_len);
-               if (error)
-                       return error;
-
-               mutex_lock(&kernfs_mutex);
-               error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
-               mutex_unlock(&kernfs_mutex);
-
-               if (secdata)
-                       security_release_secctx(secdata, secdata_len);
-               return error;
-       } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
-               return simple_xattr_set(&attrs->xattrs, name, value, size,
-                                       flags);
-       }
-
-       return -EINVAL;
-}
-
-int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
-{
-       struct kernfs_node *kn = dentry->d_fsdata;
-       struct kernfs_iattrs *attrs;
-
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
-
-       return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
-}
-
-ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
-                           const char *name, void *buf, size_t size)
-{
-       struct kernfs_node *kn = inode->i_private;
-       struct kernfs_iattrs *attrs;
-
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
-
-       return simple_xattr_get(&attrs->xattrs, name, buf, size);
-}
-
 ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
 {
        struct kernfs_node *kn = dentry->d_fsdata;
@@ -376,3 +303,83 @@ int kernfs_iop_permission(struct inode *inode, int mask)
 
        return generic_permission(inode, mask);
 }
+
+static int kernfs_xattr_get(const struct xattr_handler *handler,
+                           struct dentry *unused, struct inode *inode,
+                           const char *suffix, void *value, size_t size)
+{
+       const char *name = xattr_full_name(handler, suffix);
+       struct kernfs_node *kn = inode->i_private;
+       struct kernfs_iattrs *attrs;
+
+       attrs = kernfs_iattrs(kn);
+       if (!attrs)
+               return -ENOMEM;
+
+       return simple_xattr_get(&attrs->xattrs, name, value, size);
+}
+
+static int kernfs_xattr_set(const struct xattr_handler *handler,
+                           struct dentry *unused, struct inode *inode,
+                           const char *suffix, const void *value,
+                           size_t size, int flags)
+{
+       const char *name = xattr_full_name(handler, suffix);
+       struct kernfs_node *kn = inode->i_private;
+       struct kernfs_iattrs *attrs;
+
+       attrs = kernfs_iattrs(kn);
+       if (!attrs)
+               return -ENOMEM;
+
+       return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
+}
+
+const struct xattr_handler kernfs_trusted_xattr_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .get = kernfs_xattr_get,
+       .set = kernfs_xattr_set,
+};
+
+static int kernfs_security_xattr_set(const struct xattr_handler *handler,
+                                    struct dentry *unused, struct inode *inode,
+                                    const char *suffix, const void *value,
+                                    size_t size, int flags)
+{
+       struct kernfs_node *kn = inode->i_private;
+       struct kernfs_iattrs *attrs;
+       void *secdata;
+       u32 secdata_len = 0;
+       int error;
+
+       attrs = kernfs_iattrs(kn);
+       if (!attrs)
+               return -ENOMEM;
+
+       error = security_inode_setsecurity(inode, suffix, value, size, flags);
+       if (error)
+               return error;
+       error = security_inode_getsecctx(inode, &secdata, &secdata_len);
+       if (error)
+               return error;
+
+       mutex_lock(&kernfs_mutex);
+       error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
+       mutex_unlock(&kernfs_mutex);
+
+       if (secdata)
+               security_release_secctx(secdata, secdata_len);
+       return error;
+}
+
+const struct xattr_handler kernfs_security_xattr_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .get = kernfs_xattr_get,
+       .set = kernfs_security_xattr_set,
+};
+
+const struct xattr_handler *kernfs_xattr_handlers[] = {
+       &kernfs_trusted_xattr_handler,
+       &kernfs_security_xattr_handler,
+       NULL
+};
index 3715923..bfd551b 100644 (file)
@@ -76,17 +76,12 @@ extern struct kmem_cache *kernfs_node_cache;
 /*
  * inode.c
  */
+extern const struct xattr_handler *kernfs_xattr_handlers[];
 void kernfs_evict_inode(struct inode *inode);
 int kernfs_iop_permission(struct inode *inode, int mask);
 int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
 int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
                       struct kstat *stat);
-int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode,
-                       const char *name, const void *value,
-                       size_t size, int flags);
-int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
-ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode,
-                           const char *name, void *buf, size_t size);
 ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
 
 /*
index b3d73ad..d5b149a 100644 (file)
@@ -158,6 +158,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
        sb->s_blocksize_bits = PAGE_SHIFT;
        sb->s_magic = magic;
        sb->s_op = &kernfs_sops;
+       sb->s_xattr = kernfs_xattr_handlers;
        sb->s_time_gran = 1;
 
        /* get root inode, initialize and unlock it */
index 117b8b3..9b43ca0 100644 (file)
@@ -134,9 +134,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
 }
 
 const struct inode_operations kernfs_symlink_iops = {
-       .setxattr       = kernfs_iop_setxattr,
-       .removexattr    = kernfs_iop_removexattr,
-       .getxattr       = kernfs_iop_getxattr,
        .listxattr      = kernfs_iop_listxattr,
        .readlink       = generic_readlink,
        .get_link       = kernfs_iop_get_link,
index 2b3c3ae..a6d89f1 100644 (file)
@@ -236,8 +236,8 @@ static const struct super_operations simple_super_operations = {
  * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
  * will never be mountable)
  */
-struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
-       const struct super_operations *ops,
+struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
+       const struct super_operations *ops, const struct xattr_handler **xattr,
        const struct dentry_operations *dops, unsigned long magic)
 {
        struct super_block *s;
@@ -254,6 +254,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
        s->s_blocksize_bits = PAGE_SHIFT;
        s->s_magic = magic;
        s->s_op = ops ? ops : &simple_super_operations;
+       s->s_xattr = xattr;
        s->s_time_gran = 1;
        root = new_inode(s);
        if (!root)
@@ -281,7 +282,7 @@ Enomem:
        deactivate_locked_super(s);
        return ERR_PTR(-ENOMEM);
 }
-EXPORT_SYMBOL(mount_pseudo);
+EXPORT_SYMBOL(mount_pseudo_xattr);
 
 int simple_open(struct inode *inode, struct file *file)
 {
@@ -1149,24 +1150,6 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
        return -EPERM;
 }
 
-static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
-                             const char *name, const void *value,
-                             size_t size, int flags)
-{
-       return -EOPNOTSUPP;
-}
-
-static ssize_t empty_dir_getxattr(struct dentry *dentry, struct inode *inode,
-                                 const char *name, void *value, size_t size)
-{
-       return -EOPNOTSUPP;
-}
-
-static int empty_dir_removexattr(struct dentry *dentry, const char *name)
-{
-       return -EOPNOTSUPP;
-}
-
 static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
 {
        return -EOPNOTSUPP;
@@ -1177,9 +1160,6 @@ static const struct inode_operations empty_dir_inode_operations = {
        .permission     = generic_permission,
        .setattr        = empty_dir_setattr,
        .getattr        = empty_dir_getattr,
-       .setxattr       = empty_dir_setxattr,
-       .getxattr       = empty_dir_getxattr,
-       .removexattr    = empty_dir_removexattr,
        .listxattr      = empty_dir_listxattr,
 };
 
@@ -1215,6 +1195,7 @@ void make_empty_dir_inode(struct inode *inode)
        inode->i_blocks = 0;
 
        inode->i_op = &empty_dir_inode_operations;
+       inode->i_opflags &= ~IOP_XATTR;
        inode->i_fop = &empty_dir_operations;
 }
 
index 698be93..dc925b5 100644 (file)
@@ -899,9 +899,6 @@ static const struct inode_operations nfs3_dir_inode_operations = {
        .setattr        = nfs_setattr,
 #ifdef CONFIG_NFS_V3_ACL
        .listxattr      = nfs3_listxattr,
-       .getxattr       = generic_getxattr,
-       .setxattr       = generic_setxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = nfs3_get_acl,
        .set_acl        = nfs3_set_acl,
 #endif
@@ -913,9 +910,6 @@ static const struct inode_operations nfs3_file_inode_operations = {
        .setattr        = nfs_setattr,
 #ifdef CONFIG_NFS_V3_ACL
        .listxattr      = nfs3_listxattr,
-       .getxattr       = generic_getxattr,
-       .setxattr       = generic_setxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = nfs3_get_acl,
        .set_acl        = nfs3_set_acl,
 #endif
index a9dec32..0e32752 100644 (file)
@@ -8941,20 +8941,14 @@ static const struct inode_operations nfs4_dir_inode_operations = {
        .permission     = nfs_permission,
        .getattr        = nfs_getattr,
        .setattr        = nfs_setattr,
-       .getxattr       = generic_getxattr,
-       .setxattr       = generic_setxattr,
        .listxattr      = nfs4_listxattr,
-       .removexattr    = generic_removexattr,
 };
 
 static const struct inode_operations nfs4_file_inode_operations = {
        .permission     = nfs_permission,
        .getattr        = nfs_getattr,
        .setattr        = nfs_setattr,
-       .getxattr       = generic_getxattr,
-       .setxattr       = generic_setxattr,
        .listxattr      = nfs4_listxattr,
-       .removexattr    = generic_removexattr,
 };
 
 const struct nfs_rpc_ops nfs_v4_clientops = {
index 5e19015..ba5c177 100644 (file)
@@ -2444,10 +2444,7 @@ const struct inode_operations ocfs2_file_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ocfs2_listxattr,
-       .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
        .get_acl        = ocfs2_iop_get_acl,
        .set_acl        = ocfs2_iop_set_acl,
index a8f1225..6cc043e 100644 (file)
@@ -2913,10 +2913,7 @@ const struct inode_operations ocfs2_dir_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ocfs2_listxattr,
-       .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
        .get_acl        = ocfs2_iop_get_acl,
        .set_acl        = ocfs2_iop_set_acl,
index 6c2a3e3..6ad8eec 100644 (file)
@@ -91,9 +91,6 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
        .get_link       = page_get_link,
        .getattr        = ocfs2_getattr,
        .setattr        = ocfs2_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ocfs2_listxattr,
-       .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
 };
index c83846f..0e3bd7e 100644 (file)
@@ -296,10 +296,7 @@ const struct inode_operations orangefs_file_inode_operations = {
        .set_acl = orangefs_set_acl,
        .setattr = orangefs_setattr,
        .getattr = orangefs_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = orangefs_listxattr,
-       .removexattr = generic_removexattr,
        .permission = orangefs_permission,
 };
 
index 0e34fcf..4d5576a 100644 (file)
@@ -462,9 +462,6 @@ const struct inode_operations orangefs_dir_inode_operations = {
        .rename = orangefs_rename,
        .setattr = orangefs_setattr,
        .getattr = orangefs_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = orangefs_listxattr,
        .permission = orangefs_permission,
 };
index 8fecf82..10b0b06 100644 (file)
@@ -14,6 +14,5 @@ const struct inode_operations orangefs_symlink_inode_operations = {
        .setattr = orangefs_setattr,
        .getattr = orangefs_getattr,
        .listxattr = orangefs_listxattr,
-       .setxattr = generic_setxattr,
        .permission = orangefs_permission,
 };
index 2a9f07f..74a81b1 100644 (file)
@@ -73,6 +73,9 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
                     "%s: name %s, buffer_size %zd\n",
                     __func__, name, size);
 
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+
        if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
                gossip_err("Invalid key length (%d)\n",
                           (int)strlen(name));
index db37a0e..3f803b3 100644 (file)
@@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
        char *buf, *name, *value = NULL;
        int uninitialized_var(error);
 
-       if (!old->d_inode->i_op->getxattr ||
-           !new->d_inode->i_op->getxattr)
+       if (!(old->d_inode->i_opflags & IOP_XATTR) ||
+           !(new->d_inode->i_opflags & IOP_XATTR))
                return 0;
 
        list_size = vfs_listxattr(old, NULL, 0);
index b0ffa1d..3a60e68 100644 (file)
@@ -1013,10 +1013,7 @@ const struct inode_operations ovl_dir_inode_operations = {
        .mknod          = ovl_mknod,
        .permission     = ovl_permission,
        .getattr        = ovl_dir_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
 };
index 251e525..c18d6a4 100644 (file)
@@ -367,10 +367,7 @@ static const struct inode_operations ovl_file_inode_operations = {
        .setattr        = ovl_setattr,
        .permission     = ovl_permission,
        .getattr        = ovl_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
 };
@@ -380,10 +377,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
        .get_link       = ovl_get_link,
        .readlink       = ovl_readlink,
        .getattr        = ovl_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
-       .removexattr    = generic_removexattr,
        .update_time    = ovl_update_time,
 };
 
index 3d0b9de..7e3f012 100644 (file)
@@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
        char val;
        struct inode *inode = dentry->d_inode;
 
-       if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
+       if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
                return false;
 
-       res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
+       res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
        if (res == 1 && val == 'y')
                return true;
 
index 90f815b..2f8c5c9 100644 (file)
@@ -260,10 +260,7 @@ const struct file_operations reiserfs_file_operations = {
 
 const struct inode_operations reiserfs_file_inode_operations = {
        .setattr = reiserfs_setattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = reiserfs_listxattr,
-       .removexattr = generic_removexattr,
        .permission = reiserfs_permission,
        .get_acl = reiserfs_get_acl,
        .set_acl = reiserfs_set_acl,
index 8a36696..fd7d060 100644 (file)
@@ -1650,10 +1650,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
        .mknod = reiserfs_mknod,
        .rename = reiserfs_rename,
        .setattr = reiserfs_setattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = reiserfs_listxattr,
-       .removexattr = generic_removexattr,
        .permission = reiserfs_permission,
        .get_acl = reiserfs_get_acl,
        .set_acl = reiserfs_set_acl,
@@ -1667,10 +1664,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
        .readlink = generic_readlink,
        .get_link       = page_get_link,
        .setattr = reiserfs_setattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = reiserfs_listxattr,
-       .removexattr = generic_removexattr,
        .permission = reiserfs_permission,
 };
 
@@ -1679,10 +1673,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
  */
 const struct inode_operations reiserfs_special_inode_operations = {
        .setattr = reiserfs_setattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = reiserfs_listxattr,
-       .removexattr = generic_removexattr,
        .permission = reiserfs_permission,
        .get_acl = reiserfs_get_acl,
        .set_acl = reiserfs_set_acl,
index 0927b1e..e9793b1 100644 (file)
@@ -425,7 +425,6 @@ failed_read:
 
 
 const struct inode_operations squashfs_inode_ops = {
-       .getxattr = generic_getxattr,
        .listxattr = squashfs_listxattr
 };
 
index 67cad77..40c10d9 100644 (file)
@@ -247,6 +247,5 @@ failed:
 
 const struct inode_operations squashfs_dir_inode_ops = {
        .lookup = squashfs_lookup,
-       .getxattr = generic_getxattr,
        .listxattr = squashfs_listxattr
 };
index d688ef4..79b9c31 100644 (file)
@@ -120,7 +120,6 @@ const struct address_space_operations squashfs_symlink_aops = {
 const struct inode_operations squashfs_symlink_inode_ops = {
        .readlink = generic_readlink,
        .get_link = page_get_link,
-       .getxattr = generic_getxattr,
        .listxattr = squashfs_listxattr
 };
 
index c83f5d9..afe70f8 100644 (file)
@@ -42,6 +42,5 @@ static inline int squashfs_xattr_lookup(struct super_block *sb,
        return 0;
 }
 #define squashfs_listxattr NULL
-#define generic_getxattr NULL
 #define squashfs_xattr_handlers NULL
 #endif
index 4b86d3a..1d55aea 100644 (file)
@@ -1182,10 +1182,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
        .rename      = ubifs_rename,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
-       .setxattr    = generic_setxattr,
-       .getxattr    = generic_getxattr,
        .listxattr   = ubifs_listxattr,
-       .removexattr = generic_removexattr,
 #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
 #endif
index b0a6a53..a746982 100644 (file)
@@ -1621,10 +1621,7 @@ const struct address_space_operations ubifs_file_address_operations = {
 const struct inode_operations ubifs_file_inode_operations = {
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
-       .setxattr    = generic_setxattr,
-       .getxattr    = generic_getxattr,
        .listxattr   = ubifs_listxattr,
-       .removexattr = generic_removexattr,
 #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
 #endif
@@ -1635,10 +1632,7 @@ const struct inode_operations ubifs_symlink_inode_operations = {
        .get_link    = simple_get_link,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
-       .setxattr    = generic_setxattr,
-       .getxattr    = generic_getxattr,
        .listxattr   = ubifs_listxattr,
-       .removexattr = generic_removexattr,
 #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
 #endif
index c243905..3368659 100644 (file)
 
 #include <asm/uaccess.h>
 
+static const char *
+strcmp_prefix(const char *a, const char *a_prefix)
+{
+       while (*a_prefix && *a == *a_prefix) {
+               a++;
+               a_prefix++;
+       }
+       return *a_prefix ? NULL : a;
+}
+
+/*
+ * In order to implement different sets of xattr operations for each xattr
+ * prefix, a filesystem should create a null-terminated array of struct
+ * xattr_handler (one for each prefix) and hang a pointer to it off of the
+ * s_xattr field of the superblock.
+ */
+#define for_each_xattr_handler(handlers, handler)              \
+       if (handlers)                                           \
+               for ((handler) = *(handlers)++;                 \
+                       (handler) != NULL;                      \
+                       (handler) = *(handlers)++)
+
+/*
+ * Find the xattr_handler with the matching prefix.
+ */
+static const struct xattr_handler *
+xattr_resolve_name(struct inode *inode, const char **name)
+{
+       const struct xattr_handler **handlers = inode->i_sb->s_xattr;
+       const struct xattr_handler *handler;
+
+       if (!(inode->i_opflags & IOP_XATTR)) {
+               if (unlikely(is_bad_inode(inode)))
+                       return ERR_PTR(-EIO);
+               return ERR_PTR(-EOPNOTSUPP);
+       }
+       for_each_xattr_handler(handlers, handler) {
+               const char *n;
+
+               n = strcmp_prefix(*name, xattr_prefix(handler));
+               if (n) {
+                       if (!handler->prefix ^ !*n) {
+                               if (*n)
+                                       continue;
+                               return ERR_PTR(-EINVAL);
+                       }
+                       *name = n;
+                       return handler;
+               }
+       }
+       return ERR_PTR(-EOPNOTSUPP);
+}
+
 /*
  * Check permissions for extended attribute access.  This is a bit complicated
  * because different namespaces have very different rules.
@@ -80,6 +133,23 @@ xattr_permission(struct inode *inode, const char *name, int mask)
        return inode_permission(inode, mask);
 }
 
+int
+__vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
+              const void *value, size_t size, int flags)
+{
+       const struct xattr_handler *handler;
+
+       handler = xattr_resolve_name(inode, &name);
+       if (IS_ERR(handler))
+               return PTR_ERR(handler);
+       if (!handler->set)
+               return -EOPNOTSUPP;
+       if (size == 0)
+               value = "";  /* empty EA, do not remove */
+       return handler->set(handler, dentry, inode, name, value, size, flags);
+}
+EXPORT_SYMBOL(__vfs_setxattr);
+
 /**
  *  __vfs_setxattr_noperm - perform setxattr operation without performing
  *  permission checks.
@@ -106,8 +176,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
 
        if (issec)
                inode->i_flags &= ~S_NOSEC;
-       if (inode->i_op->setxattr) {
-               error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
+       if (inode->i_opflags & IOP_XATTR) {
+               error = __vfs_setxattr(dentry, inode, name, value, size, flags);
                if (!error) {
                        fsnotify_xattr(dentry);
                        security_inode_post_setxattr(dentry, name, value,
@@ -115,6 +185,9 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
                }
        } else if (issec) {
                const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
+
+               if (unlikely(is_bad_inode(inode)))
+                       return -EIO;
                error = security_inode_setsecurity(inode, suffix, value,
                                                   size, flags);
                if (!error)
@@ -188,6 +261,7 @@ ssize_t
 vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
                   size_t xattr_size, gfp_t flags)
 {
+       const struct xattr_handler *handler;
        struct inode *inode = dentry->d_inode;
        char *value = *xattr_value;
        int error;
@@ -196,10 +270,12 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
        if (error)
                return error;
 
-       if (!inode->i_op->getxattr)
+       handler = xattr_resolve_name(inode, &name);
+       if (IS_ERR(handler))
+               return PTR_ERR(handler);
+       if (!handler->get)
                return -EOPNOTSUPP;
-
-       error = inode->i_op->getxattr(dentry, inode, name, NULL, 0);
+       error = handler->get(handler, dentry, inode, name, NULL, 0);
        if (error < 0)
                return error;
 
@@ -210,11 +286,26 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
                memset(value, 0, error + 1);
        }
 
-       error = inode->i_op->getxattr(dentry, inode, name, value, error);
+       error = handler->get(handler, dentry, inode, name, value, error);
        *xattr_value = value;
        return error;
 }
 
+ssize_t
+__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
+              void *value, size_t size)
+{
+       const struct xattr_handler *handler;
+
+       handler = xattr_resolve_name(inode, &name);
+       if (IS_ERR(handler))
+               return PTR_ERR(handler);
+       if (!handler->get)
+               return -EOPNOTSUPP;
+       return handler->get(handler, dentry, inode, name, value, size);
+}
+EXPORT_SYMBOL(__vfs_getxattr);
+
 ssize_t
 vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
 {
@@ -242,28 +333,24 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
                return ret;
        }
 nolsm:
-       if (inode->i_op->getxattr)
-               error = inode->i_op->getxattr(dentry, inode, name, value, size);
-       else
-               error = -EOPNOTSUPP;
-
-       return error;
+       return __vfs_getxattr(dentry, inode, name, value, size);
 }
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
 ssize_t
-vfs_listxattr(struct dentry *d, char *list, size_t size)
+vfs_listxattr(struct dentry *dentry, char *list, size_t size)
 {
+       struct inode *inode = d_inode(dentry);
        ssize_t error;
 
-       error = security_inode_listxattr(d);
+       error = security_inode_listxattr(dentry);
        if (error)
                return error;
-       error = -EOPNOTSUPP;
-       if (d->d_inode->i_op->listxattr) {
-               error = d->d_inode->i_op->listxattr(d, list, size);
+       if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
+               error = -EOPNOTSUPP;
+               error = inode->i_op->listxattr(dentry, list, size);
        } else {
-               error = security_inode_listsecurity(d->d_inode, list, size);
+               error = security_inode_listsecurity(inode, list, size);
                if (size && error > size)
                        error = -ERANGE;
        }
@@ -271,15 +358,27 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
 }
 EXPORT_SYMBOL_GPL(vfs_listxattr);
 
+int
+__vfs_removexattr(struct dentry *dentry, const char *name)
+{
+       struct inode *inode = d_inode(dentry);
+       const struct xattr_handler *handler;
+
+       handler = xattr_resolve_name(inode, &name);
+       if (IS_ERR(handler))
+               return PTR_ERR(handler);
+       if (!handler->set)
+               return -EOPNOTSUPP;
+       return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
+}
+EXPORT_SYMBOL(__vfs_removexattr);
+
 int
 vfs_removexattr(struct dentry *dentry, const char *name)
 {
        struct inode *inode = dentry->d_inode;
        int error;
 
-       if (!inode->i_op->removexattr)
-               return -EOPNOTSUPP;
-
        error = xattr_permission(inode, name, MAY_WRITE);
        if (error)
                return error;
@@ -289,7 +388,7 @@ vfs_removexattr(struct dentry *dentry, const char *name)
        if (error)
                goto out;
 
-       error = inode->i_op->removexattr(dentry, name);
+       error = __vfs_removexattr(dentry, name);
 
        if (!error) {
                fsnotify_xattr(dentry);
@@ -641,76 +740,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
        return error;
 }
 
-
-static const char *
-strcmp_prefix(const char *a, const char *a_prefix)
-{
-       while (*a_prefix && *a == *a_prefix) {
-               a++;
-               a_prefix++;
-       }
-       return *a_prefix ? NULL : a;
-}
-
-/*
- * In order to implement different sets of xattr operations for each xattr
- * prefix with the generic xattr API, a filesystem should create a
- * null-terminated array of struct xattr_handler (one for each prefix) and
- * hang a pointer to it off of the s_xattr field of the superblock.
- *
- * The generic_fooxattr() functions will use this list to dispatch xattr
- * operations to the correct xattr_handler.
- */
-#define for_each_xattr_handler(handlers, handler)              \
-       if (handlers)                                           \
-               for ((handler) = *(handlers)++;                 \
-                       (handler) != NULL;                      \
-                       (handler) = *(handlers)++)
-
-/*
- * Find the xattr_handler with the matching prefix.
- */
-static const struct xattr_handler *
-xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
-{
-       const struct xattr_handler *handler;
-
-       if (!*name)
-               return ERR_PTR(-EINVAL);
-
-       for_each_xattr_handler(handlers, handler) {
-               const char *n;
-
-               n = strcmp_prefix(*name, xattr_prefix(handler));
-               if (n) {
-                       if (!handler->prefix ^ !*n) {
-                               if (*n)
-                                       continue;
-                               return ERR_PTR(-EINVAL);
-                       }
-                       *name = n;
-                       return handler;
-               }
-       }
-       return ERR_PTR(-EOPNOTSUPP);
-}
-
-/*
- * Find the handler for the prefix and dispatch its get() operation.
- */
-ssize_t
-generic_getxattr(struct dentry *dentry, struct inode *inode,
-                const char *name, void *buffer, size_t size)
-{
-       const struct xattr_handler *handler;
-
-       handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
-       if (IS_ERR(handler))
-               return PTR_ERR(handler);
-       return handler->get(handler, dentry, inode,
-                           name, buffer, size);
-}
-
 /*
  * Combine the results of the list() operation from every xattr_handler in the
  * list.
@@ -747,44 +776,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
        }
        return size;
 }
-
-/*
- * Find the handler for the prefix and dispatch its set() operation.
- */
-int
-generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
-                const void *value, size_t size, int flags)
-{
-       const struct xattr_handler *handler;
-
-       if (size == 0)
-               value = "";  /* empty EA, do not remove */
-       handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
-       if (IS_ERR(handler))
-               return PTR_ERR(handler);
-       return handler->set(handler, dentry, inode, name, value, size, flags);
-}
-
-/*
- * Find the handler for the prefix and dispatch its set() operation to remove
- * any associated extended attribute.
- */
-int
-generic_removexattr(struct dentry *dentry, const char *name)
-{
-       const struct xattr_handler *handler;
-
-       handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
-       if (IS_ERR(handler))
-               return PTR_ERR(handler);
-       return handler->set(handler, dentry, d_inode(dentry), name, NULL,
-                           0, XATTR_REPLACE);
-}
-
-EXPORT_SYMBOL(generic_getxattr);
 EXPORT_SYMBOL(generic_listxattr);
-EXPORT_SYMBOL(generic_setxattr);
-EXPORT_SYMBOL(generic_removexattr);
 
 /**
  * xattr_full_name  -  Compute full attribute name from suffix
index ba99803..a7404c5 100644 (file)
@@ -1066,9 +1066,6 @@ static const struct inode_operations xfs_inode_operations = {
        .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .fiemap                 = xfs_vn_fiemap,
        .update_time            = xfs_vn_update_time,
@@ -1094,9 +1091,6 @@ static const struct inode_operations xfs_dir_inode_operations = {
        .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
        .tmpfile                = xfs_vn_tmpfile,
@@ -1122,9 +1116,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
        .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
        .tmpfile                = xfs_vn_tmpfile,
@@ -1135,9 +1126,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
        .get_link               = xfs_vn_get_link,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
 };
@@ -1147,9 +1135,6 @@ static const struct inode_operations xfs_inline_symlink_inode_operations = {
        .get_link               = xfs_vn_get_link_inline,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
 };
index 4ba5957..7e09f59 100644 (file)
@@ -592,6 +592,7 @@ is_uncached_acl(struct posix_acl *acl)
 #define IOP_FASTPERM   0x0001
 #define IOP_LOOKUP     0x0002
 #define IOP_NOFOLLOW   0x0004
+#define IOP_XATTR      0x0008
 
 /*
  * Keep mostly read-only and often accessed (especially for
@@ -1751,12 +1752,7 @@ struct inode_operations {
                        struct inode *, struct dentry *, unsigned int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
-       int (*setxattr) (struct dentry *, struct inode *,
-                        const char *, const void *, size_t, int);
-       ssize_t (*getxattr) (struct dentry *, struct inode *,
-                            const char *, void *, size_t);
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
-       int (*removexattr) (struct dentry *, const char *);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
        int (*update_time)(struct inode *, struct timespec *, int);
@@ -2087,10 +2083,19 @@ struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
                        int flags, void *data);
-extern struct dentry *mount_pseudo(struct file_system_type *, char *,
-       const struct super_operations *ops,
-       const struct dentry_operations *dops,
-       unsigned long);
+extern struct dentry *mount_pseudo_xattr(struct file_system_type *, char *,
+                                        const struct super_operations *ops,
+                                        const struct xattr_handler **xattr,
+                                        const struct dentry_operations *dops,
+                                        unsigned long);
+
+static inline struct dentry *
+mount_pseudo(struct file_system_type *fs_type, char *name,
+            const struct super_operations *ops,
+            const struct dentry_operations *dops, unsigned long magic)
+{
+       return mount_pseudo_xattr(fs_type, name, ops, NULL, dops, magic);
+}
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
 #define fops_get(fops) \
index 94079ba..e77605a 100644 (file)
@@ -46,17 +46,16 @@ struct xattr {
 };
 
 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
+ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t);
 ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int);
 int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int);
 int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
+int __vfs_removexattr(struct dentry *, const char *);
 int vfs_removexattr(struct dentry *, const char *);
 
-ssize_t generic_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
-int generic_setxattr(struct dentry *dentry, struct inode *inode,
-                    const char *name, const void *value, size_t size, int flags);
-int generic_removexattr(struct dentry *dentry, const char *name);
 ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name,
                           char **xattr_value, size_t size, gfp_t flags);
 
index 828253a..8596217 100644 (file)
@@ -3175,10 +3175,7 @@ static const struct inode_operations shmem_short_symlink_operations = {
        .readlink       = generic_readlink,
        .get_link       = simple_get_link,
 #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
 
@@ -3186,10 +3183,7 @@ static const struct inode_operations shmem_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = shmem_get_link,
 #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 };
 
@@ -3683,10 +3677,7 @@ static const struct inode_operations shmem_inode_operations = {
        .getattr        = shmem_getattr,
        .setattr        = shmem_setattr,
 #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
        .set_acl        = simple_set_acl,
 #endif
 };
@@ -3705,10 +3696,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
        .tmpfile        = shmem_tmpfile,
 #endif
 #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
@@ -3718,10 +3706,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
 
 static const struct inode_operations shmem_special_inode_operations = {
 #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
index a1bd161..5a9bf5e 100644 (file)
@@ -320,11 +320,38 @@ static const struct dentry_operations sockfs_dentry_operations = {
        .d_dname  = sockfs_dname,
 };
 
+static int sockfs_xattr_get(const struct xattr_handler *handler,
+                           struct dentry *dentry, struct inode *inode,
+                           const char *suffix, void *value, size_t size)
+{
+       if (value) {
+               if (dentry->d_name.len + 1 > size)
+                       return -ERANGE;
+               memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
+       }
+       return dentry->d_name.len + 1;
+}
+
+#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
+#define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
+#define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
+
+static const struct xattr_handler sockfs_xattr_handler = {
+       .name = XATTR_NAME_SOCKPROTONAME,
+       .get = sockfs_xattr_get,
+};
+
+static const struct xattr_handler *sockfs_xattr_handlers[] = {
+       &sockfs_xattr_handler,
+       NULL
+};
+
 static struct dentry *sockfs_mount(struct file_system_type *fs_type,
                         int flags, const char *dev_name, void *data)
 {
-       return mount_pseudo(fs_type, "socket:", &sockfs_ops,
-               &sockfs_dentry_operations, SOCKFS_MAGIC);
+       return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
+                                 sockfs_xattr_handlers,
+                                 &sockfs_dentry_operations, SOCKFS_MAGIC);
 }
 
 static struct vfsmount *sock_mnt __read_mostly;
@@ -463,35 +490,6 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
        return NULL;
 }
 
-#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
-#define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
-#define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
-static ssize_t sockfs_getxattr(struct dentry *dentry, struct inode *inode,
-                              const char *name, void *value, size_t size)
-{
-       const char *proto_name;
-       size_t proto_size;
-       int error;
-
-       error = -ENODATA;
-       if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
-               proto_name = dentry->d_name.name;
-               proto_size = strlen(proto_name);
-
-               if (value) {
-                       error = -ERANGE;
-                       if (proto_size + 1 > size)
-                               goto out;
-
-                       strncpy(value, proto_name, proto_size + 1);
-               }
-               error = proto_size + 1;
-       }
-
-out:
-       return error;
-}
-
 static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
                                size_t size)
 {
@@ -521,7 +519,6 @@ static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
 }
 
 static const struct inode_operations sockfs_inode_ops = {
-       .getxattr = sockfs_getxattr,
        .listxattr = sockfs_listxattr,
 };
 
index 14540bd..8df676f 100644 (file)
@@ -310,13 +310,8 @@ int cap_inode_need_killpriv(struct dentry *dentry)
        struct inode *inode = d_backing_inode(dentry);
        int error;
 
-       if (!inode->i_op->getxattr)
-              return 0;
-
-       error = inode->i_op->getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
-       if (error <= 0)
-               return 0;
-       return 1;
+       error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
+       return error > 0;
 }
 
 /**
@@ -329,12 +324,12 @@ int cap_inode_need_killpriv(struct dentry *dentry)
  */
 int cap_inode_killpriv(struct dentry *dentry)
 {
-       struct inode *inode = d_backing_inode(dentry);
-
-       if (!inode->i_op->removexattr)
-              return 0;
+       int error;
 
-       return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
+       error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
+       if (error == -EOPNOTSUPP)
+               error = 0;
+       return error;
 }
 
 /*
@@ -394,11 +389,11 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
 
        memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
 
-       if (!inode || !inode->i_op->getxattr)
+       if (!inode)
                return -ENODATA;
 
-       size = inode->i_op->getxattr((struct dentry *)dentry, inode,
-                                    XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
+       size = __vfs_getxattr((struct dentry *)dentry, inode,
+                             XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
        if (size == -ENODATA || size == -EOPNOTSUPP)
                /* no data, that's ok */
                return -ENODATA;
index 11c1d30..bf66391 100644 (file)
@@ -182,8 +182,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
        int error;
        int size;
 
-       if (!inode->i_op->getxattr)
+       if (!(inode->i_opflags & IOP_XATTR))
                return -EOPNOTSUPP;
+
        desc = init_desc(type);
        if (IS_ERR(desc))
                return PTR_ERR(desc);
@@ -253,8 +254,8 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
                rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
                                           &xattr_data,
                                           sizeof(xattr_data), 0);
-       } else if (rc == -ENODATA && inode->i_op->removexattr) {
-               rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
+       } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
+               rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
        }
        return rc;
 }
index b9e2628..ba86155 100644 (file)
@@ -78,11 +78,11 @@ static int evm_find_protected_xattrs(struct dentry *dentry)
        int error;
        int count = 0;
 
-       if (!inode->i_op->getxattr)
+       if (!(inode->i_opflags & IOP_XATTR))
                return -EOPNOTSUPP;
 
        for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
-               error = inode->i_op->getxattr(dentry, inode, *xattr, NULL, 0);
+               error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0);
                if (error < 0) {
                        if (error == -ENODATA)
                                continue;
index ef1e4e7..389325a 100644 (file)
@@ -165,13 +165,13 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
 int ima_read_xattr(struct dentry *dentry,
                   struct evm_ima_xattr_data **xattr_value)
 {
-       struct inode *inode = d_backing_inode(dentry);
-
-       if (!inode->i_op->getxattr)
-               return 0;
+       ssize_t ret;
 
-       return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
-                                 0, GFP_NOFS);
+       ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
+                                0, GFP_NOFS);
+       if (ret == -EOPNOTSUPP)
+               ret = 0;
+       return ret;
 }
 
 /*
@@ -195,7 +195,7 @@ int ima_appraise_measurement(enum ima_hooks func,
        enum integrity_status status = INTEGRITY_UNKNOWN;
        int rc = xattr_len, hash_start = 0;
 
-       if (!inode->i_op->getxattr)
+       if (!(inode->i_opflags & IOP_XATTR))
                return INTEGRITY_UNKNOWN;
 
        if (rc <= 0) {
@@ -322,10 +322,10 @@ void ima_inode_post_setattr(struct dentry *dentry)
 {
        struct inode *inode = d_backing_inode(dentry);
        struct integrity_iint_cache *iint;
-       int must_appraise, rc;
+       int must_appraise;
 
        if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
-           || !inode->i_op->removexattr)
+           || !(inode->i_opflags & IOP_XATTR))
                return;
 
        must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
@@ -338,8 +338,7 @@ void ima_inode_post_setattr(struct dentry *dentry)
                        iint->flags |= IMA_APPRAISE;
        }
        if (!must_appraise)
-               rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
-       return;
+               __vfs_removexattr(dentry, XATTR_NAME_IMA);
 }
 
 /*
index 2205ea2..0850579 100644 (file)
@@ -507,14 +507,14 @@ static int sb_finish_set_opts(struct super_block *sb)
                   the root directory.  -ENODATA is ok, as this may be
                   the first boot of the SELinux kernel before we have
                   assigned xattr values to the filesystem. */
-               if (!root_inode->i_op->getxattr) {
+               if (!(root_inode->i_opflags & IOP_XATTR)) {
                        printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
                               "xattr support\n", sb->s_id, sb->s_type->name);
                        rc = -EOPNOTSUPP;
                        goto out;
                }
-               rc = root_inode->i_op->getxattr(root, root_inode,
-                                               XATTR_NAME_SELINUX, NULL, 0);
+
+               rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
                if (rc < 0 && rc != -ENODATA) {
                        if (rc == -EOPNOTSUPP)
                                printk(KERN_WARNING "SELinux: (dev %s, type "
@@ -1410,11 +1410,10 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
        case SECURITY_FS_USE_NATIVE:
                break;
        case SECURITY_FS_USE_XATTR:
-               if (!inode->i_op->getxattr) {
+               if (!(inode->i_opflags & IOP_XATTR)) {
                        isec->sid = sbsec->def_sid;
                        break;
                }
-
                /* Need a dentry, since the xattr API requires one.
                   Life would be simpler if we could just pass the inode. */
                if (opt_dentry) {
@@ -1445,14 +1444,12 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                        goto out_unlock;
                }
                context[len] = '\0';
-               rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
-                                          context, len);
+               rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
                if (rc == -ERANGE) {
                        kfree(context);
 
                        /* Need a larger buffer.  Query for the right size. */
-                       rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
-                                                  NULL, 0);
+                       rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
                        if (rc < 0) {
                                dput(dentry);
                                goto out_unlock;
@@ -1465,9 +1462,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                                goto out_unlock;
                        }
                        context[len] = '\0';
-                       rc = inode->i_op->getxattr(dentry, inode,
-                                                  XATTR_NAME_SELINUX,
-                                                  context, len);
+                       rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
                }
                dput(dentry);
                if (rc < 0) {
index caec225..1cb0602 100644 (file)
@@ -265,14 +265,14 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
        char *buffer;
        struct smack_known *skp = NULL;
 
-       if (ip->i_op->getxattr == NULL)
+       if (!(ip->i_opflags & IOP_XATTR))
                return ERR_PTR(-EOPNOTSUPP);
 
        buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
        if (buffer == NULL)
                return ERR_PTR(-ENOMEM);
 
-       rc = ip->i_op->getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
+       rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
        if (rc < 0)
                skp = ERR_PTR(rc);
        else if (rc == 0)
@@ -3520,8 +3520,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                 * It would be curious if the label of the task
                 * does not match that assigned.
                 */
-               if (inode->i_op->getxattr == NULL)
-                       break;
+               if (!(inode->i_opflags & IOP_XATTR))
+                       break;
                /*
                 * Get the dentry for xattr.
                 */
@@ -3545,12 +3545,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                         */
                        if (isp->smk_flags & SMK_INODE_CHANGED) {
                                isp->smk_flags &= ~SMK_INODE_CHANGED;
-                               rc = inode->i_op->setxattr(dp, inode,
+                               rc = __vfs_setxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE,
                                        TRANS_TRUE, TRANS_TRUE_SIZE,
                                        0);
                        } else {
-                               rc = inode->i_op->getxattr(dp, inode,
+                               rc = __vfs_getxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE, trattr,
                                        TRANS_TRUE_SIZE);
                                if (rc >= 0 && strncmp(trattr, TRANS_TRUE,