Commit e31d2d1f authored by Eric Sandeen's avatar Eric Sandeen Committed by Linus Torvalds

[XFS] Wait for all async buffers to complete before tearing down the

filesystem at umount time

SGI-PV: 901236
SGI-Modid: xfs-linux:xfs-kern:182694a
Signed-off-by: default avatarEric Sandeen <sandeen@sgi.com>
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent 63cf3246
......@@ -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,
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment