summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-10 20:11:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-10 20:11:50 -0400
commit97d2116708ca0fd6ad8b00811ee4349b7e19e96f (patch)
tree81f73fc1a6daee60737b591cf1be73cc4f79de37 /fs
parent30066ce675d3af350bc5a53858991c0b518dda00 (diff)
parentfd50ecaddf8372a1d96e0daeaac0f93cf04e4d42 (diff)
Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
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
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_inode_dotl.c9
-rw-r--r--fs/bad_inode.c21
-rw-r--r--fs/btrfs/inode.c12
-rw-r--r--fs/cachefiles/bind.c4
-rw-r--r--fs/cachefiles/namei.c4
-rw-r--r--fs/ceph/dir.c3
-rw-r--r--fs/ceph/inode.c6
-rw-r--r--fs/cifs/cifsfs.c9
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h2
-rw-r--r--fs/ecryptfs/inode.c67
-rw-r--r--fs/ecryptfs/main.c1
-rw-r--r--fs/ecryptfs/mmap.c13
-rw-r--r--fs/ext2/file.c3
-rw-r--r--fs/ext2/namei.c6
-rw-r--r--fs/ext2/symlink.c6
-rw-r--r--fs/ext4/file.c3
-rw-r--r--fs/ext4/namei.c6
-rw-r--r--fs/ext4/symlink.c9
-rw-r--r--fs/f2fs/file.c3
-rw-r--r--fs/f2fs/namei.c12
-rw-r--r--fs/fuse/dir.c9
-rw-r--r--fs/gfs2/inode.c9
-rw-r--r--fs/hfs/attr.c83
-rw-r--r--fs/hfs/hfs_fs.h6
-rw-r--r--fs/hfs/inode.c5
-rw-r--r--fs/hfs/super.c1
-rw-r--r--fs/hfsplus/dir.c3
-rw-r--r--fs/hfsplus/inode.c3
-rw-r--r--fs/inode.c2
-rw-r--r--fs/jffs2/dir.c3
-rw-r--r--fs/jffs2/file.c3
-rw-r--r--fs/jffs2/symlink.c3
-rw-r--r--fs/jffs2/xattr.h6
-rw-r--r--fs/jfs/file.c3
-rw-r--r--fs/jfs/namei.c3
-rw-r--r--fs/jfs/symlink.c6
-rw-r--r--fs/kernfs/dir.c3
-rw-r--r--fs/kernfs/inode.c155
-rw-r--r--fs/kernfs/kernfs-internal.h7
-rw-r--r--fs/kernfs/mount.c1
-rw-r--r--fs/kernfs/symlink.c3
-rw-r--r--fs/libfs.c29
-rw-r--r--fs/nfs/nfs3proc.c6
-rw-r--r--fs/nfs/nfs4proc.c6
-rw-r--r--fs/ocfs2/file.c3
-rw-r--r--fs/ocfs2/namei.c3
-rw-r--r--fs/ocfs2/symlink.c3
-rw-r--r--fs/orangefs/inode.c3
-rw-r--r--fs/orangefs/namei.c3
-rw-r--r--fs/orangefs/symlink.c1
-rw-r--r--fs/orangefs/xattr.c3
-rw-r--r--fs/overlayfs/copy_up.c4
-rw-r--r--fs/overlayfs/dir.c3
-rw-r--r--fs/overlayfs/inode.c6
-rw-r--r--fs/overlayfs/super.c4
-rw-r--r--fs/reiserfs/file.c3
-rw-r--r--fs/reiserfs/namei.c9
-rw-r--r--fs/squashfs/inode.c1
-rw-r--r--fs/squashfs/namei.c1
-rw-r--r--fs/squashfs/symlink.c1
-rw-r--r--fs/squashfs/xattr.h1
-rw-r--r--fs/ubifs/dir.c3
-rw-r--r--fs/ubifs/file.c6
-rw-r--r--fs/xattr.c250
-rw-r--r--fs/xfs/xfs_iops.c15
65 files changed, 338 insertions, 545 deletions
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 0e6ad3019711..afaa4b6de801 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -967,9 +967,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
967 .rename = v9fs_vfs_rename, 967 .rename = v9fs_vfs_rename,
968 .getattr = v9fs_vfs_getattr_dotl, 968 .getattr = v9fs_vfs_getattr_dotl,
969 .setattr = v9fs_vfs_setattr_dotl, 969 .setattr = v9fs_vfs_setattr_dotl,
970 .setxattr = generic_setxattr,
971 .getxattr = generic_getxattr,
972 .removexattr = generic_removexattr,
973 .listxattr = v9fs_listxattr, 970 .listxattr = v9fs_listxattr,
974 .get_acl = v9fs_iop_get_acl, 971 .get_acl = v9fs_iop_get_acl,
975}; 972};
@@ -977,9 +974,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
977const struct inode_operations v9fs_file_inode_operations_dotl = { 974const struct inode_operations v9fs_file_inode_operations_dotl = {
978 .getattr = v9fs_vfs_getattr_dotl, 975 .getattr = v9fs_vfs_getattr_dotl,
979 .setattr = v9fs_vfs_setattr_dotl, 976 .setattr = v9fs_vfs_setattr_dotl,
980 .setxattr = generic_setxattr,
981 .getxattr = generic_getxattr,
982 .removexattr = generic_removexattr,
983 .listxattr = v9fs_listxattr, 977 .listxattr = v9fs_listxattr,
984 .get_acl = v9fs_iop_get_acl, 978 .get_acl = v9fs_iop_get_acl,
985}; 979};
@@ -989,8 +983,5 @@ const struct inode_operations v9fs_symlink_inode_operations_dotl = {
989 .get_link = v9fs_vfs_get_link_dotl, 983 .get_link = v9fs_vfs_get_link_dotl,
990 .getattr = v9fs_vfs_getattr_dotl, 984 .getattr = v9fs_vfs_getattr_dotl,
991 .setattr = v9fs_vfs_setattr_dotl, 985 .setattr = v9fs_vfs_setattr_dotl,
992 .setxattr = generic_setxattr,
993 .getxattr = generic_getxattr,
994 .removexattr = generic_removexattr,
995 .listxattr = v9fs_listxattr, 986 .listxattr = v9fs_listxattr,
996}; 987};
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 3ba385eaa26e..7bb153c33459 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -100,29 +100,12 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
100 return -EIO; 100 return -EIO;
101} 101}
102 102
103static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
104 const char *name, const void *value, size_t size, int flags)
105{
106 return -EIO;
107}
108
109static ssize_t bad_inode_getxattr(struct dentry *dentry, struct inode *inode,
110 const char *name, void *buffer, size_t size)
111{
112 return -EIO;
113}
114
115static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer, 103static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
116 size_t buffer_size) 104 size_t buffer_size)
117{ 105{
118 return -EIO; 106 return -EIO;
119} 107}
120 108
121static int bad_inode_removexattr(struct dentry *dentry, const char *name)
122{
123 return -EIO;
124}
125
126static const struct inode_operations bad_inode_ops = 109static const struct inode_operations bad_inode_ops =
127{ 110{
128 .create = bad_inode_create, 111 .create = bad_inode_create,
@@ -142,10 +125,7 @@ static const struct inode_operations bad_inode_ops =
142 .permission = bad_inode_permission, 125 .permission = bad_inode_permission,
143 .getattr = bad_inode_getattr, 126 .getattr = bad_inode_getattr,
144 .setattr = bad_inode_setattr, 127 .setattr = bad_inode_setattr,
145 .setxattr = bad_inode_setxattr,
146 .getxattr = bad_inode_getxattr,
147 .listxattr = bad_inode_listxattr, 128 .listxattr = bad_inode_listxattr,
148 .removexattr = bad_inode_removexattr,
149}; 129};
150 130
151 131
@@ -175,6 +155,7 @@ void make_bad_inode(struct inode *inode)
175 inode->i_atime = inode->i_mtime = inode->i_ctime = 155 inode->i_atime = inode->i_mtime = inode->i_ctime =
176 current_fs_time(inode->i_sb); 156 current_fs_time(inode->i_sb);
177 inode->i_op = &bad_inode_ops; 157 inode->i_op = &bad_inode_ops;
158 inode->i_opflags &= ~IOP_XATTR;
178 inode->i_fop = &bad_file_ops; 159 inode->i_fop = &bad_file_ops;
179} 160}
180EXPORT_SYMBOL(make_bad_inode); 161EXPORT_SYMBOL(make_bad_inode);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a0d3016f6c26..994fe5af160b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -10556,10 +10556,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
10556 .symlink = btrfs_symlink, 10556 .symlink = btrfs_symlink,
10557 .setattr = btrfs_setattr, 10557 .setattr = btrfs_setattr,
10558 .mknod = btrfs_mknod, 10558 .mknod = btrfs_mknod,
10559 .setxattr = generic_setxattr,
10560 .getxattr = generic_getxattr,
10561 .listxattr = btrfs_listxattr, 10559 .listxattr = btrfs_listxattr,
10562 .removexattr = generic_removexattr,
10563 .permission = btrfs_permission, 10560 .permission = btrfs_permission,
10564 .get_acl = btrfs_get_acl, 10561 .get_acl = btrfs_get_acl,
10565 .set_acl = btrfs_set_acl, 10562 .set_acl = btrfs_set_acl,
@@ -10633,10 +10630,7 @@ static const struct address_space_operations btrfs_symlink_aops = {
10633static const struct inode_operations btrfs_file_inode_operations = { 10630static const struct inode_operations btrfs_file_inode_operations = {
10634 .getattr = btrfs_getattr, 10631 .getattr = btrfs_getattr,
10635 .setattr = btrfs_setattr, 10632 .setattr = btrfs_setattr,
10636 .setxattr = generic_setxattr,
10637 .getxattr = generic_getxattr,
10638 .listxattr = btrfs_listxattr, 10633 .listxattr = btrfs_listxattr,
10639 .removexattr = generic_removexattr,
10640 .permission = btrfs_permission, 10634 .permission = btrfs_permission,
10641 .fiemap = btrfs_fiemap, 10635 .fiemap = btrfs_fiemap,
10642 .get_acl = btrfs_get_acl, 10636 .get_acl = btrfs_get_acl,
@@ -10647,10 +10641,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
10647 .getattr = btrfs_getattr, 10641 .getattr = btrfs_getattr,
10648 .setattr = btrfs_setattr, 10642 .setattr = btrfs_setattr,
10649 .permission = btrfs_permission, 10643 .permission = btrfs_permission,
10650 .setxattr = generic_setxattr,
10651 .getxattr = generic_getxattr,
10652 .listxattr = btrfs_listxattr, 10644 .listxattr = btrfs_listxattr,
10653 .removexattr = generic_removexattr,
10654 .get_acl = btrfs_get_acl, 10645 .get_acl = btrfs_get_acl,
10655 .set_acl = btrfs_set_acl, 10646 .set_acl = btrfs_set_acl,
10656 .update_time = btrfs_update_time, 10647 .update_time = btrfs_update_time,
@@ -10661,10 +10652,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
10661 .getattr = btrfs_getattr, 10652 .getattr = btrfs_getattr,
10662 .setattr = btrfs_setattr, 10653 .setattr = btrfs_setattr,
10663 .permission = btrfs_permission, 10654 .permission = btrfs_permission,
10664 .setxattr = generic_setxattr,
10665 .getxattr = generic_getxattr,
10666 .listxattr = btrfs_listxattr, 10655 .listxattr = btrfs_listxattr,
10667 .removexattr = generic_removexattr,
10668 .update_time = btrfs_update_time, 10656 .update_time = btrfs_update_time,
10669}; 10657};
10670 10658
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 6af790fc3df8..3ff867f87d73 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -20,6 +20,7 @@
20#include <linux/mount.h> 20#include <linux/mount.h>
21#include <linux/statfs.h> 21#include <linux/statfs.h>
22#include <linux/ctype.h> 22#include <linux/ctype.h>
23#include <linux/xattr.h>
23#include "internal.h" 24#include "internal.h"
24 25
25static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches); 26static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
@@ -126,8 +127,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
126 if (d_is_negative(root) || 127 if (d_is_negative(root) ||
127 !d_backing_inode(root)->i_op->lookup || 128 !d_backing_inode(root)->i_op->lookup ||
128 !d_backing_inode(root)->i_op->mkdir || 129 !d_backing_inode(root)->i_op->mkdir ||
129 !d_backing_inode(root)->i_op->setxattr || 130 !(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
130 !d_backing_inode(root)->i_op->getxattr ||
131 !root->d_sb->s_op->statfs || 131 !root->d_sb->s_op->statfs ||
132 !root->d_sb->s_op->sync_fs) 132 !root->d_sb->s_op->sync_fs)
133 goto error_unsupported; 133 goto error_unsupported;
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index c6ee4b5fb7e6..339c910da916 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -20,6 +20,7 @@
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include <linux/security.h> 21#include <linux/security.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/xattr.h>
23#include "internal.h" 24#include "internal.h"
24 25
25#define CACHEFILES_KEYBUF_SIZE 512 26#define CACHEFILES_KEYBUF_SIZE 512
@@ -799,8 +800,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
799 } 800 }
800 801
801 ret = -EPERM; 802 ret = -EPERM;
802 if (!d_backing_inode(subdir)->i_op->setxattr || 803 if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
803 !d_backing_inode(subdir)->i_op->getxattr ||
804 !d_backing_inode(subdir)->i_op->lookup || 804 !d_backing_inode(subdir)->i_op->lookup ||
805 !d_backing_inode(subdir)->i_op->mkdir || 805 !d_backing_inode(subdir)->i_op->mkdir ||
806 !d_backing_inode(subdir)->i_op->create || 806 !d_backing_inode(subdir)->i_op->create ||
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index df4b3e6fa563..e33bd0933396 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1486,10 +1486,7 @@ const struct inode_operations ceph_dir_iops = {
1486 .permission = ceph_permission, 1486 .permission = ceph_permission,
1487 .getattr = ceph_getattr, 1487 .getattr = ceph_getattr,
1488 .setattr = ceph_setattr, 1488 .setattr = ceph_setattr,
1489 .setxattr = generic_setxattr,
1490 .getxattr = generic_getxattr,
1491 .listxattr = ceph_listxattr, 1489 .listxattr = ceph_listxattr,
1492 .removexattr = generic_removexattr,
1493 .get_acl = ceph_get_acl, 1490 .get_acl = ceph_get_acl,
1494 .set_acl = ceph_set_acl, 1491 .set_acl = ceph_set_acl,
1495 .mknod = ceph_mknod, 1492 .mknod = ceph_mknod,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 082e82dcbaa4..da00b11d4a7a 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -94,10 +94,7 @@ const struct inode_operations ceph_file_iops = {
94 .permission = ceph_permission, 94 .permission = ceph_permission,
95 .setattr = ceph_setattr, 95 .setattr = ceph_setattr,
96 .getattr = ceph_getattr, 96 .getattr = ceph_getattr,
97 .setxattr = generic_setxattr,
98 .getxattr = generic_getxattr,
99 .listxattr = ceph_listxattr, 97 .listxattr = ceph_listxattr,
100 .removexattr = generic_removexattr,
101 .get_acl = ceph_get_acl, 98 .get_acl = ceph_get_acl,
102 .set_acl = ceph_set_acl, 99 .set_acl = ceph_set_acl,
103}; 100};
@@ -1885,10 +1882,7 @@ static const struct inode_operations ceph_symlink_iops = {
1885 .get_link = simple_get_link, 1882 .get_link = simple_get_link,
1886 .setattr = ceph_setattr, 1883 .setattr = ceph_setattr,
1887 .getattr = ceph_getattr, 1884 .getattr = ceph_getattr,
1888 .setxattr = generic_setxattr,
1889 .getxattr = generic_getxattr,
1890 .listxattr = ceph_listxattr, 1885 .listxattr = ceph_listxattr,
1891 .removexattr = generic_removexattr,
1892}; 1886};
1893 1887
1894int __ceph_setattr(struct inode *inode, struct iattr *attr) 1888int __ceph_setattr(struct inode *inode, struct iattr *attr)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 14ae4b8e1a3c..34aac1c73ee1 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -901,30 +901,21 @@ const struct inode_operations cifs_dir_inode_ops = {
901 .setattr = cifs_setattr, 901 .setattr = cifs_setattr,
902 .symlink = cifs_symlink, 902 .symlink = cifs_symlink,
903 .mknod = cifs_mknod, 903 .mknod = cifs_mknod,
904 .setxattr = generic_setxattr,
905 .getxattr = generic_getxattr,
906 .listxattr = cifs_listxattr, 904 .listxattr = cifs_listxattr,
907 .removexattr = generic_removexattr,
908}; 905};
909 906
910const struct inode_operations cifs_file_inode_ops = { 907const struct inode_operations cifs_file_inode_ops = {
911 .setattr = cifs_setattr, 908 .setattr = cifs_setattr,
912 .getattr = cifs_getattr, 909 .getattr = cifs_getattr,
913 .permission = cifs_permission, 910 .permission = cifs_permission,
914 .setxattr = generic_setxattr,
915 .getxattr = generic_getxattr,
916 .listxattr = cifs_listxattr, 911 .listxattr = cifs_listxattr,
917 .removexattr = generic_removexattr,
918}; 912};
919 913
920const struct inode_operations cifs_symlink_inode_ops = { 914const struct inode_operations cifs_symlink_inode_ops = {
921 .readlink = generic_readlink, 915 .readlink = generic_readlink,
922 .get_link = cifs_get_link, 916 .get_link = cifs_get_link,
923 .permission = cifs_permission, 917 .permission = cifs_permission,
924 .setxattr = generic_setxattr,
925 .getxattr = generic_getxattr,
926 .listxattr = cifs_listxattr, 918 .listxattr = cifs_listxattr,
927 .removexattr = generic_removexattr,
928}; 919};
929 920
930static int cifs_clone_file_range(struct file *src_file, loff_t off, 921static int cifs_clone_file_range(struct file *src_file, loff_t off,
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 4ba1547bb9ad..599a29237cfe 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -715,4 +715,6 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
715int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, 715int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
716 loff_t offset); 716 loff_t offset);
717 717
718extern const struct xattr_handler *ecryptfs_xattr_handlers[];
719
718#endif /* #ifndef ECRYPTFS_KERNEL_H */ 720#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 5ffba186f352..ddccec3124d7 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -1005,15 +1005,14 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
1005 const char *name, const void *value, 1005 const char *name, const void *value,
1006 size_t size, int flags) 1006 size_t size, int flags)
1007{ 1007{
1008 int rc = 0; 1008 int rc;
1009 struct dentry *lower_dentry; 1009 struct dentry *lower_dentry;
1010 1010
1011 lower_dentry = ecryptfs_dentry_to_lower(dentry); 1011 lower_dentry = ecryptfs_dentry_to_lower(dentry);
1012 if (!d_inode(lower_dentry)->i_op->setxattr) { 1012 if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
1013 rc = -EOPNOTSUPP; 1013 rc = -EOPNOTSUPP;
1014 goto out; 1014 goto out;
1015 } 1015 }
1016
1017 rc = vfs_setxattr(lower_dentry, name, value, size, flags); 1016 rc = vfs_setxattr(lower_dentry, name, value, size, flags);
1018 if (!rc && inode) 1017 if (!rc && inode)
1019 fsstack_copy_attr_all(inode, d_inode(lower_dentry)); 1018 fsstack_copy_attr_all(inode, d_inode(lower_dentry));
@@ -1025,15 +1024,14 @@ ssize_t
1025ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode, 1024ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
1026 const char *name, void *value, size_t size) 1025 const char *name, void *value, size_t size)
1027{ 1026{
1028 int rc = 0; 1027 int rc;
1029 1028
1030 if (!lower_inode->i_op->getxattr) { 1029 if (!(lower_inode->i_opflags & IOP_XATTR)) {
1031 rc = -EOPNOTSUPP; 1030 rc = -EOPNOTSUPP;
1032 goto out; 1031 goto out;
1033 } 1032 }
1034 inode_lock(lower_inode); 1033 inode_lock(lower_inode);
1035 rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode, 1034 rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
1036 name, value, size);
1037 inode_unlock(lower_inode); 1035 inode_unlock(lower_inode);
1038out: 1036out:
1039 return rc; 1037 return rc;
@@ -1066,19 +1064,22 @@ out:
1066 return rc; 1064 return rc;
1067} 1065}
1068 1066
1069static int ecryptfs_removexattr(struct dentry *dentry, const char *name) 1067static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
1068 const char *name)
1070{ 1069{
1071 int rc = 0; 1070 int rc;
1072 struct dentry *lower_dentry; 1071 struct dentry *lower_dentry;
1072 struct inode *lower_inode;
1073 1073
1074 lower_dentry = ecryptfs_dentry_to_lower(dentry); 1074 lower_dentry = ecryptfs_dentry_to_lower(dentry);
1075 if (!d_inode(lower_dentry)->i_op->removexattr) { 1075 lower_inode = ecryptfs_inode_to_lower(inode);
1076 if (!(lower_inode->i_opflags & IOP_XATTR)) {
1076 rc = -EOPNOTSUPP; 1077 rc = -EOPNOTSUPP;
1077 goto out; 1078 goto out;
1078 } 1079 }
1079 inode_lock(d_inode(lower_dentry)); 1080 inode_lock(lower_inode);
1080 rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name); 1081 rc = __vfs_removexattr(lower_dentry, name);
1081 inode_unlock(d_inode(lower_dentry)); 1082 inode_unlock(lower_inode);
1082out: 1083out:
1083 return rc; 1084 return rc;
1084} 1085}
@@ -1089,10 +1090,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
1089 .permission = ecryptfs_permission, 1090 .permission = ecryptfs_permission,
1090 .setattr = ecryptfs_setattr, 1091 .setattr = ecryptfs_setattr,
1091 .getattr = ecryptfs_getattr_link, 1092 .getattr = ecryptfs_getattr_link,
1092 .setxattr = ecryptfs_setxattr,
1093 .getxattr = ecryptfs_getxattr,
1094 .listxattr = ecryptfs_listxattr, 1093 .listxattr = ecryptfs_listxattr,
1095 .removexattr = ecryptfs_removexattr
1096}; 1094};
1097 1095
1098const struct inode_operations ecryptfs_dir_iops = { 1096const struct inode_operations ecryptfs_dir_iops = {
@@ -1107,18 +1105,43 @@ const struct inode_operations ecryptfs_dir_iops = {
1107 .rename = ecryptfs_rename, 1105 .rename = ecryptfs_rename,
1108 .permission = ecryptfs_permission, 1106 .permission = ecryptfs_permission,
1109 .setattr = ecryptfs_setattr, 1107 .setattr = ecryptfs_setattr,
1110 .setxattr = ecryptfs_setxattr,
1111 .getxattr = ecryptfs_getxattr,
1112 .listxattr = ecryptfs_listxattr, 1108 .listxattr = ecryptfs_listxattr,
1113 .removexattr = ecryptfs_removexattr
1114}; 1109};
1115 1110
1116const struct inode_operations ecryptfs_main_iops = { 1111const struct inode_operations ecryptfs_main_iops = {
1117 .permission = ecryptfs_permission, 1112 .permission = ecryptfs_permission,
1118 .setattr = ecryptfs_setattr, 1113 .setattr = ecryptfs_setattr,
1119 .getattr = ecryptfs_getattr, 1114 .getattr = ecryptfs_getattr,
1120 .setxattr = ecryptfs_setxattr,
1121 .getxattr = ecryptfs_getxattr,
1122 .listxattr = ecryptfs_listxattr, 1115 .listxattr = ecryptfs_listxattr,
1123 .removexattr = ecryptfs_removexattr 1116};
1117
1118static int ecryptfs_xattr_get(const struct xattr_handler *handler,
1119 struct dentry *dentry, struct inode *inode,
1120 const char *name, void *buffer, size_t size)
1121{
1122 return ecryptfs_getxattr(dentry, inode, name, buffer, size);
1123}
1124
1125static int ecryptfs_xattr_set(const struct xattr_handler *handler,
1126 struct dentry *dentry, struct inode *inode,
1127 const char *name, const void *value, size_t size,
1128 int flags)
1129{
1130 if (value)
1131 return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
1132 else {
1133 BUG_ON(flags != XATTR_REPLACE);
1134 return ecryptfs_removexattr(dentry, inode, name);
1135 }
1136}
1137
1138const struct xattr_handler ecryptfs_xattr_handler = {
1139 .prefix = "", /* match anything */
1140 .get = ecryptfs_xattr_get,
1141 .set = ecryptfs_xattr_set,
1142};
1143
1144const struct xattr_handler *ecryptfs_xattr_handlers[] = {
1145 &ecryptfs_xattr_handler,
1146 NULL
1124}; 1147};
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 612004495141..151872dcc1f4 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -529,6 +529,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
529 /* ->kill_sb() will take care of sbi after that point */ 529 /* ->kill_sb() will take care of sbi after that point */
530 sbi = NULL; 530 sbi = NULL;
531 s->s_op = &ecryptfs_sops; 531 s->s_op = &ecryptfs_sops;
532 s->s_xattr = ecryptfs_xattr_handlers;
532 s->s_d_op = &ecryptfs_dops; 533 s->s_d_op = &ecryptfs_dops;
533 534
534 err = "Reading sb failed"; 535 err = "Reading sb failed";
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 9c3437c8a5b1..1f0c471b4ba3 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -32,6 +32,7 @@
32#include <linux/file.h> 32#include <linux/file.h>
33#include <linux/scatterlist.h> 33#include <linux/scatterlist.h>
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/xattr.h>
35#include <asm/unaligned.h> 36#include <asm/unaligned.h>
36#include "ecryptfs_kernel.h" 37#include "ecryptfs_kernel.h"
37 38
@@ -422,7 +423,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
422 struct inode *lower_inode = d_inode(lower_dentry); 423 struct inode *lower_inode = d_inode(lower_dentry);
423 int rc; 424 int rc;
424 425
425 if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) { 426 if (!(lower_inode->i_opflags & IOP_XATTR)) {
426 printk(KERN_WARNING 427 printk(KERN_WARNING
427 "No support for setting xattr in lower filesystem\n"); 428 "No support for setting xattr in lower filesystem\n");
428 rc = -ENOSYS; 429 rc = -ENOSYS;
@@ -436,15 +437,13 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
436 goto out; 437 goto out;
437 } 438 }
438 inode_lock(lower_inode); 439 inode_lock(lower_inode);
439 size = lower_inode->i_op->getxattr(lower_dentry, lower_inode, 440 size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
440 ECRYPTFS_XATTR_NAME, 441 xattr_virt, PAGE_SIZE);
441 xattr_virt, PAGE_SIZE);
442 if (size < 0) 442 if (size < 0)
443 size = 8; 443 size = 8;
444 put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt); 444 put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
445 rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode, 445 rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
446 ECRYPTFS_XATTR_NAME, 446 xattr_virt, size, 0);
447 xattr_virt, size, 0);
448 inode_unlock(lower_inode); 447 inode_unlock(lower_inode);
449 if (rc) 448 if (rc)
450 printk(KERN_ERR "Error whilst attempting to write inode size " 449 printk(KERN_ERR "Error whilst attempting to write inode size "
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 0ca363d1341c..a0e1478dfd04 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -241,10 +241,7 @@ const struct file_operations ext2_file_operations = {
241 241
242const struct inode_operations ext2_file_inode_operations = { 242const struct inode_operations ext2_file_inode_operations = {
243#ifdef CONFIG_EXT2_FS_XATTR 243#ifdef CONFIG_EXT2_FS_XATTR
244 .setxattr = generic_setxattr,
245 .getxattr = generic_getxattr,
246 .listxattr = ext2_listxattr, 244 .listxattr = ext2_listxattr,
247 .removexattr = generic_removexattr,
248#endif 245#endif
249 .setattr = ext2_setattr, 246 .setattr = ext2_setattr,
250 .get_acl = ext2_get_acl, 247 .get_acl = ext2_get_acl,
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index d446203127fc..ff32ea799496 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -428,10 +428,7 @@ const struct inode_operations ext2_dir_inode_operations = {
428 .mknod = ext2_mknod, 428 .mknod = ext2_mknod,
429 .rename = ext2_rename, 429 .rename = ext2_rename,
430#ifdef CONFIG_EXT2_FS_XATTR 430#ifdef CONFIG_EXT2_FS_XATTR
431 .setxattr = generic_setxattr,
432 .getxattr = generic_getxattr,
433 .listxattr = ext2_listxattr, 431 .listxattr = ext2_listxattr,
434 .removexattr = generic_removexattr,
435#endif 432#endif
436 .setattr = ext2_setattr, 433 .setattr = ext2_setattr,
437 .get_acl = ext2_get_acl, 434 .get_acl = ext2_get_acl,
@@ -441,10 +438,7 @@ const struct inode_operations ext2_dir_inode_operations = {
441 438
442const struct inode_operations ext2_special_inode_operations = { 439const struct inode_operations ext2_special_inode_operations = {
443#ifdef CONFIG_EXT2_FS_XATTR 440#ifdef CONFIG_EXT2_FS_XATTR
444 .setxattr = generic_setxattr,
445 .getxattr = generic_getxattr,
446 .listxattr = ext2_listxattr, 441 .listxattr = ext2_listxattr,
447 .removexattr = generic_removexattr,
448#endif 442#endif
449 .setattr = ext2_setattr, 443 .setattr = ext2_setattr,
450 .get_acl = ext2_get_acl, 444 .get_acl = ext2_get_acl,
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 3495d8ae4b33..8437b191bf5d 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -25,10 +25,7 @@ const struct inode_operations ext2_symlink_inode_operations = {
25 .get_link = page_get_link, 25 .get_link = page_get_link,
26 .setattr = ext2_setattr, 26 .setattr = ext2_setattr,
27#ifdef CONFIG_EXT2_FS_XATTR 27#ifdef CONFIG_EXT2_FS_XATTR
28 .setxattr = generic_setxattr,
29 .getxattr = generic_getxattr,
30 .listxattr = ext2_listxattr, 28 .listxattr = ext2_listxattr,
31 .removexattr = generic_removexattr,
32#endif 29#endif
33}; 30};
34 31
@@ -37,9 +34,6 @@ const struct inode_operations ext2_fast_symlink_inode_operations = {
37 .get_link = simple_get_link, 34 .get_link = simple_get_link,
38 .setattr = ext2_setattr, 35 .setattr = ext2_setattr,
39#ifdef CONFIG_EXT2_FS_XATTR 36#ifdef CONFIG_EXT2_FS_XATTR
40 .setxattr = generic_setxattr,
41 .getxattr = generic_getxattr,
42 .listxattr = ext2_listxattr, 37 .listxattr = ext2_listxattr,
43 .removexattr = generic_removexattr,
44#endif 38#endif
45}; 39};
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 36d49cfbf2dc..2a822d30e73f 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -706,10 +706,7 @@ const struct file_operations ext4_file_operations = {
706const struct inode_operations ext4_file_inode_operations = { 706const struct inode_operations ext4_file_inode_operations = {
707 .setattr = ext4_setattr, 707 .setattr = ext4_setattr,
708 .getattr = ext4_getattr, 708 .getattr = ext4_getattr,
709 .setxattr = generic_setxattr,
710 .getxattr = generic_getxattr,
711 .listxattr = ext4_listxattr, 709 .listxattr = ext4_listxattr,
712 .removexattr = generic_removexattr,
713 .get_acl = ext4_get_acl, 710 .get_acl = ext4_get_acl,
714 .set_acl = ext4_set_acl, 711 .set_acl = ext4_set_acl,
715 .fiemap = ext4_fiemap, 712 .fiemap = ext4_fiemap,
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index c344b819cffa..a73a9196b929 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3880,10 +3880,7 @@ const struct inode_operations ext4_dir_inode_operations = {
3880 .tmpfile = ext4_tmpfile, 3880 .tmpfile = ext4_tmpfile,
3881 .rename2 = ext4_rename2, 3881 .rename2 = ext4_rename2,
3882 .setattr = ext4_setattr, 3882 .setattr = ext4_setattr,
3883 .setxattr = generic_setxattr,
3884 .getxattr = generic_getxattr,
3885 .listxattr = ext4_listxattr, 3883 .listxattr = ext4_listxattr,
3886 .removexattr = generic_removexattr,
3887 .get_acl = ext4_get_acl, 3884 .get_acl = ext4_get_acl,
3888 .set_acl = ext4_set_acl, 3885 .set_acl = ext4_set_acl,
3889 .fiemap = ext4_fiemap, 3886 .fiemap = ext4_fiemap,
@@ -3891,10 +3888,7 @@ const struct inode_operations ext4_dir_inode_operations = {
3891 3888
3892const struct inode_operations ext4_special_inode_operations = { 3889const struct inode_operations ext4_special_inode_operations = {
3893 .setattr = ext4_setattr, 3890 .setattr = ext4_setattr,
3894 .setxattr = generic_setxattr,
3895 .getxattr = generic_getxattr,
3896 .listxattr = ext4_listxattr, 3891 .listxattr = ext4_listxattr,
3897 .removexattr = generic_removexattr,
3898 .get_acl = ext4_get_acl, 3892 .get_acl = ext4_get_acl,
3899 .set_acl = ext4_set_acl, 3893 .set_acl = ext4_set_acl,
3900}; 3894};
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index fdf1c6154745..557b3b0d668c 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -86,28 +86,19 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
86 .readlink = generic_readlink, 86 .readlink = generic_readlink,
87 .get_link = ext4_encrypted_get_link, 87 .get_link = ext4_encrypted_get_link,
88 .setattr = ext4_setattr, 88 .setattr = ext4_setattr,
89 .setxattr = generic_setxattr,
90 .getxattr = generic_getxattr,
91 .listxattr = ext4_listxattr, 89 .listxattr = ext4_listxattr,
92 .removexattr = generic_removexattr,
93}; 90};
94 91
95const struct inode_operations ext4_symlink_inode_operations = { 92const struct inode_operations ext4_symlink_inode_operations = {
96 .readlink = generic_readlink, 93 .readlink = generic_readlink,
97 .get_link = page_get_link, 94 .get_link = page_get_link,
98 .setattr = ext4_setattr, 95 .setattr = ext4_setattr,
99 .setxattr = generic_setxattr,
100 .getxattr = generic_getxattr,
101 .listxattr = ext4_listxattr, 96 .listxattr = ext4_listxattr,
102 .removexattr = generic_removexattr,
103}; 97};
104 98
105const struct inode_operations ext4_fast_symlink_inode_operations = { 99const struct inode_operations ext4_fast_symlink_inode_operations = {
106 .readlink = generic_readlink, 100 .readlink = generic_readlink,
107 .get_link = simple_get_link, 101 .get_link = simple_get_link,
108 .setattr = ext4_setattr, 102 .setattr = ext4_setattr,
109 .setxattr = generic_setxattr,
110 .getxattr = generic_getxattr,
111 .listxattr = ext4_listxattr, 103 .listxattr = ext4_listxattr,
112 .removexattr = generic_removexattr,
113}; 104};
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 90455974c2ae..acdf4b929f97 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -732,10 +732,7 @@ const struct inode_operations f2fs_file_inode_operations = {
732 .get_acl = f2fs_get_acl, 732 .get_acl = f2fs_get_acl,
733 .set_acl = f2fs_set_acl, 733 .set_acl = f2fs_set_acl,
734#ifdef CONFIG_F2FS_FS_XATTR 734#ifdef CONFIG_F2FS_FS_XATTR
735 .setxattr = generic_setxattr,
736 .getxattr = generic_getxattr,
737 .listxattr = f2fs_listxattr, 735 .listxattr = f2fs_listxattr,
738 .removexattr = generic_removexattr,
739#endif 736#endif
740 .fiemap = f2fs_fiemap, 737 .fiemap = f2fs_fiemap,
741}; 738};
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 5625b879c98a..e80ed0302c22 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -1080,10 +1080,7 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
1080 .getattr = f2fs_getattr, 1080 .getattr = f2fs_getattr,
1081 .setattr = f2fs_setattr, 1081 .setattr = f2fs_setattr,
1082#ifdef CONFIG_F2FS_FS_XATTR 1082#ifdef CONFIG_F2FS_FS_XATTR
1083 .setxattr = generic_setxattr,
1084 .getxattr = generic_getxattr,
1085 .listxattr = f2fs_listxattr, 1083 .listxattr = f2fs_listxattr,
1086 .removexattr = generic_removexattr,
1087#endif 1084#endif
1088}; 1085};
1089 1086
@@ -1103,10 +1100,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
1103 .get_acl = f2fs_get_acl, 1100 .get_acl = f2fs_get_acl,
1104 .set_acl = f2fs_set_acl, 1101 .set_acl = f2fs_set_acl,
1105#ifdef CONFIG_F2FS_FS_XATTR 1102#ifdef CONFIG_F2FS_FS_XATTR
1106 .setxattr = generic_setxattr,
1107 .getxattr = generic_getxattr,
1108 .listxattr = f2fs_listxattr, 1103 .listxattr = f2fs_listxattr,
1109 .removexattr = generic_removexattr,
1110#endif 1104#endif
1111}; 1105};
1112 1106
@@ -1116,10 +1110,7 @@ const struct inode_operations f2fs_symlink_inode_operations = {
1116 .getattr = f2fs_getattr, 1110 .getattr = f2fs_getattr,
1117 .setattr = f2fs_setattr, 1111 .setattr = f2fs_setattr,
1118#ifdef CONFIG_F2FS_FS_XATTR 1112#ifdef CONFIG_F2FS_FS_XATTR
1119 .setxattr = generic_setxattr,
1120 .getxattr = generic_getxattr,
1121 .listxattr = f2fs_listxattr, 1113 .listxattr = f2fs_listxattr,
1122 .removexattr = generic_removexattr,
1123#endif 1114#endif
1124}; 1115};
1125 1116
@@ -1129,9 +1120,6 @@ const struct inode_operations f2fs_special_inode_operations = {
1129 .get_acl = f2fs_get_acl, 1120 .get_acl = f2fs_get_acl,
1130 .set_acl = f2fs_set_acl, 1121 .set_acl = f2fs_set_acl,
1131#ifdef CONFIG_F2FS_FS_XATTR 1122#ifdef CONFIG_F2FS_FS_XATTR
1132 .setxattr = generic_setxattr,
1133 .getxattr = generic_getxattr,
1134 .listxattr = f2fs_listxattr, 1123 .listxattr = f2fs_listxattr,
1135 .removexattr = generic_removexattr,
1136#endif 1124#endif
1137}; 1125};
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index a430c19607f4..572d12410c7c 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1801,10 +1801,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
1801 .mknod = fuse_mknod, 1801 .mknod = fuse_mknod,
1802 .permission = fuse_permission, 1802 .permission = fuse_permission,
1803 .getattr = fuse_getattr, 1803 .getattr = fuse_getattr,
1804 .setxattr = generic_setxattr,
1805 .getxattr = generic_getxattr,
1806 .listxattr = fuse_listxattr, 1804 .listxattr = fuse_listxattr,
1807 .removexattr = generic_removexattr,
1808 .get_acl = fuse_get_acl, 1805 .get_acl = fuse_get_acl,
1809 .set_acl = fuse_set_acl, 1806 .set_acl = fuse_set_acl,
1810}; 1807};
@@ -1824,10 +1821,7 @@ static const struct inode_operations fuse_common_inode_operations = {
1824 .setattr = fuse_setattr, 1821 .setattr = fuse_setattr,
1825 .permission = fuse_permission, 1822 .permission = fuse_permission,
1826 .getattr = fuse_getattr, 1823 .getattr = fuse_getattr,
1827 .setxattr = generic_setxattr,
1828 .getxattr = generic_getxattr,
1829 .listxattr = fuse_listxattr, 1824 .listxattr = fuse_listxattr,
1830 .removexattr = generic_removexattr,
1831 .get_acl = fuse_get_acl, 1825 .get_acl = fuse_get_acl,
1832 .set_acl = fuse_set_acl, 1826 .set_acl = fuse_set_acl,
1833}; 1827};
@@ -1837,10 +1831,7 @@ static const struct inode_operations fuse_symlink_inode_operations = {
1837 .get_link = fuse_get_link, 1831 .get_link = fuse_get_link,
1838 .readlink = generic_readlink, 1832 .readlink = generic_readlink,
1839 .getattr = fuse_getattr, 1833 .getattr = fuse_getattr,
1840 .setxattr = generic_setxattr,
1841 .getxattr = generic_getxattr,
1842 .listxattr = fuse_listxattr, 1834 .listxattr = fuse_listxattr,
1843 .removexattr = generic_removexattr,
1844}; 1835};
1845 1836
1846void fuse_init_common(struct inode *inode) 1837void fuse_init_common(struct inode *inode)
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 7efd1d19d325..f6c4f0058899 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2040,10 +2040,7 @@ const struct inode_operations gfs2_file_iops = {
2040 .permission = gfs2_permission, 2040 .permission = gfs2_permission,
2041 .setattr = gfs2_setattr, 2041 .setattr = gfs2_setattr,
2042 .getattr = gfs2_getattr, 2042 .getattr = gfs2_getattr,
2043 .setxattr = generic_setxattr,
2044 .getxattr = generic_getxattr,
2045 .listxattr = gfs2_listxattr, 2043 .listxattr = gfs2_listxattr,
2046 .removexattr = generic_removexattr,
2047 .fiemap = gfs2_fiemap, 2044 .fiemap = gfs2_fiemap,
2048 .get_acl = gfs2_get_acl, 2045 .get_acl = gfs2_get_acl,
2049 .set_acl = gfs2_set_acl, 2046 .set_acl = gfs2_set_acl,
@@ -2062,10 +2059,7 @@ const struct inode_operations gfs2_dir_iops = {
2062 .permission = gfs2_permission, 2059 .permission = gfs2_permission,
2063 .setattr = gfs2_setattr, 2060 .setattr = gfs2_setattr,
2064 .getattr = gfs2_getattr, 2061 .getattr = gfs2_getattr,
2065 .setxattr = generic_setxattr,
2066 .getxattr = generic_getxattr,
2067 .listxattr = gfs2_listxattr, 2062 .listxattr = gfs2_listxattr,
2068 .removexattr = generic_removexattr,
2069 .fiemap = gfs2_fiemap, 2063 .fiemap = gfs2_fiemap,
2070 .get_acl = gfs2_get_acl, 2064 .get_acl = gfs2_get_acl,
2071 .set_acl = gfs2_set_acl, 2065 .set_acl = gfs2_set_acl,
@@ -2078,10 +2072,7 @@ const struct inode_operations gfs2_symlink_iops = {
2078 .permission = gfs2_permission, 2072 .permission = gfs2_permission,
2079 .setattr = gfs2_setattr, 2073 .setattr = gfs2_setattr,
2080 .getattr = gfs2_getattr, 2074 .getattr = gfs2_getattr,
2081 .setxattr = generic_setxattr,
2082 .getxattr = generic_getxattr,
2083 .listxattr = gfs2_listxattr, 2075 .listxattr = gfs2_listxattr,
2084 .removexattr = generic_removexattr,
2085 .fiemap = gfs2_fiemap, 2076 .fiemap = gfs2_fiemap,
2086}; 2077};
2087 2078
diff --git a/fs/hfs/attr.c b/fs/hfs/attr.c
index d9a86919fdf6..0933600e11c8 100644
--- a/fs/hfs/attr.c
+++ b/fs/hfs/attr.c
@@ -13,9 +13,13 @@
13#include "hfs_fs.h" 13#include "hfs_fs.h"
14#include "btree.h" 14#include "btree.h"
15 15
16int hfs_setxattr(struct dentry *unused, struct inode *inode, 16enum hfs_xattr_type {
17 const char *name, const void *value, 17 HFS_TYPE,
18 size_t size, int flags) 18 HFS_CREATOR,
19};
20
21static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
22 const void *value, size_t size, int flags)
19{ 23{
20 struct hfs_find_data fd; 24 struct hfs_find_data fd;
21 hfs_cat_rec rec; 25 hfs_cat_rec rec;
@@ -36,18 +40,22 @@ int hfs_setxattr(struct dentry *unused, struct inode *inode,
36 sizeof(struct hfs_cat_file)); 40 sizeof(struct hfs_cat_file));
37 file = &rec.file; 41 file = &rec.file;
38 42
39 if (!strcmp(name, "hfs.type")) { 43 switch (type) {
44 case HFS_TYPE:
40 if (size == 4) 45 if (size == 4)
41 memcpy(&file->UsrWds.fdType, value, 4); 46 memcpy(&file->UsrWds.fdType, value, 4);
42 else 47 else
43 res = -ERANGE; 48 res = -ERANGE;
44 } else if (!strcmp(name, "hfs.creator")) { 49 break;
50
51 case HFS_CREATOR:
45 if (size == 4) 52 if (size == 4)
46 memcpy(&file->UsrWds.fdCreator, value, 4); 53 memcpy(&file->UsrWds.fdCreator, value, 4);
47 else 54 else
48 res = -ERANGE; 55 res = -ERANGE;
49 } else 56 break;
50 res = -EOPNOTSUPP; 57 }
58
51 if (!res) 59 if (!res)
52 hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, 60 hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
53 sizeof(struct hfs_cat_file)); 61 sizeof(struct hfs_cat_file));
@@ -56,8 +64,8 @@ out:
56 return res; 64 return res;
57} 65}
58 66
59ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode, 67static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
60 const char *name, void *value, size_t size) 68 void *value, size_t size)
61{ 69{
62 struct hfs_find_data fd; 70 struct hfs_find_data fd;
63 hfs_cat_rec rec; 71 hfs_cat_rec rec;
@@ -80,41 +88,64 @@ ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
80 } 88 }
81 file = &rec.file; 89 file = &rec.file;
82 90
83 if (!strcmp(name, "hfs.type")) { 91 switch (type) {
92 case HFS_TYPE:
84 if (size >= 4) { 93 if (size >= 4) {
85 memcpy(value, &file->UsrWds.fdType, 4); 94 memcpy(value, &file->UsrWds.fdType, 4);
86 res = 4; 95 res = 4;
87 } else 96 } else
88 res = size ? -ERANGE : 4; 97 res = size ? -ERANGE : 4;
89 } else if (!strcmp(name, "hfs.creator")) { 98 break;
99
100 case HFS_CREATOR:
90 if (size >= 4) { 101 if (size >= 4) {
91 memcpy(value, &file->UsrWds.fdCreator, 4); 102 memcpy(value, &file->UsrWds.fdCreator, 4);
92 res = 4; 103 res = 4;
93 } else 104 } else
94 res = size ? -ERANGE : 4; 105 res = size ? -ERANGE : 4;
95 } else 106 break;
96 res = -ENODATA; 107 }
108
97out: 109out:
98 if (size) 110 if (size)
99 hfs_find_exit(&fd); 111 hfs_find_exit(&fd);
100 return res; 112 return res;
101} 113}
102 114
103#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type")) 115static int hfs_xattr_get(const struct xattr_handler *handler,
104 116 struct dentry *unused, struct inode *inode,
105ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size) 117 const char *name, void *value, size_t size)
106{ 118{
107 struct inode *inode = d_inode(dentry); 119 return __hfs_getxattr(inode, handler->flags, value, size);
120}
108 121
109 if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode)) 122static int hfs_xattr_set(const struct xattr_handler *handler,
123 struct dentry *unused, struct inode *inode,
124 const char *name, const void *value, size_t size,
125 int flags)
126{
127 if (!value)
110 return -EOPNOTSUPP; 128 return -EOPNOTSUPP;
111 129
112 if (!buffer || !size) 130 return __hfs_setxattr(inode, handler->flags, value, size, flags);
113 return HFS_ATTRLIST_SIZE;
114 if (size < HFS_ATTRLIST_SIZE)
115 return -ERANGE;
116 strcpy(buffer, "hfs.type");
117 strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
118
119 return HFS_ATTRLIST_SIZE;
120} 131}
132
133static const struct xattr_handler hfs_creator_handler = {
134 .name = "hfs.creator",
135 .flags = HFS_CREATOR,
136 .get = hfs_xattr_get,
137 .set = hfs_xattr_set,
138};
139
140static const struct xattr_handler hfs_type_handler = {
141 .name = "hfs.type",
142 .flags = HFS_TYPE,
143 .get = hfs_xattr_get,
144 .set = hfs_xattr_set,
145};
146
147const struct xattr_handler *hfs_xattr_handlers[] = {
148 &hfs_creator_handler,
149 &hfs_type_handler,
150 NULL
151};
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 16f5172ee40d..4cdec5a19347 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -212,11 +212,7 @@ extern void hfs_evict_inode(struct inode *);
212extern void hfs_delete_inode(struct inode *); 212extern void hfs_delete_inode(struct inode *);
213 213
214/* attr.c */ 214/* attr.c */
215extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name, 215extern const struct xattr_handler *hfs_xattr_handlers[];
216 const void *value, size_t size, int flags);
217extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode,
218 const char *name, void *value, size_t size);
219extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
220 216
221/* mdb.c */ 217/* mdb.c */
222extern int hfs_mdb_get(struct super_block *); 218extern int hfs_mdb_get(struct super_block *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 09cce23864da..ed373261f26d 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -15,6 +15,7 @@
15#include <linux/mpage.h> 15#include <linux/mpage.h>
16#include <linux/sched.h> 16#include <linux/sched.h>
17#include <linux/uio.h> 17#include <linux/uio.h>
18#include <linux/xattr.h>
18 19
19#include "hfs_fs.h" 20#include "hfs_fs.h"
20#include "btree.h" 21#include "btree.h"
@@ -687,7 +688,5 @@ static const struct file_operations hfs_file_operations = {
687static const struct inode_operations hfs_file_inode_operations = { 688static const struct inode_operations hfs_file_inode_operations = {
688 .lookup = hfs_file_lookup, 689 .lookup = hfs_file_lookup,
689 .setattr = hfs_inode_setattr, 690 .setattr = hfs_inode_setattr,
690 .setxattr = hfs_setxattr, 691 .listxattr = generic_listxattr,
691 .getxattr = hfs_getxattr,
692 .listxattr = hfs_listxattr,
693}; 692};
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 1ca95c232bb5..bf6304a350a6 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -406,6 +406,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
406 } 406 }
407 407
408 sb->s_op = &hfs_super_operations; 408 sb->s_op = &hfs_super_operations;
409 sb->s_xattr = hfs_xattr_handlers;
409 sb->s_flags |= MS_NODIRATIME; 410 sb->s_flags |= MS_NODIRATIME;
410 mutex_init(&sbi->bitmap_lock); 411 mutex_init(&sbi->bitmap_lock);
411 412
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 42e128661dc1..9cbe43075de5 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -562,10 +562,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
562 .symlink = hfsplus_symlink, 562 .symlink = hfsplus_symlink,
563 .mknod = hfsplus_mknod, 563 .mknod = hfsplus_mknod,
564 .rename = hfsplus_rename, 564 .rename = hfsplus_rename,
565 .setxattr = generic_setxattr,
566 .getxattr = generic_getxattr,
567 .listxattr = hfsplus_listxattr, 565 .listxattr = hfsplus_listxattr,
568 .removexattr = generic_removexattr,
569#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL 566#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
570 .get_acl = hfsplus_get_posix_acl, 567 .get_acl = hfsplus_get_posix_acl,
571 .set_acl = hfsplus_set_posix_acl, 568 .set_acl = hfsplus_set_posix_acl,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index c43ef397a3aa..10827c912c4d 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -333,10 +333,7 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
333 333
334static const struct inode_operations hfsplus_file_inode_operations = { 334static const struct inode_operations hfsplus_file_inode_operations = {
335 .setattr = hfsplus_setattr, 335 .setattr = hfsplus_setattr,
336 .setxattr = generic_setxattr,
337 .getxattr = generic_getxattr,
338 .listxattr = hfsplus_listxattr, 336 .listxattr = hfsplus_listxattr,
339 .removexattr = generic_removexattr,
340#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL 337#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
341 .get_acl = hfsplus_get_posix_acl, 338 .get_acl = hfsplus_get_posix_acl,
342 .set_acl = hfsplus_set_posix_acl, 339 .set_acl = hfsplus_set_posix_acl,
diff --git a/fs/inode.c b/fs/inode.c
index a3c7ba7f6b59..7d037591259d 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -140,6 +140,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
140 inode->i_fop = &no_open_fops; 140 inode->i_fop = &no_open_fops;
141 inode->__i_nlink = 1; 141 inode->__i_nlink = 1;
142 inode->i_opflags = 0; 142 inode->i_opflags = 0;
143 if (sb->s_xattr)
144 inode->i_opflags |= IOP_XATTR;
143 i_uid_write(inode, 0); 145 i_uid_write(inode, 0);
144 i_gid_write(inode, 0); 146 i_gid_write(inode, 0);
145 atomic_set(&inode->i_writecount, 0); 147 atomic_set(&inode->i_writecount, 0);
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 30eb33ff8189..9b242434adf2 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -61,10 +61,7 @@ const struct inode_operations jffs2_dir_inode_operations =
61 .get_acl = jffs2_get_acl, 61 .get_acl = jffs2_get_acl,
62 .set_acl = jffs2_set_acl, 62 .set_acl = jffs2_set_acl,
63 .setattr = jffs2_setattr, 63 .setattr = jffs2_setattr,
64 .setxattr = jffs2_setxattr,
65 .getxattr = jffs2_getxattr,
66 .listxattr = jffs2_listxattr, 64 .listxattr = jffs2_listxattr,
67 .removexattr = jffs2_removexattr
68}; 65};
69 66
70/***********************************************************************/ 67/***********************************************************************/
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 0e62dec3effc..c12476e309c6 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -66,10 +66,7 @@ const struct inode_operations jffs2_file_inode_operations =
66 .get_acl = jffs2_get_acl, 66 .get_acl = jffs2_get_acl,
67 .set_acl = jffs2_set_acl, 67 .set_acl = jffs2_set_acl,
68 .setattr = jffs2_setattr, 68 .setattr = jffs2_setattr,
69 .setxattr = jffs2_setxattr,
70 .getxattr = jffs2_getxattr,
71 .listxattr = jffs2_listxattr, 69 .listxattr = jffs2_listxattr,
72 .removexattr = jffs2_removexattr
73}; 70};
74 71
75const struct address_space_operations jffs2_file_address_operations = 72const struct address_space_operations jffs2_file_address_operations =
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index 2cabd649d4fb..8f3f0855fcd2 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -16,8 +16,5 @@ const struct inode_operations jffs2_symlink_inode_operations =
16 .readlink = generic_readlink, 16 .readlink = generic_readlink,
17 .get_link = simple_get_link, 17 .get_link = simple_get_link,
18 .setattr = jffs2_setattr, 18 .setattr = jffs2_setattr,
19 .setxattr = jffs2_setxattr,
20 .getxattr = jffs2_getxattr,
21 .listxattr = jffs2_listxattr, 19 .listxattr = jffs2_listxattr,
22 .removexattr = jffs2_removexattr
23}; 20};
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 467ff376ee26..720007b2fd65 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -99,9 +99,6 @@ extern const struct xattr_handler jffs2_user_xattr_handler;
99extern const struct xattr_handler jffs2_trusted_xattr_handler; 99extern const struct xattr_handler jffs2_trusted_xattr_handler;
100 100
101extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); 101extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
102#define jffs2_getxattr generic_getxattr
103#define jffs2_setxattr generic_setxattr
104#define jffs2_removexattr generic_removexattr
105 102
106#else 103#else
107 104
@@ -116,9 +113,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
116 113
117#define jffs2_xattr_handlers NULL 114#define jffs2_xattr_handlers NULL
118#define jffs2_listxattr NULL 115#define jffs2_listxattr NULL
119#define jffs2_getxattr NULL
120#define jffs2_setxattr NULL
121#define jffs2_removexattr NULL
122 116
123#endif /* CONFIG_JFFS2_FS_XATTR */ 117#endif /* CONFIG_JFFS2_FS_XATTR */
124 118
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index cf62037b8a04..739492c7a3fd 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -140,10 +140,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
140} 140}
141 141
142const struct inode_operations jfs_file_inode_operations = { 142const struct inode_operations jfs_file_inode_operations = {
143 .setxattr = generic_setxattr,
144 .getxattr = generic_getxattr,
145 .listxattr = jfs_listxattr, 143 .listxattr = jfs_listxattr,
146 .removexattr = generic_removexattr,
147 .setattr = jfs_setattr, 144 .setattr = jfs_setattr,
148#ifdef CONFIG_JFS_POSIX_ACL 145#ifdef CONFIG_JFS_POSIX_ACL
149 .get_acl = jfs_get_acl, 146 .get_acl = jfs_get_acl,
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 814b0c58016c..e420c6088336 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1537,10 +1537,7 @@ const struct inode_operations jfs_dir_inode_operations = {
1537 .rmdir = jfs_rmdir, 1537 .rmdir = jfs_rmdir,
1538 .mknod = jfs_mknod, 1538 .mknod = jfs_mknod,
1539 .rename = jfs_rename, 1539 .rename = jfs_rename,
1540 .setxattr = generic_setxattr,
1541 .getxattr = generic_getxattr,
1542 .listxattr = jfs_listxattr, 1540 .listxattr = jfs_listxattr,
1543 .removexattr = generic_removexattr,
1544 .setattr = jfs_setattr, 1541 .setattr = jfs_setattr,
1545#ifdef CONFIG_JFS_POSIX_ACL 1542#ifdef CONFIG_JFS_POSIX_ACL
1546 .get_acl = jfs_get_acl, 1543 .get_acl = jfs_get_acl,
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index c94c7e4a1323..c82404fee6cd 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -25,19 +25,13 @@ const struct inode_operations jfs_fast_symlink_inode_operations = {
25 .readlink = generic_readlink, 25 .readlink = generic_readlink,
26 .get_link = simple_get_link, 26 .get_link = simple_get_link,
27 .setattr = jfs_setattr, 27 .setattr = jfs_setattr,
28 .setxattr = generic_setxattr,
29 .getxattr = generic_getxattr,
30 .listxattr = jfs_listxattr, 28 .listxattr = jfs_listxattr,
31 .removexattr = generic_removexattr,
32}; 29};
33 30
34const struct inode_operations jfs_symlink_inode_operations = { 31const struct inode_operations jfs_symlink_inode_operations = {
35 .readlink = generic_readlink, 32 .readlink = generic_readlink,
36 .get_link = page_get_link, 33 .get_link = page_get_link,
37 .setattr = jfs_setattr, 34 .setattr = jfs_setattr,
38 .setxattr = generic_setxattr,
39 .getxattr = generic_getxattr,
40 .listxattr = jfs_listxattr, 35 .listxattr = jfs_listxattr,
41 .removexattr = generic_removexattr,
42}; 36};
43 37
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index e57174d43683..2b23ad91a464 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -1126,9 +1126,6 @@ const struct inode_operations kernfs_dir_iops = {
1126 .permission = kernfs_iop_permission, 1126 .permission = kernfs_iop_permission,
1127 .setattr = kernfs_iop_setattr, 1127 .setattr = kernfs_iop_setattr,
1128 .getattr = kernfs_iop_getattr, 1128 .getattr = kernfs_iop_getattr,
1129 .setxattr = kernfs_iop_setxattr,
1130 .removexattr = kernfs_iop_removexattr,
1131 .getxattr = kernfs_iop_getxattr,
1132 .listxattr = kernfs_iop_listxattr, 1129 .listxattr = kernfs_iop_listxattr,
1133 1130
1134 .mkdir = kernfs_iop_mkdir, 1131 .mkdir = kernfs_iop_mkdir,
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index df21f5b75549..102b6f0bc7af 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -28,9 +28,6 @@ static const struct inode_operations kernfs_iops = {
28 .permission = kernfs_iop_permission, 28 .permission = kernfs_iop_permission,
29 .setattr = kernfs_iop_setattr, 29 .setattr = kernfs_iop_setattr,
30 .getattr = kernfs_iop_getattr, 30 .getattr = kernfs_iop_getattr,
31 .setxattr = kernfs_iop_setxattr,
32 .removexattr = kernfs_iop_removexattr,
33 .getxattr = kernfs_iop_getxattr,
34 .listxattr = kernfs_iop_listxattr, 31 .listxattr = kernfs_iop_listxattr,
35}; 32};
36 33
@@ -138,17 +135,12 @@ out:
138 return error; 135 return error;
139} 136}
140 137
141static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata, 138static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
142 u32 *secdata_len) 139 u32 *secdata_len)
143{ 140{
144 struct kernfs_iattrs *attrs;
145 void *old_secdata; 141 void *old_secdata;
146 size_t old_secdata_len; 142 size_t old_secdata_len;
147 143
148 attrs = kernfs_iattrs(kn);
149 if (!attrs)
150 return -ENOMEM;
151
152 old_secdata = attrs->ia_secdata; 144 old_secdata = attrs->ia_secdata;
153 old_secdata_len = attrs->ia_secdata_len; 145 old_secdata_len = attrs->ia_secdata_len;
154 146
@@ -160,71 +152,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
160 return 0; 152 return 0;
161} 153}
162 154
163int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
164 const char *name, const void *value,
165 size_t size, int flags)
166{
167 struct kernfs_node *kn = inode->i_private;
168 struct kernfs_iattrs *attrs;
169 void *secdata;
170 int error;
171 u32 secdata_len = 0;
172
173 attrs = kernfs_iattrs(kn);
174 if (!attrs)
175 return -ENOMEM;
176
177 if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
178 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
179 error = security_inode_setsecurity(inode, suffix,
180 value, size, flags);
181 if (error)
182 return error;
183 error = security_inode_getsecctx(inode,
184 &secdata, &secdata_len);
185 if (error)
186 return error;
187
188 mutex_lock(&kernfs_mutex);
189 error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
190 mutex_unlock(&kernfs_mutex);
191
192 if (secdata)
193 security_release_secctx(secdata, secdata_len);
194 return error;
195 } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
196 return simple_xattr_set(&attrs->xattrs, name, value, size,
197 flags);
198 }
199
200 return -EINVAL;
201}
202
203int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
204{
205 struct kernfs_node *kn = dentry->d_fsdata;
206 struct kernfs_iattrs *attrs;
207
208 attrs = kernfs_iattrs(kn);
209 if (!attrs)
210 return -ENOMEM;
211
212 return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
213}
214
215ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
216 const char *name, void *buf, size_t size)
217{
218 struct kernfs_node *kn = inode->i_private;
219 struct kernfs_iattrs *attrs;
220
221 attrs = kernfs_iattrs(kn);
222 if (!attrs)
223 return -ENOMEM;
224
225 return simple_xattr_get(&attrs->xattrs, name, buf, size);
226}
227
228ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) 155ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
229{ 156{
230 struct kernfs_node *kn = dentry->d_fsdata; 157 struct kernfs_node *kn = dentry->d_fsdata;
@@ -376,3 +303,83 @@ int kernfs_iop_permission(struct inode *inode, int mask)
376 303
377 return generic_permission(inode, mask); 304 return generic_permission(inode, mask);
378} 305}
306
307static int kernfs_xattr_get(const struct xattr_handler *handler,
308 struct dentry *unused, struct inode *inode,
309 const char *suffix, void *value, size_t size)
310{
311 const char *name = xattr_full_name(handler, suffix);
312 struct kernfs_node *kn = inode->i_private;
313 struct kernfs_iattrs *attrs;
314
315 attrs = kernfs_iattrs(kn);
316 if (!attrs)
317 return -ENOMEM;
318
319 return simple_xattr_get(&attrs->xattrs, name, value, size);
320}
321
322static int kernfs_xattr_set(const struct xattr_handler *handler,
323 struct dentry *unused, struct inode *inode,
324 const char *suffix, const void *value,
325 size_t size, int flags)
326{
327 const char *name = xattr_full_name(handler, suffix);
328 struct kernfs_node *kn = inode->i_private;
329 struct kernfs_iattrs *attrs;
330
331 attrs = kernfs_iattrs(kn);
332 if (!attrs)
333 return -ENOMEM;
334
335 return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
336}
337
338const struct xattr_handler kernfs_trusted_xattr_handler = {
339 .prefix = XATTR_TRUSTED_PREFIX,
340 .get = kernfs_xattr_get,
341 .set = kernfs_xattr_set,
342};
343
344static int kernfs_security_xattr_set(const struct xattr_handler *handler,
345 struct dentry *unused, struct inode *inode,
346 const char *suffix, const void *value,
347 size_t size, int flags)
348{
349 struct kernfs_node *kn = inode->i_private;
350 struct kernfs_iattrs *attrs;
351 void *secdata;
352 u32 secdata_len = 0;
353 int error;
354
355 attrs = kernfs_iattrs(kn);
356 if (!attrs)
357 return -ENOMEM;
358
359 error = security_inode_setsecurity(inode, suffix, value, size, flags);
360 if (error)
361 return error;
362 error = security_inode_getsecctx(inode, &secdata, &secdata_len);
363 if (error)
364 return error;
365
366 mutex_lock(&kernfs_mutex);
367 error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
368 mutex_unlock(&kernfs_mutex);
369
370 if (secdata)
371 security_release_secctx(secdata, secdata_len);
372 return error;
373}
374
375const struct xattr_handler kernfs_security_xattr_handler = {
376 .prefix = XATTR_SECURITY_PREFIX,
377 .get = kernfs_xattr_get,
378 .set = kernfs_security_xattr_set,
379};
380
381const struct xattr_handler *kernfs_xattr_handlers[] = {
382 &kernfs_trusted_xattr_handler,
383 &kernfs_security_xattr_handler,
384 NULL
385};
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 37159235ac10..bfd551bbf231 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -76,17 +76,12 @@ extern struct kmem_cache *kernfs_node_cache;
76/* 76/*
77 * inode.c 77 * inode.c
78 */ 78 */
79extern const struct xattr_handler *kernfs_xattr_handlers[];
79void kernfs_evict_inode(struct inode *inode); 80void kernfs_evict_inode(struct inode *inode);
80int kernfs_iop_permission(struct inode *inode, int mask); 81int kernfs_iop_permission(struct inode *inode, int mask);
81int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr); 82int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
82int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, 83int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
83 struct kstat *stat); 84 struct kstat *stat);
84int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode,
85 const char *name, const void *value,
86 size_t size, int flags);
87int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
88ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode,
89 const char *name, void *buf, size_t size);
90ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); 85ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
91 86
92/* 87/*
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index b3d73ad52b22..d5b149a45be1 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -158,6 +158,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
158 sb->s_blocksize_bits = PAGE_SHIFT; 158 sb->s_blocksize_bits = PAGE_SHIFT;
159 sb->s_magic = magic; 159 sb->s_magic = magic;
160 sb->s_op = &kernfs_sops; 160 sb->s_op = &kernfs_sops;
161 sb->s_xattr = kernfs_xattr_handlers;
161 sb->s_time_gran = 1; 162 sb->s_time_gran = 1;
162 163
163 /* get root inode, initialize and unlock it */ 164 /* get root inode, initialize and unlock it */
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index 117b8b3416f9..9b43ca02b7ab 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -134,9 +134,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
134} 134}
135 135
136const struct inode_operations kernfs_symlink_iops = { 136const struct inode_operations kernfs_symlink_iops = {
137 .setxattr = kernfs_iop_setxattr,
138 .removexattr = kernfs_iop_removexattr,
139 .getxattr = kernfs_iop_getxattr,
140 .listxattr = kernfs_iop_listxattr, 137 .listxattr = kernfs_iop_listxattr,
141 .readlink = generic_readlink, 138 .readlink = generic_readlink,
142 .get_link = kernfs_iop_get_link, 139 .get_link = kernfs_iop_get_link,
diff --git a/fs/libfs.c b/fs/libfs.c
index 2b3c3ae70153..a6d89f151771 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -236,8 +236,8 @@ static const struct super_operations simple_super_operations = {
236 * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that 236 * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
237 * will never be mountable) 237 * will never be mountable)
238 */ 238 */
239struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name, 239struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
240 const struct super_operations *ops, 240 const struct super_operations *ops, const struct xattr_handler **xattr,
241 const struct dentry_operations *dops, unsigned long magic) 241 const struct dentry_operations *dops, unsigned long magic)
242{ 242{
243 struct super_block *s; 243 struct super_block *s;
@@ -254,6 +254,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
254 s->s_blocksize_bits = PAGE_SHIFT; 254 s->s_blocksize_bits = PAGE_SHIFT;
255 s->s_magic = magic; 255 s->s_magic = magic;
256 s->s_op = ops ? ops : &simple_super_operations; 256 s->s_op = ops ? ops : &simple_super_operations;
257 s->s_xattr = xattr;
257 s->s_time_gran = 1; 258 s->s_time_gran = 1;
258 root = new_inode(s); 259 root = new_inode(s);
259 if (!root) 260 if (!root)
@@ -281,7 +282,7 @@ Enomem:
281 deactivate_locked_super(s); 282 deactivate_locked_super(s);
282 return ERR_PTR(-ENOMEM); 283 return ERR_PTR(-ENOMEM);
283} 284}
284EXPORT_SYMBOL(mount_pseudo); 285EXPORT_SYMBOL(mount_pseudo_xattr);
285 286
286int simple_open(struct inode *inode, struct file *file) 287int simple_open(struct inode *inode, struct file *file)
287{ 288{
@@ -1149,24 +1150,6 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
1149 return -EPERM; 1150 return -EPERM;
1150} 1151}
1151 1152
1152static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
1153 const char *name, const void *value,
1154 size_t size, int flags)
1155{
1156 return -EOPNOTSUPP;
1157}
1158
1159static ssize_t empty_dir_getxattr(struct dentry *dentry, struct inode *inode,
1160 const char *name, void *value, size_t size)
1161{
1162 return -EOPNOTSUPP;
1163}
1164
1165static int empty_dir_removexattr(struct dentry *dentry, const char *name)
1166{
1167 return -EOPNOTSUPP;
1168}
1169
1170static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size) 1153static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
1171{ 1154{
1172 return -EOPNOTSUPP; 1155 return -EOPNOTSUPP;
@@ -1177,9 +1160,6 @@ static const struct inode_operations empty_dir_inode_operations = {
1177 .permission = generic_permission, 1160 .permission = generic_permission,
1178 .setattr = empty_dir_setattr, 1161 .setattr = empty_dir_setattr,
1179 .getattr = empty_dir_getattr, 1162 .getattr = empty_dir_getattr,
1180 .setxattr = empty_dir_setxattr,
1181 .getxattr = empty_dir_getxattr,
1182 .removexattr = empty_dir_removexattr,
1183 .listxattr = empty_dir_listxattr, 1163 .listxattr = empty_dir_listxattr,
1184}; 1164};
1185 1165
@@ -1215,6 +1195,7 @@ void make_empty_dir_inode(struct inode *inode)
1215 inode->i_blocks = 0; 1195 inode->i_blocks = 0;
1216 1196
1217 inode->i_op = &empty_dir_inode_operations; 1197 inode->i_op = &empty_dir_inode_operations;
1198 inode->i_opflags &= ~IOP_XATTR;
1218 inode->i_fop = &empty_dir_operations; 1199 inode->i_fop = &empty_dir_operations;
1219} 1200}
1220 1201
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 698be9361280..dc925b531f32 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -899,9 +899,6 @@ static const struct inode_operations nfs3_dir_inode_operations = {
899 .setattr = nfs_setattr, 899 .setattr = nfs_setattr,
900#ifdef CONFIG_NFS_V3_ACL 900#ifdef CONFIG_NFS_V3_ACL
901 .listxattr = nfs3_listxattr, 901 .listxattr = nfs3_listxattr,
902 .getxattr = generic_getxattr,
903 .setxattr = generic_setxattr,
904 .removexattr = generic_removexattr,
905 .get_acl = nfs3_get_acl, 902 .get_acl = nfs3_get_acl,
906 .set_acl = nfs3_set_acl, 903 .set_acl = nfs3_set_acl,
907#endif 904#endif
@@ -913,9 +910,6 @@ static const struct inode_operations nfs3_file_inode_operations = {
913 .setattr = nfs_setattr, 910 .setattr = nfs_setattr,
914#ifdef CONFIG_NFS_V3_ACL 911#ifdef CONFIG_NFS_V3_ACL
915 .listxattr = nfs3_listxattr, 912 .listxattr = nfs3_listxattr,
916 .getxattr = generic_getxattr,
917 .setxattr = generic_setxattr,
918 .removexattr = generic_removexattr,
919 .get_acl = nfs3_get_acl, 913 .get_acl = nfs3_get_acl,
920 .set_acl = nfs3_set_acl, 914 .set_acl = nfs3_set_acl,
921#endif 915#endif
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a9dec32ba9ba..0e327528a3ce 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -8941,20 +8941,14 @@ static const struct inode_operations nfs4_dir_inode_operations = {
8941 .permission = nfs_permission, 8941 .permission = nfs_permission,
8942 .getattr = nfs_getattr, 8942 .getattr = nfs_getattr,
8943 .setattr = nfs_setattr, 8943 .setattr = nfs_setattr,
8944 .getxattr = generic_getxattr,
8945 .setxattr = generic_setxattr,
8946 .listxattr = nfs4_listxattr, 8944 .listxattr = nfs4_listxattr,
8947 .removexattr = generic_removexattr,
8948}; 8945};
8949 8946
8950static const struct inode_operations nfs4_file_inode_operations = { 8947static const struct inode_operations nfs4_file_inode_operations = {
8951 .permission = nfs_permission, 8948 .permission = nfs_permission,
8952 .getattr = nfs_getattr, 8949 .getattr = nfs_getattr,
8953 .setattr = nfs_setattr, 8950 .setattr = nfs_setattr,
8954 .getxattr = generic_getxattr,
8955 .setxattr = generic_setxattr,
8956 .listxattr = nfs4_listxattr, 8951 .listxattr = nfs4_listxattr,
8957 .removexattr = generic_removexattr,
8958}; 8952};
8959 8953
8960const struct nfs_rpc_ops nfs_v4_clientops = { 8954const struct nfs_rpc_ops nfs_v4_clientops = {
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 5e1901546868..ba5c177d0ed6 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2444,10 +2444,7 @@ const struct inode_operations ocfs2_file_iops = {
2444 .setattr = ocfs2_setattr, 2444 .setattr = ocfs2_setattr,
2445 .getattr = ocfs2_getattr, 2445 .getattr = ocfs2_getattr,
2446 .permission = ocfs2_permission, 2446 .permission = ocfs2_permission,
2447 .setxattr = generic_setxattr,
2448 .getxattr = generic_getxattr,
2449 .listxattr = ocfs2_listxattr, 2447 .listxattr = ocfs2_listxattr,
2450 .removexattr = generic_removexattr,
2451 .fiemap = ocfs2_fiemap, 2448 .fiemap = ocfs2_fiemap,
2452 .get_acl = ocfs2_iop_get_acl, 2449 .get_acl = ocfs2_iop_get_acl,
2453 .set_acl = ocfs2_iop_set_acl, 2450 .set_acl = ocfs2_iop_set_acl,
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index a8f1225e6d9b..6cc043ebb9fa 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2913,10 +2913,7 @@ const struct inode_operations ocfs2_dir_iops = {
2913 .setattr = ocfs2_setattr, 2913 .setattr = ocfs2_setattr,
2914 .getattr = ocfs2_getattr, 2914 .getattr = ocfs2_getattr,
2915 .permission = ocfs2_permission, 2915 .permission = ocfs2_permission,
2916 .setxattr = generic_setxattr,
2917 .getxattr = generic_getxattr,
2918 .listxattr = ocfs2_listxattr, 2916 .listxattr = ocfs2_listxattr,
2919 .removexattr = generic_removexattr,
2920 .fiemap = ocfs2_fiemap, 2917 .fiemap = ocfs2_fiemap,
2921 .get_acl = ocfs2_iop_get_acl, 2918 .get_acl = ocfs2_iop_get_acl,
2922 .set_acl = ocfs2_iop_set_acl, 2919 .set_acl = ocfs2_iop_set_acl,
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 6c2a3e3c521c..6ad8eecefe21 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -91,9 +91,6 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
91 .get_link = page_get_link, 91 .get_link = page_get_link,
92 .getattr = ocfs2_getattr, 92 .getattr = ocfs2_getattr,
93 .setattr = ocfs2_setattr, 93 .setattr = ocfs2_setattr,
94 .setxattr = generic_setxattr,
95 .getxattr = generic_getxattr,
96 .listxattr = ocfs2_listxattr, 94 .listxattr = ocfs2_listxattr,
97 .removexattr = generic_removexattr,
98 .fiemap = ocfs2_fiemap, 95 .fiemap = ocfs2_fiemap,
99}; 96};
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index c83846fb9b14..0e3bd7e07f88 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -296,10 +296,7 @@ const struct inode_operations orangefs_file_inode_operations = {
296 .set_acl = orangefs_set_acl, 296 .set_acl = orangefs_set_acl,
297 .setattr = orangefs_setattr, 297 .setattr = orangefs_setattr,
298 .getattr = orangefs_getattr, 298 .getattr = orangefs_getattr,
299 .setxattr = generic_setxattr,
300 .getxattr = generic_getxattr,
301 .listxattr = orangefs_listxattr, 299 .listxattr = orangefs_listxattr,
302 .removexattr = generic_removexattr,
303 .permission = orangefs_permission, 300 .permission = orangefs_permission,
304}; 301};
305 302
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index 0e34fcfa4d51..4d5576a21c82 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -462,9 +462,6 @@ const struct inode_operations orangefs_dir_inode_operations = {
462 .rename = orangefs_rename, 462 .rename = orangefs_rename,
463 .setattr = orangefs_setattr, 463 .setattr = orangefs_setattr,
464 .getattr = orangefs_getattr, 464 .getattr = orangefs_getattr,
465 .setxattr = generic_setxattr,
466 .getxattr = generic_getxattr,
467 .removexattr = generic_removexattr,
468 .listxattr = orangefs_listxattr, 465 .listxattr = orangefs_listxattr,
469 .permission = orangefs_permission, 466 .permission = orangefs_permission,
470}; 467};
diff --git a/fs/orangefs/symlink.c b/fs/orangefs/symlink.c
index 8fecf823f5ba..10b0b06e075e 100644
--- a/fs/orangefs/symlink.c
+++ b/fs/orangefs/symlink.c
@@ -14,6 +14,5 @@ const struct inode_operations orangefs_symlink_inode_operations = {
14 .setattr = orangefs_setattr, 14 .setattr = orangefs_setattr,
15 .getattr = orangefs_getattr, 15 .getattr = orangefs_getattr,
16 .listxattr = orangefs_listxattr, 16 .listxattr = orangefs_listxattr,
17 .setxattr = generic_setxattr,
18 .permission = orangefs_permission, 17 .permission = orangefs_permission,
19}; 18};
diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c
index 2a9f07f06d10..74a81b1daaac 100644
--- a/fs/orangefs/xattr.c
+++ b/fs/orangefs/xattr.c
@@ -73,6 +73,9 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
73 "%s: name %s, buffer_size %zd\n", 73 "%s: name %s, buffer_size %zd\n",
74 __func__, name, size); 74 __func__, name, size);
75 75
76 if (S_ISLNK(inode->i_mode))
77 return -EOPNOTSUPP;
78
76 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) { 79 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
77 gossip_err("Invalid key length (%d)\n", 80 gossip_err("Invalid key length (%d)\n",
78 (int)strlen(name)); 81 (int)strlen(name));
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index db37a0e02d32..3f803b3a1f82 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
58 char *buf, *name, *value = NULL; 58 char *buf, *name, *value = NULL;
59 int uninitialized_var(error); 59 int uninitialized_var(error);
60 60
61 if (!old->d_inode->i_op->getxattr || 61 if (!(old->d_inode->i_opflags & IOP_XATTR) ||
62 !new->d_inode->i_op->getxattr) 62 !(new->d_inode->i_opflags & IOP_XATTR))
63 return 0; 63 return 0;
64 64
65 list_size = vfs_listxattr(old, NULL, 0); 65 list_size = vfs_listxattr(old, NULL, 0);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index b0ffa1d1677e..3a60e68ec965 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -1013,10 +1013,7 @@ const struct inode_operations ovl_dir_inode_operations = {
1013 .mknod = ovl_mknod, 1013 .mknod = ovl_mknod,
1014 .permission = ovl_permission, 1014 .permission = ovl_permission,
1015 .getattr = ovl_dir_getattr, 1015 .getattr = ovl_dir_getattr,
1016 .setxattr = generic_setxattr,
1017 .getxattr = generic_getxattr,
1018 .listxattr = ovl_listxattr, 1016 .listxattr = ovl_listxattr,
1019 .removexattr = generic_removexattr,
1020 .get_acl = ovl_get_acl, 1017 .get_acl = ovl_get_acl,
1021 .update_time = ovl_update_time, 1018 .update_time = ovl_update_time,
1022}; 1019};
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 251e5253f2c1..c18d6a4ff456 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -367,10 +367,7 @@ static const struct inode_operations ovl_file_inode_operations = {
367 .setattr = ovl_setattr, 367 .setattr = ovl_setattr,
368 .permission = ovl_permission, 368 .permission = ovl_permission,
369 .getattr = ovl_getattr, 369 .getattr = ovl_getattr,
370 .setxattr = generic_setxattr,
371 .getxattr = generic_getxattr,
372 .listxattr = ovl_listxattr, 370 .listxattr = ovl_listxattr,
373 .removexattr = generic_removexattr,
374 .get_acl = ovl_get_acl, 371 .get_acl = ovl_get_acl,
375 .update_time = ovl_update_time, 372 .update_time = ovl_update_time,
376}; 373};
@@ -380,10 +377,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
380 .get_link = ovl_get_link, 377 .get_link = ovl_get_link,
381 .readlink = ovl_readlink, 378 .readlink = ovl_readlink,
382 .getattr = ovl_getattr, 379 .getattr = ovl_getattr,
383 .setxattr = generic_setxattr,
384 .getxattr = generic_getxattr,
385 .listxattr = ovl_listxattr, 380 .listxattr = ovl_listxattr,
386 .removexattr = generic_removexattr,
387 .update_time = ovl_update_time, 381 .update_time = ovl_update_time,
388}; 382};
389 383
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 3d0b9dee2b76..7e3f0127fc1a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
275 char val; 275 char val;
276 struct inode *inode = dentry->d_inode; 276 struct inode *inode = dentry->d_inode;
277 277
278 if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr) 278 if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
279 return false; 279 return false;
280 280
281 res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1); 281 res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
282 if (res == 1 && val == 'y') 282 if (res == 1 && val == 'y')
283 return true; 283 return true;
284 284
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 90f815bdfa8a..2f8c5c9bdaf6 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -260,10 +260,7 @@ const struct file_operations reiserfs_file_operations = {
260 260
261const struct inode_operations reiserfs_file_inode_operations = { 261const struct inode_operations reiserfs_file_inode_operations = {
262 .setattr = reiserfs_setattr, 262 .setattr = reiserfs_setattr,
263 .setxattr = generic_setxattr,
264 .getxattr = generic_getxattr,
265 .listxattr = reiserfs_listxattr, 263 .listxattr = reiserfs_listxattr,
266 .removexattr = generic_removexattr,
267 .permission = reiserfs_permission, 264 .permission = reiserfs_permission,
268 .get_acl = reiserfs_get_acl, 265 .get_acl = reiserfs_get_acl,
269 .set_acl = reiserfs_set_acl, 266 .set_acl = reiserfs_set_acl,
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 8a36696d6df9..fd7d0606aa96 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1650,10 +1650,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
1650 .mknod = reiserfs_mknod, 1650 .mknod = reiserfs_mknod,
1651 .rename = reiserfs_rename, 1651 .rename = reiserfs_rename,
1652 .setattr = reiserfs_setattr, 1652 .setattr = reiserfs_setattr,
1653 .setxattr = generic_setxattr,
1654 .getxattr = generic_getxattr,
1655 .listxattr = reiserfs_listxattr, 1653 .listxattr = reiserfs_listxattr,
1656 .removexattr = generic_removexattr,
1657 .permission = reiserfs_permission, 1654 .permission = reiserfs_permission,
1658 .get_acl = reiserfs_get_acl, 1655 .get_acl = reiserfs_get_acl,
1659 .set_acl = reiserfs_set_acl, 1656 .set_acl = reiserfs_set_acl,
@@ -1667,10 +1664,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
1667 .readlink = generic_readlink, 1664 .readlink = generic_readlink,
1668 .get_link = page_get_link, 1665 .get_link = page_get_link,
1669 .setattr = reiserfs_setattr, 1666 .setattr = reiserfs_setattr,
1670 .setxattr = generic_setxattr,
1671 .getxattr = generic_getxattr,
1672 .listxattr = reiserfs_listxattr, 1667 .listxattr = reiserfs_listxattr,
1673 .removexattr = generic_removexattr,
1674 .permission = reiserfs_permission, 1668 .permission = reiserfs_permission,
1675}; 1669};
1676 1670
@@ -1679,10 +1673,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
1679 */ 1673 */
1680const struct inode_operations reiserfs_special_inode_operations = { 1674const struct inode_operations reiserfs_special_inode_operations = {
1681 .setattr = reiserfs_setattr, 1675 .setattr = reiserfs_setattr,
1682 .setxattr = generic_setxattr,
1683 .getxattr = generic_getxattr,
1684 .listxattr = reiserfs_listxattr, 1676 .listxattr = reiserfs_listxattr,
1685 .removexattr = generic_removexattr,
1686 .permission = reiserfs_permission, 1677 .permission = reiserfs_permission,
1687 .get_acl = reiserfs_get_acl, 1678 .get_acl = reiserfs_get_acl,
1688 .set_acl = reiserfs_set_acl, 1679 .set_acl = reiserfs_set_acl,
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 0927b1e80ab6..e9793b1e49a5 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -425,7 +425,6 @@ failed_read:
425 425
426 426
427const struct inode_operations squashfs_inode_ops = { 427const struct inode_operations squashfs_inode_ops = {
428 .getxattr = generic_getxattr,
429 .listxattr = squashfs_listxattr 428 .listxattr = squashfs_listxattr
430}; 429};
431 430
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
index 67cad77fefb4..40c10d9974c9 100644
--- a/fs/squashfs/namei.c
+++ b/fs/squashfs/namei.c
@@ -247,6 +247,5 @@ failed:
247 247
248const struct inode_operations squashfs_dir_inode_ops = { 248const struct inode_operations squashfs_dir_inode_ops = {
249 .lookup = squashfs_lookup, 249 .lookup = squashfs_lookup,
250 .getxattr = generic_getxattr,
251 .listxattr = squashfs_listxattr 250 .listxattr = squashfs_listxattr
252}; 251};
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
index d688ef42a6a1..79b9c31a0c8f 100644
--- a/fs/squashfs/symlink.c
+++ b/fs/squashfs/symlink.c
@@ -120,7 +120,6 @@ const struct address_space_operations squashfs_symlink_aops = {
120const struct inode_operations squashfs_symlink_inode_ops = { 120const struct inode_operations squashfs_symlink_inode_ops = {
121 .readlink = generic_readlink, 121 .readlink = generic_readlink,
122 .get_link = page_get_link, 122 .get_link = page_get_link,
123 .getxattr = generic_getxattr,
124 .listxattr = squashfs_listxattr 123 .listxattr = squashfs_listxattr
125}; 124};
126 125
diff --git a/fs/squashfs/xattr.h b/fs/squashfs/xattr.h
index c83f5d9ec125..afe70f815e3d 100644
--- a/fs/squashfs/xattr.h
+++ b/fs/squashfs/xattr.h
@@ -42,6 +42,5 @@ static inline int squashfs_xattr_lookup(struct super_block *sb,
42 return 0; 42 return 0;
43} 43}
44#define squashfs_listxattr NULL 44#define squashfs_listxattr NULL
45#define generic_getxattr NULL
46#define squashfs_xattr_handlers NULL 45#define squashfs_xattr_handlers NULL
47#endif 46#endif
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 4b86d3a738e1..1d55aeaebf23 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1182,10 +1182,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
1182 .rename = ubifs_rename, 1182 .rename = ubifs_rename,
1183 .setattr = ubifs_setattr, 1183 .setattr = ubifs_setattr,
1184 .getattr = ubifs_getattr, 1184 .getattr = ubifs_getattr,
1185 .setxattr = generic_setxattr,
1186 .getxattr = generic_getxattr,
1187 .listxattr = ubifs_listxattr, 1185 .listxattr = ubifs_listxattr,
1188 .removexattr = generic_removexattr,
1189#ifdef CONFIG_UBIFS_ATIME_SUPPORT 1186#ifdef CONFIG_UBIFS_ATIME_SUPPORT
1190 .update_time = ubifs_update_time, 1187 .update_time = ubifs_update_time,
1191#endif 1188#endif
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index b0a6a53263f3..a746982fbcda 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1621,10 +1621,7 @@ const struct address_space_operations ubifs_file_address_operations = {
1621const struct inode_operations ubifs_file_inode_operations = { 1621const struct inode_operations ubifs_file_inode_operations = {
1622 .setattr = ubifs_setattr, 1622 .setattr = ubifs_setattr,
1623 .getattr = ubifs_getattr, 1623 .getattr = ubifs_getattr,
1624 .setxattr = generic_setxattr,
1625 .getxattr = generic_getxattr,
1626 .listxattr = ubifs_listxattr, 1624 .listxattr = ubifs_listxattr,
1627 .removexattr = generic_removexattr,
1628#ifdef CONFIG_UBIFS_ATIME_SUPPORT 1625#ifdef CONFIG_UBIFS_ATIME_SUPPORT
1629 .update_time = ubifs_update_time, 1626 .update_time = ubifs_update_time,
1630#endif 1627#endif
@@ -1635,10 +1632,7 @@ const struct inode_operations ubifs_symlink_inode_operations = {
1635 .get_link = simple_get_link, 1632 .get_link = simple_get_link,
1636 .setattr = ubifs_setattr, 1633 .setattr = ubifs_setattr,
1637 .getattr = ubifs_getattr, 1634 .getattr = ubifs_getattr,
1638 .setxattr = generic_setxattr,
1639 .getxattr = generic_getxattr,
1640 .listxattr = ubifs_listxattr, 1635 .listxattr = ubifs_listxattr,
1641 .removexattr = generic_removexattr,
1642#ifdef CONFIG_UBIFS_ATIME_SUPPORT 1636#ifdef CONFIG_UBIFS_ATIME_SUPPORT
1643 .update_time = ubifs_update_time, 1637 .update_time = ubifs_update_time,
1644#endif 1638#endif
diff --git a/fs/xattr.c b/fs/xattr.c
index c243905835ab..3368659c471e 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -24,6 +24,59 @@
24 24
25#include <asm/uaccess.h> 25#include <asm/uaccess.h>
26 26
27static const char *
28strcmp_prefix(const char *a, const char *a_prefix)
29{
30 while (*a_prefix && *a == *a_prefix) {
31 a++;
32 a_prefix++;
33 }
34 return *a_prefix ? NULL : a;
35}
36
37/*
38 * In order to implement different sets of xattr operations for each xattr
39 * prefix, a filesystem should create a null-terminated array of struct
40 * xattr_handler (one for each prefix) and hang a pointer to it off of the
41 * s_xattr field of the superblock.
42 */
43#define for_each_xattr_handler(handlers, handler) \
44 if (handlers) \
45 for ((handler) = *(handlers)++; \
46 (handler) != NULL; \
47 (handler) = *(handlers)++)
48
49/*
50 * Find the xattr_handler with the matching prefix.
51 */
52static const struct xattr_handler *
53xattr_resolve_name(struct inode *inode, const char **name)
54{
55 const struct xattr_handler **handlers = inode->i_sb->s_xattr;
56 const struct xattr_handler *handler;
57
58 if (!(inode->i_opflags & IOP_XATTR)) {
59 if (unlikely(is_bad_inode(inode)))
60 return ERR_PTR(-EIO);
61 return ERR_PTR(-EOPNOTSUPP);
62 }
63 for_each_xattr_handler(handlers, handler) {
64 const char *n;
65
66 n = strcmp_prefix(*name, xattr_prefix(handler));
67 if (n) {
68 if (!handler->prefix ^ !*n) {
69 if (*n)
70 continue;
71 return ERR_PTR(-EINVAL);
72 }
73 *name = n;
74 return handler;
75 }
76 }
77 return ERR_PTR(-EOPNOTSUPP);
78}
79
27/* 80/*
28 * Check permissions for extended attribute access. This is a bit complicated 81 * Check permissions for extended attribute access. This is a bit complicated
29 * because different namespaces have very different rules. 82 * because different namespaces have very different rules.
@@ -80,6 +133,23 @@ xattr_permission(struct inode *inode, const char *name, int mask)
80 return inode_permission(inode, mask); 133 return inode_permission(inode, mask);
81} 134}
82 135
136int
137__vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
138 const void *value, size_t size, int flags)
139{
140 const struct xattr_handler *handler;
141
142 handler = xattr_resolve_name(inode, &name);
143 if (IS_ERR(handler))
144 return PTR_ERR(handler);
145 if (!handler->set)
146 return -EOPNOTSUPP;
147 if (size == 0)
148 value = ""; /* empty EA, do not remove */
149 return handler->set(handler, dentry, inode, name, value, size, flags);
150}
151EXPORT_SYMBOL(__vfs_setxattr);
152
83/** 153/**
84 * __vfs_setxattr_noperm - perform setxattr operation without performing 154 * __vfs_setxattr_noperm - perform setxattr operation without performing
85 * permission checks. 155 * permission checks.
@@ -106,8 +176,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
106 176
107 if (issec) 177 if (issec)
108 inode->i_flags &= ~S_NOSEC; 178 inode->i_flags &= ~S_NOSEC;
109 if (inode->i_op->setxattr) { 179 if (inode->i_opflags & IOP_XATTR) {
110 error = inode->i_op->setxattr(dentry, inode, name, value, size, flags); 180 error = __vfs_setxattr(dentry, inode, name, value, size, flags);
111 if (!error) { 181 if (!error) {
112 fsnotify_xattr(dentry); 182 fsnotify_xattr(dentry);
113 security_inode_post_setxattr(dentry, name, value, 183 security_inode_post_setxattr(dentry, name, value,
@@ -115,6 +185,9 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
115 } 185 }
116 } else if (issec) { 186 } else if (issec) {
117 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; 187 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
188
189 if (unlikely(is_bad_inode(inode)))
190 return -EIO;
118 error = security_inode_setsecurity(inode, suffix, value, 191 error = security_inode_setsecurity(inode, suffix, value,
119 size, flags); 192 size, flags);
120 if (!error) 193 if (!error)
@@ -188,6 +261,7 @@ ssize_t
188vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, 261vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
189 size_t xattr_size, gfp_t flags) 262 size_t xattr_size, gfp_t flags)
190{ 263{
264 const struct xattr_handler *handler;
191 struct inode *inode = dentry->d_inode; 265 struct inode *inode = dentry->d_inode;
192 char *value = *xattr_value; 266 char *value = *xattr_value;
193 int error; 267 int error;
@@ -196,10 +270,12 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
196 if (error) 270 if (error)
197 return error; 271 return error;
198 272
199 if (!inode->i_op->getxattr) 273 handler = xattr_resolve_name(inode, &name);
274 if (IS_ERR(handler))
275 return PTR_ERR(handler);
276 if (!handler->get)
200 return -EOPNOTSUPP; 277 return -EOPNOTSUPP;
201 278 error = handler->get(handler, dentry, inode, name, NULL, 0);
202 error = inode->i_op->getxattr(dentry, inode, name, NULL, 0);
203 if (error < 0) 279 if (error < 0)
204 return error; 280 return error;
205 281
@@ -210,12 +286,27 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
210 memset(value, 0, error + 1); 286 memset(value, 0, error + 1);
211 } 287 }
212 288
213 error = inode->i_op->getxattr(dentry, inode, name, value, error); 289 error = handler->get(handler, dentry, inode, name, value, error);
214 *xattr_value = value; 290 *xattr_value = value;
215 return error; 291 return error;
216} 292}
217 293
218ssize_t 294ssize_t
295__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
296 void *value, size_t size)
297{
298 const struct xattr_handler *handler;
299
300 handler = xattr_resolve_name(inode, &name);
301 if (IS_ERR(handler))
302 return PTR_ERR(handler);
303 if (!handler->get)
304 return -EOPNOTSUPP;
305 return handler->get(handler, dentry, inode, name, value, size);
306}
307EXPORT_SYMBOL(__vfs_getxattr);
308
309ssize_t
219vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) 310vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
220{ 311{
221 struct inode *inode = dentry->d_inode; 312 struct inode *inode = dentry->d_inode;
@@ -242,28 +333,24 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
242 return ret; 333 return ret;
243 } 334 }
244nolsm: 335nolsm:
245 if (inode->i_op->getxattr) 336 return __vfs_getxattr(dentry, inode, name, value, size);
246 error = inode->i_op->getxattr(dentry, inode, name, value, size);
247 else
248 error = -EOPNOTSUPP;
249
250 return error;
251} 337}
252EXPORT_SYMBOL_GPL(vfs_getxattr); 338EXPORT_SYMBOL_GPL(vfs_getxattr);
253 339
254ssize_t 340ssize_t
255vfs_listxattr(struct dentry *d, char *list, size_t size) 341vfs_listxattr(struct dentry *dentry, char *list, size_t size)
256{ 342{
343 struct inode *inode = d_inode(dentry);
257 ssize_t error; 344 ssize_t error;
258 345
259 error = security_inode_listxattr(d); 346 error = security_inode_listxattr(dentry);
260 if (error) 347 if (error)
261 return error; 348 return error;
262 error = -EOPNOTSUPP; 349 if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
263 if (d->d_inode->i_op->listxattr) { 350 error = -EOPNOTSUPP;
264 error = d->d_inode->i_op->listxattr(d, list, size); 351 error = inode->i_op->listxattr(dentry, list, size);
265 } else { 352 } else {
266 error = security_inode_listsecurity(d->d_inode, list, size); 353 error = security_inode_listsecurity(inode, list, size);
267 if (size && error > size) 354 if (size && error > size)
268 error = -ERANGE; 355 error = -ERANGE;
269 } 356 }
@@ -272,14 +359,26 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
272EXPORT_SYMBOL_GPL(vfs_listxattr); 359EXPORT_SYMBOL_GPL(vfs_listxattr);
273 360
274int 361int
362__vfs_removexattr(struct dentry *dentry, const char *name)
363{
364 struct inode *inode = d_inode(dentry);
365 const struct xattr_handler *handler;
366
367 handler = xattr_resolve_name(inode, &name);
368 if (IS_ERR(handler))
369 return PTR_ERR(handler);
370 if (!handler->set)
371 return -EOPNOTSUPP;
372 return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
373}
374EXPORT_SYMBOL(__vfs_removexattr);
375
376int
275vfs_removexattr(struct dentry *dentry, const char *name) 377vfs_removexattr(struct dentry *dentry, const char *name)
276{ 378{
277 struct inode *inode = dentry->d_inode; 379 struct inode *inode = dentry->d_inode;
278 int error; 380 int error;
279 381
280 if (!inode->i_op->removexattr)
281 return -EOPNOTSUPP;
282
283 error = xattr_permission(inode, name, MAY_WRITE); 382 error = xattr_permission(inode, name, MAY_WRITE);
284 if (error) 383 if (error)
285 return error; 384 return error;
@@ -289,7 +388,7 @@ vfs_removexattr(struct dentry *dentry, const char *name)
289 if (error) 388 if (error)
290 goto out; 389 goto out;
291 390
292 error = inode->i_op->removexattr(dentry, name); 391 error = __vfs_removexattr(dentry, name);
293 392
294 if (!error) { 393 if (!error) {
295 fsnotify_xattr(dentry); 394 fsnotify_xattr(dentry);
@@ -641,76 +740,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
641 return error; 740 return error;
642} 741}
643 742
644
645static const char *
646strcmp_prefix(const char *a, const char *a_prefix)
647{
648 while (*a_prefix && *a == *a_prefix) {
649 a++;
650 a_prefix++;
651 }
652 return *a_prefix ? NULL : a;
653}
654
655/*
656 * In order to implement different sets of xattr operations for each xattr
657 * prefix with the generic xattr API, a filesystem should create a
658 * null-terminated array of struct xattr_handler (one for each prefix) and
659 * hang a pointer to it off of the s_xattr field of the superblock.
660 *
661 * The generic_fooxattr() functions will use this list to dispatch xattr
662 * operations to the correct xattr_handler.
663 */
664#define for_each_xattr_handler(handlers, handler) \
665 if (handlers) \
666 for ((handler) = *(handlers)++; \
667 (handler) != NULL; \
668 (handler) = *(handlers)++)
669
670/*
671 * Find the xattr_handler with the matching prefix.
672 */
673static const struct xattr_handler *
674xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
675{
676 const struct xattr_handler *handler;
677
678 if (!*name)
679 return ERR_PTR(-EINVAL);
680
681 for_each_xattr_handler(handlers, handler) {
682 const char *n;
683
684 n = strcmp_prefix(*name, xattr_prefix(handler));
685 if (n) {
686 if (!handler->prefix ^ !*n) {
687 if (*n)
688 continue;
689 return ERR_PTR(-EINVAL);
690 }
691 *name = n;
692 return handler;
693 }
694 }
695 return ERR_PTR(-EOPNOTSUPP);
696}
697
698/*
699 * Find the handler for the prefix and dispatch its get() operation.
700 */
701ssize_t
702generic_getxattr(struct dentry *dentry, struct inode *inode,
703 const char *name, void *buffer, size_t size)
704{
705 const struct xattr_handler *handler;
706
707 handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
708 if (IS_ERR(handler))
709 return PTR_ERR(handler);
710 return handler->get(handler, dentry, inode,
711 name, buffer, size);
712}
713
714/* 743/*
715 * Combine the results of the list() operation from every xattr_handler in the 744 * Combine the results of the list() operation from every xattr_handler in the
716 * list. 745 * list.
@@ -747,44 +776,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
747 } 776 }
748 return size; 777 return size;
749} 778}
750
751/*
752 * Find the handler for the prefix and dispatch its set() operation.
753 */
754int
755generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
756 const void *value, size_t size, int flags)
757{
758 const struct xattr_handler *handler;
759
760 if (size == 0)
761 value = ""; /* empty EA, do not remove */
762 handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
763 if (IS_ERR(handler))
764 return PTR_ERR(handler);
765 return handler->set(handler, dentry, inode, name, value, size, flags);
766}
767
768/*
769 * Find the handler for the prefix and dispatch its set() operation to remove
770 * any associated extended attribute.
771 */
772int
773generic_removexattr(struct dentry *dentry, const char *name)
774{
775 const struct xattr_handler *handler;
776
777 handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
778 if (IS_ERR(handler))
779 return PTR_ERR(handler);
780 return handler->set(handler, dentry, d_inode(dentry), name, NULL,
781 0, XATTR_REPLACE);
782}
783
784EXPORT_SYMBOL(generic_getxattr);
785EXPORT_SYMBOL(generic_listxattr); 779EXPORT_SYMBOL(generic_listxattr);
786EXPORT_SYMBOL(generic_setxattr);
787EXPORT_SYMBOL(generic_removexattr);
788 780
789/** 781/**
790 * xattr_full_name - Compute full attribute name from suffix 782 * xattr_full_name - Compute full attribute name from suffix
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index ba99803eba98..a7404c5aafe2 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1066,9 +1066,6 @@ static const struct inode_operations xfs_inode_operations = {
1066 .set_acl = xfs_set_acl, 1066 .set_acl = xfs_set_acl,
1067 .getattr = xfs_vn_getattr, 1067 .getattr = xfs_vn_getattr,
1068 .setattr = xfs_vn_setattr, 1068 .setattr = xfs_vn_setattr,
1069 .setxattr = generic_setxattr,
1070 .getxattr = generic_getxattr,
1071 .removexattr = generic_removexattr,
1072 .listxattr = xfs_vn_listxattr, 1069 .listxattr = xfs_vn_listxattr,
1073 .fiemap = xfs_vn_fiemap, 1070 .fiemap = xfs_vn_fiemap,
1074 .update_time = xfs_vn_update_time, 1071 .update_time = xfs_vn_update_time,
@@ -1094,9 +1091,6 @@ static const struct inode_operations xfs_dir_inode_operations = {
1094 .set_acl = xfs_set_acl, 1091 .set_acl = xfs_set_acl,
1095 .getattr = xfs_vn_getattr, 1092 .getattr = xfs_vn_getattr,
1096 .setattr = xfs_vn_setattr, 1093 .setattr = xfs_vn_setattr,
1097 .setxattr = generic_setxattr,
1098 .getxattr = generic_getxattr,
1099 .removexattr = generic_removexattr,
1100 .listxattr = xfs_vn_listxattr, 1094 .listxattr = xfs_vn_listxattr,
1101 .update_time = xfs_vn_update_time, 1095 .update_time = xfs_vn_update_time,
1102 .tmpfile = xfs_vn_tmpfile, 1096 .tmpfile = xfs_vn_tmpfile,
@@ -1122,9 +1116,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
1122 .set_acl = xfs_set_acl, 1116 .set_acl = xfs_set_acl,
1123 .getattr = xfs_vn_getattr, 1117 .getattr = xfs_vn_getattr,
1124 .setattr = xfs_vn_setattr, 1118 .setattr = xfs_vn_setattr,
1125 .setxattr = generic_setxattr,
1126 .getxattr = generic_getxattr,
1127 .removexattr = generic_removexattr,
1128 .listxattr = xfs_vn_listxattr, 1119 .listxattr = xfs_vn_listxattr,
1129 .update_time = xfs_vn_update_time, 1120 .update_time = xfs_vn_update_time,
1130 .tmpfile = xfs_vn_tmpfile, 1121 .tmpfile = xfs_vn_tmpfile,
@@ -1135,9 +1126,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
1135 .get_link = xfs_vn_get_link, 1126 .get_link = xfs_vn_get_link,
1136 .getattr = xfs_vn_getattr, 1127 .getattr = xfs_vn_getattr,
1137 .setattr = xfs_vn_setattr, 1128 .setattr = xfs_vn_setattr,
1138 .setxattr = generic_setxattr,
1139 .getxattr = generic_getxattr,
1140 .removexattr = generic_removexattr,
1141 .listxattr = xfs_vn_listxattr, 1129 .listxattr = xfs_vn_listxattr,
1142 .update_time = xfs_vn_update_time, 1130 .update_time = xfs_vn_update_time,
1143}; 1131};
@@ -1147,9 +1135,6 @@ static const struct inode_operations xfs_inline_symlink_inode_operations = {
1147 .get_link = xfs_vn_get_link_inline, 1135 .get_link = xfs_vn_get_link_inline,
1148 .getattr = xfs_vn_getattr, 1136 .getattr = xfs_vn_getattr,
1149 .setattr = xfs_vn_setattr, 1137 .setattr = xfs_vn_setattr,
1150 .setxattr = generic_setxattr,
1151 .getxattr = generic_getxattr,
1152 .removexattr = generic_removexattr,
1153 .listxattr = xfs_vn_listxattr, 1138 .listxattr = xfs_vn_listxattr,
1154 .update_time = xfs_vn_update_time, 1139 .update_time = xfs_vn_update_time,
1155}; 1140};