diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-05-19 21:31:13 -0400 |
---|---|---|
committer | Niv Sardi <xaiki@debian.org> | 2008-07-28 02:58:25 -0400 |
commit | 19f354d4c3f4c48bf6b2a86227d8e3050e5f7d50 (patch) | |
tree | a45bf7262dcac3a5f87a3db1d42e2e9a43577cd2 /fs/xfs/linux-2.6/xfs_super.c | |
parent | af15b8953a60d336aade96a2c162abffdba75ec9 (diff) |
[XFS] sort out opening and closing of the block devices
Currently closing the rt/log block device is done in the wrong spot, and
far too early. So revampt it:
- xfs_blkdev_put moved out of xfs_free_buftarg into the caller so that
it is done after tearing down the buftarg completely.
- call to xfs_unmountfs_close moved from xfs_mountfs into caller so
that it's done after tearing down the filesystem completely.
- xfs_unmountfs_close is renamed to xfs_close_devices and made static
in xfs_super.c
- opening of the block devices is split into a helper xfs_open_devices
that is symetric in use to xfs_close_devices
- xfs_unmountfs can now lose struct cred
- error handling around device opening sanitized in xfs_fs_fill_super
SGI-PV: 981951
SGI-Modid: xfs-linux-melb:xfs-kern:31193a
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_super.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 192 |
1 files changed, 119 insertions, 73 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 4b6ddf88d44e..055faa06ca22 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -766,6 +766,103 @@ xfs_blkdev_issue_flush( | |||
766 | blkdev_issue_flush(buftarg->bt_bdev, NULL); | 766 | blkdev_issue_flush(buftarg->bt_bdev, NULL); |
767 | } | 767 | } |
768 | 768 | ||
769 | STATIC void | ||
770 | xfs_close_devices( | ||
771 | struct xfs_mount *mp) | ||
772 | { | ||
773 | if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) { | ||
774 | xfs_free_buftarg(mp->m_logdev_targp); | ||
775 | xfs_blkdev_put(mp->m_logdev_targp->bt_bdev); | ||
776 | } | ||
777 | if (mp->m_rtdev_targp) { | ||
778 | xfs_free_buftarg(mp->m_rtdev_targp); | ||
779 | xfs_blkdev_put(mp->m_rtdev_targp->bt_bdev); | ||
780 | } | ||
781 | xfs_free_buftarg(mp->m_ddev_targp); | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * The file system configurations are: | ||
786 | * (1) device (partition) with data and internal log | ||
787 | * (2) logical volume with data and log subvolumes. | ||
788 | * (3) logical volume with data, log, and realtime subvolumes. | ||
789 | * | ||
790 | * We only have to handle opening the log and realtime volumes here if | ||
791 | * they are present. The data subvolume has already been opened by | ||
792 | * get_sb_bdev() and is stored in sb->s_bdev. | ||
793 | */ | ||
794 | STATIC int | ||
795 | xfs_open_devices( | ||
796 | struct xfs_mount *mp, | ||
797 | struct xfs_mount_args *args) | ||
798 | { | ||
799 | struct block_device *ddev = mp->m_super->s_bdev; | ||
800 | struct block_device *logdev = NULL, *rtdev = NULL; | ||
801 | int error; | ||
802 | |||
803 | /* | ||
804 | * Open real time and log devices - order is important. | ||
805 | */ | ||
806 | if (args->logname[0]) { | ||
807 | error = xfs_blkdev_get(mp, args->logname, &logdev); | ||
808 | if (error) | ||
809 | goto out; | ||
810 | } | ||
811 | |||
812 | if (args->rtname[0]) { | ||
813 | error = xfs_blkdev_get(mp, args->rtname, &rtdev); | ||
814 | if (error) | ||
815 | goto out_close_logdev; | ||
816 | |||
817 | if (rtdev == ddev || rtdev == logdev) { | ||
818 | cmn_err(CE_WARN, | ||
819 | "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); | ||
820 | error = EINVAL; | ||
821 | goto out_close_rtdev; | ||
822 | } | ||
823 | } | ||
824 | |||
825 | /* | ||
826 | * Setup xfs_mount buffer target pointers | ||
827 | */ | ||
828 | error = ENOMEM; | ||
829 | mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0); | ||
830 | if (!mp->m_ddev_targp) | ||
831 | goto out_close_rtdev; | ||
832 | |||
833 | if (rtdev) { | ||
834 | mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1); | ||
835 | if (!mp->m_rtdev_targp) | ||
836 | goto out_free_ddev_targ; | ||
837 | } | ||
838 | |||
839 | if (logdev && logdev != ddev) { | ||
840 | mp->m_logdev_targp = xfs_alloc_buftarg(logdev, 1); | ||
841 | if (!mp->m_logdev_targp) | ||
842 | goto out_free_rtdev_targ; | ||
843 | } else { | ||
844 | mp->m_logdev_targp = mp->m_ddev_targp; | ||
845 | } | ||
846 | |||
847 | return 0; | ||
848 | |||
849 | out_free_rtdev_targ: | ||
850 | if (mp->m_rtdev_targp) | ||
851 | xfs_free_buftarg(mp->m_rtdev_targp); | ||
852 | out_free_ddev_targ: | ||
853 | xfs_free_buftarg(mp->m_ddev_targp); | ||
854 | out_close_rtdev: | ||
855 | if (rtdev) | ||
856 | xfs_blkdev_put(rtdev); | ||
857 | out_close_logdev: | ||
858 | if (logdev && logdev != ddev) | ||
859 | xfs_blkdev_put(logdev); | ||
860 | out: | ||
861 | return error; | ||
862 | } | ||
863 | |||
864 | |||
865 | |||
769 | /* | 866 | /* |
770 | * XFS AIL push thread support | 867 | * XFS AIL push thread support |
771 | */ | 868 | */ |
@@ -1138,7 +1235,8 @@ xfs_fs_put_super( | |||
1138 | unmount_event_flags); | 1235 | unmount_event_flags); |
1139 | } | 1236 | } |
1140 | 1237 | ||
1141 | xfs_unmountfs(mp, NULL); | 1238 | xfs_unmountfs(mp); |
1239 | xfs_close_devices(mp); | ||
1142 | xfs_qmops_put(mp); | 1240 | xfs_qmops_put(mp); |
1143 | xfs_dmops_put(mp); | 1241 | xfs_dmops_put(mp); |
1144 | kmem_free(mp); | 1242 | kmem_free(mp); |
@@ -1585,16 +1683,6 @@ xfs_finish_flags( | |||
1585 | return 0; | 1683 | return 0; |
1586 | } | 1684 | } |
1587 | 1685 | ||
1588 | /* | ||
1589 | * The file system configurations are: | ||
1590 | * (1) device (partition) with data and internal log | ||
1591 | * (2) logical volume with data and log subvolumes. | ||
1592 | * (3) logical volume with data, log, and realtime subvolumes. | ||
1593 | * | ||
1594 | * We only have to handle opening the log and realtime volumes here if | ||
1595 | * they are present. The data subvolume has already been opened by | ||
1596 | * get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev. | ||
1597 | */ | ||
1598 | STATIC int | 1686 | STATIC int |
1599 | xfs_fs_fill_super( | 1687 | xfs_fs_fill_super( |
1600 | struct super_block *sb, | 1688 | struct super_block *sb, |
@@ -1604,8 +1692,6 @@ xfs_fs_fill_super( | |||
1604 | struct inode *root; | 1692 | struct inode *root; |
1605 | struct xfs_mount *mp = NULL; | 1693 | struct xfs_mount *mp = NULL; |
1606 | struct xfs_mount_args *args = xfs_args_allocate(sb, silent); | 1694 | struct xfs_mount_args *args = xfs_args_allocate(sb, silent); |
1607 | struct block_device *ddev = sb->s_bdev; | ||
1608 | struct block_device *logdev = NULL, *rtdev = NULL; | ||
1609 | int flags = 0, error; | 1695 | int flags = 0, error; |
1610 | 1696 | ||
1611 | mp = xfs_mount_init(); | 1697 | mp = xfs_mount_init(); |
@@ -1634,61 +1720,14 @@ xfs_fs_fill_super( | |||
1634 | goto fail_vfsop; | 1720 | goto fail_vfsop; |
1635 | error = xfs_qmops_get(mp, args); | 1721 | error = xfs_qmops_get(mp, args); |
1636 | if (error) | 1722 | if (error) |
1637 | goto fail_vfsop; | 1723 | goto out_put_dmops; |
1638 | 1724 | ||
1639 | if (args->flags & XFSMNT_QUIET) | 1725 | if (args->flags & XFSMNT_QUIET) |
1640 | flags |= XFS_MFSI_QUIET; | 1726 | flags |= XFS_MFSI_QUIET; |
1641 | 1727 | ||
1642 | /* | 1728 | error = xfs_open_devices(mp, args); |
1643 | * Open real time and log devices - order is important. | 1729 | if (error) |
1644 | */ | 1730 | goto out_put_qmops; |
1645 | if (args->logname[0]) { | ||
1646 | error = xfs_blkdev_get(mp, args->logname, &logdev); | ||
1647 | if (error) | ||
1648 | goto fail_vfsop; | ||
1649 | } | ||
1650 | if (args->rtname[0]) { | ||
1651 | error = xfs_blkdev_get(mp, args->rtname, &rtdev); | ||
1652 | if (error) { | ||
1653 | xfs_blkdev_put(logdev); | ||
1654 | goto fail_vfsop; | ||
1655 | } | ||
1656 | |||
1657 | if (rtdev == ddev || rtdev == logdev) { | ||
1658 | cmn_err(CE_WARN, | ||
1659 | "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); | ||
1660 | xfs_blkdev_put(logdev); | ||
1661 | xfs_blkdev_put(rtdev); | ||
1662 | error = EINVAL; | ||
1663 | goto fail_vfsop; | ||
1664 | } | ||
1665 | } | ||
1666 | |||
1667 | /* | ||
1668 | * Setup xfs_mount buffer target pointers | ||
1669 | */ | ||
1670 | error = ENOMEM; | ||
1671 | mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0); | ||
1672 | if (!mp->m_ddev_targp) { | ||
1673 | xfs_blkdev_put(logdev); | ||
1674 | xfs_blkdev_put(rtdev); | ||
1675 | goto fail_vfsop; | ||
1676 | } | ||
1677 | if (rtdev) { | ||
1678 | mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1); | ||
1679 | if (!mp->m_rtdev_targp) { | ||
1680 | xfs_blkdev_put(logdev); | ||
1681 | xfs_blkdev_put(rtdev); | ||
1682 | goto error0; | ||
1683 | } | ||
1684 | } | ||
1685 | mp->m_logdev_targp = (logdev && logdev != ddev) ? | ||
1686 | xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp; | ||
1687 | if (!mp->m_logdev_targp) { | ||
1688 | xfs_blkdev_put(logdev); | ||
1689 | xfs_blkdev_put(rtdev); | ||
1690 | goto error0; | ||
1691 | } | ||
1692 | 1731 | ||
1693 | /* | 1732 | /* |
1694 | * Setup flags based on mount(2) options and then the superblock | 1733 | * Setup flags based on mount(2) options and then the superblock |
@@ -1708,7 +1747,9 @@ xfs_fs_fill_super( | |||
1708 | */ | 1747 | */ |
1709 | error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize, | 1748 | error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize, |
1710 | mp->m_sb.sb_sectsize); | 1749 | mp->m_sb.sb_sectsize); |
1711 | if (!error && logdev && logdev != ddev) { | 1750 | if (error) |
1751 | goto error2; | ||
1752 | if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) { | ||
1712 | unsigned int log_sector_size = BBSIZE; | 1753 | unsigned int log_sector_size = BBSIZE; |
1713 | 1754 | ||
1714 | if (xfs_sb_version_hassector(&mp->m_sb)) | 1755 | if (xfs_sb_version_hassector(&mp->m_sb)) |
@@ -1716,13 +1757,16 @@ xfs_fs_fill_super( | |||
1716 | error = xfs_setsize_buftarg(mp->m_logdev_targp, | 1757 | error = xfs_setsize_buftarg(mp->m_logdev_targp, |
1717 | mp->m_sb.sb_blocksize, | 1758 | mp->m_sb.sb_blocksize, |
1718 | log_sector_size); | 1759 | log_sector_size); |
1760 | if (error) | ||
1761 | goto error2; | ||
1719 | } | 1762 | } |
1720 | if (!error && rtdev) | 1763 | if (mp->m_rtdev_targp) { |
1721 | error = xfs_setsize_buftarg(mp->m_rtdev_targp, | 1764 | error = xfs_setsize_buftarg(mp->m_rtdev_targp, |
1722 | mp->m_sb.sb_blocksize, | 1765 | mp->m_sb.sb_blocksize, |
1723 | mp->m_sb.sb_sectsize); | 1766 | mp->m_sb.sb_sectsize); |
1724 | if (error) | 1767 | if (error) |
1725 | goto error2; | 1768 | goto error2; |
1769 | } | ||
1726 | 1770 | ||
1727 | if (mp->m_flags & XFS_MOUNT_BARRIER) | 1771 | if (mp->m_flags & XFS_MOUNT_BARRIER) |
1728 | xfs_mountfs_check_barriers(mp); | 1772 | xfs_mountfs_check_barriers(mp); |
@@ -1778,13 +1822,14 @@ xfs_fs_fill_super( | |||
1778 | xfs_freesb(mp); | 1822 | xfs_freesb(mp); |
1779 | error1: | 1823 | error1: |
1780 | xfs_binval(mp->m_ddev_targp); | 1824 | xfs_binval(mp->m_ddev_targp); |
1781 | if (logdev && logdev != ddev) | 1825 | if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) |
1782 | xfs_binval(mp->m_logdev_targp); | 1826 | xfs_binval(mp->m_logdev_targp); |
1783 | if (rtdev) | 1827 | if (mp->m_rtdev_targp) |
1784 | xfs_binval(mp->m_rtdev_targp); | 1828 | xfs_binval(mp->m_rtdev_targp); |
1785 | error0: | 1829 | xfs_close_devices(mp); |
1786 | xfs_unmountfs_close(mp, NULL); | 1830 | out_put_qmops: |
1787 | xfs_qmops_put(mp); | 1831 | xfs_qmops_put(mp); |
1832 | out_put_dmops: | ||
1788 | xfs_dmops_put(mp); | 1833 | xfs_dmops_put(mp); |
1789 | goto fail_vfsop; | 1834 | goto fail_vfsop; |
1790 | 1835 | ||
@@ -1810,7 +1855,8 @@ xfs_fs_fill_super( | |||
1810 | 1855 | ||
1811 | IRELE(mp->m_rootip); | 1856 | IRELE(mp->m_rootip); |
1812 | 1857 | ||
1813 | xfs_unmountfs(mp, NULL); | 1858 | xfs_unmountfs(mp); |
1859 | xfs_close_devices(mp); | ||
1814 | xfs_qmops_put(mp); | 1860 | xfs_qmops_put(mp); |
1815 | xfs_dmops_put(mp); | 1861 | xfs_dmops_put(mp); |
1816 | kmem_free(mp); | 1862 | kmem_free(mp); |