Пример #1
0
/*
 * xfs_trans_unreserve_and_mod_sb() is called to release unused
 * reservations and apply superblock counter changes to the in-core
 * superblock.
 *
 * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
 */
STATIC void
xfs_trans_unreserve_and_mod_sb(
	xfs_trans_t	*tp)
{
	xfs_mod_sb_t	msb[14];	/* If you add cases, add entries */
	xfs_mod_sb_t	*msbp;
	/* REFERENCED */
	int		error;
	int		rsvd;

	msbp = msb;
	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;

	/*
	 * Release any reserved blocks.  Any that were allocated
	 * will be taken back again by fdblocks_delta below.
	 */
	if (tp->t_blk_res > 0) {
		msbp->msb_field = XFS_SBS_FDBLOCKS;
		msbp->msb_delta = tp->t_blk_res;
		msbp++;
	}

	/*
	 * Release any reserved real time extents .  Any that were
	 * allocated will be taken back again by frextents_delta below.
	 */
	if (tp->t_rtx_res > 0) {
		msbp->msb_field = XFS_SBS_FREXTENTS;
		msbp->msb_delta = tp->t_rtx_res;
		msbp++;
	}

	/*
	 * Apply any superblock modifications to the in-core version.
	 * The t_res_fdblocks_delta and t_res_frextents_delta fields are
	 * explicitly NOT applied to the in-core superblock.
	 * The idea is that that has already been done.
	 */
	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
		if (tp->t_icount_delta != 0) {
			msbp->msb_field = XFS_SBS_ICOUNT;
			msbp->msb_delta = (int)tp->t_icount_delta;
			msbp++;
		}
		if (tp->t_ifree_delta != 0) {
			msbp->msb_field = XFS_SBS_IFREE;
			msbp->msb_delta = (int)tp->t_ifree_delta;
			msbp++;
		}
		if (tp->t_fdblocks_delta != 0) {
			msbp->msb_field = XFS_SBS_FDBLOCKS;
			msbp->msb_delta = (int)tp->t_fdblocks_delta;
			msbp++;
		}
		if (tp->t_frextents_delta != 0) {
			msbp->msb_field = XFS_SBS_FREXTENTS;
			msbp->msb_delta = (int)tp->t_frextents_delta;
			msbp++;
		}
		if (tp->t_dblocks_delta != 0) {
			msbp->msb_field = XFS_SBS_DBLOCKS;
			msbp->msb_delta = (int)tp->t_dblocks_delta;
			msbp++;
		}
		if (tp->t_agcount_delta != 0) {
			msbp->msb_field = XFS_SBS_AGCOUNT;
			msbp->msb_delta = (int)tp->t_agcount_delta;
			msbp++;
		}
		if (tp->t_imaxpct_delta != 0) {
			msbp->msb_field = XFS_SBS_IMAX_PCT;
			msbp->msb_delta = (int)tp->t_imaxpct_delta;
			msbp++;
		}
		if (tp->t_rextsize_delta != 0) {
			msbp->msb_field = XFS_SBS_REXTSIZE;
			msbp->msb_delta = (int)tp->t_rextsize_delta;
			msbp++;
		}
		if (tp->t_rbmblocks_delta != 0) {
			msbp->msb_field = XFS_SBS_RBMBLOCKS;
			msbp->msb_delta = (int)tp->t_rbmblocks_delta;
			msbp++;
		}
		if (tp->t_rblocks_delta != 0) {
			msbp->msb_field = XFS_SBS_RBLOCKS;
			msbp->msb_delta = (int)tp->t_rblocks_delta;
			msbp++;
		}
		if (tp->t_rextents_delta != 0) {
			msbp->msb_field = XFS_SBS_REXTENTS;
			msbp->msb_delta = (int)tp->t_rextents_delta;
			msbp++;
		}
		if (tp->t_rextslog_delta != 0) {
			msbp->msb_field = XFS_SBS_REXTSLOG;
			msbp->msb_delta = (int)tp->t_rextslog_delta;
			msbp++;
		}
	}

	/*
	 * 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);
		ASSERT(error == 0);
	}
}
Пример #2
0
/*
 * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
 * and apply superblock counter changes to the in-core superblock.  The
 * t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT
 * applied to the in-core superblock.  The idea is that that has already been
 * 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
 * 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
 * still need to update the incore superblock with the changes.
 */
STATIC void
xfs_trans_unreserve_and_mod_sb(
    xfs_trans_t    *tp)
{
    xfs_mod_sb_t    msb[14];    /* If you add cases, add entries */
    xfs_mod_sb_t    *msbp;
    xfs_mount_t    *mp = tp->t_mountp;
    /* REFERENCED */
    int        error;
    int        rsvd;
    int64_t        blkdelta = 0;
    int64_t        rtxdelta = 0;

    msbp = msb;
    rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;

    /* calculate free blocks delta */
    if (tp->t_blk_res > 0)
        blkdelta = tp->t_blk_res;

    if ((tp->t_fdblocks_delta != 0) &&
        (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
         (tp->t_flags & XFS_TRANS_SB_DIRTY)))
            blkdelta += tp->t_fdblocks_delta;

    if (blkdelta != 0) {
        msbp->msb_field = XFS_SBS_FDBLOCKS;
        msbp->msb_delta = blkdelta;
        msbp++;
    }

    /* calculate free realtime extents delta */
    if (tp->t_rtx_res > 0)
        rtxdelta = tp->t_rtx_res;

    if ((tp->t_frextents_delta != 0) &&
        (tp->t_flags & XFS_TRANS_SB_DIRTY))
        rtxdelta += tp->t_frextents_delta;

    if (rtxdelta != 0) {
        msbp->msb_field = XFS_SBS_FREXTENTS;
        msbp->msb_delta = rtxdelta;
        msbp++;
    }

    /* apply remaining deltas */

    if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
         (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
        if (tp->t_icount_delta != 0) {
            msbp->msb_field = XFS_SBS_ICOUNT;
            msbp->msb_delta = tp->t_icount_delta;
            msbp++;
        }
        if (tp->t_ifree_delta != 0) {
            msbp->msb_field = XFS_SBS_IFREE;
            msbp->msb_delta = tp->t_ifree_delta;
            msbp++;
        }
    }

    if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
        if (tp->t_dblocks_delta != 0) {
            msbp->msb_field = XFS_SBS_DBLOCKS;
            msbp->msb_delta = tp->t_dblocks_delta;
            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 we need to change anything, do it.
     */
    if (msbp > msb) {
        error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
            (uint)(msbp - msb), rsvd);
        ASSERT(error == 0);
    }
}