forked from Minki/linux
[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>
This commit is contained in:
parent
2d0f864be3
commit
e8234a6871
|
@ -73,6 +73,8 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/notifier.h>
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
|
|
|
@ -60,6 +60,7 @@ STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
|
||||||
int, int);
|
int, int);
|
||||||
STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t,
|
STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t,
|
||||||
int, int);
|
int, int);
|
||||||
|
STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -1716,9 +1717,72 @@ xfs_mount_log_sbunit(
|
||||||
* To ensure counters don't remain disabled, they are rebalanced when
|
* To ensure counters don't remain disabled, they are rebalanced when
|
||||||
* the global resource goes above a higher threshold (i.e. some hysteresis
|
* the global resource goes above a higher threshold (i.e. some hysteresis
|
||||||
* is present to prevent thrashing).
|
* is present to prevent thrashing).
|
||||||
*
|
|
||||||
* Note: hotplug CPUs not yet supported
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hot-plug CPU notifier support.
|
||||||
|
*
|
||||||
|
* We cannot use the hotcpu_register() function because it does
|
||||||
|
* not allow notifier instances. We need a notifier per filesystem
|
||||||
|
* as we need to be able to identify the filesystem to balance
|
||||||
|
* the counters out. This is acheived by having a notifier block
|
||||||
|
* embedded in the xfs_mount_t and doing pointer magic to get the
|
||||||
|
* mount pointer from the notifier block address.
|
||||||
|
*/
|
||||||
|
STATIC int
|
||||||
|
xfs_icsb_cpu_notify(
|
||||||
|
struct notifier_block *nfb,
|
||||||
|
unsigned long action,
|
||||||
|
void *hcpu)
|
||||||
|
{
|
||||||
|
xfs_icsb_cnts_t *cntp;
|
||||||
|
xfs_mount_t *mp;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
|
||||||
|
cntp = (xfs_icsb_cnts_t *)
|
||||||
|
per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
|
||||||
|
switch (action) {
|
||||||
|
case CPU_UP_PREPARE:
|
||||||
|
/* Easy Case - initialize the area and locks, and
|
||||||
|
* then rebalance when online does everything else for us. */
|
||||||
|
spin_lock_init(&cntp->icsb_lock);
|
||||||
|
cntp->icsb_icount = 0;
|
||||||
|
cntp->icsb_ifree = 0;
|
||||||
|
cntp->icsb_fdblocks = 0;
|
||||||
|
break;
|
||||||
|
case CPU_ONLINE:
|
||||||
|
xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
|
||||||
|
xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
|
||||||
|
xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
|
||||||
|
break;
|
||||||
|
case CPU_DEAD:
|
||||||
|
/* Disable all the counters, then fold the dead cpu's
|
||||||
|
* count into the total on the global superblock and
|
||||||
|
* re-enable the counters. */
|
||||||
|
s = XFS_SB_LOCK(mp);
|
||||||
|
xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
|
||||||
|
xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
|
||||||
|
xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
|
||||||
|
|
||||||
|
mp->m_sb.sb_icount += cntp->icsb_icount;
|
||||||
|
mp->m_sb.sb_ifree += cntp->icsb_ifree;
|
||||||
|
mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
|
||||||
|
|
||||||
|
cntp->icsb_icount = 0;
|
||||||
|
cntp->icsb_ifree = 0;
|
||||||
|
cntp->icsb_fdblocks = 0;
|
||||||
|
|
||||||
|
xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED);
|
||||||
|
xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED);
|
||||||
|
xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED);
|
||||||
|
XFS_SB_UNLOCK(mp, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_icsb_init_counters(
|
xfs_icsb_init_counters(
|
||||||
xfs_mount_t *mp)
|
xfs_mount_t *mp)
|
||||||
|
@ -1730,6 +1794,10 @@ xfs_icsb_init_counters(
|
||||||
if (mp->m_sb_cnts == NULL)
|
if (mp->m_sb_cnts == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
|
||||||
|
mp->m_icsb_notifier.priority = 0;
|
||||||
|
register_cpu_notifier(&mp->m_icsb_notifier);
|
||||||
|
|
||||||
for_each_online_cpu(i) {
|
for_each_online_cpu(i) {
|
||||||
cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
|
cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
|
||||||
spin_lock_init(&cntp->icsb_lock);
|
spin_lock_init(&cntp->icsb_lock);
|
||||||
|
@ -1746,8 +1814,10 @@ STATIC void
|
||||||
xfs_icsb_destroy_counters(
|
xfs_icsb_destroy_counters(
|
||||||
xfs_mount_t *mp)
|
xfs_mount_t *mp)
|
||||||
{
|
{
|
||||||
if (mp->m_sb_cnts)
|
if (mp->m_sb_cnts) {
|
||||||
|
unregister_cpu_notifier(&mp->m_icsb_notifier);
|
||||||
free_percpu(mp->m_sb_cnts);
|
free_percpu(mp->m_sb_cnts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -401,6 +401,7 @@ typedef struct xfs_mount {
|
||||||
#ifdef HAVE_PERCPU_SB
|
#ifdef HAVE_PERCPU_SB
|
||||||
xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */
|
xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */
|
||||||
unsigned long m_icsb_counters; /* disabled per-cpu counters */
|
unsigned long m_icsb_counters; /* disabled per-cpu counters */
|
||||||
|
struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */
|
||||||
#endif
|
#endif
|
||||||
} xfs_mount_t;
|
} xfs_mount_t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user