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/ext3/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/ext3/xattr.c')
-rw-r--r-- | fs/ext3/xattr.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 0db74f94229681..b89f8be46f0f7d 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -199,11 +199,16 @@ ext3_getxattr(struct dentry *dentry, const char *name, { struct ext3_xattr_handler *handler; struct inode *inode = dentry->d_inode; + ssize_t error; handler = ext3_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; } /* @@ -214,7 +219,13 @@ ext3_getxattr(struct dentry *dentry, const char *name, ssize_t ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) { - return ext3_xattr_list(dentry->d_inode, buffer, size); + ssize_t error; + + down(&dentry->d_inode->i_sem); + error = ext3_xattr_list(dentry->d_inode, buffer, size); + up(&dentry->d_inode->i_sem); + + return error; } /* |