blkdev_issue_flush(buftarg->bt_bdev, NULL);
 }
 
+STATIC void
+xfs_close_devices(
+       struct xfs_mount        *mp)
+{
+       if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
+               xfs_free_buftarg(mp->m_logdev_targp);
+               xfs_blkdev_put(mp->m_logdev_targp->bt_bdev);
+       }
+       if (mp->m_rtdev_targp) {
+               xfs_free_buftarg(mp->m_rtdev_targp);
+               xfs_blkdev_put(mp->m_rtdev_targp->bt_bdev);
+       }
+       xfs_free_buftarg(mp->m_ddev_targp);
+}
+
+/*
+ * The file system configurations are:
+ *     (1) device (partition) with data and internal log
+ *     (2) logical volume with data and log subvolumes.
+ *     (3) logical volume with data, log, and realtime subvolumes.
+ *
+ * We only have to handle opening the log and realtime volumes here if
+ * they are present.  The data subvolume has already been opened by
+ * get_sb_bdev() and is stored in sb->s_bdev.
+ */
+STATIC int
+xfs_open_devices(
+       struct xfs_mount        *mp,
+       struct xfs_mount_args   *args)
+{
+       struct block_device     *ddev = mp->m_super->s_bdev;
+       struct block_device     *logdev = NULL, *rtdev = NULL;
+       int                     error;
+
+       /*
+        * Open real time and log devices - order is important.
+        */
+       if (args->logname[0]) {
+               error = xfs_blkdev_get(mp, args->logname, &logdev);
+               if (error)
+                       goto out;
+       }
+
+       if (args->rtname[0]) {
+               error = xfs_blkdev_get(mp, args->rtname, &rtdev);
+               if (error)
+                       goto out_close_logdev;
+
+               if (rtdev == ddev || rtdev == logdev) {
+                       cmn_err(CE_WARN,
+       "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
+                       error = EINVAL;
+                       goto out_close_rtdev;
+               }
+       }
+
+       /*
+        * Setup xfs_mount buffer target pointers
+        */
+       error = ENOMEM;
+       mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
+       if (!mp->m_ddev_targp)
+               goto out_close_rtdev;
+
+       if (rtdev) {
+               mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
+               if (!mp->m_rtdev_targp)
+                       goto out_free_ddev_targ;
+       }
+
+       if (logdev && logdev != ddev) {
+               mp->m_logdev_targp = xfs_alloc_buftarg(logdev, 1);
+               if (!mp->m_logdev_targp)
+                       goto out_free_rtdev_targ;
+       } else {
+               mp->m_logdev_targp = mp->m_ddev_targp;
+       }
+
+       return 0;
+
+ out_free_rtdev_targ:
+       if (mp->m_rtdev_targp)
+               xfs_free_buftarg(mp->m_rtdev_targp);
+ out_free_ddev_targ:
+       xfs_free_buftarg(mp->m_ddev_targp);
+ out_close_rtdev:
+       if (rtdev)
+               xfs_blkdev_put(rtdev);
+ out_close_logdev:
+       if (logdev && logdev != ddev)
+               xfs_blkdev_put(logdev);
+ out:
+       return error;
+}
+
+
+
 /*
  * XFS AIL push thread support
  */
                                unmount_event_flags);
        }
 
-       xfs_unmountfs(mp, NULL);
+       xfs_unmountfs(mp);
+       xfs_close_devices(mp);
        xfs_qmops_put(mp);
        xfs_dmops_put(mp);
        kmem_free(mp);
        return 0;
 }
 
-/*
- * The file system configurations are:
- *     (1) device (partition) with data and internal log
- *     (2) logical volume with data and log subvolumes.
- *     (3) logical volume with data, log, and realtime subvolumes.
- *
- * We only have to handle opening the log and realtime volumes here if
- * they are present.  The data subvolume has already been opened by
- * get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev.
- */
 STATIC int
 xfs_fs_fill_super(
        struct super_block      *sb,
        struct inode            *root;
        struct xfs_mount        *mp = NULL;
        struct xfs_mount_args   *args = xfs_args_allocate(sb, silent);
-       struct block_device     *ddev = sb->s_bdev;
-       struct block_device     *logdev = NULL, *rtdev = NULL;
        int                     flags = 0, error;
 
        mp = xfs_mount_init();
                goto fail_vfsop;
        error = xfs_qmops_get(mp, args);
        if (error)
-               goto fail_vfsop;
+               goto out_put_dmops;
 
        if (args->flags & XFSMNT_QUIET)
                flags |= XFS_MFSI_QUIET;
 
-       /*
-        * Open real time and log devices - order is important.
-        */
-       if (args->logname[0]) {
-               error = xfs_blkdev_get(mp, args->logname, &logdev);
-               if (error)
-                       goto fail_vfsop;
-       }
-       if (args->rtname[0]) {
-               error = xfs_blkdev_get(mp, args->rtname, &rtdev);
-               if (error) {
-                       xfs_blkdev_put(logdev);
-                       goto fail_vfsop;
-               }
-
-               if (rtdev == ddev || rtdev == logdev) {
-                       cmn_err(CE_WARN,
-       "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
-                       xfs_blkdev_put(logdev);
-                       xfs_blkdev_put(rtdev);
-                       error = EINVAL;
-                       goto fail_vfsop;
-               }
-       }
-
-       /*
-        * Setup xfs_mount buffer target pointers
-        */
-       error = ENOMEM;
-       mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
-       if (!mp->m_ddev_targp) {
-               xfs_blkdev_put(logdev);
-               xfs_blkdev_put(rtdev);
-               goto fail_vfsop;
-       }
-       if (rtdev) {
-               mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
-               if (!mp->m_rtdev_targp) {
-                       xfs_blkdev_put(logdev);
-                       xfs_blkdev_put(rtdev);
-                       goto error0;
-               }
-       }
-       mp->m_logdev_targp = (logdev && logdev != ddev) ?
-                               xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
-       if (!mp->m_logdev_targp) {
-               xfs_blkdev_put(logdev);
-               xfs_blkdev_put(rtdev);
-               goto error0;
-       }
+       error = xfs_open_devices(mp, args);
+       if (error)
+               goto out_put_qmops;
 
        /*
         * Setup flags based on mount(2) options and then the superblock
         */
        error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
                                    mp->m_sb.sb_sectsize);
-       if (!error && logdev && logdev != ddev) {
+       if (error)
+               goto error2;
+       if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
                unsigned int    log_sector_size = BBSIZE;
 
                if (xfs_sb_version_hassector(&mp->m_sb))
                error = xfs_setsize_buftarg(mp->m_logdev_targp,
                                            mp->m_sb.sb_blocksize,
                                            log_sector_size);
+               if (error)
+                       goto error2;
        }
-       if (!error && rtdev)
+       if (mp->m_rtdev_targp) {
                error = xfs_setsize_buftarg(mp->m_rtdev_targp,
                                            mp->m_sb.sb_blocksize,
                                            mp->m_sb.sb_sectsize);
-       if (error)
-               goto error2;
+               if (error)
+                       goto error2;
+       }
 
        if (mp->m_flags & XFS_MOUNT_BARRIER)
                xfs_mountfs_check_barriers(mp);
                xfs_freesb(mp);
  error1:
        xfs_binval(mp->m_ddev_targp);
-       if (logdev && logdev != ddev)
+       if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
                xfs_binval(mp->m_logdev_targp);
-       if (rtdev)
+       if (mp->m_rtdev_targp)
                xfs_binval(mp->m_rtdev_targp);
- error0:
-       xfs_unmountfs_close(mp, NULL);
+       xfs_close_devices(mp);
+ out_put_qmops:
        xfs_qmops_put(mp);
+ out_put_dmops:
        xfs_dmops_put(mp);
        goto fail_vfsop;
 
 
        IRELE(mp->m_rootip);
 
-       xfs_unmountfs(mp, NULL);
+       xfs_unmountfs(mp);
+       xfs_close_devices(mp);
        xfs_qmops_put(mp);
        xfs_dmops_put(mp);
        kmem_free(mp);