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 d30fb2cb5066940e70d9a43f48d944500483a92b..f56b39ee2e54f20050f157cb526a506c193c2222 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 cbec006e10e44da624684546cb6a7fde189c1c0a..43ef86c266ec83b90208a29cb0f98a187a032dfe 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 65c945d8bae2ea6ffe0f0faa102bb399da3ca48b..e1d784bae06494e0ae477cbd4818d1fea585b698 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 dfa36d34c645271c57e3bebfd87ae3a3a47f451d..ff3ce7486b29b28f1a4663599cf180c6c872f7a8 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 f8bc7ed596466db0dbd2f459ad3e663e2573eb77..82c7c48aa619c7090127025664f58eaed769cc5a 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 0e6ad301971109dea109bac917c3c738b1c063e5..afaa4b6de8018f37f6bbc2c8595c0af01d14fdef 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 3ba385eaa26ee0131e5e3eaf7bfed77290222942..7bb153c334594aeccd20da3dc705e8341de65b61 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 a0d3016f6c2639cbd4722501b65df16265b110d4..994fe5af160b5a548f2ffa4f4486d43182f04639 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 6af790fc3df8a163249b7863d443fc7ab2ae4e9d..3ff867f87d73ee4abbb9b6d8b94b5bd78532f305 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 c6ee4b5fb7e6801f632b5e47710de09d171af372..339c910da916e03a2ae9b9722159429b4b8ade50 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 df4b3e6fa56398d248d51e0b6215a1773dacc1ec..e33bd0933396ff08ccaf856c760c5e1626706ee7 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 082e82dcbaa41c9f305294fb07603645a2c41b1e..da00b11d4a7acf20a7b8b2c63c27a1bbced06ffb 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 14ae4b8e1a3ce8370b282503c91a1ff428d61f5b..34aac1c73ee1cf2b6288ad09e14133ac36b33a4c 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 4ba1547bb9adc861c0598ad3ff200f110d3f4614..599a29237cfea5e401ac2ab225b48df080240a3b 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 5ffba186f35210385085e12ff56b8587721c9e98..ddccec3124d70f08fefb4d017f86d05a6384cd1a 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 6120044951415d7840308eea25a21bd125085109..151872dcc1f402ef47273b6da96a5d15a3f251ba 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 9c3437c8a5b12ae107978266e067bd8ef35f815f..1f0c471b4ba311568648f77c8c8bc41500f2a13a 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 0ca363d1341c113cb067c41a417fac070104ce47..a0e1478dfd04746e31bd04d113a75a67744bcaf7 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 d446203127fcfd47ee08694c5f9e884938f9c4a2..ff32ea7994962dd622917f9de932e7960bb94ea6 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 3495d8ae4b33b1e8dc5a1d9341fa7d6d9835e4c5..8437b191bf5de334a5c8908832c0dec0ac1f0fc7 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 36d49cfbf2dcc81ae4e88eba87a4c6ea6392d7ae..2a822d30e73f950daa452c09867f91a6c23198d4 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 c344b819cffa64bd22c829ee45d7ddbae7a5b8e9..a73a9196b92902072d13d65be17b1502a791e0c4 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 fdf1c61547450b36473001758481623286669199..557b3b0d668c3f12d458a194d819ecb1da407645 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 90455974c2ae5918e5fe1b6bf8b6d8de1301907d..acdf4b929f9715161a20826015a9a0d5ac81e03b 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 5625b879c98a307ab3d182f7802b3284ca443f5e..e80ed0302c22c6e517791e46585cbb2984c3e0b3 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 a430c19607f4eae83e76bc3bf353c219a74ff878..572d12410c7c1ad405e753cb0627d77186259406 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 7efd1d19d32592b5394d01b15b7eb0aa9399377d..f6c4f0058899021a54ee109f34c40717e95f3ab5 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 d9a86919fdf6e9d371b7d01d048acf100f0cc0a6..0933600e11c8a9d2eb4113ae24e481c540e358f3 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 16f5172ee40dba88ce1e2027e2e6c4d5a41bfd47..4cdec5a1934776fda13253c7aeae54b172744580 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 09cce23864dae266344a655df8ab4cc11365dbdd..ed373261f26dda982c5cfe4177857dd8b6e0c1a3 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 1ca95c232bb5c7d071250f46bed489a73b807abd..bf6304a350a6b58351947b8a96998623e380aad1 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 42e128661dc15e4a2593f8cf321fd71f997188bc..9cbe43075de5b2ae5de5ecf05540fd9b245a4f04 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 c43ef397a3aab0b5223b57ccbca54d733c30da84..10827c912c4de6f1363819c4da979f4ed55f174c 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 a3c7ba7f6b593237dd1492bfd59e21fc900f5578..7d037591259d6298602dd08f7ce218ee61a7673d 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 30eb33ff81892586a227a366669c2a133eaadf4a..9b242434adf27ed629381c13853501e48a1348c8 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 0e62dec3effce59d7ce8e5069191e3321643d45b..c12476e309c67c26883d5d2ae95166595359d5ab 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 2cabd649d4fb69dbdbd22aeb40d19f605f605f20..8f3f0855fcd230a28563105108c5e0e19cf55b72 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 467ff376ee265041b40d94d30ee73c6b7edae4aa..720007b2fd65defb63ded33466f60a9ec52ec364 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 cf62037b8a042ac034581abbf737f54764bf96b7..739492c7a3fd9b79b356053e778d9859694ae7fe 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 814b0c58016cc162518b5a2692026353696572af..e420c60883362d785bf5549cd9f0bd3d64010a2b 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 c94c7e4a1323362811b02d53fa4bd89ed9d7e0eb..c82404fee6cd3b391de27297996d5bd6246f9960 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 e57174d436830a4111a1bfdf7c9b7fa11a124908..2b23ad91a464383b96c74af2ce0c577d59ab25aa 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 df21f5b755499323e822d20cf2a0f8546110d236..102b6f0bc7af6461d2875fd4d9b52fa75d15b446 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 37159235ac10969db99278598724adfedda23889..bfd551bbf2312c10e71099dc4a49d076d36d2e28 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 b3d73ad52b22ae9d22f2cea762fa0d5d34809e3e..d5b149a45be14940ed60210a6ccb42a993126a2f 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 117b8b3416f9e761dacf36e8a3e3ff1e84f9e29b..9b43ca02b7ab2b28c5a17ea36856b3fa4237a55a 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 2b3c3ae701533ffb8233aee819050e6aba10c26a..a6d89f151771ff8046e463e543680306f59b46e8 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 698be93612808b2cefd071a4180bb804f5b594a7..dc925b531f32632bb708c3f8490d0d00c7315495 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 a9dec32ba9ba787f95693a8e7f266292376b0132..0e327528a3ce899ae0470bd6ddc516253796879e 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 5e19015468688fa6c90e7771f33409ecae0b9cab..ba5c177d0ed62784a68d59145c0c7ec67c989307 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 a8f1225e6d9b767f5551bca0699f8e5e8f045e4c..6cc043ebb9faaa0ba46352df27ee01d7e8116d51 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 6c2a3e3c521ce66fbd6085840ae69897628ca45b..6ad8eecefe21ff26fa43ca92fbe16ee02b90c323 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 c83846fb9b1464280779908802777869d10da038..0e3bd7e07f88c2c6e9075a9d1c485f66d7eb705e 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 0e34fcfa4d51e08ce1298493c7e2d7806f3b78e1..4d5576a21c828f61965fa7fc219aa1de9e363439 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 8fecf823f5ba2e0241441f96e4d48693ef9d58a2..10b0b06e075ef0295a39f9833360a936a3a221bf 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 2a9f07f06d100f18ef5369aae096594de876c0da..74a81b1daaac8850b68f37bc46110657082dfcc1 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 db37a0e02d32b6e351a396e55f3ce9cb75e8b3a5..3f803b3a1f8295b9d9d3f903cc9f1198c6910f4a 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 b0ffa1d1677eb88a7ca9fe74bf9e145e5a5a26f1..3a60e68ec9658f773064770ac12b2451ba4fe203 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 251e5253f2c1a19f2173448d2220bbb6179c6aad..c18d6a4ff456bfd57015eebc0e0c083246d55fb0 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 3d0b9dee2b76771a78179f4691f7bf294b6982b1..7e3f0127fc1aa7fea2096fcf806bca4dc9c9b60f 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 90f815bdfa8a1159cc8fccc849b8e73124d26a57..2f8c5c9bdaf600abdee1883ceab6633d5caf6467 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 8a36696d6df99c782353c033b070aa666f6db016..fd7d0606aa96cd3c0513afaa85de64ace287d036 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 0927b1e80ab6e0b5a039f41840131c3f40988f75..e9793b1e49a56040453bb0fd92e35b070867ae72 100644 (file)
@@ -425,7 +425,6 @@ failed_read:
 
 
 const struct inode_operations squashfs_inode_ops = {
-       .getxattr = generic_getxattr,
        .listxattr = squashfs_listxattr
 };
 
index 67cad77fefb4ac165bfd92fbba02db473a02e22e..40c10d9974c972c640435b92e571c3da148355d4 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 d688ef42a6a1ff74ce8467cc94b0ff69c9095ce0..79b9c31a0c8ffdd223b83f9c243918e64ef3ed59 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 c83f5d9ec125c75a79d8578f261fe07988ad2254..afe70f815e3def9d8269b3187c41daaca9fec66e 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 4b86d3a738e1807c667fb6736f1deaa28a93d429..1d55aeaebf23bc5a9a6e9f9eb0e7aed9abd3bc0c 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 b0a6a53263f37855af3a357897924cfb6ee8064d..a746982fbcda53b886d60f145a2b43ab85477380 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 c243905835abd25b52eb8daf061b5f11b3a5708e..3368659c471e4f7dc8cd425738bccb7d5fec78a6 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 ba99803eba9854b7b06038f1321b5e6652d676c5..a7404c5aafe2382b36ed594ae4087ddeee257b2d 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 4ba5957ae0894bee1cad8db67f7f3b152e2b6f46..7e09f5926b3be33bc107fa496d267b0cda085cc7 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 94079bab92434d928f839a59b124e1bb739c4145..e77605a0c8da34ec14807fe912d1a5ed45ad999d 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 828253ab772c7969b32e48980f5b2f6896c99b3c..8596217b5e2645400fee72f01592eb1c2c5c8f43 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 a1bd16106625a14ef95f1da0e560a5638ffa4774..5a9bf5ee2464da20fbb42ea6699b29318553e210 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 14540bd7856182260486d549ccab5fd179363060..8df676fbd39366274bf7da334ac5f2aca00c36ae 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 11c1d30bd705a93450dc2b275581fc63cd3b8c77..bf663915412eb8da3ff42e7a565c78c752ec6f4c 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 b9e26288d30c23a43c0f7648471008791a93f9f3..ba8615576d4da93fb3185edfd57e7ebb7ede123b 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 ef1e4e701780d1d242fc1a6876832d4b8363fe90..389325ac6067d547718c957ff110047de986ff56 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 2205ea27aa0afb03e1aaa9120158b8b684bef46d..085057936287bdaa559e7c4be9e593e17ec1dfa9 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 caec2256ab22286a0a2aed59136d92b712bc326e..1cb060293505d14046f084d5c7c5c3e80b480594 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,