Commit 184d8aa1 authored by Dave Kleikamp's avatar Dave Kleikamp

JFS: fine-grained xattr locking

Since the getxattr and listxattr iops no longer hold the i_sem, we can move
the xattr locking into another semaphore.  This allows us to simplify much
of the xattr and acl code that went to lengths to avoid recursively setting
i_sem.
parent f4defcee
......@@ -123,11 +123,11 @@ int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
}
/*
* __jfs_permission()
* jfs_permission()
*
* modified vfs_permission to check posix acl
*/
static int __jfs_permission(struct inode * inode, int mask, int have_sem)
int jfs_permission(struct inode * inode, int mask, struct nameidata *nd)
{
umode_t mode = inode->i_mode;
struct jfs_inode_info *ji = JFS_IP(inode);
......@@ -161,11 +161,7 @@ static int __jfs_permission(struct inode * inode, int mask, int have_sem)
if (ji->i_acl == JFS_ACL_NOT_CACHED) {
struct posix_acl *acl;
if (!have_sem)
down(&inode->i_sem);
acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
if (!have_sem)
up(&inode->i_sem);
if (IS_ERR(acl))
return PTR_ERR(acl);
......@@ -208,14 +204,6 @@ static int __jfs_permission(struct inode * inode, int mask, int have_sem)
return -EACCES;
}
int jfs_permission(struct inode * inode, int mask, struct nameidata *nd)
{
return __jfs_permission(inode, mask, 0);
}
int jfs_permission_have_sem(struct inode * inode, int mask)
{
return __jfs_permission(inode, mask, 1);
}
int jfs_init_acl(struct inode *inode, struct inode *dir)
{
......
......@@ -24,7 +24,6 @@
struct posix_acl *jfs_get_acl(struct inode *, int);
int jfs_set_acl(struct inode *, int, struct posix_acl *);
int jfs_permission_have_sem(struct inode *, int);
int jfs_permission(struct inode *, int, struct nameidata *);
int jfs_init_acl(struct inode *, struct inode *);
int jfs_setattr(struct dentry *, struct iattr *);
......
......@@ -67,6 +67,8 @@ struct jfs_inode_info {
* inode is blocked in txBegin or TxBeginAnon
*/
struct semaphore commit_sem;
/* xattr_sem allows us to access the xattrs without taking i_sem */
struct rw_semaphore xattr_sem;
lid_t xtlid; /* lid of xtree lock on directory */
#ifdef CONFIG_JFS_POSIX_ACL
struct posix_acl *i_acl;
......
......@@ -457,6 +457,7 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
init_rwsem(&jfs_ip->rdwrlock);
init_MUTEX(&jfs_ip->commit_sem);
init_rwsem(&jfs_ip->xattr_sem);
jfs_ip->atlhead = 0;
jfs_ip->active_ag = -1;
#ifdef CONFIG_JFS_POSIX_ACL
......
......@@ -729,7 +729,7 @@ static int can_set_xattr(struct inode *inode, const char *name,
return -EPERM;
#ifdef CONFIG_JFS_POSIX_ACL
return jfs_permission_have_sem(inode, MAY_WRITE);
return jfs_permission(inode, MAY_WRITE, NULL);
#else
return permission(inode, MAY_WRITE, NULL);
#endif
......@@ -763,6 +763,8 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
namelen -= XATTR_OS2_PREFIX_LEN;
}
down_write(&JFS_IP(inode)->xattr_sem);
xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) {
rc = xattr_size;
......@@ -868,6 +870,8 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
release:
ea_release(inode, &ea_buf);
out:
up_write(&JFS_IP(inode)->xattr_sem);
if (os2name)
kfree(os2name);
......@@ -890,8 +894,7 @@ static int can_get_xattr(struct inode *inode, const char *name)
#ifdef CONFIG_JFS_POSIX_ACL
if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)
return 0;
else
return jfs_permission_have_sem(inode, MAY_READ);
return jfs_permission(inode, MAY_READ, NULL);
#else
return permission(inode, MAY_READ, NULL);
#endif
......@@ -923,7 +926,10 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
namelen -= XATTR_OS2_PREFIX_LEN;
}
down_read(&JFS_IP(inode)->xattr_sem);
xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) {
size = xattr_size;
goto out;
......@@ -955,6 +961,8 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
release:
ea_release(inode, &ea_buf);
out:
up_read(&JFS_IP(inode)->xattr_sem);
if (os2name)
kfree(os2name);
......@@ -966,15 +974,12 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
{
int err;
down(&dentry->d_inode->i_sem);
err = __jfs_getxattr(dentry->d_inode, name, data, buf_size);
up(&dentry->d_inode->i_sem);
return err;
}
static ssize_t __jfs_listxattr(struct dentry * dentry, char *data,
size_t buf_size)
ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
{
struct inode *inode = dentry->d_inode;
char *buffer;
......@@ -984,6 +989,8 @@ static ssize_t __jfs_listxattr(struct dentry * dentry, char *data,
struct jfs_ea *ea;
struct ea_buffer ea_buf;
down_read(&JFS_IP(inode)->xattr_sem);
xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) {
size = xattr_size;
......@@ -1017,20 +1024,10 @@ static ssize_t __jfs_listxattr(struct dentry * dentry, char *data,
release:
ea_release(inode, &ea_buf);
out:
up_read(&JFS_IP(inode)->xattr_sem);
return size;
}
ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
{
int err;
down(&dentry->d_inode->i_sem);
err = __jfs_listxattr(dentry, data, buf_size);
up(&dentry->d_inode->i_sem);
return err;
}
int jfs_removexattr(struct dentry *dentry, const char *name)
{
return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment