diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 10:08:45 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 10:08:45 -0700 |
commit | ba5a2655c270f59dea2d9b4d764aec2f6e7f5f41 (patch) | |
tree | 72b60e6899dfd156b2e9033818f894381da9355c /fs | |
parent | 8908c94d6cd7513ba4512295abc945a6ff7f979c (diff) | |
parent | e0d46f5c6e0ba3a79e64cd60e62b7b7191ed93f3 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull remaining vfs xattr work from Al Viro:
"The rest of work.xattr (non-cifs conversions)"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
btrfs: Switch to generic xattr handlers
ubifs: Switch to generic xattr handlers
jfs: Switch to generic xattr handlers
jfs: Clean up xattr name mapping
gfs2: Switch to generic xattr handlers
ceph: kill __ceph_removexattr()
ceph: Switch to generic xattr handlers
ceph: Get rid of d_find_alias in ceph_set_acl
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/inode.c | 16 | ||||
-rw-r--r-- | fs/btrfs/xattr.c | 22 | ||||
-rw-r--r-- | fs/btrfs/xattr.h | 3 | ||||
-rw-r--r-- | fs/ceph/acl.c | 14 | ||||
-rw-r--r-- | fs/ceph/dir.c | 7 | ||||
-rw-r--r-- | fs/ceph/inode.c | 29 | ||||
-rw-r--r-- | fs/ceph/super.h | 8 | ||||
-rw-r--r-- | fs/ceph/xattr.c | 192 | ||||
-rw-r--r-- | fs/gfs2/acl.c | 58 | ||||
-rw-r--r-- | fs/gfs2/acl.h | 1 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 82 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 46 | ||||
-rw-r--r-- | fs/jfs/file.c | 6 | ||||
-rw-r--r-- | fs/jfs/jfs_xattr.h | 6 | ||||
-rw-r--r-- | fs/jfs/namei.c | 6 | ||||
-rw-r--r-- | fs/jfs/symlink.c | 12 | ||||
-rw-r--r-- | fs/jfs/xattr.c | 224 | ||||
-rw-r--r-- | fs/ubifs/dir.c | 6 | ||||
-rw-r--r-- | fs/ubifs/file.c | 12 | ||||
-rw-r--r-- | fs/ubifs/super.c | 1 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 7 | ||||
-rw-r--r-- | fs/ubifs/xattr.c | 143 |
22 files changed, 338 insertions, 563 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index da5799c56160..6e1ae72b8949 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10160,10 +10160,10 @@ static const struct inode_operations btrfs_dir_inode_operations = { .symlink = btrfs_symlink, .setattr = btrfs_setattr, .mknod = btrfs_mknod, - .setxattr = btrfs_setxattr, + .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = btrfs_listxattr, - .removexattr = btrfs_removexattr, + .removexattr = generic_removexattr, .permission = btrfs_permission, .get_acl = btrfs_get_acl, .set_acl = btrfs_set_acl, @@ -10237,10 +10237,10 @@ static const struct address_space_operations btrfs_symlink_aops = { static const struct inode_operations btrfs_file_inode_operations = { .getattr = btrfs_getattr, .setattr = btrfs_setattr, - .setxattr = btrfs_setxattr, + .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = btrfs_listxattr, - .removexattr = btrfs_removexattr, + .removexattr = generic_removexattr, .permission = btrfs_permission, .fiemap = btrfs_fiemap, .get_acl = btrfs_get_acl, @@ -10251,10 +10251,10 @@ static const struct inode_operations btrfs_special_inode_operations = { .getattr = btrfs_getattr, .setattr = btrfs_setattr, .permission = btrfs_permission, - .setxattr = btrfs_setxattr, + .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = btrfs_listxattr, - .removexattr = btrfs_removexattr, + .removexattr = generic_removexattr, .get_acl = btrfs_get_acl, .set_acl = btrfs_set_acl, .update_time = btrfs_update_time, @@ -10265,10 +10265,10 @@ static const struct inode_operations btrfs_symlink_inode_operations = { .getattr = btrfs_getattr, .setattr = btrfs_setattr, .permission = btrfs_permission, - .setxattr = btrfs_setxattr, + .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = btrfs_listxattr, - .removexattr = btrfs_removexattr, + .removexattr = generic_removexattr, .update_time = btrfs_update_time, }; diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 03224b00ea70..3bfb252206c7 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -237,6 +237,9 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans, struct btrfs_root *root = BTRFS_I(inode)->root; int ret; + if (btrfs_root_readonly(root)) + return -EROFS; + if (trans) return do_setxattr(trans, inode, name, value, size, flags); @@ -432,25 +435,6 @@ const struct xattr_handler *btrfs_xattr_handlers[] = { NULL, }; -int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) -{ - struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; - - if (btrfs_root_readonly(root)) - return -EROFS; - return generic_setxattr(dentry, name, value, size, flags); -} - -int btrfs_removexattr(struct dentry *dentry, const char *name) -{ - struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; - - if (btrfs_root_readonly(root)) - return -EROFS; - return generic_removexattr(dentry, name); -} - static int btrfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, void *fs_info) { diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h index 96807b3d22f5..15fc4743dc70 100644 --- a/fs/btrfs/xattr.h +++ b/fs/btrfs/xattr.h @@ -28,9 +28,6 @@ extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name, extern int __btrfs_setxattr(struct btrfs_trans_handle *trans, struct inode *inode, const char *name, const void *value, size_t size, int flags); -extern int btrfs_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); -extern int btrfs_removexattr(struct dentry *dentry, const char *name); extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir, diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 5457f216e2e5..4f67227f69a5 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -90,7 +90,6 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) char *value = NULL; struct iattr newattrs; umode_t new_mode = inode->i_mode, old_mode = inode->i_mode; - struct dentry *dentry; switch (type) { case ACL_TYPE_ACCESS: @@ -128,29 +127,26 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) goto out_free; } - dentry = d_find_alias(inode); if (new_mode != old_mode) { newattrs.ia_mode = new_mode; newattrs.ia_valid = ATTR_MODE; - ret = ceph_setattr(dentry, &newattrs); + ret = __ceph_setattr(inode, &newattrs); if (ret) - goto out_dput; + goto out_free; } - ret = __ceph_setxattr(dentry, name, value, size, 0); + ret = __ceph_setxattr(inode, name, value, size, 0); if (ret) { if (new_mode != old_mode) { newattrs.ia_mode = old_mode; newattrs.ia_valid = ATTR_MODE; - ceph_setattr(dentry, &newattrs); + __ceph_setattr(inode, &newattrs); } - goto out_dput; + goto out_free; } ceph_set_cached_acl(inode, type, acl); -out_dput: - dput(dentry); out_free: kfree(value); out: diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 4fb2bbc2a272..3ab1192d2029 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -5,6 +5,7 @@ #include <linux/namei.h> #include <linux/slab.h> #include <linux/sched.h> +#include <linux/xattr.h> #include "super.h" #include "mds_client.h" @@ -1342,10 +1343,10 @@ const struct inode_operations ceph_dir_iops = { .permission = ceph_permission, .getattr = ceph_getattr, .setattr = ceph_setattr, - .setxattr = ceph_setxattr, - .getxattr = ceph_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ceph_listxattr, - .removexattr = ceph_removexattr, + .removexattr = generic_removexattr, .get_acl = ceph_get_acl, .set_acl = ceph_set_acl, .mknod = ceph_mknod, diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index edfade037738..e669cfa9d793 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/writeback.h> #include <linux/vmalloc.h> +#include <linux/xattr.h> #include <linux/posix_acl.h> #include <linux/random.h> @@ -92,10 +93,10 @@ const struct inode_operations ceph_file_iops = { .permission = ceph_permission, .setattr = ceph_setattr, .getattr = ceph_getattr, - .setxattr = ceph_setxattr, - .getxattr = ceph_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ceph_listxattr, - .removexattr = ceph_removexattr, + .removexattr = generic_removexattr, .get_acl = ceph_get_acl, .set_acl = ceph_set_acl, }; @@ -1770,22 +1771,18 @@ static const struct inode_operations ceph_symlink_iops = { .get_link = simple_get_link, .setattr = ceph_setattr, .getattr = ceph_getattr, - .setxattr = ceph_setxattr, - .getxattr = ceph_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ceph_listxattr, - .removexattr = ceph_removexattr, + .removexattr = generic_removexattr, }; -/* - * setattr - */ -int ceph_setattr(struct dentry *dentry, struct iattr *attr) +int __ceph_setattr(struct inode *inode, struct iattr *attr) { - struct inode *inode = d_inode(dentry); struct ceph_inode_info *ci = ceph_inode(inode); const unsigned int ia_valid = attr->ia_valid; struct ceph_mds_request *req; - struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; + struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; struct ceph_cap_flush *prealloc_cf; int issued; int release = 0, dirtied = 0; @@ -2010,6 +2007,14 @@ out_put: } /* + * setattr + */ +int ceph_setattr(struct dentry *dentry, struct iattr *attr) +{ + return __ceph_setattr(d_inode(dentry), attr); +} + +/* * Verify that we have a lease on the given mask. If not, * do a getattr against an mds. */ diff --git a/fs/ceph/super.h b/fs/ceph/super.h index beb893bb234f..7b99eb756477 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -785,19 +785,15 @@ static inline int ceph_do_getattr(struct inode *inode, int mask, bool force) return __ceph_do_getattr(inode, NULL, mask, force); } extern int ceph_permission(struct inode *inode, int mask); +extern int __ceph_setattr(struct inode *inode, struct iattr *attr); extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); /* xattr.c */ -extern int ceph_setxattr(struct dentry *, const char *, const void *, - size_t, int); -int __ceph_setxattr(struct dentry *, const char *, const void *, size_t, int); +int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int); ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t); -int __ceph_removexattr(struct dentry *, const char *); -extern ssize_t ceph_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); extern ssize_t ceph_listxattr(struct dentry *, char *, size_t); -extern int ceph_removexattr(struct dentry *, const char *); extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci); extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci); extern void __init ceph_xattr_init(void); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index c6e917d360f7..0d66722c6a52 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -16,6 +16,8 @@ static int __remove_xattr(struct ceph_inode_info *ci, struct ceph_inode_xattr *xattr); +const struct xattr_handler ceph_other_xattr_handler; + /* * List of handlers for synthetic system.* attributes. Other * attributes are handled directly. @@ -25,6 +27,7 @@ const struct xattr_handler *ceph_xattr_handlers[] = { &posix_acl_access_xattr_handler, &posix_acl_default_xattr_handler, #endif + &ceph_other_xattr_handler, NULL, }; @@ -33,7 +36,6 @@ static bool ceph_is_valid_xattr(const char *name) return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) || !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) || - !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); } @@ -496,19 +498,6 @@ static int __remove_xattr(struct ceph_inode_info *ci, return 0; } -static int __remove_xattr_by_name(struct ceph_inode_info *ci, - const char *name) -{ - struct rb_node **p; - struct ceph_inode_xattr *xattr; - int err; - - p = &ci->i_xattrs.index.rb_node; - xattr = __get_xattr(ci, name); - err = __remove_xattr(ci, xattr); - return err; -} - static char *__copy_xattr_names(struct ceph_inode_info *ci, char *dest) { @@ -740,9 +729,6 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, int req_mask; int err; - if (!ceph_is_valid_xattr(name)) - return -ENODATA; - /* let's see if a virtual xattr was requested */ vxattr = ceph_match_vxattr(inode, name); if (vxattr) { @@ -804,15 +790,6 @@ out: return err; } -ssize_t ceph_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *value, size_t size) -{ - if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_getxattr(dentry, inode, name, value, size); - - return __ceph_getxattr(inode, name, value, size); -} - ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) { struct inode *inode = d_inode(dentry); @@ -877,11 +854,10 @@ out: return err; } -static int ceph_sync_setxattr(struct dentry *dentry, const char *name, +static int ceph_sync_setxattr(struct inode *inode, const char *name, const char *value, size_t size, int flags) { - struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); - struct inode *inode = d_inode(dentry); + struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb); struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_mds_request *req; struct ceph_mds_client *mdsc = fsc->mdsc; @@ -939,13 +915,12 @@ out: return err; } -int __ceph_setxattr(struct dentry *dentry, const char *name, +int __ceph_setxattr(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - struct inode *inode = d_inode(dentry); struct ceph_vxattr *vxattr; struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; + struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; struct ceph_cap_flush *prealloc_cf = NULL; int issued; int err; @@ -958,8 +933,8 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, int required_blob_size; bool lock_snap_rwsem = false; - if (!ceph_is_valid_xattr(name)) - return -EOPNOTSUPP; + if (ceph_snap(inode) != CEPH_NOSNAP) + return -EROFS; vxattr = ceph_match_vxattr(inode, name); if (vxattr && vxattr->readonly) @@ -1056,7 +1031,7 @@ do_sync_unlocked: "during filling trace\n", inode); err = -EBUSY; } else { - err = ceph_sync_setxattr(dentry, name, value, size, flags); + err = ceph_sync_setxattr(inode, name, value, size, flags); } out: ceph_free_cap_flush(prealloc_cf); @@ -1066,146 +1041,29 @@ out: return err; } -int ceph_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP) - return -EROFS; - - if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_setxattr(dentry, name, value, size, flags); - - if (size == 0) - value = ""; /* empty EA, do not remove */ - - return __ceph_setxattr(dentry, name, value, size, flags); -} - -static int ceph_send_removexattr(struct dentry *dentry, const char *name) +static int ceph_get_xattr_handler(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) { - struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb); - struct ceph_mds_client *mdsc = fsc->mdsc; - struct inode *inode = d_inode(dentry); - struct ceph_mds_request *req; - int err; - - req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_RMXATTR, - USE_AUTH_MDS); - if (IS_ERR(req)) - return PTR_ERR(req); - req->r_path2 = kstrdup(name, GFP_NOFS); - if (!req->r_path2) - return -ENOMEM; - - req->r_inode = inode; - ihold(inode); - req->r_num_caps = 1; - req->r_inode_drop = CEPH_CAP_XATTR_SHARED; - err = ceph_mdsc_do_request(mdsc, NULL, req); - ceph_mdsc_put_request(req); - return err; + if (!ceph_is_valid_xattr(name)) + return -EOPNOTSUPP; + return __ceph_getxattr(inode, name, value, size); } -int __ceph_removexattr(struct dentry *dentry, const char *name) +static int ceph_set_xattr_handler(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) { - struct inode *inode = d_inode(dentry); - struct ceph_vxattr *vxattr; - struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; - struct ceph_cap_flush *prealloc_cf = NULL; - int issued; - int err; - int required_blob_size; - int dirty; - bool lock_snap_rwsem = false; - if (!ceph_is_valid_xattr(name)) return -EOPNOTSUPP; - - vxattr = ceph_match_vxattr(inode, name); - if (vxattr && vxattr->readonly) - return -EOPNOTSUPP; - - /* pass any unhandled ceph.* xattrs through to the MDS */ - if (!strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN)) - goto do_sync_unlocked; - - prealloc_cf = ceph_alloc_cap_flush(); - if (!prealloc_cf) - return -ENOMEM; - - err = -ENOMEM; - spin_lock(&ci->i_ceph_lock); -retry: - issued = __ceph_caps_issued(ci, NULL); - if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) - goto do_sync; - - if (!lock_snap_rwsem && !ci->i_head_snapc) { - lock_snap_rwsem = true; - if (!down_read_trylock(&mdsc->snap_rwsem)) { - spin_unlock(&ci->i_ceph_lock); - down_read(&mdsc->snap_rwsem); - spin_lock(&ci->i_ceph_lock); - goto retry; - } - } - - dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); - - __build_xattrs(inode); - - required_blob_size = __get_required_blob_size(ci, 0, 0); - - if (!ci->i_xattrs.prealloc_blob || - required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { - struct ceph_buffer *blob; - - spin_unlock(&ci->i_ceph_lock); - dout(" preaallocating new blob size=%d\n", required_blob_size); - blob = ceph_buffer_new(required_blob_size, GFP_NOFS); - if (!blob) - goto do_sync_unlocked; - spin_lock(&ci->i_ceph_lock); - if (ci->i_xattrs.prealloc_blob) - ceph_buffer_put(ci->i_xattrs.prealloc_blob); - ci->i_xattrs.prealloc_blob = blob; - goto retry; - } - - err = __remove_xattr_by_name(ceph_inode(inode), name); - - dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL, - &prealloc_cf); - ci->i_xattrs.dirty = true; - inode->i_ctime = current_fs_time(inode->i_sb); - spin_unlock(&ci->i_ceph_lock); - if (lock_snap_rwsem) - up_read(&mdsc->snap_rwsem); - if (dirty) - __mark_inode_dirty(inode, dirty); - ceph_free_cap_flush(prealloc_cf); - return err; -do_sync: - spin_unlock(&ci->i_ceph_lock); -do_sync_unlocked: - if (lock_snap_rwsem) - up_read(&mdsc->snap_rwsem); - ceph_free_cap_flush(prealloc_cf); - err = ceph_send_removexattr(dentry, name); - return err; + return __ceph_setxattr(d_inode(dentry), name, value, size, flags); } -int ceph_removexattr(struct dentry *dentry, const char *name) -{ - if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP) - return -EROFS; - - if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) - return generic_removexattr(dentry, name); - - return __ceph_removexattr(dentry, name); -} +const struct xattr_handler ceph_other_xattr_handler = { + .prefix = "", /* match any name => handlers called with full name */ + .get = ceph_get_xattr_handler, + .set = ceph_set_xattr_handler, +}; #ifdef CONFIG_SECURITY bool ceph_security_xattr_wanted(struct inode *in) diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 791932617d1a..363ba9e9d8d0 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -24,6 +24,7 @@ #include "glock.h" #include "inode.h" #include "meta_io.h" +#include "rgrp.h" #include "trans.h" #include "util.h" @@ -38,7 +39,7 @@ static const char *gfs2_acl_name(int type) return NULL; } -struct posix_acl *gfs2_get_acl(struct inode *inode, int type) +static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type) { struct gfs2_inode *ip = GFS2_I(inode); struct posix_acl *acl; @@ -50,29 +51,41 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type) return NULL; name = gfs2_acl_name(type); - if (name == NULL) - return ERR_PTR(-EINVAL); - len = gfs2_xattr_acl_get(ip, name, &data); - if (len < 0) + if (len <= 0) return ERR_PTR(len); - if (len == 0) - return NULL; - acl = posix_acl_from_xattr(&init_user_ns, data, len); kfree(data); return acl; } -int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) +struct posix_acl *gfs2_get_acl(struct inode *inode, int type) +{ + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_holder gh; + bool need_unlock = false; + struct posix_acl *acl; + + if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { + int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, + LM_FLAG_ANY, &gh); + if (ret) + return ERR_PTR(ret); + need_unlock = true; + } + acl = __gfs2_get_acl(inode, type); + if (need_unlock) + gfs2_glock_dq_uninit(&gh); + return acl; +} + +int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int error; int len; char *data; const char *name = gfs2_acl_name(type); - BUG_ON(name == NULL); - if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) return -E2BIG; @@ -115,3 +128,26 @@ out: kfree(data); return error; } + +int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) +{ + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_holder gh; + bool need_unlock = false; + int ret; + + ret = gfs2_rsqa_alloc(ip); + if (ret) + return ret; + + if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (ret) + return ret; + need_unlock = true; + } + ret = __gfs2_set_acl(inode, acl, type); + if (need_unlock) + gfs2_glock_dq_uninit(&gh); + return ret; +} diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h index 3af4f407a483..f674fdd22337 100644 --- a/fs/gfs2/acl.h +++ b/fs/gfs2/acl.h @@ -15,6 +15,7 @@ #define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12) extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type); +extern int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type); extern int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type); #endif /* __ACL_DOT_H__ */ diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 45f516cada78..72e9c64ae371 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -692,12 +692,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, considered free. Any failures need to undo the gfs2 structures. */ if (default_acl) { - error = gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); + error = __gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); posix_acl_release(default_acl); } if (acl) { if (!error) - error = gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS); + error = __gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS); posix_acl_release(acl); } @@ -1948,66 +1948,6 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, return 0; } -static int gfs2_setxattr(struct dentry *dentry, const char *name, - const void *data, size_t size, int flags) -{ - struct inode *inode = d_inode(dentry); - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_holder gh; - int ret; - - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); - ret = gfs2_glock_nq(&gh); - if (ret == 0) { - ret = gfs2_rsqa_alloc(ip); - if (ret == 0) - ret = generic_setxattr(dentry, name, data, size, flags); - gfs2_glock_dq(&gh); - } - gfs2_holder_uninit(&gh); - return ret; -} - -static ssize_t gfs2_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *data, size_t size) -{ - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_holder gh; - int ret; - - /* For selinux during lookup */ - if (gfs2_glock_is_locked_by_me(ip->i_gl)) - return generic_getxattr(dentry, inode, name, data, size); - - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); - ret = gfs2_glock_nq(&gh); - if (ret == 0) { - ret = generic_getxattr(dentry, inode, name, data, size); - gfs2_glock_dq(&gh); - } - gfs2_holder_uninit(&gh); - return ret; -} - -static int gfs2_removexattr(struct dentry *dentry, const char *name) -{ - struct inode *inode = d_inode(dentry); - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_holder gh; - int ret; - - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); - ret = gfs2_glock_nq(&gh); - if (ret == 0) { - ret = gfs2_rsqa_alloc(ip); - if (ret == 0) - ret = generic_removexattr(dentry, name); - gfs2_glock_dq(&gh); - } - gfs2_holder_uninit(&gh); - return ret; -} - static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { @@ -2054,10 +1994,10 @@ const struct inode_operations gfs2_file_iops = { .permission = gfs2_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, - .setxattr = gfs2_setxattr, - .getxattr = gfs2_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = gfs2_listxattr, - .removexattr = gfs2_removexattr, + .removexattr = generic_removexattr, .fiemap = gfs2_fiemap, .get_acl = gfs2_get_acl, .set_acl = gfs2_set_acl, @@ -2076,10 +2016,10 @@ const struct inode_operations gfs2_dir_iops = { .permission = gfs2_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, - .setxattr = gfs2_setxattr, - .getxattr = gfs2_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = gfs2_listxattr, - .removexattr = gfs2_removexattr, + .removexattr = generic_removexattr, .fiemap = gfs2_fiemap, .get_acl = gfs2_get_acl, .set_acl = gfs2_set_acl, @@ -2092,10 +2032,10 @@ const struct inode_operations gfs2_symlink_iops = { .permission = gfs2_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, - .setxattr = gfs2_setxattr, - .getxattr = gfs2_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = gfs2_listxattr, - .removexattr = gfs2_removexattr, + .removexattr = generic_removexattr, .fiemap = gfs2_fiemap, }; diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 619886ba6e78..f42ab53bd30d 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -583,13 +583,11 @@ out: * * Returns: actual size of data on success, -errno on error */ -static int gfs2_xattr_get(const struct xattr_handler *handler, - struct dentry *unused, struct inode *inode, - const char *name, void *buffer, size_t size) +static int __gfs2_xattr_get(struct inode *inode, const char *name, + void *buffer, size_t size, int type) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_ea_location el; - int type = handler->flags; int error; if (!ip->i_eattr) @@ -611,6 +609,29 @@ static int gfs2_xattr_get(const struct xattr_handler *handler, return error; } +static int gfs2_xattr_get(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) +{ + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_holder gh; + bool need_unlock = false; + int ret; + + /* During lookup, SELinux calls this function with the glock locked. */ + + if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); + if (ret) + return ret; + need_unlock = true; + } + ret = __gfs2_xattr_get(inode, name, buffer, size, handler->flags); + if (need_unlock) + gfs2_glock_dq_uninit(&gh); + return ret; +} + /** * ea_alloc_blk - allocates a new block for extended attributes. * @ip: A pointer to the inode that's getting extended attributes @@ -1233,8 +1254,21 @@ static int gfs2_xattr_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - return __gfs2_xattr_set(d_inode(dentry), name, value, - size, flags, handler->flags); + struct inode *inode = d_inode(dentry); + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_holder gh; + int ret; + + ret = gfs2_rsqa_alloc(ip); + if (ret) + return ret; + + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (ret) + return ret; + ret = __gfs2_xattr_set(inode, name, value, size, flags, handler->flags); + gfs2_glock_dq_uninit(&gh); + return ret; } static int ea_dealloc_indirect(struct gfs2_inode *ip) diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 4ce7735dd042..7f1a585a0a94 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -140,10 +140,10 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr) } const struct inode_operations jfs_file_inode_operations = { - .setxattr = jfs_setxattr, - .getxattr = jfs_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = jfs_listxattr, - .removexattr = jfs_removexattr, + .removexattr = generic_removexattr, .setattr = jfs_setattr, #ifdef CONFIG_JFS_POSIX_ACL .get_acl = jfs_get_acl, diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h index e69e14f3777b..561f6af46288 100644 --- a/fs/jfs/jfs_xattr.h +++ b/fs/jfs/jfs_xattr.h @@ -19,6 +19,8 @@ #ifndef H_JFS_XATTR #define H_JFS_XATTR +#include <linux/xattr.h> + /* * jfs_ea_list describe the on-disk format of the extended attributes. * I know the null-terminator is redundant since namelen is stored, but @@ -54,12 +56,8 @@ struct jfs_ea_list { extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *, size_t, int); -extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, - int); extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); |