diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-05-13 03:59:17 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-05-12 22:28:05 -0400 |
commit | 1a39ba99b5d533647c5dac45cd6a3e0baa7cb66a (patch) | |
tree | 24f0508c7d380168e333f9ee8921d8b8550f9ef6 /fs/gfs2/xattr.c | |
parent | b971e94e8f4c09ff775cfb2c4f846b4431a00598 (diff) | |
download | linux-1a39ba99b5d533647c5dac45cd6a3e0baa7cb66a.tar.gz linux-1a39ba99b5d533647c5dac45cd6a3e0baa7cb66a.tar.bz2 linux-1a39ba99b5d533647c5dac45cd6a3e0baa7cb66a.zip |
gfs2: Switch to generic xattr handlers
Switch to the generic xattr handlers and take the necessary glocks at
the layer below. The following are the new xattr "entry points"; they
are called with the glock held already in the following cases:
gfs2_xattr_get: From SELinux, during lookups.
gfs2_xattr_set: The glock is never held.
gfs2_get_acl: From gfs2_create_inode -> posix_acl_create and
gfs2_setattr -> posix_acl_chmod.
gfs2_set_acl: From gfs2_setattr -> posix_acl_chmod.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/gfs2/xattr.c')
-rw-r--r-- | fs/gfs2/xattr.c | 46 |
1 files changed, 40 insertions, 6 deletions
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) |