diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 11 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.c | 28 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 47 |
4 files changed, 32 insertions, 58 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index bd9aba1f235..b55cb7f02e8 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -139,7 +139,7 @@ linvfs_unwritten_convert( XFS_BUF_SET_FSPRIVATE(bp, NULL); XFS_BUF_CLR_IODONE_FUNC(bp); XFS_BUF_UNDATAIO(bp); - iput(LINVFS_GET_IP(vp)); + vn_iowake(vp); pagebuf_iodone(bp, 0, 0); } @@ -448,14 +448,7 @@ xfs_map_unwritten( if (!pb) return -EAGAIN; - /* Take a reference to the inode to prevent it from - * being reclaimed while we have outstanding unwritten - * extent IO on it. - */ - if ((igrab(inode)) != inode) { - pagebuf_free(pb); - return -EAGAIN; - } + atomic_inc(&LINVFS_GET_VP(inode)->v_iocount); /* Set the count to 1 initially, this will stop an I/O * completion callout which happens before we have started diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 654da98de2a..46afc86a286 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -42,17 +42,33 @@ DEFINE_SPINLOCK(vnumber_lock); */ #define NVSYNC 37 #define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC]) -sv_t vsync[NVSYNC]; +STATIC wait_queue_head_t vsync[NVSYNC]; void vn_init(void) { - register sv_t *svp; - register int i; + int i; - for (svp = vsync, i = 0; i < NVSYNC; i++, svp++) - init_sv(svp, SV_DEFAULT, "vsy", i); + for (i = 0; i < NVSYNC; i++) + init_waitqueue_head(&vsync[i]); +} + +void +vn_iowait( + struct vnode *vp) +{ + wait_queue_head_t *wq = vptosync(vp); + + wait_event(*wq, (atomic_read(&vp->v_iocount) == 0)); +} + +void +vn_iowake( + struct vnode *vp) +{ + if (atomic_dec_and_test(&vp->v_iocount)) + wake_up(vptosync(vp)); } /* @@ -111,6 +127,8 @@ vn_initialize( /* Initialize the first behavior and the behavior chain head. */ vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode"); + atomic_set(&vp->v_iocount, 0); + #ifdef XFS_VNODE_TRACE vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); #endif /* XFS_VNODE_TRACE */ diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 4a74569a569..9977afa3890 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -80,6 +80,7 @@ typedef struct vnode { vnumber_t v_number; /* in-core vnode number */ vn_bhv_head_t v_bh; /* behavior head */ spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ + atomic_t v_iocount; /* outstanding I/O count */ #ifdef XFS_VNODE_TRACE struct ktrace *v_trace; /* trace header structure */ #endif @@ -506,6 +507,9 @@ extern int vn_revalidate(struct vnode *); extern void vn_revalidate_core(struct vnode *, vattr_t *); extern void vn_remove(struct vnode *); +extern void vn_iowait(struct vnode *vp); +extern void vn_iowake(struct vnode *vp); + static inline int vn_count(struct vnode *vp) { return atomic_read(&LINVFS_GET_IP(vp)->i_count); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index c4aa24ff85a..58bfe629b93 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -3846,51 +3846,10 @@ xfs_reclaim( return 0; } - if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) { - if (ip->i_d.di_size > 0) { - /* - * Flush and invalidate any data left around that is - * a part of this file. - * - * Get the inode's i/o lock so that buffers are pushed - * out while holding the proper lock. We can't hold - * the inode lock here since flushing out buffers may - * cause us to try to get the lock in xfs_strategy(). - * - * We don't have to call remapf() here, because there - * cannot be any mapped file references to this vnode - * since it is being reclaimed. - */ - xfs_ilock(ip, XFS_IOLOCK_EXCL); - - /* - * If we hit an IO error, we need to make sure that the - * buffer and page caches of file data for - * the file are tossed away. We don't want to use - * VOP_FLUSHINVAL_PAGES here because we don't want dirty - * pages to stay attached to the vnode, but be - * marked P_BAD. pdflush/vnode_pagebad - * hates that. - */ - if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_NONE); - } else { - VOP_TOSS_PAGES(vp, 0, -1, FI_NONE); - } + vn_iowait(vp); - ASSERT(VN_CACHED(vp) == 0); - ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || - ip->i_delayed_blks == 0); - xfs_iunlock(ip, XFS_IOLOCK_EXCL); - } else if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { - /* - * di_size field may not be quite accurate if we're - * shutting down. - */ - VOP_TOSS_PAGES(vp, 0, -1, FI_NONE); - ASSERT(VN_CACHED(vp) == 0); - } - } + ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); + ASSERT(VN_CACHED(vp) == 0); /* If we have nothing to flush with this inode then complete the * teardown now, otherwise break the link between the xfs inode |