Re: [PATCH 4/5] xfs: use generic percpu counters for free block counter

Christoph Hellwig
2015-02-02T16:48:52Z

> case XFS_SBS_FDBLOCKS:
>
> if (delta > 0) { /* Putting blocks back */
> + if (mp->m_resblks == mp->m_resblks_avail) {
> + percpu_counter_add(&mp->m_sb.sb_fdblocks, delta);
> + return 0;
> + }
> +
> + /* put blocks back into reserve pool first */
> + spin_lock(&mp->m_sb_lock);
> + res_used = (long long)
> + (mp->m_resblks - mp->m_resblks_avail);
> +
> if (res_used > delta) {
> mp->m_resblks_avail += delta;
> } else {
> + delta -= res_used;
> mp->m_resblks_avail = mp->m_resblks;
> + percpu_counter_add(&mp->m_sb.sb_fdblocks, delta);
> }
> + spin_unlock(&mp->m_sb_lock);
> + return 0;
>
> + }

>
> + /*
> + * Taking blocks away, need to be more accurate the closer we
> + * are to zero.
> + *
> + * batch size is set to a maximum of 1024 blocks - if we are
> + * allocating of freeing extents larger than this then we aren't
> + * going to be hammering the counter lock so a lock per update
> + * is not a problem.
> + *
> + * If the counter has a value of less than 2 * max batch size,
> + * then make everything serialise as we are real close to
> + * ENOSPC.
> + */
> +#define __BATCH 1024
> + if (percpu_counter_compare(&mp->m_sb.sb_fdblocks,
> + 2 * __BATCH) < 0)
> + batch = 1;
> + else
> + batch = __BATCH;
> +
> + __percpu_counter_add(&mp->m_sb.sb_fdblocks, delta, batch);
> + if (percpu_counter_compare(&mp->m_sb.sb_fdblocks,
> + XFS_ALLOC_SET_ASIDE(mp)) >= 0) {
> + /* we had space! */
> + return 0;
> }
>
> + /*
> + * lock up the sb for dipping into reserves before releasing
> + * the space that took us to ENOSPC.
> + */
> + spin_lock(&mp->m_sb_lock);
> + percpu_counter_add(&mp->m_sb.sb_fdblocks, -delta);
> + if (!rsvd)
> + goto fdblocks_enospc;
> +
> + lcounter = (long long)mp->m_resblks_avail + delta;
> + if (lcounter >= 0) {
> + mp->m_resblks_avail = lcounter;
> + spin_unlock(&mp->m_sb_lock);
> + return 0;
> + }
> + printk_once(KERN_WARNING
> + "Filesystem \"%s\": reserve blocks depleted! "
> + "Consider increasing reserve pool size.",
> + mp->m_fsname);
> +fdblocks_enospc:
> + spin_unlock(&mp->m_sb_lock);
> + return -ENOSPC;
> +

This screams for having two different helpers for removing vs adding back
reserved blocks.