All of lore.kernel.org
 help / color / mirror / Atom feed
* xattr iops locking improvement
@ 2003-07-07 17:48 Andreas Gruenbacher
  2003-07-07 17:57 ` Christoph Hellwig
  0 siblings, 1 reply; 2+ messages in thread
From: Andreas Gruenbacher @ 2003-07-07 17:48 UTC (permalink / raw)
  To: Marcelo Tossati
  Cc: linux-fsdevel, Andrew Morton, Andrea Arcangeli, Dave Kleikamp,
	Nathan Scott, Chris Mason, Tim Shimmin, Jeff Mahoney, Steve Best

[-- Attachment #1: Type: text/plain, Size: 1220 bytes --]

Hi Marcelo,

Andrew Morton has found that taking i_sem for all xattr iops leads to lock 
contention. Particularly annoying is that writers can block operations like 
`ls -l' because both need i_sem. We have bene working on a fix for 2.4 and 
2.5. The solution is a series of patches that are in Andrew's current tree, 
and have been sent to Linus. I will also shortly put them on 
http://acl.bestbits.at/.

For vanilla 2.4 the relevant patch is xattr-fine-grained-locking-1. i_sem is 
no longer taken in the listxattr and getxattr iops. It is still taken for 
setxattr and removexattr. The patch moves the lock taking down to the file 
system level.

I have patches ready that remove the need for i_sem in ext2 and ext3, and I'm 
sure the xfs, jfs, and reiserfs coders will be quick to follow up with 
improved xattr and acl patches as well.

I am attaching xattr-fine-grained-locking-2 and xattr-fine-grained-locking-3 
for reference.


Cheers,
Andreas.

------------------------------------------------------------------
 Andreas Gruenbacher                                SuSE Linux AG
 mailto:agruen@suse.de                     Deutschherrnstr. 15-19
 http://www.suse.de/                   D-90429 Nuernberg, Germany

[-- Attachment #2: xattr-fine-grained-locking-1 --]
[-- Type: text/x-diff, Size: 3138 bytes --]

More fine-grained locking for extended attributes

No longer take inode->i_sem for iops->getxattr and iops->listxattr.
Move taking inode->i_sem down to the file system level.

Andreas Gruenbacher <agruen@suse.de>, SuSE Labs


Index: linux-2.4.21/fs/xattr.c
===================================================================
--- linux-2.4.21.orig/fs/xattr.c	2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.21/fs/xattr.c	2003-06-25 22:03:05.000000000 +0200
@@ -159,11 +159,9 @@ getxattr(struct dentry *d, char *name, v
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
-		down(&d->d_inode->i_sem);
 		lock_kernel();
 		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
 		unlock_kernel();
-		up(&d->d_inode->i_sem);
 	}
 
 	if (kvalue && error > 0)
@@ -230,11 +228,9 @@ listxattr(struct dentry *d, char *list, 
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
-		down(&d->d_inode->i_sem);
 		lock_kernel();
 		error = d->d_inode->i_op->listxattr(d, klist, size);
 		unlock_kernel();
-		up(&d->d_inode->i_sem);
 	}
 
 	if (klist && error > 0)
Index: linux-2.4.21/fs/jfs/xattr.c
===================================================================
--- linux-2.4.21.orig/fs/jfs/xattr.c	2003-06-25 22:00:29.000000000 +0200
+++ linux-2.4.21/fs/jfs/xattr.c	2003-06-25 22:17:53.000000000 +0200
@@ -964,12 +964,18 @@ ssize_t __jfs_getxattr(struct inode *ino
 ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
 		     size_t buf_size)
 {
-	return __jfs_getxattr(dentry->d_inode, name, data, buf_size);
+	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;
 }
 
-ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
+static ssize_t __jfs_listxattr(struct inode *inode, char *data,
+			       size_t buf_size)
 {
-	struct inode *inode = dentry->d_inode;
 	char *buffer;
 	ssize_t size = 0;
 	int xattr_size;
@@ -1013,6 +1019,17 @@ ssize_t jfs_listxattr(struct dentry * de
 	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->d_inode, 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);
Index: linux-2.4.21/Documentation/filesystems/Locking
===================================================================
--- linux-2.4.21.orig/Documentation/filesystems/Locking	2003-06-25 21:58:40.000000000 +0200
+++ linux-2.4.21/Documentation/filesystems/Locking	2003-06-25 22:03:05.000000000 +0200
@@ -69,8 +69,8 @@ permission:	yes	no		no
 getattr:						(see below)
 revalidate:	no					(see below)
 setxattr:	yes	yes		no
-getxattr:	yes	yes		no
-listxattr:	yes	yes		no
+getxattr:	yes	no		no
+listxattr:	yes	no		no
 removexattr:	yes	yes		no
 	Additionally, ->rmdir() has i_zombie on victim and so does ->rename()
 in case when target exists and is a directory.

[-- Attachment #3: xattr-fine-grained-locking-2 --]
[-- Type: text/x-diff, Size: 2066 bytes --]

Index: linux-2.4.21/fs/ext2/xattr.c
===================================================================
--- linux-2.4.21.orig/fs/ext2/xattr.c	2003-06-25 15:29:13.000000000 +0200
+++ linux-2.4.21/fs/ext2/xattr.c	2003-06-25 15:59:05.000000000 +0200
@@ -290,11 +290,17 @@ ext2_getxattr(struct dentry *dentry, con
 {
 	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;
 }
 
 /*
@@ -306,7 +312,13 @@ ext2_getxattr(struct dentry *dentry, con
 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;
 }
 
 /*
Index: linux-2.4.21/fs/ext3/xattr.c
===================================================================
--- linux-2.4.21.orig/fs/ext3/xattr.c	2003-06-25 15:29:13.000000000 +0200
+++ linux-2.4.21/fs/ext3/xattr.c	2003-06-25 15:58:50.000000000 +0200
@@ -289,11 +289,17 @@ ext3_getxattr(struct dentry *dentry, con
 {
 	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;
 }
 
 /*
@@ -305,7 +311,13 @@ ext3_getxattr(struct dentry *dentry, con
 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;
 }
 
 /*

[-- Attachment #4: xattr-fine-grained-locking-3 --]
[-- Type: text/x-diff, Size: 2843 bytes --]

Index: linux-2.4.21/fs/reiserfs/xattr.c
===================================================================
--- linux-2.4.21.orig/fs/reiserfs/xattr.c	2003-06-25 15:29:19.000000000 +0200
+++ linux-2.4.21/fs/reiserfs/xattr.c	2003-06-25 16:04:39.000000000 +0200
@@ -1322,7 +1322,9 @@ reiserfs_getxattr (struct dentry *dentry
         return -EOPNOTSUPP;
     
     reiserfs_read_lock_xattrs (dentry->d_sb);
+    down(&dentry->d_inode->i_sem);
     err = xah->get (dentry->d_inode, name, buffer, size);
+    up(&dentry->d_inode->i_sem);
     reiserfs_read_unlock_xattrs (dentry->d_sb);
     return err;
 }
@@ -1426,14 +1428,9 @@ reiserfs_listxattr_filler (void *buf, co
 
     return 0;
 }
-/*
- * Inode operation listxattr()
- *
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
- */
-ssize_t
-reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
+
+static ssize_t
+__reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
 {
     struct file *fp;
     struct dentry *dir;
@@ -1485,6 +1482,24 @@ out:
     return err;
 }
 
+/*
+ * Inode operation listxattr()
+ *
+ * dentry->d_inode->i_sem down
+ * BKL held [before 2.5.x]
+ */
+ssize_t
+reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
+{
+    int error;
+
+    down(&dentry->d_inode->i_sem);
+    error = __reiserfs_listxattr(dentry, buffer, size);
+    up(&dentry->d_inode->i_sem);
+
+    return error;
+}
+
 /* This is the implementation for the xattr plugin infrastructure */
 static struct reiserfs_xattr_handler *xattr_handlers;
 static rwlock_t handler_lock = RW_LOCK_UNLOCKED;
Index: linux-2.4.21/fs/xfs/linux/xfs_iops.c
===================================================================
--- linux-2.4.21.orig/fs/xfs/linux/xfs_iops.c	2003-06-25 15:28:43.000000000 +0200
+++ linux-2.4.21/fs/xfs/linux/xfs_iops.c	2003-06-25 16:13:33.000000000 +0200
@@ -644,7 +644,7 @@ linvfs_setxattr(
 }
 
 STATIC ssize_t
-linvfs_getxattr(
+__linvfs_getxattr(
 	struct dentry	*dentry,
 	const char	*name,
 	void		*data,
@@ -699,9 +699,25 @@ linvfs_getxattr(
 	return -EOPNOTSUPP;
 }
 
+STATIC ssize_t
+linvfs_getxattr(
+	struct dentry	*dentry,
+	const char	*name,
+	void		*data,
+	size_t		size)
+{
+	int error;
+
+	down(&dentry->d_inode->i_sem);
+	error = __linvfs_getxattr(dentry, name, data, size);
+	up(&dentry->d_inode->i_sem);
+
+	return error;
+}
+
 
 STATIC ssize_t
-linvfs_listxattr(
+__linvfs_listxattr(
 	struct dentry		*dentry,
 	char			*data,
 	size_t			size)
@@ -743,6 +759,21 @@ linvfs_listxattr(
 	return result;
 }
 
+STATIC ssize_t
+linvfs_listxattr(
+	struct dentry		*dentry,
+	char			*data,
+	size_t			size)
+{
+	int error;
+
+	down(&dentry->d_inode->i_sem);
+	error = __linvfs_listxattr(dentry, data, size);
+	up(&dentry->d_inode->i_sem);
+
+	return error;
+}
+
 STATIC int
 linvfs_removexattr(
 	struct dentry	*dentry,

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: xattr iops locking improvement
  2003-07-07 17:48 xattr iops locking improvement Andreas Gruenbacher
@ 2003-07-07 17:57 ` Christoph Hellwig
  0 siblings, 0 replies; 2+ messages in thread
From: Christoph Hellwig @ 2003-07-07 17:57 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Marcelo Tossati, linux-fsdevel, Andrew Morton, Andrea Arcangeli,
	Dave Kleikamp, Nathan Scott, Chris Mason, Tim Shimmin,
	Jeff Mahoney, Steve Best

On Mon, Jul 07, 2003 at 07:48:04PM +0200, Andreas Gruenbacher wrote:
> Hi Marcelo,
> 
> Andrew Morton has found that taking i_sem for all xattr iops leads to lock 
> contention. Particularly annoying is that writers can block operations like 
> `ls -l' because both need i_sem. We have bene working on a fix for 2.4 and 
> 2.5. The solution is a series of patches that are in Andrew's current tree, 
> and have been sent to Linus. I will also shortly put them on 
> http://acl.bestbits.at/.

~o(/me remembers having argued for no VFS-level locking on them a while ago)

Can we please get rid of the i_sem on the other two operations, and finally
move all locking to the implementation?


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-07-07 17:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-07-07 17:48 xattr iops locking improvement Andreas Gruenbacher
2003-07-07 17:57 ` Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.