summaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@sgi.com>2005-09-02 16:58:38 +1000
committerNathan Scott <nathans@sgi.com>2005-09-02 16:58:38 +1000
commit51c91ed52b8a9a30fcb2a465b40c20a1f11735ba (patch)
treeedebb01cbfe550a2edb066d5b4185445cfff11ba /fs/xfs/linux-2.6
parent592cb26bda6fe69838529acf71e50a6dee7acbb4 (diff)
[XFS] add infrastructure for waiting on I/O completion at inode reclaim
time SGI-PV: 934766 SGI-Modid: xfs-linux:xfs-kern:196854a Signed-off-by: Christoph Hellwig <hch@sgi.com> Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c28
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h4
3 files changed, 29 insertions, 14 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);