diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 9b43b7b3d760..a64110b9023b 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -60,6 +60,7 @@ STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t, | |||
60 | int, int); | 60 | int, int); |
61 | STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t, | 61 | STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t, |
62 | int, int); | 62 | int, int); |
63 | STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t); | ||
63 | 64 | ||
64 | #else | 65 | #else |
65 | 66 | ||
@@ -1716,9 +1717,72 @@ xfs_mount_log_sbunit( | |||
1716 | * To ensure counters don't remain disabled, they are rebalanced when | 1717 | * To ensure counters don't remain disabled, they are rebalanced when |
1717 | * the global resource goes above a higher threshold (i.e. some hysteresis | 1718 | * the global resource goes above a higher threshold (i.e. some hysteresis |
1718 | * is present to prevent thrashing). | 1719 | * is present to prevent thrashing). |
1720 | */ | ||
1721 | |||
1722 | /* | ||
1723 | * hot-plug CPU notifier support. | ||
1719 | * | 1724 | * |
1720 | * Note: hotplug CPUs not yet supported | 1725 | * We cannot use the hotcpu_register() function because it does |
1726 | * not allow notifier instances. We need a notifier per filesystem | ||
1727 | * as we need to be able to identify the filesystem to balance | ||
1728 | * the counters out. This is acheived by having a notifier block | ||
1729 | * embedded in the xfs_mount_t and doing pointer magic to get the | ||
1730 | * mount pointer from the notifier block address. | ||
1721 | */ | 1731 | */ |
1732 | STATIC int | ||
1733 | xfs_icsb_cpu_notify( | ||
1734 | struct notifier_block *nfb, | ||
1735 | unsigned long action, | ||
1736 | void *hcpu) | ||
1737 | { | ||
1738 | xfs_icsb_cnts_t *cntp; | ||
1739 | xfs_mount_t *mp; | ||
1740 | int s; | ||
1741 | |||
1742 | mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier); | ||
1743 | cntp = (xfs_icsb_cnts_t *) | ||
1744 | per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu); | ||
1745 | switch (action) { | ||
1746 | case CPU_UP_PREPARE: | ||
1747 | /* Easy Case - initialize the area and locks, and | ||
1748 | * then rebalance when online does everything else for us. */ | ||
1749 | spin_lock_init(&cntp->icsb_lock); | ||
1750 | cntp->icsb_icount = 0; | ||
1751 | cntp->icsb_ifree = 0; | ||
1752 | cntp->icsb_fdblocks = 0; | ||
1753 | break; | ||
1754 | case CPU_ONLINE: | ||
1755 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); | ||
1756 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); | ||
1757 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); | ||
1758 | break; | ||
1759 | case CPU_DEAD: | ||
1760 | /* Disable all the counters, then fold the dead cpu's | ||
1761 | * count into the total on the global superblock and | ||
1762 | * re-enable the counters. */ | ||
1763 | s = XFS_SB_LOCK(mp); | ||
1764 | xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT); | ||
1765 | xfs_icsb_disable_counter(mp, XFS_SBS_IFREE); | ||
1766 | xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS); | ||
1767 | |||
1768 | mp->m_sb.sb_icount += cntp->icsb_icount; | ||
1769 | mp->m_sb.sb_ifree += cntp->icsb_ifree; | ||
1770 | mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks; | ||
1771 | |||
1772 | cntp->icsb_icount = 0; | ||
1773 | cntp->icsb_ifree = 0; | ||
1774 | cntp->icsb_fdblocks = 0; | ||
1775 | |||
1776 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED); | ||
1777 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED); | ||
1778 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED); | ||
1779 | XFS_SB_UNLOCK(mp, s); | ||
1780 | break; | ||
1781 | } | ||
1782 | |||
1783 | return NOTIFY_OK; | ||
1784 | } | ||
1785 | |||
1722 | int | 1786 | int |
1723 | xfs_icsb_init_counters( | 1787 | xfs_icsb_init_counters( |
1724 | xfs_mount_t *mp) | 1788 | xfs_mount_t *mp) |
@@ -1730,6 +1794,10 @@ xfs_icsb_init_counters( | |||
1730 | if (mp->m_sb_cnts == NULL) | 1794 | if (mp->m_sb_cnts == NULL) |
1731 | return -ENOMEM; | 1795 | return -ENOMEM; |
1732 | 1796 | ||
1797 | mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify; | ||
1798 | mp->m_icsb_notifier.priority = 0; | ||
1799 | register_cpu_notifier(&mp->m_icsb_notifier); | ||
1800 | |||
1733 | for_each_online_cpu(i) { | 1801 | for_each_online_cpu(i) { |
1734 | cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); | 1802 | cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); |
1735 | spin_lock_init(&cntp->icsb_lock); | 1803 | spin_lock_init(&cntp->icsb_lock); |
@@ -1746,8 +1814,10 @@ STATIC void | |||
1746 | xfs_icsb_destroy_counters( | 1814 | xfs_icsb_destroy_counters( |
1747 | xfs_mount_t *mp) | 1815 | xfs_mount_t *mp) |
1748 | { | 1816 | { |
1749 | if (mp->m_sb_cnts) | 1817 | if (mp->m_sb_cnts) { |
1818 | unregister_cpu_notifier(&mp->m_icsb_notifier); | ||
1750 | free_percpu(mp->m_sb_cnts); | 1819 | free_percpu(mp->m_sb_cnts); |
1820 | } | ||
1751 | } | 1821 | } |
1752 | 1822 | ||
1753 | 1823 | ||