|
@@ -766,6 +766,103 @@ xfs_blkdev_issue_flush(
|
|
|
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
|
|
|
*/
|
|
@@ -1138,7 +1235,8 @@ xfs_fs_put_super(
|
|
|
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);
|
|
@@ -1585,16 +1683,6 @@ xfs_finish_flags(
|
|
|
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,
|
|
@@ -1604,8 +1692,6 @@ xfs_fs_fill_super(
|
|
|
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();
|
|
@@ -1634,61 +1720,14 @@ xfs_fs_fill_super(
|
|
|
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
|
|
@@ -1708,7 +1747,9 @@ xfs_fs_fill_super(
|
|
|
*/
|
|
|
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))
|
|
@@ -1716,13 +1757,16 @@ xfs_fs_fill_super(
|
|
|
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);
|
|
@@ -1778,13 +1822,14 @@ xfs_fs_fill_super(
|
|
|
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;
|
|
|
|
|
@@ -1810,7 +1855,8 @@ xfs_fs_fill_super(
|
|
|
|
|
|
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);
|