From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: with ECARTIS (v1.0.0; list xfs); Wed, 08 Aug 2007 16:10:25 -0700 (PDT) Received: from larry.melbourne.sgi.com (larry.melbourne.sgi.com [134.14.52.130]) by oss.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with SMTP id l78NAIbm011693 for ; Wed, 8 Aug 2007 16:10:21 -0700 Date: Thu, 9 Aug 2007 09:10:16 +1000 From: David Chinner Subject: [PATCH 2 of 4] Per cluster-object inode chain locks Message-ID: <20070808231016.GQ12413810@sgi.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Sender: xfs-bounce@oss.sgi.com Errors-to: xfs-bounce@oss.sgi.com List-Id: xfs To: xfs-dev Cc: xfs-oss 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 --- 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 {