public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: David Chinner <dgc@sgi.com>
To: xfs-dev <xfs-dev@sgi.com>
Cc: xfs-oss <xfs@oss.sgi.com>
Subject: [PATCH 2 of 4] Per cluster-object inode chain locks
Date: Thu, 9 Aug 2007 09:10:16 +1000	[thread overview]
Message-ID: <20070808231016.GQ12413810@sgi.com> (raw)

Per cluster-object inode chain locks.

Currently, the cluster inode chain is protected by the cluster hash
chain lock. This means that any operation on the cluster inode chain
can hold out searches of the cluster hash. It also means that the
cluster inode chain is not independent of the cluster hash and hence
cannot be cleanly separated.

Give the cluster object it's own lock so that inode chain operations
can be done independently of the cluster hash.

Signed-off-by: Dave Chinner <dgc@sgi.com>

---
 fs/xfs/xfs_iget.c  |   26 +++++++++++++++++++++-----
 fs/xfs/xfs_inode.c |   10 +++-------
 fs/xfs/xfs_inode.h |    1 +
 3 files changed, 25 insertions(+), 12 deletions(-)

Index: 2.6.x-xfs-new/fs/xfs/xfs_iget.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_iget.c	2006-10-19 10:52:04.731953950 +1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_iget.c	2006-10-19 10:52:24.661381439 +1000
@@ -367,7 +367,9 @@ finish_inode:
 		if (chl->chl_blkno == ip->i_blkno) {
 
 			/* insert this inode into the doubly-linked list
-			 * where chl points */
+			 * where chl points. lock the chl to protect against
+			 * others traversing the chl list */
+			spin_lock(&chl->chl_lock);
 			if ((iq = chl->chl_ip)) {
 				ip->i_cprev = iq->i_cprev;
 				iq->i_cprev->i_cnext = ip;
@@ -379,6 +381,7 @@ finish_inode:
 			}
 			chl->chl_ip = ip;
 			ip->i_chash = chl;
+			spin_unlock(&chl->chl_lock);
 			break;
 		}
 	}
@@ -392,8 +395,11 @@ finish_inode:
 					kmem_zone_alloc(xfs_chashlist_zone,
 						KM_SLEEP);
 			ASSERT(chlnew != NULL);
+			spin_lock_init(&chlnew->chl_lock);
 			goto chlredo;
 		} else {
+			/* exclusive access to this chl thanks to the ch_lock
+			 * in write mode, so no lock really needed */
 			ip->i_cnext = ip;
 			ip->i_cprev = ip;
 			ip->i_chash = chlnew;
@@ -679,13 +685,21 @@ xfs_iextract(
 	 */
 	mp = ip->i_mount;
 	ch = XFS_CHASH(mp, ip->i_blkno);
-	s = mutex_spinlock(&ch->ch_lock);
-
-	if (ip->i_cnext == ip) {
+	spin_lock(&ip->i_chash->chl_lock);
+	if (unlikely(ip->i_cnext == ip)) {
 		/* Last inode on chashlist */
 		ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
 		ASSERT(ip->i_chash != NULL);
 		chm=NULL;
+
+		spin_unlock(&ip->i_chash->chl_lock);
+		spin_lock(&ch->ch_lock);
+		spin_lock(&ip->i_chash->chl_lock);
+		if (ip->i_cnext != ip) {
+			spin_unlock(&ch->ch_lock);
+			goto delete;
+		}
+		spin_unlock(&ip->i_chash->chl_lock);
 		chl = ip->i_chash;
 		if (chl->chl_prev)
 			chl->chl_prev->chl_next = chl->chl_next;
@@ -693,20 +707,22 @@ xfs_iextract(
 			ch->ch_list = chl->chl_next;
 		if (chl->chl_next)
 			chl->chl_next->chl_prev = chl->chl_prev;
+		spin_unlock(&ch->ch_lock);
 		kmem_zone_free(xfs_chashlist_zone, chl);
 	} else {
 		/* delete one inode from a non-empty list */
+delete:
 		iq = ip->i_cnext;
 		iq->i_cprev = ip->i_cprev;
 		ip->i_cprev->i_cnext = iq;
 		if (ip->i_chash->chl_ip == ip) {
 			ip->i_chash->chl_ip = iq;
 		}
+		spin_unlock(&ip->i_chash->chl_lock);
 		ip->i_chash = __return_address;
 		ip->i_cprev = __return_address;
 		ip->i_cnext = __return_address;
 	}
-	mutex_spinunlock(&ch->ch_lock, s);
 
 	/*
 	 * Remove from mount's inode list.
Index: 2.6.x-xfs-new/fs/xfs/xfs_inode.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_inode.c	2006-10-19 10:45:26.243612163 +1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_inode.c	2006-10-19 10:52:24.661381439 +1000
@@ -3004,7 +3004,6 @@ xfs_iflush(
 	xfs_mount_t		*mp;
 	int			error;
 	/* REFERENCED */
-	xfs_chash_t		*ch;
 	xfs_inode_t		*iq;
 	int			clcount;	/* count of inodes clustered */
 	int			bufwasdelwri;
@@ -3123,12 +3122,9 @@ xfs_iflush(
 	 * inode clustering:
 	 * see if other inodes can be gathered into this write
 	 */
-
+	spin_lock(&ip->i_chash->chl_lock);
 	ip->i_chash->chl_buf = bp;
 
-	ch = XFS_CHASH(mp, ip->i_blkno);
-	s = mutex_spinlock(&ch->ch_lock);
-
 	clcount = 0;
 	for (iq = ip->i_cnext; iq != ip; iq = iq->i_cnext) {
 		/*
@@ -3181,7 +3177,7 @@ xfs_iflush(
 			xfs_iunlock(iq, XFS_ILOCK_SHARED);
 		}
 	}
-	mutex_spinunlock(&ch->ch_lock, s);
+	spin_unlock(&ip->i_chash->chl_lock);
 
 	if (clcount) {
 		XFS_STATS_INC(xs_icluster_flushcnt);
@@ -3218,7 +3214,7 @@ cluster_corrupt_out:
 	/* Corruption detected in the clustering loop.  Invalidate the
 	 * inode buffer and shut down the filesystem.
 	 */
-	mutex_spinunlock(&ch->ch_lock, s);
+	spin_unlock(&ip->i_chash->chl_lock);
 
 	/*
 	 * Clean up the buffer.  If it was B_DELWRI, just release it --
Index: 2.6.x-xfs-new/fs/xfs/xfs_inode.h
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_inode.h	2006-10-19 10:45:26.243612163 +1000
+++ 2.6.x-xfs-new/fs/xfs/xfs_inode.h	2006-10-19 10:52:24.665380923 +1000
@@ -194,6 +194,7 @@ typedef struct xfs_chashlist {
 	xfs_daddr_t		chl_blkno;	/* starting block number of
 						 * the cluster */
 	struct xfs_buf		*chl_buf;	/* the inode buffer */
+	lock_t			chl_lock;	/* inode list lock */
 } xfs_chashlist_t;
 
 typedef struct xfs_chash {

                 reply	other threads:[~2007-08-08 23:10 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070808231016.GQ12413810@sgi.com \
    --to=dgc@sgi.com \
    --cc=xfs-dev@sgi.com \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox