]> git.neil.brown.name Git - history.git/commitdiff
[XFS] Wait for all async buffers to complete before tearing down the
authorEric Sandeen <sandeen@sgi.com>
Mon, 13 Dec 2004 23:25:40 +0000 (10:25 +1100)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 13 Dec 2004 23:25:40 +0000 (10:25 +1100)
filesystem at umount time

SGI-PV: 901236
SGI-Modid: xfs-linux:xfs-kern:182694a
Signed-off-by: Eric Sandeen <sandeen@sgi.com>
Signed-off-by: Nathan Scott <nathans@sgi.com>
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h

index 28dce29ebc8693c1f8b3557f890301404c659c17..a86d2eb4004de4bc76910cd2db2c8f510dca6bfb 100644 (file)
@@ -1468,6 +1468,34 @@ pagebuf_iomove(
  *     Handling of buftargs.
  */
 
+/*
+ * Wait for any bufs with callbacks that have been submitted but
+ * have not yet returned... walk the hash list for the target.
+ */
+void
+xfs_wait_buftarg(
+       xfs_buftarg_t *target)
+{
+       xfs_buf_t       *pb, *n;
+       pb_hash_t       *h;
+       int             i;
+
+       for (i = 0; i < NHASH; i++) {
+               h = &pbhash[i];
+again:
+               spin_lock(&h->pb_hash_lock);
+               list_for_each_entry_safe(pb, n, &h->pb_hash, pb_hash_list) {
+                       if (pb->pb_target == target &&
+                                       !(pb->pb_flags & PBF_FS_MANAGED)) {
+                               spin_unlock(&h->pb_hash_lock);
+                               delay(100);
+                               goto again;
+                       }
+               }
+               spin_unlock(&h->pb_hash_lock);
+       }
+}
+
 void
 xfs_free_buftarg(
        xfs_buftarg_t           *btp,
index 296aae4e21cd2d556ef284cbe19c0539f3f7dc64..dc43517d8e316fe7b0bdf92d604c29f0685a36ed 100644 (file)
@@ -566,6 +566,7 @@ static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
 
 extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *);
 extern void xfs_free_buftarg(xfs_buftarg_t *, int);
+extern void xfs_wait_buftarg(xfs_buftarg_t *);
 extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
 extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
index e7342ed7757ab1dfc3e00f6f53d3a146e3802906..96e94778940aa5acb2e0c8dca2783b26a9ee3985 100644 (file)
@@ -1098,6 +1098,8 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
 
        xfs_unmountfs_writesb(mp);
 
+       xfs_unmountfs_wait(mp);                 /* wait for async bufs */
+
        xfs_log_unmount(mp);                    /* Done! No more fs ops. */
 
        xfs_freesb(mp);
@@ -1142,6 +1144,16 @@ xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
        xfs_free_buftarg(mp->m_ddev_targp, 0);
 }
 
+void
+xfs_unmountfs_wait(xfs_mount_t *mp)
+{
+       if (mp->m_logdev_targp != mp->m_ddev_targp)
+               xfs_wait_buftarg(mp->m_logdev_targp);
+       if (mp->m_rtdev_targp)
+               xfs_wait_buftarg(mp->m_rtdev_targp);
+       xfs_wait_buftarg(mp->m_ddev_targp);
+}
+
 int
 xfs_unmountfs_writesb(xfs_mount_t *mp)
 {
index caae8ba2c2df56bbe2e40857078d3709e03f1b62..a37420eb5fc6b8bcf8567604474fc9683754d84e 100644 (file)
@@ -541,6 +541,7 @@ extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
 extern int     xfs_mountfs(struct vfs *, xfs_mount_t *mp, int);
 
 extern int     xfs_unmountfs(xfs_mount_t *, struct cred *);
+extern void    xfs_unmountfs_wait(xfs_mount_t *);
 extern void    xfs_unmountfs_close(xfs_mount_t *, struct cred *);
 extern int     xfs_unmountfs_writesb(xfs_mount_t *);
 extern int     xfs_unmount_flush(xfs_mount_t *, int);