aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-05-19 21:31:13 -0400
committerNiv Sardi <xaiki@debian.org>2008-07-28 02:58:25 -0400
commit19f354d4c3f4c48bf6b2a86227d8e3050e5f7d50 (patch)
treea45bf7262dcac3a5f87a3db1d42e2e9a43577cd2 /fs/xfs/linux-2.6
parentaf15b8953a60d336aade96a2c162abffdba75ec9 (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')
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c192
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h3
4 files changed, 121 insertions, 81 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index ed03c6d3c9c1..9cc8f0213095 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1427,13 +1427,10 @@ xfs_unregister_buftarg(
1427 1427
1428void 1428void
1429xfs_free_buftarg( 1429xfs_free_buftarg(
1430 xfs_buftarg_t *btp, 1430 xfs_buftarg_t *btp)
1431 int external)
1432{ 1431{
1433 xfs_flush_buftarg(btp, 1); 1432 xfs_flush_buftarg(btp, 1);
1434 xfs_blkdev_issue_flush(btp); 1433 xfs_blkdev_issue_flush(btp);
1435 if (external)
1436 xfs_blkdev_put(btp->bt_bdev);
1437 xfs_free_bufhash(btp); 1434 xfs_free_bufhash(btp);
1438 iput(btp->bt_mapping->host); 1435 iput(btp->bt_mapping->host);
1439 1436
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index f948ec7ba9a4..29d1d4adc078 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -429,7 +429,7 @@ static inline void xfs_bdwrite(void *mp, xfs_buf_t *bp)
429 * Handling of buftargs. 429 * Handling of buftargs.
430 */ 430 */
431extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int); 431extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
432extern void xfs_free_buftarg(xfs_buftarg_t *, int); 432extern void xfs_free_buftarg(xfs_buftarg_t *);
433extern void xfs_wait_buftarg(xfs_buftarg_t *); 433extern void xfs_wait_buftarg(xfs_buftarg_t *);
434extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); 434extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
435extern int xfs_flush_buftarg(xfs_buftarg_t *, int); 435extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
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
769STATIC void
770xfs_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 */
794STATIC int
795xfs_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 */
1598STATIC int 1686STATIC int
1599xfs_fs_fill_super( 1687xfs_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);
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 3efb7c6d3303..212bdc7a7897 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -107,9 +107,6 @@ extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp,
107extern void xfs_flush_inode(struct xfs_inode *); 107extern void xfs_flush_inode(struct xfs_inode *);
108extern void xfs_flush_device(struct xfs_inode *); 108extern void xfs_flush_device(struct xfs_inode *);
109 109
110extern int xfs_blkdev_get(struct xfs_mount *, const char *,
111 struct block_device **);
112extern void xfs_blkdev_put(struct block_device *);
113extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); 110extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
114 111
115extern const struct export_operations xfs_export_operations; 112extern const struct export_operations xfs_export_operations;