diff options
author | Andrew Morton <akpm@osdl.org> | 2003-07-06 05:41:05 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-07-06 05:41:05 -0700 |
commit | 430cab6d8dc4b79ad691c1d50d7ef217777e2593 (patch) | |
tree | 2444215ccf5e8a930b03f1a85d1b06c888aff0bc /fs/ext2/xattr.c | |
parent | a39afa31c59075459f1b0f89d9e6e3446d0ff6a2 (diff) | |
download | history-430cab6d8dc4b79ad691c1d50d7ef217777e2593.tar.gz |
[PATCH] xattrr: preparation for fine-grained locking
From: Andreas Gruenbacher <agruen@suse.de>
Andrew Morton found that there is lock contention between extended
attribute operations (like reading ACLs, which `ls -l' needs to do)
and other operations on the same files. This is due to the fact that
all extended attribute syscalls take inode->i_sem before calling into
the filesystem code.
To fix this problem, this patch no longer takes inode->i_sem in the
getxattr and listxattr syscalls, and moves the lock taking code into
the file systems. (Another patch improves the locking strategy in
ext2 and ext3.)
Diffstat (limited to 'fs/ext2/xattr.c')
-rw-r--r-- | fs/ext2/xattr.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 2dc9c65452a27a..aa29871da68e34 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -204,11 +204,16 @@ ext2_getxattr(struct dentry *dentry, const char *name, { struct ext2_xattr_handler *handler; struct inode *inode = dentry->d_inode; + ssize_t error; handler = ext2_xattr_resolve_name(&name); if (!handler) return -EOPNOTSUPP; - return handler->get(inode, name, buffer, size); + down(&inode->i_sem); + error = handler->get(inode, name, buffer, size); + up(&inode->i_sem); + + return error; } /* @@ -219,7 +224,13 @@ ext2_getxattr(struct dentry *dentry, const char *name, ssize_t ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) { - return ext2_xattr_list(dentry->d_inode, buffer, size); + ssize_t error; + + down(&dentry->d_inode->i_sem); + error = ext2_xattr_list(dentry->d_inode, buffer, size); + up(&dentry->d_inode->i_sem); + + return error; } /* |