xfs: fix buffer flushing during unmount
authorChristoph Hellwig <hch@infradead.org>
Sat, 19 Nov 2011 18:13:43 +0000 (13:13 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sat, 26 Nov 2011 17:10:06 +0000 (09:10 -0800)
commit 87c7bec7fc3377b3873eb3a0f4b603981ea16ebb upstream.

The code to flush buffers in the umount code is a bit iffy: we first
flush all delwri buffers out, but then might be able to queue up a
new one when logging the sb counts.  On a normal shutdown that one
would get flushed out when doing the synchronous superblock write in
xfs_unmountfs_writesb, but we skip that one if the filesystem has
been shut down.

Fix this by moving the delwri list flushing until just before unmounting
the log, and while we're at it also remove the superflous delwri list
and buffer lru flusing for the rt and log device that can never have
cached or delwri buffers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reported-by: Amit Sahrawat <amit.sahrawat83@gmail.com>
Tested-by: Amit Sahrawat <amit.sahrawat83@gmail.com>
Signed-off-by: Alex Elder <aelder@sgi.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/xfs_mount.c

index 50a7d5fb3b73dca40017a9b55252444f81c84a7b..36d6ee44386702f6aaeeafa05e5f44daa9907fa7 100644 (file)
@@ -346,7 +346,6 @@ extern struct list_head *xfs_get_buftarg_list(void);
 #define xfs_getsize_buftarg(buftarg)   block_size((buftarg)->bt_bdev)
 #define xfs_readonly_buftarg(buftarg)  bdev_read_only((buftarg)->bt_bdev)
 
-#define xfs_binval(buftarg)            xfs_flush_buftarg(buftarg, 1)
 #define XFS_bflush(buftarg)            xfs_flush_buftarg(buftarg, 1)
 
 #endif /* __XFS_BUF_H__ */
index b49b82363d203dfa8d2c19abe9e08993b34c27e9..9afdd497369c13e8dffea7f71f8f057c833038ba 100644 (file)
@@ -44,9 +44,6 @@
 #include "xfs_trace.h"
 
 
-STATIC void    xfs_unmountfs_wait(xfs_mount_t *);
-
-
 #ifdef HAVE_PERCPU_SB
 STATIC void    xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
                                                int);
@@ -1507,11 +1504,6 @@ xfs_unmountfs(
         */
        xfs_log_force(mp, XFS_LOG_SYNC);
 
-       xfs_binval(mp->m_ddev_targp);
-       if (mp->m_rtdev_targp) {
-               xfs_binval(mp->m_rtdev_targp);
-       }
-
        /*
         * Unreserve any blocks we have so that when we unmount we don't account
         * the reserved free space as used. This is really only necessary for
@@ -1537,7 +1529,16 @@ xfs_unmountfs(
                xfs_warn(mp, "Unable to update superblock counters. "
                                "Freespace may not be correct on next mount.");
        xfs_unmountfs_writesb(mp);
-       xfs_unmountfs_wait(mp);                 /* wait for async bufs */
+
+       /*
+        * Make sure all buffers have been flushed and completed before
+        * unmounting the log.
+        */
+       error = xfs_flush_buftarg(mp->m_ddev_targp, 1);
+       if (error)
+               xfs_warn(mp, "%d busy buffers during unmount.", error);
+       xfs_wait_buftarg(mp->m_ddev_targp);
+
        xfs_log_unmount_write(mp);
        xfs_log_unmount(mp);
        xfs_uuid_unmount(mp);
@@ -1548,16 +1549,6 @@ xfs_unmountfs(
        xfs_free_perag(mp);
 }
 
-STATIC 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_fs_writable(xfs_mount_t *mp)
 {