|
@@ -43,18 +43,6 @@
|
|
|
#include "xfs_sysfs.h"
|
|
|
|
|
|
|
|
|
-#ifdef HAVE_PERCPU_SB
|
|
|
-STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
|
|
|
- int);
|
|
|
-STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
|
|
|
- int);
|
|
|
-STATIC void xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
|
|
|
-#else
|
|
|
-
|
|
|
-#define xfs_icsb_balance_counter(mp, a, b) do { } while (0)
|
|
|
-#define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0)
|
|
|
-#endif
|
|
|
-
|
|
|
static DEFINE_MUTEX(xfs_uuid_table_mutex);
|
|
|
static int xfs_uuid_table_size;
|
|
|
static uuid_t *xfs_uuid_table;
|
|
@@ -347,8 +335,7 @@ reread:
|
|
|
goto reread;
|
|
|
}
|
|
|
|
|
|
- /* Initialize per-cpu counters */
|
|
|
- xfs_icsb_reinit_counters(mp);
|
|
|
+ xfs_reinit_percpu_counters(mp);
|
|
|
|
|
|
/* no need to be quiet anymore, so reset the buf ops */
|
|
|
bp->b_ops = &xfs_sb_buf_ops;
|
|
@@ -1087,8 +1074,6 @@ xfs_log_sbcount(xfs_mount_t *mp)
|
|
|
if (!xfs_fs_writable(mp, SB_FREEZE_COMPLETE))
|
|
|
return 0;
|
|
|
|
|
|
- xfs_icsb_sync_counters(mp, 0);
|
|
|
-
|
|
|
/*
|
|
|
* we don't need to do this if we are updating the superblock
|
|
|
* counters on every modification.
|
|
@@ -1466,502 +1451,3 @@ xfs_dev_is_read_only(
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
-
|
|
|
-#ifdef HAVE_PERCPU_SB
|
|
|
-/*
|
|
|
- * Per-cpu incore superblock counters
|
|
|
- *
|
|
|
- * Simple concept, difficult implementation
|
|
|
- *
|
|
|
- * Basically, replace the incore superblock counters with a distributed per cpu
|
|
|
- * counter for contended fields (e.g. free block count).
|
|
|
- *
|
|
|
- * Difficulties arise in that the incore sb is used for ENOSPC checking, and
|
|
|
- * hence needs to be accurately read when we are running low on space. Hence
|
|
|
- * there is a method to enable and disable the per-cpu counters based on how
|
|
|
- * much "stuff" is available in them.
|
|
|
- *
|
|
|
- * Basically, a counter is enabled if there is enough free resource to justify
|
|
|
- * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local
|
|
|
- * ENOSPC), then we disable the counters to synchronise all callers and
|
|
|
- * re-distribute the available resources.
|
|
|
- *
|
|
|
- * If, once we redistributed the available resources, we still get a failure,
|
|
|
- * we disable the per-cpu counter and go through the slow path.
|
|
|
- *
|
|
|
- * The slow path is the current xfs_mod_incore_sb() function. This means that
|
|
|
- * when we disable a per-cpu counter, we need to drain its resources back to
|
|
|
- * the global superblock. We do this after disabling the counter to prevent
|
|
|
- * more threads from queueing up on the counter.
|
|
|
- *
|
|
|
- * Essentially, this means that we still need a lock in the fast path to enable
|
|
|
- * synchronisation between the global counters and the per-cpu counters. This
|
|
|
- * is not a problem because the lock will be local to a CPU almost all the time
|
|
|
- * and have little contention except when we get to ENOSPC conditions.
|
|
|
- *
|
|
|
- * Basically, this lock becomes a barrier that enables us to lock out the fast
|
|
|
- * path while we do things like enabling and disabling counters and
|
|
|
- * synchronising the counters.
|
|
|
- *
|
|
|
- * Locking rules:
|
|
|
- *
|
|
|
- * 1. m_sb_lock before picking up per-cpu locks
|
|
|
- * 2. per-cpu locks always picked up via for_each_online_cpu() order
|
|
|
- * 3. accurate counter sync requires m_sb_lock + per cpu locks
|
|
|
- * 4. modifying per-cpu counters requires holding per-cpu lock
|
|
|
- * 5. modifying global counters requires holding m_sb_lock
|
|
|
- * 6. enabling or disabling a counter requires holding the m_sb_lock
|
|
|
- * and _none_ of the per-cpu locks.
|
|
|
- *
|
|
|
- * Disabled counters are only ever re-enabled by a balance operation
|
|
|
- * that results in more free resources per CPU than a given threshold.
|
|
|
- * To ensure counters don't remain disabled, they are rebalanced when
|
|
|
- * the global resource goes above a higher threshold (i.e. some hysteresis
|
|
|
- * is present to prevent thrashing).
|
|
|
- */
|
|
|
-
|
|
|
-#ifdef CONFIG_HOTPLUG_CPU
|
|
|
-/*
|
|
|
- * hot-plug CPU notifier support.
|
|
|
- *
|
|
|
- * We need a notifier per filesystem as we need to be able to identify
|
|
|
- * the filesystem to balance the counters out. This is achieved 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;
|
|
|
-
|
|
|
- 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:
|
|
|
- case CPU_UP_PREPARE_FROZEN:
|
|
|
- /* Easy Case - initialize the area and locks, and
|
|
|
- * then rebalance when online does everything else for us. */
|
|
|
- memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
|
|
|
- break;
|
|
|
- case CPU_ONLINE:
|
|
|
- case CPU_ONLINE_FROZEN:
|
|
|
- xfs_icsb_lock(mp);
|
|
|
- xfs_icsb_unlock(mp);
|
|
|
- break;
|
|
|
- case CPU_DEAD:
|
|
|
- case CPU_DEAD_FROZEN:
|
|
|
- /* Disable all the counters, then fold the dead cpu's
|
|
|
- * count into the total on the global superblock and
|
|
|
- * re-enable the counters. */
|
|
|
- xfs_icsb_lock(mp);
|
|
|
- spin_lock(&mp->m_sb_lock);
|
|
|
-
|
|
|
- memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
|
|
|
-
|
|
|
- spin_unlock(&mp->m_sb_lock);
|
|
|
- xfs_icsb_unlock(mp);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return NOTIFY_OK;
|
|
|
-}
|
|
|
-#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
-
|
|
|
-int
|
|
|
-xfs_icsb_init_counters(
|
|
|
- xfs_mount_t *mp)
|
|
|
-{
|
|
|
- xfs_icsb_cnts_t *cntp;
|
|
|
- int error;
|
|
|
- int i;
|
|
|
-
|
|
|
- error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
-
|
|
|
- error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
|
|
|
- if (error)
|
|
|
- goto free_icount;
|
|
|
-
|
|
|
- error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
|
|
|
- if (error)
|
|
|
- goto free_ifree;
|
|
|
-
|
|
|
- mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
|
|
|
- if (!mp->m_sb_cnts) {
|
|
|
- error = -ENOMEM;
|
|
|
- goto free_fdblocks;
|
|
|
- }
|
|
|
-
|
|
|
- for_each_online_cpu(i) {
|
|
|
- cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
|
|
|
- memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
|
|
|
- }
|
|
|
-
|
|
|
- mutex_init(&mp->m_icsb_mutex);
|
|
|
-
|
|
|
- /*
|
|
|
- * start with all counters disabled so that the
|
|
|
- * initial balance kicks us off correctly
|
|
|
- */
|
|
|
- mp->m_icsb_counters = -1;
|
|
|
-
|
|
|
-#ifdef CONFIG_HOTPLUG_CPU
|
|
|
- mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
|
|
|
- mp->m_icsb_notifier.priority = 0;
|
|
|
- register_hotcpu_notifier(&mp->m_icsb_notifier);
|
|
|
-#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
-free_fdblocks:
|
|
|
- percpu_counter_destroy(&mp->m_fdblocks);
|
|
|
-free_ifree:
|
|
|
- percpu_counter_destroy(&mp->m_ifree);
|
|
|
-free_icount:
|
|
|
- percpu_counter_destroy(&mp->m_icount);
|
|
|
- return error;
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-xfs_icsb_reinit_counters(
|
|
|
- xfs_mount_t *mp)
|
|
|
-{
|
|
|
- percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
|
|
|
- percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
|
|
|
- percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
|
|
|
-
|
|
|
- xfs_icsb_lock(mp);
|
|
|
- /*
|
|
|
- * start with all counters disabled so that the
|
|
|
- * initial balance kicks us off correctly
|
|
|
- */
|
|
|
- mp->m_icsb_counters = -1;
|
|
|
- xfs_icsb_unlock(mp);
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-xfs_icsb_destroy_counters(
|
|
|
- xfs_mount_t *mp)
|
|
|
-{
|
|
|
- if (mp->m_sb_cnts) {
|
|
|
- unregister_hotcpu_notifier(&mp->m_icsb_notifier);
|
|
|
- free_percpu(mp->m_sb_cnts);
|
|
|
- }
|
|
|
-
|
|
|
- percpu_counter_destroy(&mp->m_icount);
|
|
|
- percpu_counter_destroy(&mp->m_ifree);
|
|
|
- percpu_counter_destroy(&mp->m_fdblocks);
|
|
|
-
|
|
|
- mutex_destroy(&mp->m_icsb_mutex);
|
|
|
-}
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_lock_cntr(
|
|
|
- xfs_icsb_cnts_t *icsbp)
|
|
|
-{
|
|
|
- while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
|
|
|
- ndelay(1000);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_unlock_cntr(
|
|
|
- xfs_icsb_cnts_t *icsbp)
|
|
|
-{
|
|
|
- clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_lock_all_counters(
|
|
|
- xfs_mount_t *mp)
|
|
|
-{
|
|
|
- xfs_icsb_cnts_t *cntp;
|
|
|
- int i;
|
|
|
-
|
|
|
- for_each_online_cpu(i) {
|
|
|
- cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
|
|
|
- xfs_icsb_lock_cntr(cntp);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_unlock_all_counters(
|
|
|
- xfs_mount_t *mp)
|
|
|
-{
|
|
|
- xfs_icsb_cnts_t *cntp;
|
|
|
- int i;
|
|
|
-
|
|
|
- for_each_online_cpu(i) {
|
|
|
- cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
|
|
|
- xfs_icsb_unlock_cntr(cntp);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_count(
|
|
|
- xfs_mount_t *mp,
|
|
|
- xfs_icsb_cnts_t *cnt,
|
|
|
- int flags)
|
|
|
-{
|
|
|
- memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
|
|
|
-
|
|
|
- if (!(flags & XFS_ICSB_LAZY_COUNT))
|
|
|
- xfs_icsb_lock_all_counters(mp);
|
|
|
-
|
|
|
-
|
|
|
- if (!(flags & XFS_ICSB_LAZY_COUNT))
|
|
|
- xfs_icsb_unlock_all_counters(mp);
|
|
|
-}
|
|
|
-
|
|
|
-STATIC int
|
|
|
-xfs_icsb_counter_disabled(
|
|
|
- xfs_mount_t *mp,
|
|
|
- xfs_sb_field_t field)
|
|
|
-{
|
|
|
- return test_bit(field, &mp->m_icsb_counters);
|
|
|
-}
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_disable_counter(
|
|
|
- xfs_mount_t *mp,
|
|
|
- xfs_sb_field_t field)
|
|
|
-{
|
|
|
- xfs_icsb_cnts_t cnt;
|
|
|
-
|
|
|
- /*
|
|
|
- * If we are already disabled, then there is nothing to do
|
|
|
- * here. We check before locking all the counters to avoid
|
|
|
- * the expensive lock operation when being called in the
|
|
|
- * slow path and the counter is already disabled. This is
|
|
|
- * safe because the only time we set or clear this state is under
|
|
|
- * the m_icsb_mutex.
|
|
|
- */
|
|
|
- if (xfs_icsb_counter_disabled(mp, field))
|
|
|
- return;
|
|
|
-
|
|
|
- xfs_icsb_lock_all_counters(mp);
|
|
|
- if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
|
|
|
- /* drain back to superblock */
|
|
|
-
|
|
|
- xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
|
|
|
- switch(field) {
|
|
|
- default:
|
|
|
- BUG();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- xfs_icsb_unlock_all_counters(mp);
|
|
|
-}
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_enable_counter(
|
|
|
- xfs_mount_t *mp,
|
|
|
- xfs_sb_field_t field,
|
|
|
- uint64_t count,
|
|
|
- uint64_t resid)
|
|
|
-{
|
|
|
- int i;
|
|
|
-
|
|
|
- xfs_icsb_lock_all_counters(mp);
|
|
|
- for_each_online_cpu(i) {
|
|
|
- switch (field) {
|
|
|
- default:
|
|
|
- BUG();
|
|
|
- break;
|
|
|
- }
|
|
|
- resid = 0;
|
|
|
- }
|
|
|
- clear_bit(field, &mp->m_icsb_counters);
|
|
|
- xfs_icsb_unlock_all_counters(mp);
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-xfs_icsb_sync_counters_locked(
|
|
|
- xfs_mount_t *mp,
|
|
|
- int flags)
|
|
|
-{
|
|
|
- xfs_icsb_cnts_t cnt;
|
|
|
-
|
|
|
- xfs_icsb_count(mp, &cnt, flags);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Accurate update of per-cpu counters to incore superblock
|
|
|
- */
|
|
|
-void
|
|
|
-xfs_icsb_sync_counters(
|
|
|
- xfs_mount_t *mp,
|
|
|
- int flags)
|
|
|
-{
|
|
|
- spin_lock(&mp->m_sb_lock);
|
|
|
- xfs_icsb_sync_counters_locked(mp, flags);
|
|
|
- spin_unlock(&mp->m_sb_lock);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Balance and enable/disable counters as necessary.
|
|
|
- *
|
|
|
- * Thresholds for re-enabling counters are somewhat magic. inode counts are
|
|
|
- * chosen to be the same number as single on disk allocation chunk per CPU, and
|
|
|
- * free blocks is something far enough zero that we aren't going thrash when we
|
|
|
- * get near ENOSPC. We also need to supply a minimum we require per cpu to
|
|
|
- * prevent looping endlessly when xfs_alloc_space asks for more than will
|
|
|
- * be distributed to a single CPU but each CPU has enough blocks to be
|
|
|
- * reenabled.
|
|
|
- *
|
|
|
- * Note that we can be called when counters are already disabled.
|
|
|
- * xfs_icsb_disable_counter() optimises the counter locking in this case to
|
|
|
- * prevent locking every per-cpu counter needlessly.
|
|
|
- */
|
|
|
-
|
|
|
-#define XFS_ICSB_INO_CNTR_REENABLE (uint64_t)64
|
|
|
-#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
|
|
|
- (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
|
|
|
-STATIC void
|
|
|
-xfs_icsb_balance_counter_locked(
|
|
|
- xfs_mount_t *mp,
|
|
|
- xfs_sb_field_t field,
|
|
|
- int min_per_cpu)
|
|
|
-{
|
|
|
- uint64_t count, resid;
|
|
|
-
|
|
|
- /* disable counter and sync counter */
|
|
|
- xfs_icsb_disable_counter(mp, field);
|
|
|
-
|
|
|
- /* update counters - first CPU gets residual*/
|
|
|
- switch (field) {
|
|
|
- default:
|
|
|
- BUG();
|
|
|
- count = resid = 0; /* quiet, gcc */
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- xfs_icsb_enable_counter(mp, field, count, resid);
|
|
|
-}
|
|
|
-
|
|
|
-STATIC void
|
|
|
-xfs_icsb_balance_counter(
|
|
|
- xfs_mount_t *mp,
|
|
|
- xfs_sb_field_t fields,
|
|
|
- int min_per_cpu)
|
|
|
-{
|
|
|
- spin_lock(&mp->m_sb_lock);
|
|
|
- xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
|
|
|
- spin_unlock(&mp->m_sb_lock);
|
|
|
-}
|
|
|
-
|
|
|
-int
|
|
|
-xfs_icsb_modify_counters(
|
|
|
- xfs_mount_t *mp,
|
|
|
- xfs_sb_field_t field,
|
|
|
- int64_t delta,
|
|
|
- int rsvd)
|
|
|
-{
|
|
|
- xfs_icsb_cnts_t *icsbp;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- might_sleep();
|
|
|
-again:
|
|
|
- preempt_disable();
|
|
|
- icsbp = this_cpu_ptr(mp->m_sb_cnts);
|
|
|
-
|
|
|
- /*
|
|
|
- * if the counter is disabled, go to slow path
|
|
|
- */
|
|
|
- if (unlikely(xfs_icsb_counter_disabled(mp, field)))
|
|
|
- goto slow_path;
|
|
|
- xfs_icsb_lock_cntr(icsbp);
|
|
|
- if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
|
|
|
- xfs_icsb_unlock_cntr(icsbp);
|
|
|
- goto slow_path;
|
|
|
- }
|
|
|
-
|
|
|
- switch (field) {
|
|
|
- default:
|
|
|
- BUG();
|
|
|
- goto balance_counter; /* be still, gcc */
|
|
|
- }
|
|
|
- xfs_icsb_unlock_cntr(icsbp);
|
|
|
- preempt_enable();
|
|
|
- return 0;
|
|
|
-
|
|
|
-slow_path:
|
|
|
- preempt_enable();
|
|
|
-
|
|
|
- /*
|
|
|
- * serialise with a mutex so we don't burn lots of cpu on
|
|
|
- * the superblock lock. We still need to hold the superblock
|
|
|
- * lock, however, when we modify the global structures.
|
|
|
- */
|
|
|
- xfs_icsb_lock(mp);
|
|
|
-
|
|
|
- /*
|
|
|
- * Now running atomically.
|
|
|
- *
|
|
|
- * If the counter is enabled, someone has beaten us to rebalancing.
|
|
|
- * Drop the lock and try again in the fast path....
|
|
|
- */
|
|
|
- if (!(xfs_icsb_counter_disabled(mp, field))) {
|
|
|
- xfs_icsb_unlock(mp);
|
|
|
- goto again;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * The counter is currently disabled. Because we are
|
|
|
- * running atomically here, we know a rebalance cannot
|
|
|
- * be in progress. Hence we can go straight to operating
|
|
|
- * on the global superblock. We do not call xfs_mod_incore_sb()
|
|
|
- * here even though we need to get the m_sb_lock. Doing so
|
|
|
- * will cause us to re-enter this function and deadlock.
|
|
|
- * Hence we get the m_sb_lock ourselves and then call
|
|
|
- * xfs_mod_incore_sb_unlocked() as the unlocked path operates
|
|
|
- * directly on the global counters.
|
|
|
- */
|
|
|
- spin_lock(&mp->m_sb_lock);
|
|
|
- ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
|
|
|
- spin_unlock(&mp->m_sb_lock);
|
|
|
-
|
|
|
- /*
|
|
|
- * Now that we've modified the global superblock, we
|
|
|
- * may be able to re-enable the distributed counters
|
|
|
- * (e.g. lots of space just got freed). After that
|
|
|
- * we are done.
|
|
|
- */
|
|
|
- if (ret != -ENOSPC)
|
|
|
- xfs_icsb_balance_counter(mp, field, 0);
|
|
|
- xfs_icsb_unlock(mp);
|
|
|
- return ret;
|
|
|
-
|
|
|
-balance_counter:
|
|
|
- xfs_icsb_unlock_cntr(icsbp);
|
|
|
- preempt_enable();
|
|
|
-
|
|
|
- /*
|
|
|
- * We may have multiple threads here if multiple per-cpu
|
|
|
- * counters run dry at the same time. This will mean we can
|
|
|
- * do more balances than strictly necessary but it is not
|
|
|
- * the common slowpath case.
|
|
|
- */
|
|
|
- xfs_icsb_lock(mp);
|
|
|
-
|
|
|
- /*
|
|
|
- * running atomically.
|
|
|
- *
|
|
|
- * This will leave the counter in the correct state for future
|
|
|
- * accesses. After the rebalance, we simply try again and our retry
|
|
|
- * will either succeed through the fast path or slow path without
|
|
|
- * another balance operation being required.
|
|
|
- */
|
|
|
- xfs_icsb_balance_counter(mp, field, delta);
|
|
|
- xfs_icsb_unlock(mp);
|
|
|
- goto again;
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|