diff options
author | David Chinner <dgc@sgi.com> | 2006-03-13 21:23:52 -0500 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2006-03-13 21:23:52 -0500 |
commit | e8234a6871aa0de1ed0aeeecb5230ecf3ab414e2 (patch) | |
tree | b88093459262dcae16a237faf45200052629d19b /fs | |
parent | 2d0f864be3266eb0a8b4b48f36e2f777eace00b3 (diff) |
[XFS] Add support for hotplug CPUs to the per-CPU superblock counters by
registering a notifier callback that listens to CPU up/down events to
modify the counters appropriately.
SGI-PV: 949726
SGI-Modid: xfs-linux-melb:xfs-kern:25214a
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_linux.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 74 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 1 |
3 files changed, 75 insertions, 2 deletions
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index e2be64982bc1..9fdc14cffb70 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -73,6 +73,8 @@ | |||
73 | #include <linux/list.h> | 73 | #include <linux/list.h> |
74 | #include <linux/proc_fs.h> | 74 | #include <linux/proc_fs.h> |
75 | #include <linux/sort.h> | 75 | #include <linux/sort.h> |
76 | #include <linux/cpu.h> | ||
77 | #include <linux/notifier.h> | ||
76 | 78 | ||
77 | #include <asm/page.h> | 79 | #include <asm/page.h> |
78 | #include <asm/div64.h> | 80 | #include <asm/div64.h> |
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 | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 7cca5110ca44..9d2ffbdc37a9 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -401,6 +401,7 @@ typedef struct xfs_mount { | |||
401 | #ifdef HAVE_PERCPU_SB | 401 | #ifdef HAVE_PERCPU_SB |
402 | xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */ | 402 | xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */ |
403 | unsigned long m_icsb_counters; /* disabled per-cpu counters */ | 403 | unsigned long m_icsb_counters; /* disabled per-cpu counters */ |
404 | struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */ | ||
404 | #endif | 405 | #endif |
405 | } xfs_mount_t; | 406 | } xfs_mount_t; |
406 | 407 | ||