xfs
[Top] [All Lists]

Re: [PATCH 4/7] xfs: Remove icsb infrastructure

To: Dave Chinner <david@xxxxxxxxxxxxx>
Subject: Re: [PATCH 4/7] xfs: Remove icsb infrastructure
From: Brian Foster <bfoster@xxxxxxxxxx>
Date: Thu, 5 Feb 2015 09:10:25 -0500
Cc: xfs@xxxxxxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1423083249-27493-5-git-send-email-david@xxxxxxxxxxxxx>
References: <1423083249-27493-1-git-send-email-david@xxxxxxxxxxxxx> <1423083249-27493-5-git-send-email-david@xxxxxxxxxxxxx>
User-agent: Mutt/1.5.23 (2014-03-12)
On Thu, Feb 05, 2015 at 07:54:06AM +1100, Dave Chinner wrote:
> From: Dave Chinner <dchinner@xxxxxxxxxx>
> 
> Now that the in-core superblock infrastructure has been replaced with
> generic per-cpu counters, we don't need it anymore. Nuke it from
> orbit so we are sure that it won't haunt us again...
> 
> Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
> ---

Reviewed-by: Brian Foster <bfoster@xxxxxxxxxx>

>  fs/xfs/libxfs/xfs_sb.c   |   8 +-
>  fs/xfs/xfs_fsops.c       |   2 -
>  fs/xfs/xfs_iomap.c       |   1 -
>  fs/xfs/xfs_linux.h       |   9 -
>  fs/xfs/xfs_log_recover.c |   4 +-
>  fs/xfs/xfs_mount.c       | 516 
> +----------------------------------------------
>  fs/xfs/xfs_mount.h       |  67 ------
>  fs/xfs/xfs_super.c       |  84 ++++++--
>  fs/xfs/xfs_super.h       |   2 +
>  9 files changed, 72 insertions(+), 621 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
> index 31a3e97..a270095 100644
> --- a/fs/xfs/libxfs/xfs_sb.c
> +++ b/fs/xfs/libxfs/xfs_sb.c
> @@ -743,17 +743,15 @@ xfs_initialize_perag_data(
>               btree += pag->pagf_btreeblks;
>               xfs_perag_put(pag);
>       }
> -     /*
> -      * Overwrite incore superblock counters with just-read data
> -      */
> +
> +     /* Overwrite incore superblock counters with just-read data */
>       spin_lock(&mp->m_sb_lock);
>       sbp->sb_ifree = ifree;
>       sbp->sb_icount = ialloc;
>       sbp->sb_fdblocks = bfree + bfreelst + btree;
>       spin_unlock(&mp->m_sb_lock);
>  
> -     /* Fixup the per-cpu counters as well. */
> -     xfs_icsb_reinit_counters(mp);
> +     xfs_reinit_percpu_counters(mp);
>  
>       return 0;
>  }
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index fed97a9..a45c82b4 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -630,7 +630,6 @@ xfs_fs_counts(
>       xfs_mount_t             *mp,
>       xfs_fsop_counts_t       *cnt)
>  {
> -     xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
>       cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
>       cnt->freeino = percpu_counter_read_positive(&mp->m_ifree);
>       cnt->freedata = percpu_counter_read_positive(&mp->m_fdblocks) -
> @@ -694,7 +693,6 @@ xfs_reserve_blocks(
>        */
>  retry:
>       spin_lock(&mp->m_sb_lock);
> -     xfs_icsb_sync_counters_locked(mp, 0);
>  
>       /*
>        * If our previous reservation was larger than the current value,
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 205b948..38e633b 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -460,7 +460,6 @@ xfs_iomap_prealloc_size(
>       alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
>                                      alloc_blocks);
>  
> -     xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
>       freesp = percpu_counter_read_positive(&mp->m_fdblocks);
>       if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
>               shift = 2;
> diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
> index c31d2c2..7c7842c 100644
> --- a/fs/xfs/xfs_linux.h
> +++ b/fs/xfs/xfs_linux.h
> @@ -116,15 +116,6 @@ typedef __uint64_t __psunsigned_t;
>  #undef XFS_NATIVE_HOST
>  #endif
>  
> -/*
> - * Feature macros (disable/enable)
> - */
> -#ifdef CONFIG_SMP
> -#define HAVE_PERCPU_SB       /* per cpu superblock counters are a 2.6 
> feature */
> -#else
> -#undef  HAVE_PERCPU_SB       /* per cpu superblock counters are a 2.6 
> feature */
> -#endif
> -
>  #define irix_sgid_inherit    xfs_params.sgid_inherit.val
>  #define irix_symlink_mode    xfs_params.symlink_mode.val
>  #define xfs_panic_mask               xfs_params.panic_mask.val
> diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
> index a5a945f..4f5784f 100644
> --- a/fs/xfs/xfs_log_recover.c
> +++ b/fs/xfs/xfs_log_recover.c
> @@ -4463,10 +4463,10 @@ xlog_do_recover(
>       xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
>       ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
>       ASSERT(xfs_sb_good_version(sbp));
> +     xfs_reinit_percpu_counters(log->l_mp);
> +
>       xfs_buf_relse(bp);
>  
> -     /* We've re-read the superblock so re-initialize per-cpu counters */
> -     xfs_icsb_reinit_counters(log->l_mp);
>  
>       xlog_recover_check_summary(log);
>  
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 9e433b2..1d26200 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -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.
> @@ -1467,502 +1452,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
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index 76f5d25..ff1d1d5 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -18,8 +18,6 @@
>  #ifndef __XFS_MOUNT_H__
>  #define      __XFS_MOUNT_H__
>  
> -#ifdef __KERNEL__
> -
>  struct xlog;
>  struct xfs_inode;
>  struct xfs_mru_cache;
> @@ -29,43 +27,6 @@ struct xfs_quotainfo;
>  struct xfs_dir_ops;
>  struct xfs_da_geometry;
>  
> -#ifdef HAVE_PERCPU_SB
> -
> -/*
> - * Valid per-cpu incore superblock counters. Note that if you add new 
> counters,
> - * you may need to define new counter disabled bit field descriptors as there
> - * are more possible fields in the superblock that can fit in a bitfield on a
> - * 32 bit platform. The XFS_SBS_* values for the current current counters 
> just
> - * fit.
> - */
> -typedef struct xfs_icsb_cnts {
> -     uint64_t        icsb_fdblocks;
> -     uint64_t        icsb_ifree;
> -     unsigned long   icsb_flags;
> -} xfs_icsb_cnts_t;
> -
> -#define XFS_ICSB_FLAG_LOCK   (1 << 0)        /* counter lock bit */
> -
> -#define XFS_ICSB_LAZY_COUNT  (1 << 1)        /* accuracy not needed */
> -
> -extern int   xfs_icsb_init_counters(struct xfs_mount *);
> -extern void  xfs_icsb_reinit_counters(struct xfs_mount *);
> -extern void  xfs_icsb_destroy_counters(struct xfs_mount *);
> -extern void  xfs_icsb_sync_counters(struct xfs_mount *, int);
> -extern void  xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
> -extern int   xfs_icsb_modify_counters(struct xfs_mount *, xfs_sb_field_t,
> -                                             int64_t, int);
> -
> -#else
> -#define xfs_icsb_init_counters(mp)           (0)
> -#define xfs_icsb_destroy_counters(mp)                do { } while (0)
> -#define xfs_icsb_reinit_counters(mp)         do { } while (0)
> -#define xfs_icsb_sync_counters(mp, flags)    do { } while (0)
> -#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
> -#define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
> -     xfs_mod_incore_sb(mp, field, delta, rsvd)
> -#endif
> -
>  /* dynamic preallocation free space thresholds, 5% down to 1% */
>  enum {
>       XFS_LOWSP_1_PCNT = 0,
> @@ -156,12 +117,6 @@ typedef struct xfs_mount {
>       const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */
>       uint                    m_chsize;       /* size of next field */
>       atomic_t                m_active_trans; /* number trans frozen */
> -#ifdef HAVE_PERCPU_SB
> -     xfs_icsb_cnts_t __percpu *m_sb_cnts;    /* per-cpu superblock counters 
> */
> -     unsigned long           m_icsb_counters; /* disabled per-cpu counters */
> -     struct notifier_block   m_icsb_notifier; /* hotplug cpu notifier */
> -     struct mutex            m_icsb_mutex;   /* balancer sync lock */
> -#endif
>       struct xfs_mru_cache    *m_filestream;  /* per-mount filestream data */
>       struct delayed_work     m_reclaim_work; /* background inode reclaim */
>       struct delayed_work     m_eofblocks_work; /* background eof blocks
> @@ -294,26 +249,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
>  }
>  
>  /*
> - * Per-cpu superblock locking functions
> - */
> -#ifdef HAVE_PERCPU_SB
> -static inline void
> -xfs_icsb_lock(xfs_mount_t *mp)
> -{
> -     mutex_lock(&mp->m_icsb_mutex);
> -}
> -
> -static inline void
> -xfs_icsb_unlock(xfs_mount_t *mp)
> -{
> -     mutex_unlock(&mp->m_icsb_mutex);
> -}
> -#else
> -#define xfs_icsb_lock(mp)
> -#define xfs_icsb_unlock(mp)
> -#endif
> -
> -/*
>   * This structure is for use by the xfs_mod_incore_sb_batch() routine.
>   * xfs_growfs can specify a few fields which are more than int limit
>   */
> @@ -396,6 +331,4 @@ extern int        xfs_dev_is_read_only(struct xfs_mount 
> *, char *);
>  
>  extern void  xfs_set_low_space_thresholds(struct xfs_mount *);
>  
> -#endif       /* __KERNEL__ */
> -
>  #endif       /* __XFS_MOUNT_H__ */
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index 4c6af31..af6d268 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -1035,23 +1035,6 @@ xfs_free_fsname(
>       kfree(mp->m_logname);
>  }
>  
> -STATIC void
> -xfs_fs_put_super(
> -     struct super_block      *sb)
> -{
> -     struct xfs_mount        *mp = XFS_M(sb);
> -
> -     xfs_filestream_unmount(mp);
> -     xfs_unmountfs(mp);
> -
> -     xfs_freesb(mp);
> -     xfs_icsb_destroy_counters(mp);
> -     xfs_destroy_mount_workqueues(mp);
> -     xfs_close_devices(mp);
> -     xfs_free_fsname(mp);
> -     kfree(mp);
> -}
> -
>  STATIC int
>  xfs_fs_sync_fs(
>       struct super_block      *sb,
> @@ -1100,7 +1083,6 @@ xfs_fs_statfs(
>       statp->f_fsid.val[0] = (u32)id;
>       statp->f_fsid.val[1] = (u32)(id >> 32);
>  
> -     xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
>       icount = percpu_counter_sum(&mp->m_icount);
>       ifree = percpu_counter_sum(&mp->m_ifree);
>       fdblocks = percpu_counter_sum(&mp->m_fdblocks);
> @@ -1405,6 +1387,51 @@ xfs_finish_flags(
>       return 0;
>  }
>  
> +static int
> +xfs_init_percpu_counters(
> +     struct xfs_mount        *mp)
> +{
> +     int             error;
> +
> +     error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
> +     if (error)
> +             return ENOMEM;
> +
> +     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;
> +
> +     return 0;
> +
> +free_ifree:
> +     percpu_counter_destroy(&mp->m_ifree);
> +free_icount:
> +     percpu_counter_destroy(&mp->m_icount);
> +     return -ENOMEM;
> +}
> +
> +void
> +xfs_reinit_percpu_counters(
> +     struct xfs_mount        *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);
> +}
> +
> +static void
> +xfs_destroy_percpu_counters(
> +     struct xfs_mount        *mp)
> +{
> +     percpu_counter_destroy(&mp->m_icount);
> +     percpu_counter_destroy(&mp->m_ifree);
> +     percpu_counter_destroy(&mp->m_fdblocks);
> +}
> +
>  STATIC int
>  xfs_fs_fill_super(
>       struct super_block      *sb,
> @@ -1453,7 +1480,7 @@ xfs_fs_fill_super(
>       if (error)
>               goto out_close_devices;
>  
> -     error = xfs_icsb_init_counters(mp);
> +     error = xfs_init_percpu_counters(mp);
>       if (error)
>               goto out_destroy_workqueues;
>  
> @@ -1511,7 +1538,7 @@ xfs_fs_fill_super(
>   out_free_sb:
>       xfs_freesb(mp);
>   out_destroy_counters:
> -     xfs_icsb_destroy_counters(mp);
> +     xfs_destroy_percpu_counters(mp);
>  out_destroy_workqueues:
>       xfs_destroy_mount_workqueues(mp);
>   out_close_devices:
> @@ -1528,6 +1555,23 @@ out_destroy_workqueues:
>       goto out_free_sb;
>  }
>  
> +STATIC void
> +xfs_fs_put_super(
> +     struct super_block      *sb)
> +{
> +     struct xfs_mount        *mp = XFS_M(sb);
> +
> +     xfs_filestream_unmount(mp);
> +     xfs_unmountfs(mp);
> +
> +     xfs_freesb(mp);
> +     xfs_destroy_percpu_counters(mp);
> +     xfs_destroy_mount_workqueues(mp);
> +     xfs_close_devices(mp);
> +     xfs_free_fsname(mp);
> +     kfree(mp);
> +}
> +
>  STATIC struct dentry *
>  xfs_fs_mount(
>       struct file_system_type *fs_type,
> diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
> index 2b830c2..499058f 100644
> --- a/fs/xfs/xfs_super.h
> +++ b/fs/xfs/xfs_super.h
> @@ -72,6 +72,8 @@ extern const struct export_operations xfs_export_operations;
>  extern const struct xattr_handler *xfs_xattr_handlers[];
>  extern const struct quotactl_ops xfs_quotactl_operations;
>  
> +extern void xfs_reinit_percpu_counters(struct xfs_mount *mp);
> +
>  #define XFS_M(sb)            ((struct xfs_mount *)((sb)->s_fs_info))
>  
>  #endif       /* __XFS_SUPER_H__ */
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@xxxxxxxxxxx
> http://oss.sgi.com/mailman/listinfo/xfs

<Prev in Thread] Current Thread [Next in Thread>