Commit 4225441a authored by Dave Chinner's avatar Dave Chinner

Merge branch 'xfs-generic-sb-counters' into for-next

Conflicts:
	fs/xfs/xfs_super.c
parents 3cabb836 964aa8d9
...@@ -2215,9 +2215,8 @@ xfs_bmap_add_extent_delay_real( ...@@ -2215,9 +2215,8 @@ xfs_bmap_add_extent_delay_real(
diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
(bma->cur ? bma->cur->bc_private.b.allocated : 0)); (bma->cur ? bma->cur->bc_private.b.allocated : 0));
if (diff > 0) { if (diff > 0) {
error = xfs_icsb_modify_counters(bma->ip->i_mount, error = xfs_mod_fdblocks(bma->ip->i_mount,
XFS_SBS_FDBLOCKS, -((int64_t)diff), false);
-((int64_t)diff), 0);
ASSERT(!error); ASSERT(!error);
if (error) if (error)
goto done; goto done;
...@@ -2268,9 +2267,8 @@ xfs_bmap_add_extent_delay_real( ...@@ -2268,9 +2267,8 @@ xfs_bmap_add_extent_delay_real(
temp += bma->cur->bc_private.b.allocated; temp += bma->cur->bc_private.b.allocated;
ASSERT(temp <= da_old); ASSERT(temp <= da_old);
if (temp < da_old) if (temp < da_old)
xfs_icsb_modify_counters(bma->ip->i_mount, xfs_mod_fdblocks(bma->ip->i_mount,
XFS_SBS_FDBLOCKS, (int64_t)(da_old - temp), false);
(int64_t)(da_old - temp), 0);
} }
/* clear out the allocated field, done with it now in any case. */ /* clear out the allocated field, done with it now in any case. */
...@@ -2948,8 +2946,8 @@ xfs_bmap_add_extent_hole_delay( ...@@ -2948,8 +2946,8 @@ xfs_bmap_add_extent_hole_delay(
} }
if (oldlen != newlen) { if (oldlen != newlen) {
ASSERT(oldlen > newlen); ASSERT(oldlen > newlen);
xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, xfs_mod_fdblocks(ip->i_mount, (int64_t)(oldlen - newlen),
(int64_t)(oldlen - newlen), 0); false);
/* /*
* Nothing to do for disk quota accounting here. * Nothing to do for disk quota accounting here.
*/ */
...@@ -4166,18 +4164,15 @@ xfs_bmapi_reserve_delalloc( ...@@ -4166,18 +4164,15 @@ xfs_bmapi_reserve_delalloc(
ASSERT(indlen > 0); ASSERT(indlen > 0);
if (rt) { if (rt) {
error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, error = xfs_mod_frextents(mp, -((int64_t)extsz));
-((int64_t)extsz), 0);
} else { } else {
error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, error = xfs_mod_fdblocks(mp, -((int64_t)alen), false);
-((int64_t)alen), 0);
} }
if (error) if (error)
goto out_unreserve_quota; goto out_unreserve_quota;
error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, error = xfs_mod_fdblocks(mp, -((int64_t)indlen), false);
-((int64_t)indlen), 0);
if (error) if (error)
goto out_unreserve_blocks; goto out_unreserve_blocks;
...@@ -4204,9 +4199,9 @@ xfs_bmapi_reserve_delalloc( ...@@ -4204,9 +4199,9 @@ xfs_bmapi_reserve_delalloc(
out_unreserve_blocks: out_unreserve_blocks:
if (rt) if (rt)
xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0); xfs_mod_frextents(mp, extsz);
else else
xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0); xfs_mod_fdblocks(mp, alen, false);
out_unreserve_quota: out_unreserve_quota:
if (XFS_IS_QUOTA_ON(mp)) if (XFS_IS_QUOTA_ON(mp))
xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ? xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
...@@ -5019,10 +5014,8 @@ xfs_bmap_del_extent( ...@@ -5019,10 +5014,8 @@ xfs_bmap_del_extent(
* Nothing to do for disk quota accounting here. * Nothing to do for disk quota accounting here.
*/ */
ASSERT(da_old >= da_new); ASSERT(da_old >= da_new);
if (da_old > da_new) { if (da_old > da_new)
xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false);
(int64_t)(da_old - da_new), 0);
}
done: done:
*logflagsp = flags; *logflagsp = flags;
return error; return error;
...@@ -5291,14 +5284,13 @@ xfs_bunmapi( ...@@ -5291,14 +5284,13 @@ xfs_bunmapi(
rtexts = XFS_FSB_TO_B(mp, del.br_blockcount); rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
do_div(rtexts, mp->m_sb.sb_rextsize); do_div(rtexts, mp->m_sb.sb_rextsize);
xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, xfs_mod_frextents(mp, (int64_t)rtexts);
(int64_t)rtexts, 0);
(void)xfs_trans_reserve_quota_nblks(NULL, (void)xfs_trans_reserve_quota_nblks(NULL,
ip, -((long)del.br_blockcount), 0, ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_RTBLKS); XFS_QMOPT_RES_RTBLKS);
} else { } else {
xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount,
(int64_t)del.br_blockcount, 0); false);
(void)xfs_trans_reserve_quota_nblks(NULL, (void)xfs_trans_reserve_quota_nblks(NULL,
ip, -((long)del.br_blockcount), 0, ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_REGBLKS); XFS_QMOPT_RES_REGBLKS);
......
...@@ -264,68 +264,6 @@ typedef struct xfs_dsb { ...@@ -264,68 +264,6 @@ typedef struct xfs_dsb {
/* must be padded to 64 bit alignment */ /* must be padded to 64 bit alignment */
} xfs_dsb_t; } xfs_dsb_t;
/*
* Sequence number values for the fields.
*/
typedef enum {
XFS_SBS_MAGICNUM, XFS_SBS_BLOCKSIZE, XFS_SBS_DBLOCKS, XFS_SBS_RBLOCKS,
XFS_SBS_REXTENTS, XFS_SBS_UUID, XFS_SBS_LOGSTART, XFS_SBS_ROOTINO,
XFS_SBS_RBMINO, XFS_SBS_RSUMINO, XFS_SBS_REXTSIZE, XFS_SBS_AGBLOCKS,
XFS_SBS_AGCOUNT, XFS_SBS_RBMBLOCKS, XFS_SBS_LOGBLOCKS,
XFS_SBS_VERSIONNUM, XFS_SBS_SECTSIZE, XFS_SBS_INODESIZE,
XFS_SBS_INOPBLOCK, XFS_SBS_FNAME, XFS_SBS_BLOCKLOG,
XFS_SBS_SECTLOG, XFS_SBS_INODELOG, XFS_SBS_INOPBLOG, XFS_SBS_AGBLKLOG,
XFS_SBS_REXTSLOG, XFS_SBS_INPROGRESS, XFS_SBS_IMAX_PCT, XFS_SBS_ICOUNT,
XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO,
XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FEATURES_COMPAT,
XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT,
XFS_SBS_FEATURES_LOG_INCOMPAT, XFS_SBS_CRC, XFS_SBS_PAD,
XFS_SBS_PQUOTINO, XFS_SBS_LSN,
XFS_SBS_FIELDCOUNT
} xfs_sb_field_t;
/*
* Mask values, defined based on the xfs_sb_field_t values.
* Only define the ones we're using.
*/
#define XFS_SB_MVAL(x) (1LL << XFS_SBS_ ## x)
#define XFS_SB_UUID XFS_SB_MVAL(UUID)
#define XFS_SB_FNAME XFS_SB_MVAL(FNAME)
#define XFS_SB_ROOTINO XFS_SB_MVAL(ROOTINO)
#define XFS_SB_RBMINO XFS_SB_MVAL(RBMINO)
#define XFS_SB_RSUMINO XFS_SB_MVAL(RSUMINO)
#define XFS_SB_VERSIONNUM XFS_SB_MVAL(VERSIONNUM)
#define XFS_SB_UQUOTINO XFS_SB_MVAL(UQUOTINO)
#define XFS_SB_GQUOTINO XFS_SB_MVAL(GQUOTINO)
#define XFS_SB_QFLAGS XFS_SB_MVAL(QFLAGS)
#define XFS_SB_SHARED_VN XFS_SB_MVAL(SHARED_VN)
#define XFS_SB_UNIT XFS_SB_MVAL(UNIT)
#define XFS_SB_WIDTH XFS_SB_MVAL(WIDTH)
#define XFS_SB_ICOUNT XFS_SB_MVAL(ICOUNT)
#define XFS_SB_IFREE XFS_SB_MVAL(IFREE)
#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)
#define XFS_SB_FEATURES2 (XFS_SB_MVAL(FEATURES2) | \
XFS_SB_MVAL(BAD_FEATURES2))
#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT)
#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT)
#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT)
#define XFS_SB_FEATURES_LOG_INCOMPAT XFS_SB_MVAL(FEATURES_LOG_INCOMPAT)
#define XFS_SB_CRC XFS_SB_MVAL(CRC)
#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO)
#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)
#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1)
#define XFS_SB_MOD_BITS \
(XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
XFS_SB_FEATURES_COMPAT | XFS_SB_FEATURES_RO_COMPAT | \
XFS_SB_FEATURES_INCOMPAT | XFS_SB_FEATURES_LOG_INCOMPAT | \
XFS_SB_PQUOTINO)
/* /*
* Misc. Flags - warning - these will be cleared by xfs_repair unless * Misc. Flags - warning - these will be cleared by xfs_repair unless
......
...@@ -376,7 +376,8 @@ xfs_ialloc_ag_alloc( ...@@ -376,7 +376,8 @@ xfs_ialloc_ag_alloc(
*/ */
newlen = args.mp->m_ialloc_inos; newlen = args.mp->m_ialloc_inos;
if (args.mp->m_maxicount && if (args.mp->m_maxicount &&
args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount) percpu_counter_read(&args.mp->m_icount) + newlen >
args.mp->m_maxicount)
return -ENOSPC; return -ENOSPC;
args.minlen = args.maxlen = args.mp->m_ialloc_blks; args.minlen = args.maxlen = args.mp->m_ialloc_blks;
/* /*
...@@ -1340,7 +1341,8 @@ xfs_dialloc( ...@@ -1340,7 +1341,8 @@ xfs_dialloc(
* inode. * inode.
*/ */
if (mp->m_maxicount && if (mp->m_maxicount &&
mp->m_sb.sb_icount + mp->m_ialloc_inos > mp->m_maxicount) { percpu_counter_read(&mp->m_icount) + mp->m_ialloc_inos >
mp->m_maxicount) {
noroom = 1; noroom = 1;
okalloc = 0; okalloc = 0;
} }
......
...@@ -735,17 +735,15 @@ xfs_initialize_perag_data( ...@@ -735,17 +735,15 @@ xfs_initialize_perag_data(
btree += pag->pagf_btreeblks; btree += pag->pagf_btreeblks;
xfs_perag_put(pag); 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); spin_lock(&mp->m_sb_lock);
sbp->sb_ifree = ifree; sbp->sb_ifree = ifree;
sbp->sb_icount = ialloc; sbp->sb_icount = ialloc;
sbp->sb_fdblocks = bfree + bfreelst + btree; sbp->sb_fdblocks = bfree + bfreelst + btree;
spin_unlock(&mp->m_sb_lock); spin_unlock(&mp->m_sb_lock);
/* Fixup the per-cpu counters as well. */ xfs_reinit_percpu_counters(mp);
xfs_icsb_reinit_counters(mp);
return 0; return 0;
} }
...@@ -763,6 +761,10 @@ xfs_log_sb( ...@@ -763,6 +761,10 @@ xfs_log_sb(
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_buf *bp = xfs_trans_getsb(tp, mp, 0); struct xfs_buf *bp = xfs_trans_getsb(tp, mp, 0);
mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks);
xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb)); xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb));
......
...@@ -637,12 +637,13 @@ xfs_fs_counts( ...@@ -637,12 +637,13 @@ xfs_fs_counts(
xfs_mount_t *mp, xfs_mount_t *mp,
xfs_fsop_counts_t *cnt) 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) -
XFS_ALLOC_SET_ASIDE(mp);
spin_lock(&mp->m_sb_lock); spin_lock(&mp->m_sb_lock);
cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
cnt->freertx = mp->m_sb.sb_frextents; cnt->freertx = mp->m_sb.sb_frextents;
cnt->freeino = mp->m_sb.sb_ifree;
cnt->allocino = mp->m_sb.sb_icount;
spin_unlock(&mp->m_sb_lock); spin_unlock(&mp->m_sb_lock);
return 0; return 0;
} }
...@@ -692,14 +693,9 @@ xfs_reserve_blocks( ...@@ -692,14 +693,9 @@ xfs_reserve_blocks(
* what to do. This means that the amount of free space can * what to do. This means that the amount of free space can
* change while we do this, so we need to retry if we end up * change while we do this, so we need to retry if we end up
* trying to reserve more space than is available. * trying to reserve more space than is available.
*
* We also use the xfs_mod_incore_sb() interface so that we
* don't have to care about whether per cpu counter are
* enabled, disabled or even compiled in....
*/ */
retry: retry:
spin_lock(&mp->m_sb_lock); spin_lock(&mp->m_sb_lock);
xfs_icsb_sync_counters_locked(mp, 0);
/* /*
* If our previous reservation was larger than the current value, * If our previous reservation was larger than the current value,
...@@ -716,7 +712,8 @@ xfs_reserve_blocks( ...@@ -716,7 +712,8 @@ xfs_reserve_blocks(
} else { } else {
__int64_t free; __int64_t free;
free = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); free = percpu_counter_sum(&mp->m_fdblocks) -
XFS_ALLOC_SET_ASIDE(mp);
if (!free) if (!free)
goto out; /* ENOSPC and fdblks_delta = 0 */ goto out; /* ENOSPC and fdblks_delta = 0 */
...@@ -755,8 +752,7 @@ xfs_reserve_blocks( ...@@ -755,8 +752,7 @@ xfs_reserve_blocks(
* the extra reserve blocks from the reserve..... * the extra reserve blocks from the reserve.....
*/ */
int error; int error;
error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, error = xfs_mod_fdblocks(mp, fdblks_delta, 0);
fdblks_delta, 0);
if (error == -ENOSPC) if (error == -ENOSPC)
goto retry; goto retry;
} }
......
...@@ -460,8 +460,7 @@ xfs_iomap_prealloc_size( ...@@ -460,8 +460,7 @@ xfs_iomap_prealloc_size(
alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN), alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
alloc_blocks); alloc_blocks);
xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); freesp = percpu_counter_read_positive(&mp->m_fdblocks);
freesp = mp->m_sb.sb_fdblocks;
if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) { if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
shift = 2; shift = 2;
if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT]) if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
......
...@@ -116,15 +116,6 @@ typedef __uint64_t __psunsigned_t; ...@@ -116,15 +116,6 @@ typedef __uint64_t __psunsigned_t;
#undef XFS_NATIVE_HOST #undef XFS_NATIVE_HOST
#endif #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_sgid_inherit xfs_params.sgid_inherit.val
#define irix_symlink_mode xfs_params.symlink_mode.val #define irix_symlink_mode xfs_params.symlink_mode.val
#define xfs_panic_mask xfs_params.panic_mask.val #define xfs_panic_mask xfs_params.panic_mask.val
......
...@@ -4463,10 +4463,10 @@ xlog_do_recover( ...@@ -4463,10 +4463,10 @@ xlog_do_recover(
xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp)); xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC); ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
ASSERT(xfs_sb_good_version(sbp)); ASSERT(xfs_sb_good_version(sbp));
xfs_reinit_percpu_counters(log->l_mp);
xfs_buf_relse(bp); 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); xlog_recover_check_summary(log);
......
This diff is collapsed.
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
#ifndef __XFS_MOUNT_H__ #ifndef __XFS_MOUNT_H__
#define __XFS_MOUNT_H__ #define __XFS_MOUNT_H__
#ifdef __KERNEL__
struct xlog; struct xlog;
struct xfs_inode; struct xfs_inode;
struct xfs_mru_cache; struct xfs_mru_cache;
...@@ -29,44 +27,6 @@ struct xfs_quotainfo; ...@@ -29,44 +27,6 @@ struct xfs_quotainfo;
struct xfs_dir_ops; struct xfs_dir_ops;
struct xfs_da_geometry; 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;
uint64_t icsb_icount;
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% */ /* dynamic preallocation free space thresholds, 5% down to 1% */
enum { enum {
XFS_LOWSP_1_PCNT = 0, XFS_LOWSP_1_PCNT = 0,
...@@ -81,8 +41,13 @@ typedef struct xfs_mount { ...@@ -81,8 +41,13 @@ typedef struct xfs_mount {
struct super_block *m_super; struct super_block *m_super;
xfs_tid_t m_tid; /* next unused tid for fs */ xfs_tid_t m_tid; /* next unused tid for fs */
struct xfs_ail *m_ail; /* fs active log item list */ struct xfs_ail *m_ail; /* fs active log item list */
xfs_sb_t m_sb; /* copy of fs superblock */
struct xfs_sb m_sb; /* copy of fs superblock */
spinlock_t m_sb_lock; /* sb counter lock */ spinlock_t m_sb_lock; /* sb counter lock */
struct percpu_counter m_icount; /* allocated inodes counter */
struct percpu_counter m_ifree; /* free inodes counter */
struct percpu_counter m_fdblocks; /* free block counter */
struct xfs_buf *m_sb_bp; /* buffer for superblock */ struct xfs_buf *m_sb_bp; /* buffer for superblock */
char *m_fsname; /* filesystem name */ char *m_fsname; /* filesystem name */
int m_fsname_len; /* strlen of fs name */ int m_fsname_len; /* strlen of fs name */
...@@ -152,12 +117,6 @@ typedef struct xfs_mount { ...@@ -152,12 +117,6 @@ typedef struct xfs_mount {
const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */ const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */
uint m_chsize; /* size of next field */ uint m_chsize; /* size of next field */
atomic_t m_active_trans; /* number trans frozen */ 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 xfs_mru_cache *m_filestream; /* per-mount filestream data */
struct delayed_work m_reclaim_work; /* background inode reclaim */ struct delayed_work m_reclaim_work; /* background inode reclaim */
struct delayed_work m_eofblocks_work; /* background eof blocks struct delayed_work m_eofblocks_work; /* background eof blocks
...@@ -300,35 +259,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d) ...@@ -300,35 +259,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
return (xfs_agblock_t) do_div(ld, mp->m_sb.sb_agblocks); return (xfs_agblock_t) do_div(ld, mp->m_sb.sb_agblocks);
} }
/*
* 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
*/
typedef struct xfs_mod_sb {
xfs_sb_field_t msb_field; /* Field to modify, see below */
int64_t msb_delta; /* Change to make to specified field */
} xfs_mod_sb_t;
/* /*
* Per-ag incore structure, copies of information in agf and agi, to improve the * Per-ag incore structure, copies of information in agf and agi, to improve the
* performance of allocation group selection. * performance of allocation group selection.
...@@ -383,11 +313,14 @@ extern __uint64_t xfs_default_resblks(xfs_mount_t *mp); ...@@ -383,11 +313,14 @@ extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
extern int xfs_mountfs(xfs_mount_t *mp); extern int xfs_mountfs(xfs_mount_t *mp);
extern int xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount, extern int xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount,
xfs_agnumber_t *maxagi); xfs_agnumber_t *maxagi);
extern void xfs_unmountfs(xfs_mount_t *); extern void xfs_unmountfs(xfs_mount_t *);
extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, extern int xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
uint, int); extern int xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
extern int xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
bool reserved);
extern int xfs_mod_frextents(struct xfs_mount *mp, int64_t delta);
extern int xfs_mount_log_sb(xfs_mount_t *); extern int xfs_mount_log_sb(xfs_mount_t *);
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int xfs_readsb(xfs_mount_t *, int); extern int xfs_readsb(xfs_mount_t *, int);
...@@ -399,6 +332,4 @@ extern int xfs_dev_is_read_only(struct xfs_mount *, char *); ...@@ -399,6 +332,4 @@ extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
extern void xfs_set_low_space_thresholds(struct xfs_mount *); extern void xfs_set_low_space_thresholds(struct xfs_mount *);
#endif /* __KERNEL__ */
#endif /* __XFS_MOUNT_H__ */ #endif /* __XFS_MOUNT_H__ */
...@@ -1013,24 +1013,6 @@ xfs_free_fsname( ...@@ -1013,24 +1013,6 @@ xfs_free_fsname(
kfree(mp->m_logname); kfree(mp->m_logname);
} }
STATIC void
xfs_fs_put_super(
struct super_block *sb)
{
struct xfs_mount *mp = XFS_M(sb);
xfs_notice(mp, "Unmounting Filesystem");
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 STATIC int
xfs_fs_sync_fs( xfs_fs_sync_fs(
struct super_block *sb, struct super_block *sb,
...@@ -1066,6 +1048,9 @@ xfs_fs_statfs( ...@@ -1066,6 +1048,9 @@ xfs_fs_statfs(
xfs_sb_t *sbp = &mp->m_sb; xfs_sb_t *sbp = &mp->m_sb;
struct xfs_inode *ip = XFS_I(dentry->d_inode); struct xfs_inode *ip = XFS_I(dentry->d_inode);
__uint64_t fakeinos, id; __uint64_t fakeinos, id;
__uint64_t icount;
__uint64_t ifree;
__uint64_t fdblocks;
xfs_extlen_t lsize; xfs_extlen_t lsize;
__int64_t ffree; __int64_t ffree;
...@@ -1076,17 +1061,21 @@ xfs_fs_statfs( ...@@ -1076,17 +1061,21 @@ xfs_fs_statfs(
statp->f_fsid.val[0] = (u32)id; statp->f_fsid.val[0] = (u32)id;
statp->f_fsid.val[1] = (u32)(id >> 32); 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);
spin_lock(&mp->m_sb_lock); spin_lock(&mp->m_sb_lock);
statp->f_bsize = sbp->sb_blocksize; statp->f_bsize = sbp->sb_blocksize;
lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
statp->f_blocks = sbp->sb_dblocks - lsize; statp->f_blocks = sbp->sb_dblocks - lsize;
statp->f_bfree = statp->f_bavail = spin_unlock(&mp->m_sb_lock);
sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp);
statp->f_bavail = statp->f_bfree;
fakeinos = statp->f_bfree << sbp->sb_inopblog; fakeinos = statp->f_bfree << sbp->sb_inopblog;
statp->f_files = statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
if (mp->m_maxicount) if (mp->m_maxicount)
statp->f_files = min_t(typeof(statp->f_files), statp->f_files = min_t(typeof(statp->f_files),
statp->f_files, statp->f_files,
...@@ -1098,10 +1087,9 @@ xfs_fs_statfs( ...@@ -1098,10 +1087,9 @@ xfs_fs_statfs(
sbp->sb_icount); sbp->sb_icount);
/* make sure statp->f_ffree does not underflow */ /* make sure statp->f_ffree does not underflow */
ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree); ffree = statp->f_files - (icount - ifree);
statp->f_ffree = max_t(__int64_t, ffree, 0); statp->f_ffree = max_t(__int64_t, ffree, 0);
spin_unlock(&mp->m_sb_lock);
if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) && if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) == ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) ==
...@@ -1382,6 +1370,51 @@ xfs_finish_flags( ...@@ -1382,6 +1370,51 @@ xfs_finish_flags(
return 0; 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 STATIC int
xfs_fs_fill_super( xfs_fs_fill_super(
struct super_block *sb, struct super_block *sb,
...@@ -1430,7 +1463,7 @@ xfs_fs_fill_super( ...@@ -1430,7 +1463,7 @@ xfs_fs_fill_super(
if (error) if (error)
goto out_close_devices; goto out_close_devices;
error = xfs_icsb_init_counters(mp); error = xfs_init_percpu_counters(mp);
if (error) if (error)
goto out_destroy_workqueues; goto out_destroy_workqueues;
...@@ -1488,7 +1521,7 @@ xfs_fs_fill_super( ...@@ -1488,7 +1521,7 @@ xfs_fs_fill_super(
out_free_sb: out_free_sb:
xfs_freesb(mp); xfs_freesb(mp);
out_destroy_counters: out_destroy_counters:
xfs_icsb_destroy_counters(mp); xfs_destroy_percpu_counters(mp);
out_destroy_workqueues: out_destroy_workqueues:
xfs_destroy_mount_workqueues(mp); xfs_destroy_mount_workqueues(mp);
out_close_devices: out_close_devices:
...@@ -1505,6 +1538,24 @@ xfs_fs_fill_super( ...@@ -1505,6 +1538,24 @@ xfs_fs_fill_super(
goto out_free_sb; goto out_free_sb;
} }
STATIC void
xfs_fs_put_super(
struct super_block *sb)
{
struct xfs_mount *mp = XFS_M(sb);
xfs_notice(mp, "Unmounting Filesystem");
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 * STATIC struct dentry *
xfs_fs_mount( xfs_fs_mount(
struct file_system_type *fs_type, struct file_system_type *fs_type,
......
...@@ -72,6 +72,8 @@ extern const struct export_operations xfs_export_operations; ...@@ -72,6 +72,8 @@ extern const struct export_operations xfs_export_operations;
extern const struct xattr_handler *xfs_xattr_handlers[]; extern const struct xattr_handler *xfs_xattr_handlers[];
extern const struct quotactl_ops xfs_quotactl_operations; 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)) #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info))
#endif /* __XFS_SUPER_H__ */ #endif /* __XFS_SUPER_H__ */
...@@ -173,7 +173,7 @@ xfs_trans_reserve( ...@@ -173,7 +173,7 @@ xfs_trans_reserve(
uint rtextents) uint rtextents)
{ {
int error = 0; int error = 0;
int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
/* Mark this thread as being in a transaction */ /* Mark this thread as being in a transaction */
current_set_flags_nested(&tp->t_pflags, PF_FSTRANS); current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
...@@ -184,8 +184,7 @@ xfs_trans_reserve( ...@@ -184,8 +184,7 @@ xfs_trans_reserve(
* fail if the count would go below zero. * fail if the count would go below zero.
*/ */
if (blocks > 0) { if (blocks > 0) {
error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS, error = xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
-((int64_t)blocks), rsvd);
if (error != 0) { if (error != 0) {
current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
return -ENOSPC; return -ENOSPC;
...@@ -236,8 +235,7 @@ xfs_trans_reserve( ...@@ -236,8 +235,7 @@ xfs_trans_reserve(
* fail if the count would go below zero. * fail if the count would go below zero.
*/ */
if (rtextents > 0) { if (rtextents > 0) {
error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS, error = xfs_mod_frextents(tp->t_mountp, -((int64_t)rtextents));
-((int64_t)rtextents), rsvd);
if (error) { if (error) {
error = -ENOSPC; error = -ENOSPC;
goto undo_log; goto undo_log;
...@@ -268,8 +266,7 @@ xfs_trans_reserve( ...@@ -268,8 +266,7 @@ xfs_trans_reserve(
undo_blocks: undo_blocks:
if (blocks > 0) { if (blocks > 0) {
xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS, xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
(int64_t)blocks, rsvd);
tp->t_blk_res = 0; tp->t_blk_res = 0;
} }
...@@ -488,6 +485,54 @@ xfs_trans_apply_sb_deltas( ...@@ -488,6 +485,54 @@ xfs_trans_apply_sb_deltas(
sizeof(sbp->sb_frextents) - 1); sizeof(sbp->sb_frextents) - 1);
} }
STATIC int
xfs_sb_mod8(
uint8_t *field,
int8_t delta)
{
int8_t counter = *field;
counter += delta;
if (counter < 0) {
ASSERT(0);
return -EINVAL;
}
*field = counter;
return 0;
}
STATIC int
xfs_sb_mod32(
uint32_t *field,
int32_t delta)
{
int32_t counter = *field;
counter += delta;
if (counter < 0) {
ASSERT(0);
return -EINVAL;
}
*field = counter;
return 0;
}
STATIC int
xfs_sb_mod64(
uint64_t *field,
int64_t delta)
{
int64_t counter = *field;
counter += delta;
if (counter < 0) {
ASSERT(0);
return -EINVAL;
}
*field = counter;
return 0;
}
/* /*
* xfs_trans_unreserve_and_mod_sb() is called to release unused reservations * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
* and apply superblock counter changes to the in-core superblock. The * and apply superblock counter changes to the in-core superblock. The
...@@ -495,13 +540,6 @@ xfs_trans_apply_sb_deltas( ...@@ -495,13 +540,6 @@ xfs_trans_apply_sb_deltas(
* applied to the in-core superblock. The idea is that that has already been * applied to the in-core superblock. The idea is that that has already been
* done. * done.
* *
* This is done efficiently with a single call to xfs_mod_incore_sb_batch().
* However, we have to ensure that we only modify each superblock field only
* once because the application of the delta values may not be atomic. That can
* lead to ENOSPC races occurring if we have two separate modifcations of the
* free space counter to put back the entire reservation and then take away
* what we used.
*
* If we are not logging superblock counters, then the inode allocated/free and * If we are not logging superblock counters, then the inode allocated/free and
* used block counts are not updated in the on disk superblock. In this case, * used block counts are not updated in the on disk superblock. In this case,
* XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
...@@ -509,21 +547,15 @@ xfs_trans_apply_sb_deltas( ...@@ -509,21 +547,15 @@ xfs_trans_apply_sb_deltas(
*/ */
void void
xfs_trans_unreserve_and_mod_sb( xfs_trans_unreserve_and_mod_sb(
xfs_trans_t *tp) struct xfs_trans *tp)
{ {
xfs_mod_sb_t msb[9]; /* If you add cases, add entries */ struct xfs_mount *mp = tp->t_mountp;
xfs_mod_sb_t *msbp; bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
xfs_mount_t *mp = tp->t_mountp; int64_t blkdelta = 0;
/* REFERENCED */ int64_t rtxdelta = 0;
int error; int64_t idelta = 0;
int rsvd; int64_t ifreedelta = 0;
int64_t blkdelta = 0; int error;
int64_t rtxdelta = 0;
int64_t idelta = 0;
int64_t ifreedelta = 0;
msbp = msb;
rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
/* calculate deltas */ /* calculate deltas */
if (tp->t_blk_res > 0) if (tp->t_blk_res > 0)
...@@ -547,97 +579,115 @@ xfs_trans_unreserve_and_mod_sb( ...@@ -547,97 +579,115 @@ xfs_trans_unreserve_and_mod_sb(
/* apply the per-cpu counters */ /* apply the per-cpu counters */
if (blkdelta) { if (blkdelta) {
error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, error = xfs_mod_fdblocks(mp, blkdelta, rsvd);
blkdelta, rsvd);
if (error) if (error)
goto out; goto out;
} }
if (idelta) { if (idelta) {
error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, error = xfs_mod_icount(mp, idelta);
idelta, rsvd);
if (error) if (error)
goto out_undo_fdblocks; goto out_undo_fdblocks;
} }
if (ifreedelta) { if (ifreedelta) {
error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, error = xfs_mod_ifree(mp, ifreedelta);
ifreedelta, rsvd);
if (error) if (error)
goto out_undo_icount; goto out_undo_icount;
} }
if (rtxdelta == 0 && !(tp->t_flags & XFS_TRANS_SB_DIRTY))
return;
/* apply remaining deltas */ /* apply remaining deltas */
if (rtxdelta != 0) { spin_lock(&mp->m_sb_lock);
msbp->msb_field = XFS_SBS_FREXTENTS; if (rtxdelta) {
msbp->msb_delta = rtxdelta; error = xfs_sb_mod64(&mp->m_sb.sb_frextents, rtxdelta);
msbp++; if (error)
goto out_undo_ifree;
} }
if (tp->t_flags & XFS_TRANS_SB_DIRTY) { if (tp->t_dblocks_delta != 0) {
if (tp->t_dblocks_delta != 0) { error = xfs_sb_mod64(&mp->m_sb.sb_dblocks, tp->t_dblocks_delta);
msbp->msb_field = XFS_SBS_DBLOCKS; if (error)
msbp->msb_delta = tp->t_dblocks_delta; goto out_undo_frextents;
msbp++;
}
if (tp->t_agcount_delta != 0) {
msbp->msb_field = XFS_SBS_AGCOUNT;
msbp->msb_delta = tp->t_agcount_delta;
msbp++;
}
if (tp->t_imaxpct_delta != 0) {
msbp->msb_field = XFS_SBS_IMAX_PCT;
msbp->msb_delta = tp->t_imaxpct_delta;
msbp++;
}
if (tp->t_rextsize_delta != 0) {
msbp->msb_field = XFS_SBS_REXTSIZE;
msbp->msb_delta = tp->t_rextsize_delta;
msbp++;
}
if (tp->t_rbmblocks_delta != 0) {
msbp->msb_field = XFS_SBS_RBMBLOCKS;
msbp->msb_delta = tp->t_rbmblocks_delta;
msbp++;
}
if (tp->t_rblocks_delta != 0) {
msbp->msb_field = XFS_SBS_RBLOCKS;
msbp->msb_delta = tp->t_rblocks_delta;
msbp++;
}
if (tp->t_rextents_delta != 0) {
msbp->msb_field = XFS_SBS_REXTENTS;
msbp->msb_delta = tp->t_rextents_delta;
msbp++;
}
if (tp->t_rextslog_delta != 0) {
msbp->msb_field = XFS_SBS_REXTSLOG;
msbp->msb_delta = tp->t_rextslog_delta;
msbp++;
}
} }
if (tp->t_agcount_delta != 0) {
/* error = xfs_sb_mod32(&mp->m_sb.sb_agcount, tp->t_agcount_delta);
* If we need to change anything, do it.
*/
if (msbp > msb) {
error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
(uint)(msbp - msb), rsvd);
if (error) if (error)
goto out_undo_ifreecount; goto out_undo_dblocks;
} }
if (tp->t_imaxpct_delta != 0) {
error = xfs_sb_mod8(&mp->m_sb.sb_imax_pct, tp->t_imaxpct_delta);
if (error)
goto out_undo_agcount;
}
if (tp->t_rextsize_delta != 0) {
error = xfs_sb_mod32(&mp->m_sb.sb_rextsize,
tp->t_rextsize_delta);
if (error)
goto out_undo_imaxpct;
}
if (tp->t_rbmblocks_delta != 0) {
error = xfs_sb_mod32(&mp->m_sb.sb_rbmblocks,
tp->t_rbmblocks_delta);
if (error)
goto out_undo_rextsize;
}
if (tp->t_rblocks_delta != 0) {
error = xfs_sb_mod64(&mp->m_sb.sb_rblocks, tp->t_rblocks_delta);
if (error)
goto out_undo_rbmblocks;
}
if (tp->t_rextents_delta != 0) {
error = xfs_sb_mod64(&mp->m_sb.sb_rextents,
tp->t_rextents_delta);
if (error)
goto out_undo_rblocks;
}
if (tp->t_rextslog_delta != 0) {
error = xfs_sb_mod8(&mp->m_sb.sb_rextslog,
tp->t_rextslog_delta);
if (error)
goto out_undo_rextents;
}
spin_unlock(&mp->m_sb_lock);
return; return;
out_undo_ifreecount: out_undo_rextents:
if (tp->t_rextents_delta)
xfs_sb_mod64(&mp->m_sb.sb_rextents, -tp->t_rextents_delta);
out_undo_rblocks:
if (tp->t_rblocks_delta)
xfs_sb_mod64(&mp->m_sb.sb_rblocks, -tp->t_rblocks_delta);
out_undo_rbmblocks:
if (tp->t_rbmblocks_delta)
xfs_sb_mod32(&mp->m_sb.sb_rbmblocks, -tp->t_rbmblocks_delta);
out_undo_rextsize:
if (tp->t_rextsize_delta)
xfs_sb_mod32(&mp->m_sb.sb_rextsize, -tp->t_rextsize_delta);
out_undo_imaxpct:
if (tp->t_rextsize_delta)
xfs_sb_mod8(&mp->m_sb.sb_imax_pct, -tp->t_imaxpct_delta);
out_undo_agcount:
if (tp->t_agcount_delta)
xfs_sb_mod32(&mp->m_sb.sb_agcount, -tp->t_agcount_delta);
out_undo_dblocks:
if (tp->t_dblocks_delta)
xfs_sb_mod64(&mp->m_sb.sb_dblocks, -tp->t_dblocks_delta);
out_undo_frextents:
if (rtxdelta)
xfs_sb_mod64(&mp->m_sb.sb_frextents, -rtxdelta);
out_undo_ifree:
spin_unlock(&mp->m_sb_lock);
if (ifreedelta) if (ifreedelta)
xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd); xfs_mod_ifree(mp, -ifreedelta);
out_undo_icount: out_undo_icount:
if (idelta) if (idelta)
xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd); xfs_mod_icount(mp, -idelta);
out_undo_fdblocks: out_undo_fdblocks:
if (blkdelta) if (blkdelta)
xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd); xfs_mod_fdblocks(mp, -blkdelta, rsvd);
out: out:
ASSERT(error == 0); ASSERT(error == 0);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment