2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2025-01-14 00:24:15 +08:00

XFS changes for 4.21:

- Fix CoW remapping of extremely fragmented file areas
 - Fix a zero-length symlink verifier error
 - Constify some of the rmap owner structures for per-AG metadata
 - Precalculate inode geometry for later use
 - Fix scrub counting problems
 - Don't crash when rtsummary inode is null
 - Fix x32 ioctl operation
 - Fix enum->string mappings for ftrace output
 - Cache realtime summary information in memory
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEUzaAxoMeQq6m2jMV+H93GTRKtOsFAlwedm4ACgkQ+H93GTRK
 tOumSBAAjP9nFAWmI9n/4GEyNI7p6Iz26q42vePiX7FspJY2iWG38gf5PyRarL7X
 eWzmUhUJVQ3koA4+h+ImGPWwjZAyDUug7r437sPPPkcMvG9WKrj8A2M+kQve39NB
 kCaXsRJFEvOdFXTMwTzCMrZrHa1b/slqj65eoUyXI7dzT0vwuU8Nj8CX6//zOHD2
 4i7yiyGGnZvQ+Ql8ad+ck7LjooeBUzl3XBeOHlFZAO+gDCu6o1TUqO+x8HZPy58N
 sfBLY/9vqlzEN8EpWjiTdI+GNH0zhO0tJQI5YJlGqa6SpIC78fWElfFF0A9CUXy4
 meKc9VmJ5oYi0Rg62S3pKTRZWtkr9FddBjS/C0thvXIpw6CSmHz/ED41P/wrtnI+
 vbknTXeiLeCuTTLtnYWJNIW1kvWjS2vXlQQT5jt/rp49ZqzfetM9nuopES0CcnCm
 a8K++V2LZuYEPzM2fKQgAdd5z02BYeNu8uaEBEHcAWDUnVo/bKInp87dEiQZ5GXx
 PBfIfOuqVooCppp9w1T7nzshI0R3k+LQj2R4S0d039hfEw8eQmPu39rfvugy6YwI
 qCZo8uErzWmqF7T4EXMtGu1FS8xIwyLPyiqcsCd8g+zep95iVySSrhha+3DgR/mG
 85s4VOE5aWijBrRZixIIqF1bIc+LPE/miBEXIyCsBPRD52+YQcQ=
 =P0gt
 -----END PGP SIGNATURE-----

Merge tag 'xfs-4.21-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull XFS updates from Darrick Wong:

 - Fix CoW remapping of extremely fragmented file areas

 - Fix a zero-length symlink verifier error

 - Constify some of the rmap owner structures for per-AG metadata

 - Precalculate inode geometry for later use

 - Fix scrub counting problems

 - Don't crash when rtsummary inode is null

 - Fix x32 ioctl operation

 - Fix enum->string mappings for ftrace output

 - Cache realtime summary information in memory

* tag 'xfs-4.21-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (24 commits)
  xfs: reallocate realtime summary cache on growfs
  xfs: stringify scrub types in ftrace output
  xfs: stringify btree cursor types in ftrace output
  xfs: move XFS_INODE_FORMAT_STR mappings to libxfs
  xfs: move XFS_AG_BTREE_CMP_FORMAT_STR mappings to libxfs
  xfs: fix symbolic enum printing in ftrace output
  xfs: fix function pointer type in ftrace format
  xfs: Fix x32 ioctls when cmd numbers differ from ia32.
  xfs: Fix bulkstat compat ioctls on x32 userspace.
  xfs: Align compat attrlist_by_handle with native implementation.
  xfs: require both realtime inodes to mount
  xfs: cache minimum realtime summary level
  xfs: count inode blocks correctly in inobt scrub
  xfs: precalculate cluster alignment in inodes and blocks
  xfs: precalculate inodes and blocks per inode cluster
  xfs: add a block to inode count converter
  xfs: remove xfs_rmap_ag_owner and friends
  xfs: const-ify xfs_owner_info arguments
  xfs: streamline defer op type handling
  xfs: idiotproof defer op type configuration
  ...
This commit is contained in:
Linus Torvalds 2018-12-27 17:04:23 -08:00
commit 47a43f2f0c
51 changed files with 936 additions and 718 deletions

View File

@ -414,7 +414,6 @@ xfs_ag_extend_space(
struct aghdr_init_data *id, struct aghdr_init_data *id,
xfs_extlen_t len) xfs_extlen_t len)
{ {
struct xfs_owner_info oinfo;
struct xfs_buf *bp; struct xfs_buf *bp;
struct xfs_agi *agi; struct xfs_agi *agi;
struct xfs_agf *agf; struct xfs_agf *agf;
@ -448,17 +447,17 @@ xfs_ag_extend_space(
/* /*
* Free the new space. * Free the new space.
* *
* XFS_RMAP_OWN_NULL is used here to tell the rmap btree that * XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that
* this doesn't actually exist in the rmap btree. * this doesn't actually exist in the rmap btree.
*/ */
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_NULL);
error = xfs_rmap_free(tp, bp, id->agno, error = xfs_rmap_free(tp, bp, id->agno,
be32_to_cpu(agf->agf_length) - len, be32_to_cpu(agf->agf_length) - len,
len, &oinfo); len, &XFS_RMAP_OINFO_SKIP_UPDATE);
if (error) if (error)
return error; return error;
return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno, return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno,
be32_to_cpu(agf->agf_length) - len), be32_to_cpu(agf->agf_length) - len),
len, &oinfo, XFS_AG_RESV_NONE); len, &XFS_RMAP_OINFO_SKIP_UPDATE,
XFS_AG_RESV_NONE);
} }

View File

@ -1594,7 +1594,6 @@ xfs_alloc_ag_vextent_small(
xfs_extlen_t *flenp, /* result length */ xfs_extlen_t *flenp, /* result length */
int *stat) /* status: 0-freelist, 1-normal/none */ int *stat) /* status: 0-freelist, 1-normal/none */
{ {
struct xfs_owner_info oinfo;
int error; int error;
xfs_agblock_t fbno; xfs_agblock_t fbno;
xfs_extlen_t flen; xfs_extlen_t flen;
@ -1648,9 +1647,8 @@ xfs_alloc_ag_vextent_small(
* doesn't live in the free space, we need to clear * doesn't live in the free space, we need to clear
* out the OWN_AG rmap. * out the OWN_AG rmap.
*/ */
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
error = xfs_rmap_free(args->tp, args->agbp, args->agno, error = xfs_rmap_free(args->tp, args->agbp, args->agno,
fbno, 1, &oinfo); fbno, 1, &XFS_RMAP_OINFO_AG);
if (error) if (error)
goto error0; goto error0;
@ -1694,28 +1692,28 @@ error0:
*/ */
STATIC int STATIC int
xfs_free_ag_extent( xfs_free_ag_extent(
xfs_trans_t *tp, struct xfs_trans *tp,
xfs_buf_t *agbp, struct xfs_buf *agbp,
xfs_agnumber_t agno, xfs_agnumber_t agno,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
enum xfs_ag_resv_type type) enum xfs_ag_resv_type type)
{ {
xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ struct xfs_mount *mp;
xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */ struct xfs_perag *pag;
int error; /* error return value */ struct xfs_btree_cur *bno_cur;
xfs_agblock_t gtbno; /* start of right neighbor block */ struct xfs_btree_cur *cnt_cur;
xfs_extlen_t gtlen; /* length of right neighbor block */ xfs_agblock_t gtbno; /* start of right neighbor */
int haveleft; /* have a left neighbor block */ xfs_extlen_t gtlen; /* length of right neighbor */
int haveright; /* have a right neighbor block */ xfs_agblock_t ltbno; /* start of left neighbor */
int i; /* temp, result code */ xfs_extlen_t ltlen; /* length of left neighbor */
xfs_agblock_t ltbno; /* start of left neighbor block */ xfs_agblock_t nbno; /* new starting block of freesp */
xfs_extlen_t ltlen; /* length of left neighbor block */ xfs_extlen_t nlen; /* new length of freespace */
xfs_mount_t *mp; /* mount point struct for filesystem */ int haveleft; /* have a left neighbor */
xfs_agblock_t nbno; /* new starting block of freespace */ int haveright; /* have a right neighbor */
xfs_extlen_t nlen; /* new length of freespace */ int i;
xfs_perag_t *pag; /* per allocation group data */ int error;
bno_cur = cnt_cur = NULL; bno_cur = cnt_cur = NULL;
mp = tp->t_mountp; mp = tp->t_mountp;
@ -2314,10 +2312,11 @@ xfs_alloc_fix_freelist(
* repair/rmap.c in xfsprogs for details. * repair/rmap.c in xfsprogs for details.
*/ */
memset(&targs, 0, sizeof(targs)); memset(&targs, 0, sizeof(targs));
/* struct copy below */
if (flags & XFS_ALLOC_FLAG_NORMAP) if (flags & XFS_ALLOC_FLAG_NORMAP)
xfs_rmap_skip_owner_update(&targs.oinfo); targs.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
else else
xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); targs.oinfo = XFS_RMAP_OINFO_AG;
while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) { while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) {
error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
if (error) if (error)
@ -2435,7 +2434,6 @@ xfs_alloc_get_freelist(
be32_add_cpu(&agf->agf_flcount, -1); be32_add_cpu(&agf->agf_flcount, -1);
xfs_trans_agflist_delta(tp, -1); xfs_trans_agflist_delta(tp, -1);
pag->pagf_flcount--; pag->pagf_flcount--;
xfs_perag_put(pag);
logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT; logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
if (btreeblk) { if (btreeblk) {
@ -2443,6 +2441,7 @@ xfs_alloc_get_freelist(
pag->pagf_btreeblks++; pag->pagf_btreeblks++;
logflags |= XFS_AGF_BTREEBLKS; logflags |= XFS_AGF_BTREEBLKS;
} }
xfs_perag_put(pag);
xfs_alloc_log_agf(tp, agbp, logflags); xfs_alloc_log_agf(tp, agbp, logflags);
*bnop = bno; *bnop = bno;
@ -3008,21 +3007,21 @@ out:
* Just break up the extent address and hand off to xfs_free_ag_extent * Just break up the extent address and hand off to xfs_free_ag_extent
* after fixing up the freelist. * after fixing up the freelist.
*/ */
int /* error */ int
__xfs_free_extent( __xfs_free_extent(
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_fsblock_t bno, /* starting block number of extent */ xfs_fsblock_t bno,
xfs_extlen_t len, /* length of extent */ xfs_extlen_t len,
struct xfs_owner_info *oinfo, /* extent owner */ const struct xfs_owner_info *oinfo,
enum xfs_ag_resv_type type, /* block reservation type */ enum xfs_ag_resv_type type,
bool skip_discard) bool skip_discard)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_buf *agbp; struct xfs_buf *agbp;
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno); xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
int error; int error;
unsigned int busy_flags = 0; unsigned int busy_flags = 0;
ASSERT(len != 0); ASSERT(len != 0);
ASSERT(type != XFS_AG_RESV_AGFL); ASSERT(type != XFS_AG_RESV_AGFL);

View File

@ -182,7 +182,7 @@ __xfs_free_extent(
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_fsblock_t bno, /* starting block number of extent */ xfs_fsblock_t bno, /* starting block number of extent */
xfs_extlen_t len, /* length of extent */ xfs_extlen_t len, /* length of extent */
struct xfs_owner_info *oinfo, /* extent owner */ const struct xfs_owner_info *oinfo, /* extent owner */
enum xfs_ag_resv_type type, /* block reservation type */ enum xfs_ag_resv_type type, /* block reservation type */
bool skip_discard); bool skip_discard);
@ -191,7 +191,7 @@ xfs_free_extent(
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_fsblock_t bno, xfs_fsblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
enum xfs_ag_resv_type type) enum xfs_ag_resv_type type)
{ {
return __xfs_free_extent(tp, bno, len, oinfo, type, false); return __xfs_free_extent(tp, bno, len, oinfo, type, false);

View File

@ -536,7 +536,7 @@ __xfs_bmap_add_free(
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_fsblock_t bno, xfs_fsblock_t bno,
xfs_filblks_t len, xfs_filblks_t len,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
bool skip_discard) bool skip_discard)
{ {
struct xfs_extent_free_item *new; /* new element */ struct xfs_extent_free_item *new; /* new element */
@ -564,7 +564,7 @@ __xfs_bmap_add_free(
if (oinfo) if (oinfo)
new->xefi_oinfo = *oinfo; new->xefi_oinfo = *oinfo;
else else
xfs_rmap_skip_owner_update(&new->xefi_oinfo); new->xefi_oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
new->xefi_skip_discard = skip_discard; new->xefi_skip_discard = skip_discard;
trace_xfs_bmap_free_defer(tp->t_mountp, trace_xfs_bmap_free_defer(tp->t_mountp,
XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0, XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
@ -3453,7 +3453,7 @@ xfs_bmap_btalloc(
args.tp = ap->tp; args.tp = ap->tp;
args.mp = mp; args.mp = mp;
args.fsbno = ap->blkno; args.fsbno = ap->blkno;
xfs_rmap_skip_owner_update(&args.oinfo); args.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
/* Trim the allocation back to the maximum an AG can fit. */ /* Trim the allocation back to the maximum an AG can fit. */
args.maxlen = min(ap->length, mp->m_ag_max_usable); args.maxlen = min(ap->length, mp->m_ag_max_usable);

View File

@ -186,7 +186,7 @@ int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
int xfs_bmap_set_attrforkoff(struct xfs_inode *ip, int size, int *version); int xfs_bmap_set_attrforkoff(struct xfs_inode *ip, int size, int *version);
void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno, void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
xfs_filblks_t len, struct xfs_owner_info *oinfo, xfs_filblks_t len, const struct xfs_owner_info *oinfo,
bool skip_discard); bool skip_discard);
void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
@ -234,7 +234,7 @@ xfs_bmap_add_free(
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_fsblock_t bno, xfs_fsblock_t bno,
xfs_filblks_t len, xfs_filblks_t len,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
__xfs_bmap_add_free(tp, bno, len, oinfo, false); __xfs_bmap_add_free(tp, bno, len, oinfo, false);
} }

View File

@ -172,7 +172,13 @@
* reoccur. * reoccur.
*/ */
static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; static const struct xfs_defer_op_type *defer_op_types[] = {
[XFS_DEFER_OPS_TYPE_BMAP] = &xfs_bmap_update_defer_type,
[XFS_DEFER_OPS_TYPE_REFCOUNT] = &xfs_refcount_update_defer_type,
[XFS_DEFER_OPS_TYPE_RMAP] = &xfs_rmap_update_defer_type,
[XFS_DEFER_OPS_TYPE_FREE] = &xfs_extent_free_defer_type,
[XFS_DEFER_OPS_TYPE_AGFL_FREE] = &xfs_agfl_free_defer_type,
};
/* /*
* For each pending item in the intake list, log its intent item and the * For each pending item in the intake list, log its intent item and the
@ -185,15 +191,15 @@ xfs_defer_create_intents(
{ {
struct list_head *li; struct list_head *li;
struct xfs_defer_pending *dfp; struct xfs_defer_pending *dfp;
const struct xfs_defer_op_type *ops;
list_for_each_entry(dfp, &tp->t_dfops, dfp_list) { list_for_each_entry(dfp, &tp->t_dfops, dfp_list) {
dfp->dfp_intent = dfp->dfp_type->create_intent(tp, ops = defer_op_types[dfp->dfp_type];
dfp->dfp_count); dfp->dfp_intent = ops->create_intent(tp, dfp->dfp_count);
trace_xfs_defer_create_intent(tp->t_mountp, dfp); trace_xfs_defer_create_intent(tp->t_mountp, dfp);
list_sort(tp->t_mountp, &dfp->dfp_work, list_sort(tp->t_mountp, &dfp->dfp_work, ops->diff_items);
dfp->dfp_type->diff_items);
list_for_each(li, &dfp->dfp_work) list_for_each(li, &dfp->dfp_work)
dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); ops->log_item(tp, dfp->dfp_intent, li);
} }
} }
@ -204,14 +210,16 @@ xfs_defer_trans_abort(
struct list_head *dop_pending) struct list_head *dop_pending)
{ {
struct xfs_defer_pending *dfp; struct xfs_defer_pending *dfp;
const struct xfs_defer_op_type *ops;
trace_xfs_defer_trans_abort(tp, _RET_IP_); trace_xfs_defer_trans_abort(tp, _RET_IP_);
/* Abort intent items that don't have a done item. */ /* Abort intent items that don't have a done item. */
list_for_each_entry(dfp, dop_pending, dfp_list) { list_for_each_entry(dfp, dop_pending, dfp_list) {
ops = defer_op_types[dfp->dfp_type];
trace_xfs_defer_pending_abort(tp->t_mountp, dfp); trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
if (dfp->dfp_intent && !dfp->dfp_done) { if (dfp->dfp_intent && !dfp->dfp_done) {
dfp->dfp_type->abort_intent(dfp->dfp_intent); ops->abort_intent(dfp->dfp_intent);
dfp->dfp_intent = NULL; dfp->dfp_intent = NULL;
} }
} }
@ -315,18 +323,20 @@ xfs_defer_cancel_list(
struct xfs_defer_pending *pli; struct xfs_defer_pending *pli;
struct list_head *pwi; struct list_head *pwi;
struct list_head *n; struct list_head *n;
const struct xfs_defer_op_type *ops;
/* /*
* Free the pending items. Caller should already have arranged * Free the pending items. Caller should already have arranged
* for the intent items to be released. * for the intent items to be released.
*/ */
list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) { list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) {
ops = defer_op_types[dfp->dfp_type];
trace_xfs_defer_cancel_list(mp, dfp); trace_xfs_defer_cancel_list(mp, dfp);
list_del(&dfp->dfp_list); list_del(&dfp->dfp_list);
list_for_each_safe(pwi, n, &dfp->dfp_work) { list_for_each_safe(pwi, n, &dfp->dfp_work) {
list_del(pwi); list_del(pwi);
dfp->dfp_count--; dfp->dfp_count--;
dfp->dfp_type->cancel_item(pwi); ops->cancel_item(pwi);
} }
ASSERT(dfp->dfp_count == 0); ASSERT(dfp->dfp_count == 0);
kmem_free(dfp); kmem_free(dfp);
@ -350,7 +360,7 @@ xfs_defer_finish_noroll(
struct list_head *n; struct list_head *n;
void *state; void *state;
int error = 0; int error = 0;
void (*cleanup_fn)(struct xfs_trans *, void *, int); const struct xfs_defer_op_type *ops;
LIST_HEAD(dop_pending); LIST_HEAD(dop_pending);
ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
@ -373,18 +383,18 @@ xfs_defer_finish_noroll(
/* Log an intent-done item for the first pending item. */ /* Log an intent-done item for the first pending item. */
dfp = list_first_entry(&dop_pending, struct xfs_defer_pending, dfp = list_first_entry(&dop_pending, struct xfs_defer_pending,
dfp_list); dfp_list);
ops = defer_op_types[dfp->dfp_type];
trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp);
dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, dfp->dfp_done = ops->create_done(*tp, dfp->dfp_intent,
dfp->dfp_count); dfp->dfp_count);
cleanup_fn = dfp->dfp_type->finish_cleanup;
/* Finish the work items. */ /* Finish the work items. */
state = NULL; state = NULL;
list_for_each_safe(li, n, &dfp->dfp_work) { list_for_each_safe(li, n, &dfp->dfp_work) {
list_del(li); list_del(li);
dfp->dfp_count--; dfp->dfp_count--;
error = dfp->dfp_type->finish_item(*tp, li, error = ops->finish_item(*tp, li, dfp->dfp_done,
dfp->dfp_done, &state); &state);
if (error == -EAGAIN) { if (error == -EAGAIN) {
/* /*
* Caller wants a fresh transaction; * Caller wants a fresh transaction;
@ -400,8 +410,8 @@ xfs_defer_finish_noroll(
* xfs_defer_cancel will take care of freeing * xfs_defer_cancel will take care of freeing
* all these lists and stuff. * all these lists and stuff.
*/ */
if (cleanup_fn) if (ops->finish_cleanup)
cleanup_fn(*tp, state, error); ops->finish_cleanup(*tp, state, error);
goto out; goto out;
} }
} }
@ -413,20 +423,19 @@ xfs_defer_finish_noroll(
* a Fresh Transaction while Finishing * a Fresh Transaction while Finishing
* Deferred Work" above. * Deferred Work" above.
*/ */
dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, dfp->dfp_intent = ops->create_intent(*tp,
dfp->dfp_count); dfp->dfp_count);
dfp->dfp_done = NULL; dfp->dfp_done = NULL;
list_for_each(li, &dfp->dfp_work) list_for_each(li, &dfp->dfp_work)
dfp->dfp_type->log_item(*tp, dfp->dfp_intent, ops->log_item(*tp, dfp->dfp_intent, li);
li);
} else { } else {
/* Done with the dfp, free it. */ /* Done with the dfp, free it. */
list_del(&dfp->dfp_list); list_del(&dfp->dfp_list);
kmem_free(dfp); kmem_free(dfp);
} }
if (cleanup_fn) if (ops->finish_cleanup)
cleanup_fn(*tp, state, error); ops->finish_cleanup(*tp, state, error);
} }
out: out:
@ -486,8 +495,10 @@ xfs_defer_add(
struct list_head *li) struct list_head *li)
{ {
struct xfs_defer_pending *dfp = NULL; struct xfs_defer_pending *dfp = NULL;
const struct xfs_defer_op_type *ops;
ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
BUILD_BUG_ON(ARRAY_SIZE(defer_op_types) != XFS_DEFER_OPS_TYPE_MAX);
/* /*
* Add the item to a pending item at the end of the intake list. * Add the item to a pending item at the end of the intake list.
@ -497,15 +508,15 @@ xfs_defer_add(
if (!list_empty(&tp->t_dfops)) { if (!list_empty(&tp->t_dfops)) {
dfp = list_last_entry(&tp->t_dfops, dfp = list_last_entry(&tp->t_dfops,
struct xfs_defer_pending, dfp_list); struct xfs_defer_pending, dfp_list);
if (dfp->dfp_type->type != type || ops = defer_op_types[dfp->dfp_type];
(dfp->dfp_type->max_items && if (dfp->dfp_type != type ||
dfp->dfp_count >= dfp->dfp_type->max_items)) (ops->max_items && dfp->dfp_count >= ops->max_items))
dfp = NULL; dfp = NULL;
} }
if (!dfp) { if (!dfp) {
dfp = kmem_alloc(sizeof(struct xfs_defer_pending), dfp = kmem_alloc(sizeof(struct xfs_defer_pending),
KM_SLEEP | KM_NOFS); KM_SLEEP | KM_NOFS);
dfp->dfp_type = defer_op_types[type]; dfp->dfp_type = type;
dfp->dfp_intent = NULL; dfp->dfp_intent = NULL;
dfp->dfp_done = NULL; dfp->dfp_done = NULL;
dfp->dfp_count = 0; dfp->dfp_count = 0;
@ -517,14 +528,6 @@ xfs_defer_add(
dfp->dfp_count++; dfp->dfp_count++;
} }
/* Initialize a deferred operation list. */
void
xfs_defer_init_op_type(
const struct xfs_defer_op_type *type)
{
defer_op_types[type->type] = type;
}
/* /*
* Move deferred ops from one transaction to another and reset the source to * Move deferred ops from one transaction to another and reset the source to
* initial state. This is primarily used to carry state forward across * initial state. This is primarily used to carry state forward across

View File

@ -8,20 +8,6 @@
struct xfs_defer_op_type; struct xfs_defer_op_type;
/*
* Save a log intent item and a list of extents, so that we can replay
* whatever action had to happen to the extent list and file the log done
* item.
*/
struct xfs_defer_pending {
const struct xfs_defer_op_type *dfp_type; /* function pointers */
struct list_head dfp_list; /* pending items */
void *dfp_intent; /* log intent item */
void *dfp_done; /* log done item */
struct list_head dfp_work; /* work items */
unsigned int dfp_count; /* # extent items */
};
/* /*
* Header for deferred operation list. * Header for deferred operation list.
*/ */
@ -34,6 +20,20 @@ enum xfs_defer_ops_type {
XFS_DEFER_OPS_TYPE_MAX, XFS_DEFER_OPS_TYPE_MAX,
}; };
/*
* Save a log intent item and a list of extents, so that we can replay
* whatever action had to happen to the extent list and file the log done
* item.
*/
struct xfs_defer_pending {
struct list_head dfp_list; /* pending items */
struct list_head dfp_work; /* work items */
void *dfp_intent; /* log intent item */
void *dfp_done; /* log done item */
unsigned int dfp_count; /* # extent items */
enum xfs_defer_ops_type dfp_type;
};
void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type, void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type,
struct list_head *h); struct list_head *h);
int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish_noroll(struct xfs_trans **tp);
@ -43,8 +43,6 @@ void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
/* Description of a deferred type. */ /* Description of a deferred type. */
struct xfs_defer_op_type { struct xfs_defer_op_type {
enum xfs_defer_ops_type type;
unsigned int max_items;
void (*abort_intent)(void *); void (*abort_intent)(void *);
void *(*create_done)(struct xfs_trans *, void *, unsigned int); void *(*create_done)(struct xfs_trans *, void *, unsigned int);
int (*finish_item)(struct xfs_trans *, struct list_head *, void *, int (*finish_item)(struct xfs_trans *, struct list_head *, void *,
@ -54,8 +52,13 @@ struct xfs_defer_op_type {
int (*diff_items)(void *, struct list_head *, struct list_head *); int (*diff_items)(void *, struct list_head *, struct list_head *);
void *(*create_intent)(struct xfs_trans *, uint); void *(*create_intent)(struct xfs_trans *, uint);
void (*log_item)(struct xfs_trans *, void *, struct list_head *); void (*log_item)(struct xfs_trans *, void *, struct list_head *);
unsigned int max_items;
}; };
void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); extern const struct xfs_defer_op_type xfs_bmap_update_defer_type;
extern const struct xfs_defer_op_type xfs_refcount_update_defer_type;
extern const struct xfs_defer_op_type xfs_rmap_update_defer_type;
extern const struct xfs_defer_op_type xfs_extent_free_defer_type;
extern const struct xfs_defer_op_type xfs_agfl_free_defer_type;
#endif /* __XFS_DEFER_H__ */ #endif /* __XFS_DEFER_H__ */

View File

@ -916,6 +916,9 @@ static inline uint xfs_dinode_size(int version)
/* /*
* Values for di_format * Values for di_format
*
* This enum is used in string mapping in xfs_trace.h; please keep the
* TRACE_DEFINE_ENUMs for it up to date.
*/ */
typedef enum xfs_dinode_fmt { typedef enum xfs_dinode_fmt {
XFS_DINODE_FMT_DEV, /* xfs_dev_t */ XFS_DINODE_FMT_DEV, /* xfs_dev_t */
@ -925,6 +928,13 @@ typedef enum xfs_dinode_fmt {
XFS_DINODE_FMT_UUID /* added long ago, but never used */ XFS_DINODE_FMT_UUID /* added long ago, but never used */
} xfs_dinode_fmt_t; } xfs_dinode_fmt_t;
#define XFS_INODE_FORMAT_STR \
{ XFS_DINODE_FMT_DEV, "dev" }, \
{ XFS_DINODE_FMT_LOCAL, "local" }, \
{ XFS_DINODE_FMT_EXTENTS, "extent" }, \
{ XFS_DINODE_FMT_BTREE, "btree" }, \
{ XFS_DINODE_FMT_UUID, "uuid" }
/* /*
* Inode minimum and maximum sizes. * Inode minimum and maximum sizes.
*/ */
@ -1083,6 +1093,8 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
((i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp))) ((i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp)))
#define XFS_OFFBNO_TO_AGINO(mp,b,o) \ #define XFS_OFFBNO_TO_AGINO(mp,b,o) \
((xfs_agino_t)(((b) << XFS_INO_OFFSET_BITS(mp)) | (o))) ((xfs_agino_t)(((b) << XFS_INO_OFFSET_BITS(mp)) | (o)))
#define XFS_FSB_TO_INO(mp, b) ((xfs_ino_t)((b) << XFS_INO_OFFSET_BITS(mp)))
#define XFS_AGB_TO_AGINO(mp, b) ((xfs_agino_t)((b) << XFS_INO_OFFSET_BITS(mp)))
#define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 56) - 1ULL)) #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 56) - 1ULL))
#define XFS_MAXINUMBER_32 ((xfs_ino_t)((1ULL << 32) - 1ULL)) #define XFS_MAXINUMBER_32 ((xfs_ino_t)((1ULL << 32) - 1ULL))

View File

@ -288,7 +288,7 @@ xfs_ialloc_inode_init(
{ {
struct xfs_buf *fbuf; struct xfs_buf *fbuf;
struct xfs_dinode *free; struct xfs_dinode *free;
int nbufs, blks_per_cluster, inodes_per_cluster; int nbufs;
int version; int version;
int i, j; int i, j;
xfs_daddr_t d; xfs_daddr_t d;
@ -299,9 +299,7 @@ xfs_ialloc_inode_init(
* sizes, manipulate the inodes in buffers which are multiples of the * sizes, manipulate the inodes in buffers which are multiples of the
* blocks size. * blocks size.
*/ */
blks_per_cluster = xfs_icluster_size_fsb(mp); nbufs = length / mp->m_blocks_per_cluster;
inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog;
nbufs = length / blks_per_cluster;
/* /*
* Figure out what version number to use in the inodes we create. If * Figure out what version number to use in the inodes we create. If
@ -312,7 +310,7 @@ xfs_ialloc_inode_init(
* *
* For v3 inodes, we also need to write the inode number into the inode, * For v3 inodes, we also need to write the inode number into the inode,
* so calculate the first inode number of the chunk here as * so calculate the first inode number of the chunk here as
* XFS_OFFBNO_TO_AGINO() only works within a filesystem block, not * XFS_AGB_TO_AGINO() only works within a filesystem block, not
* across multiple filesystem blocks (such as a cluster) and so cannot * across multiple filesystem blocks (such as a cluster) and so cannot
* be used in the cluster buffer loop below. * be used in the cluster buffer loop below.
* *
@ -324,8 +322,7 @@ xfs_ialloc_inode_init(
*/ */
if (xfs_sb_version_hascrc(&mp->m_sb)) { if (xfs_sb_version_hascrc(&mp->m_sb)) {
version = 3; version = 3;
ino = XFS_AGINO_TO_INO(mp, agno, ino = XFS_AGINO_TO_INO(mp, agno, XFS_AGB_TO_AGINO(mp, agbno));
XFS_OFFBNO_TO_AGINO(mp, agbno, 0));
/* /*
* log the initialisation that is about to take place as an * log the initialisation that is about to take place as an
@ -345,9 +342,10 @@ xfs_ialloc_inode_init(
/* /*
* Get the block. * Get the block.
*/ */
d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster)); d = XFS_AGB_TO_DADDR(mp, agno, agbno +
(j * mp->m_blocks_per_cluster));
fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
mp->m_bsize * blks_per_cluster, mp->m_bsize * mp->m_blocks_per_cluster,
XBF_UNMAPPED); XBF_UNMAPPED);
if (!fbuf) if (!fbuf)
return -ENOMEM; return -ENOMEM;
@ -355,7 +353,7 @@ xfs_ialloc_inode_init(
/* Initialize the inode buffers and log them appropriately. */ /* Initialize the inode buffers and log them appropriately. */
fbuf->b_ops = &xfs_inode_buf_ops; fbuf->b_ops = &xfs_inode_buf_ops;
xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length)); xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length));
for (i = 0; i < inodes_per_cluster; i++) { for (i = 0; i < mp->m_inodes_per_cluster; i++) {
int ioffset = i << mp->m_sb.sb_inodelog; int ioffset = i << mp->m_sb.sb_inodelog;
uint isize = xfs_dinode_size(version); uint isize = xfs_dinode_size(version);
@ -445,7 +443,7 @@ xfs_align_sparse_ino(
return; return;
/* calculate the inode offset and align startino */ /* calculate the inode offset and align startino */
offset = mod << mp->m_sb.sb_inopblog; offset = XFS_AGB_TO_AGINO(mp, mod);
*startino -= offset; *startino -= offset;
/* /*
@ -641,7 +639,7 @@ xfs_ialloc_ag_alloc(
args.tp = tp; args.tp = tp;
args.mp = tp->t_mountp; args.mp = tp->t_mountp;
args.fsbno = NULLFSBLOCK; args.fsbno = NULLFSBLOCK;
xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INODES); args.oinfo = XFS_RMAP_OINFO_INODES;
#ifdef DEBUG #ifdef DEBUG
/* randomly do sparse inode allocations */ /* randomly do sparse inode allocations */
@ -692,7 +690,7 @@ xfs_ialloc_ag_alloc(
* but not to use them in the actual exact allocation. * but not to use them in the actual exact allocation.
*/ */
args.alignment = 1; args.alignment = 1;
args.minalignslop = xfs_ialloc_cluster_alignment(args.mp) - 1; args.minalignslop = args.mp->m_cluster_align - 1;
/* Allow space for the inode btree to split. */ /* Allow space for the inode btree to split. */
args.minleft = args.mp->m_in_maxlevels - 1; args.minleft = args.mp->m_in_maxlevels - 1;
@ -727,7 +725,7 @@ xfs_ialloc_ag_alloc(
args.alignment = args.mp->m_dalign; args.alignment = args.mp->m_dalign;
isaligned = 1; isaligned = 1;
} else } else
args.alignment = xfs_ialloc_cluster_alignment(args.mp); args.alignment = args.mp->m_cluster_align;
/* /*
* Need to figure out where to allocate the inode blocks. * Need to figure out where to allocate the inode blocks.
* Ideally they should be spaced out through the a.g. * Ideally they should be spaced out through the a.g.
@ -756,7 +754,7 @@ xfs_ialloc_ag_alloc(
args.type = XFS_ALLOCTYPE_NEAR_BNO; args.type = XFS_ALLOCTYPE_NEAR_BNO;
args.agbno = be32_to_cpu(agi->agi_root); args.agbno = be32_to_cpu(agi->agi_root);
args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno); args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
args.alignment = xfs_ialloc_cluster_alignment(args.mp); args.alignment = args.mp->m_cluster_align;
if ((error = xfs_alloc_vextent(&args))) if ((error = xfs_alloc_vextent(&args)))
return error; return error;
} }
@ -797,7 +795,7 @@ sparse_alloc:
if (error) if (error)
return error; return error;
newlen = args.len << args.mp->m_sb.sb_inopblog; newlen = XFS_AGB_TO_AGINO(args.mp, args.len);
ASSERT(newlen <= XFS_INODES_PER_CHUNK); ASSERT(newlen <= XFS_INODES_PER_CHUNK);
allocmask = (1 << (newlen / XFS_INODES_PER_HOLEMASK_BIT)) - 1; allocmask = (1 << (newlen / XFS_INODES_PER_HOLEMASK_BIT)) - 1;
} }
@ -825,7 +823,7 @@ sparse_alloc:
/* /*
* Convert the results. * Convert the results.
*/ */
newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0); newino = XFS_AGB_TO_AGINO(args.mp, args.agbno);
if (xfs_inobt_issparse(~allocmask)) { if (xfs_inobt_issparse(~allocmask)) {
/* /*
@ -1019,7 +1017,7 @@ xfs_ialloc_ag_select(
*/ */
ineed = mp->m_ialloc_min_blks; ineed = mp->m_ialloc_min_blks;
if (flags && ineed > 1) if (flags && ineed > 1)
ineed += xfs_ialloc_cluster_alignment(mp); ineed += mp->m_cluster_align;
longest = pag->pagf_longest; longest = pag->pagf_longest;
if (!longest) if (!longest)
longest = pag->pagf_flcount > 0; longest = pag->pagf_flcount > 0;
@ -1849,14 +1847,12 @@ xfs_difree_inode_chunk(
int nextbit; int nextbit;
xfs_agblock_t agbno; xfs_agblock_t agbno;
int contigblk; int contigblk;
struct xfs_owner_info oinfo;
DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS); DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
if (!xfs_inobt_issparse(rec->ir_holemask)) { if (!xfs_inobt_issparse(rec->ir_holemask)) {
/* not sparse, calculate extent info directly */ /* not sparse, calculate extent info directly */
xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, sagbno), xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, sagbno),
mp->m_ialloc_blks, &oinfo); mp->m_ialloc_blks, &XFS_RMAP_OINFO_INODES);
return; return;
} }
@ -1900,7 +1896,7 @@ xfs_difree_inode_chunk(
ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(agbno % mp->m_sb.sb_spino_align == 0);
ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0);
xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, agbno), xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, agbno),
contigblk, &oinfo); contigblk, &XFS_RMAP_OINFO_INODES);
/* reset range to current bit and carry on... */ /* reset range to current bit and carry on... */
startidx = endidx = nextbit; startidx = endidx = nextbit;
@ -2292,7 +2288,6 @@ xfs_imap(
xfs_agblock_t agbno; /* block number of inode in the alloc group */ xfs_agblock_t agbno; /* block number of inode in the alloc group */
xfs_agino_t agino; /* inode number within alloc group */ xfs_agino_t agino; /* inode number within alloc group */
xfs_agnumber_t agno; /* allocation group number */ xfs_agnumber_t agno; /* allocation group number */
int blks_per_cluster; /* num blocks per inode cluster */
xfs_agblock_t chunk_agbno; /* first block in inode chunk */ xfs_agblock_t chunk_agbno; /* first block in inode chunk */
xfs_agblock_t cluster_agbno; /* first block in inode cluster */ xfs_agblock_t cluster_agbno; /* first block in inode cluster */
int error; /* error code */ int error; /* error code */
@ -2338,8 +2333,6 @@ xfs_imap(
return -EINVAL; return -EINVAL;
} }
blks_per_cluster = xfs_icluster_size_fsb(mp);
/* /*
* For bulkstat and handle lookups, we have an untrusted inode number * For bulkstat and handle lookups, we have an untrusted inode number
* that we have to verify is valid. We cannot do this just by reading * that we have to verify is valid. We cannot do this just by reading
@ -2359,7 +2352,7 @@ xfs_imap(
* If the inode cluster size is the same as the blocksize or * If the inode cluster size is the same as the blocksize or
* smaller we get to the buffer by simple arithmetics. * smaller we get to the buffer by simple arithmetics.
*/ */
if (blks_per_cluster == 1) { if (mp->m_blocks_per_cluster == 1) {
offset = XFS_INO_TO_OFFSET(mp, ino); offset = XFS_INO_TO_OFFSET(mp, ino);
ASSERT(offset < mp->m_sb.sb_inopblock); ASSERT(offset < mp->m_sb.sb_inopblock);
@ -2388,12 +2381,13 @@ xfs_imap(
out_map: out_map:
ASSERT(agbno >= chunk_agbno); ASSERT(agbno >= chunk_agbno);
cluster_agbno = chunk_agbno + cluster_agbno = chunk_agbno +
((offset_agbno / blks_per_cluster) * blks_per_cluster); ((offset_agbno / mp->m_blocks_per_cluster) *
mp->m_blocks_per_cluster);
offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) + offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
XFS_INO_TO_OFFSET(mp, ino); XFS_INO_TO_OFFSET(mp, ino);
imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno); imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno);
imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster); imap->im_len = XFS_FSB_TO_BB(mp, mp->m_blocks_per_cluster);
imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog); imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog);
/* /*
@ -2726,8 +2720,8 @@ xfs_ialloc_has_inodes_at_extent(
xfs_agino_t low; xfs_agino_t low;
xfs_agino_t high; xfs_agino_t high;
low = XFS_OFFBNO_TO_AGINO(cur->bc_mp, bno, 0); low = XFS_AGB_TO_AGINO(cur->bc_mp, bno);
high = XFS_OFFBNO_TO_AGINO(cur->bc_mp, bno + len, 0) - 1; high = XFS_AGB_TO_AGINO(cur->bc_mp, bno + len) - 1;
return xfs_ialloc_has_inode_record(cur, low, high, exists); return xfs_ialloc_has_inode_record(cur, low, high, exists);
} }

View File

@ -84,7 +84,7 @@ __xfs_inobt_alloc_block(
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.tp = cur->bc_tp; args.tp = cur->bc_tp;
args.mp = cur->bc_mp; args.mp = cur->bc_mp;
xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INOBT); args.oinfo = XFS_RMAP_OINFO_INOBT;
args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno);
args.minlen = 1; args.minlen = 1;
args.maxlen = 1; args.maxlen = 1;
@ -136,12 +136,9 @@ __xfs_inobt_free_block(
struct xfs_buf *bp, struct xfs_buf *bp,
enum xfs_ag_resv_type resv) enum xfs_ag_resv_type resv)
{ {
struct xfs_owner_info oinfo;
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT);
return xfs_free_extent(cur->bc_tp, return xfs_free_extent(cur->bc_tp,
XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1, XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
&oinfo, resv); &XFS_RMAP_OINFO_INOBT, resv);
} }
STATIC int STATIC int

View File

@ -70,7 +70,7 @@ xfs_refcountbt_alloc_block(
args.type = XFS_ALLOCTYPE_NEAR_BNO; args.type = XFS_ALLOCTYPE_NEAR_BNO;
args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno,
xfs_refc_block(args.mp)); xfs_refc_block(args.mp));
xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); args.oinfo = XFS_RMAP_OINFO_REFC;
args.minlen = args.maxlen = args.prod = 1; args.minlen = args.maxlen = args.prod = 1;
args.resv = XFS_AG_RESV_METADATA; args.resv = XFS_AG_RESV_METADATA;
@ -106,15 +106,13 @@ xfs_refcountbt_free_block(
struct xfs_buf *agbp = cur->bc_private.a.agbp; struct xfs_buf *agbp = cur->bc_private.a.agbp;
struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
struct xfs_owner_info oinfo;
int error; int error;
trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno,
XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC);
be32_add_cpu(&agf->agf_refcount_blocks, -1); be32_add_cpu(&agf->agf_refcount_blocks, -1);
xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS);
error = xfs_free_extent(cur->bc_tp, fsbno, 1, &oinfo, error = xfs_free_extent(cur->bc_tp, fsbno, 1, &XFS_RMAP_OINFO_REFC,
XFS_AG_RESV_METADATA); XFS_AG_RESV_METADATA);
if (error) if (error)
return error; return error;

View File

@ -458,21 +458,21 @@ out:
*/ */
STATIC int STATIC int
xfs_rmap_unmap( xfs_rmap_unmap(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
bool unwritten, bool unwritten,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
struct xfs_rmap_irec ltrec; struct xfs_rmap_irec ltrec;
uint64_t ltoff; uint64_t ltoff;
int error = 0; int error = 0;
int i; int i;
uint64_t owner; uint64_t owner;
uint64_t offset; uint64_t offset;
unsigned int flags; unsigned int flags;
bool ignore_off; bool ignore_off;
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
@ -653,16 +653,16 @@ out_error:
*/ */
int int
xfs_rmap_free( xfs_rmap_free(
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_buf *agbp, struct xfs_buf *agbp,
xfs_agnumber_t agno, xfs_agnumber_t agno,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
int error; int error;
if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
return 0; return 0;
@ -710,23 +710,23 @@ xfs_rmap_is_mergeable(
*/ */
STATIC int STATIC int
xfs_rmap_map( xfs_rmap_map(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
bool unwritten, bool unwritten,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
struct xfs_rmap_irec ltrec; struct xfs_rmap_irec ltrec;
struct xfs_rmap_irec gtrec; struct xfs_rmap_irec gtrec;
int have_gt; int have_gt;
int have_lt; int have_lt;
int error = 0; int error = 0;
int i; int i;
uint64_t owner; uint64_t owner;
uint64_t offset; uint64_t offset;
unsigned int flags = 0; unsigned int flags = 0;
bool ignore_off; bool ignore_off;
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
ASSERT(owner != 0); ASSERT(owner != 0);
@ -890,16 +890,16 @@ out_error:
*/ */
int int
xfs_rmap_alloc( xfs_rmap_alloc(
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_buf *agbp, struct xfs_buf *agbp,
xfs_agnumber_t agno, xfs_agnumber_t agno,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
int error; int error;
if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
return 0; return 0;
@ -929,16 +929,16 @@ xfs_rmap_alloc(
*/ */
STATIC int STATIC int
xfs_rmap_convert( xfs_rmap_convert(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
bool unwritten, bool unwritten,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
struct xfs_rmap_irec r[4]; /* neighbor extent entries */ struct xfs_rmap_irec r[4]; /* neighbor extent entries */
/* left is 0, right is 1, prev is 2 */ /* left is 0, right is 1, */
/* new is 3 */ /* prev is 2, new is 3 */
uint64_t owner; uint64_t owner;
uint64_t offset; uint64_t offset;
uint64_t new_endoff; uint64_t new_endoff;
@ -1354,16 +1354,16 @@ done:
*/ */
STATIC int STATIC int
xfs_rmap_convert_shared( xfs_rmap_convert_shared(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
bool unwritten, bool unwritten,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
struct xfs_rmap_irec r[4]; /* neighbor extent entries */ struct xfs_rmap_irec r[4]; /* neighbor extent entries */
/* left is 0, right is 1, prev is 2 */ /* left is 0, right is 1, */
/* new is 3 */ /* prev is 2, new is 3 */
uint64_t owner; uint64_t owner;
uint64_t offset; uint64_t offset;
uint64_t new_endoff; uint64_t new_endoff;
@ -1743,20 +1743,20 @@ done:
*/ */
STATIC int STATIC int
xfs_rmap_unmap_shared( xfs_rmap_unmap_shared(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
bool unwritten, bool unwritten,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
struct xfs_rmap_irec ltrec; struct xfs_rmap_irec ltrec;
uint64_t ltoff; uint64_t ltoff;
int error = 0; int error = 0;
int i; int i;
uint64_t owner; uint64_t owner;
uint64_t offset; uint64_t offset;
unsigned int flags; unsigned int flags;
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
if (unwritten) if (unwritten)
@ -1905,22 +1905,22 @@ out_error:
*/ */
STATIC int STATIC int
xfs_rmap_map_shared( xfs_rmap_map_shared(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
bool unwritten, bool unwritten,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
struct xfs_rmap_irec ltrec; struct xfs_rmap_irec ltrec;
struct xfs_rmap_irec gtrec; struct xfs_rmap_irec gtrec;
int have_gt; int have_gt;
int have_lt; int have_lt;
int error = 0; int error = 0;
int i; int i;
uint64_t owner; uint64_t owner;
uint64_t offset; uint64_t offset;
unsigned int flags = 0; unsigned int flags = 0;
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
if (unwritten) if (unwritten)
@ -2459,18 +2459,18 @@ xfs_rmap_has_record(
*/ */
int int
xfs_rmap_record_exists( xfs_rmap_record_exists(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
bool *has_rmap) bool *has_rmap)
{ {
uint64_t owner; uint64_t owner;
uint64_t offset; uint64_t offset;
unsigned int flags; unsigned int flags;
int has_record; int has_record;
struct xfs_rmap_irec irec; struct xfs_rmap_irec irec;
int error; int error;
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) || ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
@ -2530,7 +2530,7 @@ xfs_rmap_has_other_keys(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
bool *has_rmap) bool *has_rmap)
{ {
struct xfs_rmap_irec low = {0}; struct xfs_rmap_irec low = {0};
@ -2550,3 +2550,31 @@ xfs_rmap_has_other_keys(
*has_rmap = rks.has_rmap; *has_rmap = rks.has_rmap;
return error; return error;
} }
const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
.oi_owner = XFS_RMAP_OWN_NULL,
};
const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
.oi_owner = XFS_RMAP_OWN_UNKNOWN,
};
const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
.oi_owner = XFS_RMAP_OWN_FS,
};
const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
.oi_owner = XFS_RMAP_OWN_LOG,
};
const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
.oi_owner = XFS_RMAP_OWN_AG,
};
const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
.oi_owner = XFS_RMAP_OWN_INOBT,
};
const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
.oi_owner = XFS_RMAP_OWN_INODES,
};
const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
.oi_owner = XFS_RMAP_OWN_REFC,
};
const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
.oi_owner = XFS_RMAP_OWN_COW,
};

View File

@ -6,16 +6,6 @@
#ifndef __XFS_RMAP_H__ #ifndef __XFS_RMAP_H__
#define __XFS_RMAP_H__ #define __XFS_RMAP_H__
static inline void
xfs_rmap_ag_owner(
struct xfs_owner_info *oi,
uint64_t owner)
{
oi->oi_owner = owner;
oi->oi_offset = 0;
oi->oi_flags = 0;
}
static inline void static inline void
xfs_rmap_ino_bmbt_owner( xfs_rmap_ino_bmbt_owner(
struct xfs_owner_info *oi, struct xfs_owner_info *oi,
@ -43,27 +33,13 @@ xfs_rmap_ino_owner(
oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
} }
static inline void
xfs_rmap_skip_owner_update(
struct xfs_owner_info *oi)
{
xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_NULL);
}
static inline bool static inline bool
xfs_rmap_should_skip_owner_update( xfs_rmap_should_skip_owner_update(
struct xfs_owner_info *oi) const struct xfs_owner_info *oi)
{ {
return oi->oi_owner == XFS_RMAP_OWN_NULL; return oi->oi_owner == XFS_RMAP_OWN_NULL;
} }
static inline void
xfs_rmap_any_owner_update(
struct xfs_owner_info *oi)
{
xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_UNKNOWN);
}
/* Reverse mapping functions. */ /* Reverse mapping functions. */
struct xfs_buf; struct xfs_buf;
@ -103,12 +79,12 @@ xfs_rmap_irec_offset_unpack(
static inline void static inline void
xfs_owner_info_unpack( xfs_owner_info_unpack(
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
uint64_t *owner, uint64_t *owner,
uint64_t *offset, uint64_t *offset,
unsigned int *flags) unsigned int *flags)
{ {
unsigned int r = 0; unsigned int r = 0;
*owner = oinfo->oi_owner; *owner = oinfo->oi_owner;
*offset = oinfo->oi_offset; *offset = oinfo->oi_offset;
@ -137,10 +113,10 @@ xfs_owner_info_pack(
int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp,
xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
struct xfs_owner_info *oinfo); const struct xfs_owner_info *oinfo);
int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp, int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp,
xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
struct xfs_owner_info *oinfo); const struct xfs_owner_info *oinfo);
int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, uint64_t owner, uint64_t offset, xfs_extlen_t len, uint64_t owner, uint64_t offset,
@ -218,11 +194,21 @@ int xfs_rmap_btrec_to_irec(union xfs_btree_rec *rec,
int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, bool *exists); xfs_extlen_t len, bool *exists);
int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, struct xfs_owner_info *oinfo, xfs_extlen_t len, const struct xfs_owner_info *oinfo,
bool *has_rmap); bool *has_rmap);
int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, struct xfs_owner_info *oinfo, xfs_extlen_t len, const struct xfs_owner_info *oinfo,
bool *has_rmap); bool *has_rmap);
int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap); int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap);
extern const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE;
extern const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER;
extern const struct xfs_owner_info XFS_RMAP_OINFO_FS;
extern const struct xfs_owner_info XFS_RMAP_OINFO_LOG;
extern const struct xfs_owner_info XFS_RMAP_OINFO_AG;
extern const struct xfs_owner_info XFS_RMAP_OINFO_INOBT;
extern const struct xfs_owner_info XFS_RMAP_OINFO_INODES;
extern const struct xfs_owner_info XFS_RMAP_OINFO_REFC;
extern const struct xfs_owner_info XFS_RMAP_OINFO_COW;
#endif /* __XFS_RMAP_H__ */ #endif /* __XFS_RMAP_H__ */

View File

@ -505,6 +505,12 @@ xfs_rtmodify_summary_int(
uint first = (uint)((char *)sp - (char *)bp->b_addr); uint first = (uint)((char *)sp - (char *)bp->b_addr);
*sp += delta; *sp += delta;
if (mp->m_rsum_cache) {
if (*sp == 0 && log == mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno]++;
if (*sp != 0 && log < mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno] = log;
}
xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1); xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
} }
if (sum) if (sum)

View File

@ -199,7 +199,10 @@ xfs_symlink_local_to_remote(
ifp->if_bytes - 1); ifp->if_bytes - 1);
} }
/* Verify the consistency of an inline symlink. */ /*
* Verify the in-memory consistency of an inline symlink data fork. This
* does not do on-disk format checks.
*/
xfs_failaddr_t xfs_failaddr_t
xfs_symlink_shortform_verify( xfs_symlink_shortform_verify(
struct xfs_inode *ip) struct xfs_inode *ip)
@ -215,9 +218,12 @@ xfs_symlink_shortform_verify(
size = ifp->if_bytes; size = ifp->if_bytes;
endp = sfp + size; endp = sfp + size;
/* Zero length symlinks can exist while we're deleting a remote one. */ /*
if (size == 0) * Zero length symlinks should never occur in memory as they are
return NULL; * never alllowed to exist on disk.
*/
if (!size)
return __this_address;
/* No negative sizes or overly long symlink targets. */ /* No negative sizes or overly long symlink targets. */
if (size < 0 || size > XFS_SYMLINK_MAXLEN) if (size < 0 || size > XFS_SYMLINK_MAXLEN)

View File

@ -87,16 +87,15 @@ xfs_agino_range(
* Calculate the first inode, which will be in the first * Calculate the first inode, which will be in the first
* cluster-aligned block after the AGFL. * cluster-aligned block after the AGFL.
*/ */
bno = round_up(XFS_AGFL_BLOCK(mp) + 1, bno = round_up(XFS_AGFL_BLOCK(mp) + 1, mp->m_cluster_align);
xfs_ialloc_cluster_alignment(mp)); *first = XFS_AGB_TO_AGINO(mp, bno);
*first = XFS_OFFBNO_TO_AGINO(mp, bno, 0);
/* /*
* Calculate the last inode, which will be at the end of the * Calculate the last inode, which will be at the end of the
* last (aligned) cluster that can be allocated in the AG. * last (aligned) cluster that can be allocated in the AG.
*/ */
bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp)); bno = round_down(eoag, mp->m_cluster_align);
*last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1; *last = XFS_AGB_TO_AGINO(mp, bno) - 1;
} }
/* /*

View File

@ -100,15 +100,37 @@ typedef void * xfs_failaddr_t;
*/ */
#define MAXNAMELEN 256 #define MAXNAMELEN 256
/*
* This enum is used in string mapping in xfs_trace.h; please keep the
* TRACE_DEFINE_ENUMs for it up to date.
*/
typedef enum { typedef enum {
XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
} xfs_lookup_t; } xfs_lookup_t;
#define XFS_AG_BTREE_CMP_FORMAT_STR \
{ XFS_LOOKUP_EQi, "eq" }, \
{ XFS_LOOKUP_LEi, "le" }, \
{ XFS_LOOKUP_GEi, "ge" }
/*
* This enum is used in string mapping in xfs_trace.h and scrub/trace.h;
* please keep the TRACE_DEFINE_ENUMs for it up to date.
*/
typedef enum { typedef enum {
XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi, XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi,
XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_MAX XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_MAX
} xfs_btnum_t; } xfs_btnum_t;
#define XFS_BTNUM_STRINGS \
{ XFS_BTNUM_BNOi, "bnobt" }, \
{ XFS_BTNUM_CNTi, "cntbt" }, \
{ XFS_BTNUM_RMAPi, "rmapbt" }, \
{ XFS_BTNUM_BMAPi, "bmbt" }, \
{ XFS_BTNUM_INOi, "inobt" }, \
{ XFS_BTNUM_FINOi, "finobt" }, \
{ XFS_BTNUM_REFCi, "refcbt" }
struct xfs_name { struct xfs_name {
const unsigned char *name; const unsigned char *name;
int len; int len;

View File

@ -32,7 +32,6 @@ xchk_superblock_xref(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_owner_info oinfo;
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
xfs_agnumber_t agno = sc->sm->sm_agno; xfs_agnumber_t agno = sc->sm->sm_agno;
xfs_agblock_t agbno; xfs_agblock_t agbno;
@ -49,8 +48,7 @@ xchk_superblock_xref(
xchk_xref_is_used_space(sc, agbno, 1); xchk_xref_is_used_space(sc, agbno, 1);
xchk_xref_is_not_inode_chunk(sc, agbno, 1); xchk_xref_is_not_inode_chunk(sc, agbno, 1);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
xchk_xref_is_not_shared(sc, agbno, 1); xchk_xref_is_not_shared(sc, agbno, 1);
/* scrub teardown will take care of sc->sa for us */ /* scrub teardown will take care of sc->sa for us */
@ -484,7 +482,6 @@ STATIC void
xchk_agf_xref( xchk_agf_xref(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_owner_info oinfo;
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
xfs_agblock_t agbno; xfs_agblock_t agbno;
int error; int error;
@ -502,8 +499,7 @@ xchk_agf_xref(
xchk_agf_xref_freeblks(sc); xchk_agf_xref_freeblks(sc);
xchk_agf_xref_cntbt(sc); xchk_agf_xref_cntbt(sc);
xchk_xref_is_not_inode_chunk(sc, agbno, 1); xchk_xref_is_not_inode_chunk(sc, agbno, 1);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
xchk_agf_xref_btreeblks(sc); xchk_agf_xref_btreeblks(sc);
xchk_xref_is_not_shared(sc, agbno, 1); xchk_xref_is_not_shared(sc, agbno, 1);
xchk_agf_xref_refcblks(sc); xchk_agf_xref_refcblks(sc);
@ -598,7 +594,6 @@ out:
/* AGFL */ /* AGFL */
struct xchk_agfl_info { struct xchk_agfl_info {
struct xfs_owner_info oinfo;
unsigned int sz_entries; unsigned int sz_entries;
unsigned int nr_entries; unsigned int nr_entries;
xfs_agblock_t *entries; xfs_agblock_t *entries;
@ -609,15 +604,14 @@ struct xchk_agfl_info {
STATIC void STATIC void
xchk_agfl_block_xref( xchk_agfl_block_xref(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_agblock_t agbno, xfs_agblock_t agbno)
struct xfs_owner_info *oinfo)
{ {
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
return; return;
xchk_xref_is_used_space(sc, agbno, 1); xchk_xref_is_used_space(sc, agbno, 1);
xchk_xref_is_not_inode_chunk(sc, agbno, 1); xchk_xref_is_not_inode_chunk(sc, agbno, 1);
xchk_xref_is_owned_by(sc, agbno, 1, oinfo); xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG);
xchk_xref_is_not_shared(sc, agbno, 1); xchk_xref_is_not_shared(sc, agbno, 1);
} }
@ -638,7 +632,7 @@ xchk_agfl_block(
else else
xchk_block_set_corrupt(sc, sc->sa.agfl_bp); xchk_block_set_corrupt(sc, sc->sa.agfl_bp);
xchk_agfl_block_xref(sc, agbno, priv); xchk_agfl_block_xref(sc, agbno);
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
return XFS_BTREE_QUERY_RANGE_ABORT; return XFS_BTREE_QUERY_RANGE_ABORT;
@ -662,7 +656,6 @@ STATIC void
xchk_agfl_xref( xchk_agfl_xref(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_owner_info oinfo;
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
xfs_agblock_t agbno; xfs_agblock_t agbno;
int error; int error;
@ -678,8 +671,7 @@ xchk_agfl_xref(
xchk_xref_is_used_space(sc, agbno, 1); xchk_xref_is_used_space(sc, agbno, 1);
xchk_xref_is_not_inode_chunk(sc, agbno, 1); xchk_xref_is_not_inode_chunk(sc, agbno, 1);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
xchk_xref_is_not_shared(sc, agbno, 1); xchk_xref_is_not_shared(sc, agbno, 1);
/* /*
@ -732,7 +724,6 @@ xchk_agfl(
} }
/* Check the blocks in the AGFL. */ /* Check the blocks in the AGFL. */
xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG);
error = xfs_agfl_walk(sc->mp, XFS_BUF_TO_AGF(sc->sa.agf_bp), error = xfs_agfl_walk(sc->mp, XFS_BUF_TO_AGF(sc->sa.agf_bp),
sc->sa.agfl_bp, xchk_agfl_block, &sai); sc->sa.agfl_bp, xchk_agfl_block, &sai);
if (error == XFS_BTREE_QUERY_RANGE_ABORT) { if (error == XFS_BTREE_QUERY_RANGE_ABORT) {
@ -791,7 +782,6 @@ STATIC void
xchk_agi_xref( xchk_agi_xref(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_owner_info oinfo;
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
xfs_agblock_t agbno; xfs_agblock_t agbno;
int error; int error;
@ -808,8 +798,7 @@ xchk_agi_xref(
xchk_xref_is_used_space(sc, agbno, 1); xchk_xref_is_used_space(sc, agbno, 1);
xchk_xref_is_not_inode_chunk(sc, agbno, 1); xchk_xref_is_not_inode_chunk(sc, agbno, 1);
xchk_agi_xref_icounts(sc); xchk_agi_xref_icounts(sc);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
xchk_xref_is_not_shared(sc, agbno, 1); xchk_xref_is_not_shared(sc, agbno, 1);
/* scrub teardown will take care of sc->sa for us */ /* scrub teardown will take care of sc->sa for us */

View File

@ -646,7 +646,6 @@ int
xrep_agfl( xrep_agfl(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_owner_info oinfo;
struct xfs_bitmap agfl_extents; struct xfs_bitmap agfl_extents;
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
struct xfs_buf *agf_bp; struct xfs_buf *agf_bp;
@ -708,8 +707,8 @@ xrep_agfl(
goto err; goto err;
/* Dump any AGFL overflow. */ /* Dump any AGFL overflow. */
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG); return xrep_reap_extents(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
return xrep_reap_extents(sc, &agfl_extents, &oinfo, XFS_AG_RESV_AGFL); XFS_AG_RESV_AGFL);
err: err:
xfs_bitmap_destroy(&agfl_extents); xfs_bitmap_destroy(&agfl_extents);
return error; return error;

View File

@ -125,12 +125,10 @@ xchk_allocbt(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_btnum_t which) xfs_btnum_t which)
{ {
struct xfs_owner_info oinfo;
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
cur = which == XFS_BTNUM_BNO ? sc->sa.bno_cur : sc->sa.cnt_cur; cur = which == XFS_BTNUM_BNO ? sc->sa.bno_cur : sc->sa.cnt_cur;
return xchk_btree(sc, cur, xchk_allocbt_rec, &oinfo, NULL); return xchk_btree(sc, cur, xchk_allocbt_rec, &XFS_RMAP_OINFO_AG, NULL);
} }
int int

View File

@ -583,31 +583,32 @@ xchk_btree_block_keys(
*/ */
int int
xchk_btree( xchk_btree(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
xchk_btree_rec_fn scrub_fn, xchk_btree_rec_fn scrub_fn,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
void *private) void *private)
{ {
struct xchk_btree bs = { NULL }; struct xchk_btree bs = {
union xfs_btree_ptr ptr; .cur = cur,
union xfs_btree_ptr *pp; .scrub_rec = scrub_fn,
union xfs_btree_rec *recp; .oinfo = oinfo,
struct xfs_btree_block *block; .firstrec = true,
int level; .private = private,
struct xfs_buf *bp; .sc = sc,
struct check_owner *co; };
struct check_owner *n; union xfs_btree_ptr ptr;
int i; union xfs_btree_ptr *pp;
int error = 0; union xfs_btree_rec *recp;
struct xfs_btree_block *block;
int level;
struct xfs_buf *bp;
struct check_owner *co;
struct check_owner *n;
int i;
int error = 0;
/* Initialize scrub state */ /* Initialize scrub state */
bs.cur = cur;
bs.scrub_rec = scrub_fn;
bs.oinfo = oinfo;
bs.firstrec = true;
bs.private = private;
bs.sc = sc;
for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) for (i = 0; i < XFS_BTREE_MAXLEVELS; i++)
bs.firstkey[i] = true; bs.firstkey[i] = true;
INIT_LIST_HEAD(&bs.to_check); INIT_LIST_HEAD(&bs.to_check);

View File

@ -31,21 +31,21 @@ typedef int (*xchk_btree_rec_fn)(
struct xchk_btree { struct xchk_btree {
/* caller-provided scrub state */ /* caller-provided scrub state */
struct xfs_scrub *sc; struct xfs_scrub *sc;
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
xchk_btree_rec_fn scrub_rec; xchk_btree_rec_fn scrub_rec;
struct xfs_owner_info *oinfo; const struct xfs_owner_info *oinfo;
void *private; void *private;
/* internal scrub state */ /* internal scrub state */
union xfs_btree_rec lastrec; union xfs_btree_rec lastrec;
bool firstrec; bool firstrec;
union xfs_btree_key lastkey[XFS_BTREE_MAXLEVELS]; union xfs_btree_key lastkey[XFS_BTREE_MAXLEVELS];
bool firstkey[XFS_BTREE_MAXLEVELS]; bool firstkey[XFS_BTREE_MAXLEVELS];
struct list_head to_check; struct list_head to_check;
}; };
int xchk_btree(struct xfs_scrub *sc, struct xfs_btree_cur *cur, int xchk_btree(struct xfs_scrub *sc, struct xfs_btree_cur *cur,
xchk_btree_rec_fn scrub_fn, struct xfs_owner_info *oinfo, xchk_btree_rec_fn scrub_fn, const struct xfs_owner_info *oinfo,
void *private); void *private);
#endif /* __XFS_SCRUB_BTREE_H__ */ #endif /* __XFS_SCRUB_BTREE_H__ */

View File

@ -313,8 +313,8 @@ xchk_set_incomplete(
*/ */
struct xchk_rmap_ownedby_info { struct xchk_rmap_ownedby_info {
struct xfs_owner_info *oinfo; const struct xfs_owner_info *oinfo;
xfs_filblks_t *blocks; xfs_filblks_t *blocks;
}; };
STATIC int STATIC int
@ -347,15 +347,15 @@ int
xchk_count_rmap_ownedby_ag( xchk_count_rmap_ownedby_ag(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
xfs_filblks_t *blocks) xfs_filblks_t *blocks)
{ {
struct xchk_rmap_ownedby_info sroi; struct xchk_rmap_ownedby_info sroi = {
.oinfo = oinfo,
.blocks = blocks,
};
sroi.oinfo = oinfo;
*blocks = 0; *blocks = 0;
sroi.blocks = blocks;
return xfs_rmap_query_all(cur, xchk_count_rmap_ownedby_irec, return xfs_rmap_query_all(cur, xchk_count_rmap_ownedby_irec,
&sroi); &sroi);
} }

View File

@ -116,7 +116,7 @@ int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno,
void xchk_ag_btcur_free(struct xchk_ag *sa); void xchk_ag_btcur_free(struct xchk_ag *sa);
int xchk_ag_btcur_init(struct xfs_scrub *sc, struct xchk_ag *sa); int xchk_ag_btcur_init(struct xfs_scrub *sc, struct xchk_ag *sa);
int xchk_count_rmap_ownedby_ag(struct xfs_scrub *sc, struct xfs_btree_cur *cur, int xchk_count_rmap_ownedby_ag(struct xfs_scrub *sc, struct xfs_btree_cur *cur,
struct xfs_owner_info *oinfo, xfs_filblks_t *blocks); const struct xfs_owner_info *oinfo, xfs_filblks_t *blocks);
int xchk_setup_ag_btree(struct xfs_scrub *sc, struct xfs_inode *ip, int xchk_setup_ag_btree(struct xfs_scrub *sc, struct xfs_inode *ip,
bool force_log); bool force_log);

View File

@ -44,6 +44,11 @@ xchk_setup_ag_iallocbt(
/* Inode btree scrubber. */ /* Inode btree scrubber. */
struct xchk_iallocbt {
/* Number of inodes we see while scanning inobt. */
unsigned long long inodes;
};
/* /*
* If we're checking the finobt, cross-reference with the inobt. * If we're checking the finobt, cross-reference with the inobt.
* Otherwise we're checking the inobt; if there is an finobt, make sure * Otherwise we're checking the inobt; if there is an finobt, make sure
@ -82,15 +87,12 @@ xchk_iallocbt_chunk_xref(
xfs_agblock_t agbno, xfs_agblock_t agbno,
xfs_extlen_t len) xfs_extlen_t len)
{ {
struct xfs_owner_info oinfo;
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
return; return;
xchk_xref_is_used_space(sc, agbno, len); xchk_xref_is_used_space(sc, agbno, len);
xchk_iallocbt_chunk_xref_other(sc, irec, agino); xchk_iallocbt_chunk_xref_other(sc, irec, agino);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); xchk_xref_is_owned_by(sc, agbno, len, &XFS_RMAP_OINFO_INODES);
xchk_xref_is_owned_by(sc, agbno, len, &oinfo);
xchk_xref_is_not_shared(sc, agbno, len); xchk_xref_is_not_shared(sc, agbno, len);
} }
@ -186,7 +188,6 @@ xchk_iallocbt_check_freemask(
struct xchk_btree *bs, struct xchk_btree *bs,
struct xfs_inobt_rec_incore *irec) struct xfs_inobt_rec_incore *irec)
{ {
struct xfs_owner_info oinfo;
struct xfs_imap imap; struct xfs_imap imap;
struct xfs_mount *mp = bs->cur->bc_mp; struct xfs_mount *mp = bs->cur->bc_mp;
struct xfs_dinode *dip; struct xfs_dinode *dip;
@ -197,19 +198,16 @@ xchk_iallocbt_check_freemask(
xfs_agino_t chunkino; xfs_agino_t chunkino;
xfs_agino_t clusterino; xfs_agino_t clusterino;
xfs_agblock_t agbno; xfs_agblock_t agbno;
int blks_per_cluster;
uint16_t holemask; uint16_t holemask;
uint16_t ir_holemask; uint16_t ir_holemask;
int error = 0; int error = 0;
/* Make sure the freemask matches the inode records. */ /* Make sure the freemask matches the inode records. */
blks_per_cluster = xfs_icluster_size_fsb(mp); nr_inodes = mp->m_inodes_per_cluster;
nr_inodes = XFS_OFFBNO_TO_AGINO(mp, blks_per_cluster, 0);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
for (agino = irec->ir_startino; for (agino = irec->ir_startino;
agino < irec->ir_startino + XFS_INODES_PER_CHUNK; agino < irec->ir_startino + XFS_INODES_PER_CHUNK;
agino += blks_per_cluster * mp->m_sb.sb_inopblock) { agino += mp->m_inodes_per_cluster) {
fsino = XFS_AGINO_TO_INO(mp, bs->cur->bc_private.a.agno, agino); fsino = XFS_AGINO_TO_INO(mp, bs->cur->bc_private.a.agno, agino);
chunkino = agino - irec->ir_startino; chunkino = agino - irec->ir_startino;
agbno = XFS_AGINO_TO_AGBNO(mp, agino); agbno = XFS_AGINO_TO_AGBNO(mp, agino);
@ -230,17 +228,18 @@ xchk_iallocbt_check_freemask(
/* If any part of this is a hole, skip it. */ /* If any part of this is a hole, skip it. */
if (ir_holemask) { if (ir_holemask) {
xchk_xref_is_not_owned_by(bs->sc, agbno, xchk_xref_is_not_owned_by(bs->sc, agbno,
blks_per_cluster, &oinfo); mp->m_blocks_per_cluster,
&XFS_RMAP_OINFO_INODES);
continue; continue;
} }
xchk_xref_is_owned_by(bs->sc, agbno, blks_per_cluster, xchk_xref_is_owned_by(bs->sc, agbno, mp->m_blocks_per_cluster,
&oinfo); &XFS_RMAP_OINFO_INODES);
/* Grab the inode cluster buffer. */ /* Grab the inode cluster buffer. */
imap.im_blkno = XFS_AGB_TO_DADDR(mp, bs->cur->bc_private.a.agno, imap.im_blkno = XFS_AGB_TO_DADDR(mp, bs->cur->bc_private.a.agno,
agbno); agbno);
imap.im_len = XFS_FSB_TO_BB(mp, blks_per_cluster); imap.im_len = XFS_FSB_TO_BB(mp, mp->m_blocks_per_cluster);
imap.im_boffset = 0; imap.im_boffset = 0;
error = xfs_imap_to_bp(mp, bs->cur->bc_tp, &imap, error = xfs_imap_to_bp(mp, bs->cur->bc_tp, &imap,
@ -272,7 +271,7 @@ xchk_iallocbt_rec(
union xfs_btree_rec *rec) union xfs_btree_rec *rec)
{ {
struct xfs_mount *mp = bs->cur->bc_mp; struct xfs_mount *mp = bs->cur->bc_mp;
xfs_filblks_t *inode_blocks = bs->private; struct xchk_iallocbt *iabt = bs->private;
struct xfs_inobt_rec_incore irec; struct xfs_inobt_rec_incore irec;
uint64_t holes; uint64_t holes;
xfs_agnumber_t agno = bs->cur->bc_private.a.agno; xfs_agnumber_t agno = bs->cur->bc_private.a.agno;
@ -306,12 +305,11 @@ xchk_iallocbt_rec(
/* Make sure this record is aligned to cluster and inoalignmnt size. */ /* Make sure this record is aligned to cluster and inoalignmnt size. */
agbno = XFS_AGINO_TO_AGBNO(mp, irec.ir_startino); agbno = XFS_AGINO_TO_AGBNO(mp, irec.ir_startino);
if ((agbno & (xfs_ialloc_cluster_alignment(mp) - 1)) || if ((agbno & (mp->m_cluster_align - 1)) ||
(agbno & (xfs_icluster_size_fsb(mp) - 1))) (agbno & (mp->m_blocks_per_cluster - 1)))
xchk_btree_set_corrupt(bs->sc, bs->cur, 0); xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
*inode_blocks += XFS_B_TO_FSB(mp, iabt->inodes += irec.ir_count;
irec.ir_count * mp->m_sb.sb_inodesize);
/* Handle non-sparse inodes */ /* Handle non-sparse inodes */
if (!xfs_inobt_issparse(irec.ir_holemask)) { if (!xfs_inobt_issparse(irec.ir_holemask)) {
@ -366,7 +364,6 @@ xchk_iallocbt_xref_rmap_btreeblks(
struct xfs_scrub *sc, struct xfs_scrub *sc,
int which) int which)
{ {
struct xfs_owner_info oinfo;
xfs_filblks_t blocks; xfs_filblks_t blocks;
xfs_extlen_t inobt_blocks = 0; xfs_extlen_t inobt_blocks = 0;
xfs_extlen_t finobt_blocks = 0; xfs_extlen_t finobt_blocks = 0;
@ -388,9 +385,8 @@ xchk_iallocbt_xref_rmap_btreeblks(
return; return;
} }
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT); error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, &oinfo, &XFS_RMAP_OINFO_INOBT, &blocks);
&blocks);
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
return; return;
if (blocks != inobt_blocks + finobt_blocks) if (blocks != inobt_blocks + finobt_blocks)
@ -405,21 +401,21 @@ STATIC void
xchk_iallocbt_xref_rmap_inodes( xchk_iallocbt_xref_rmap_inodes(
struct xfs_scrub *sc, struct xfs_scrub *sc,
int which, int which,
xfs_filblks_t inode_blocks) unsigned long long inodes)
{ {
struct xfs_owner_info oinfo;
xfs_filblks_t blocks; xfs_filblks_t blocks;
xfs_filblks_t inode_blocks;
int error; int error;
if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
return; return;
/* Check that we saw as many inode blocks as the rmap knows about. */ /* Check that we saw as many inode blocks as the rmap knows about. */
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, &oinfo, &XFS_RMAP_OINFO_INODES, &blocks);
&blocks);
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
return; return;
inode_blocks = XFS_B_TO_FSB(sc->mp, inodes * sc->mp->m_sb.sb_inodesize);
if (blocks != inode_blocks) if (blocks != inode_blocks)
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
} }
@ -431,14 +427,14 @@ xchk_iallocbt(
xfs_btnum_t which) xfs_btnum_t which)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
struct xfs_owner_info oinfo; struct xchk_iallocbt iabt = {
xfs_filblks_t inode_blocks = 0; .inodes = 0,
};
int error; int error;
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT);
cur = which == XFS_BTNUM_INO ? sc->sa.ino_cur : sc->sa.fino_cur; cur = which == XFS_BTNUM_INO ? sc->sa.ino_cur : sc->sa.fino_cur;
error = xchk_btree(sc, cur, xchk_iallocbt_rec, &oinfo, error = xchk_btree(sc, cur, xchk_iallocbt_rec, &XFS_RMAP_OINFO_INOBT,
&inode_blocks); &iabt);
if (error) if (error)
return error; return error;
@ -452,7 +448,7 @@ xchk_iallocbt(
* to inode chunks with free inodes. * to inode chunks with free inodes.
*/ */
if (which == XFS_BTNUM_INO) if (which == XFS_BTNUM_INO)
xchk_iallocbt_xref_rmap_inodes(sc, which, inode_blocks); xchk_iallocbt_xref_rmap_inodes(sc, which, iabt.inodes);
return error; return error;
} }

View File

@ -509,7 +509,6 @@ xchk_inode_xref(
xfs_ino_t ino, xfs_ino_t ino,
struct xfs_dinode *dip) struct xfs_dinode *dip)
{ {
struct xfs_owner_info oinfo;
xfs_agnumber_t agno; xfs_agnumber_t agno;
xfs_agblock_t agbno; xfs_agblock_t agbno;
int error; int error;
@ -526,8 +525,7 @@ xchk_inode_xref(
xchk_xref_is_used_space(sc, agbno, 1); xchk_xref_is_used_space(sc, agbno, 1);
xchk_inode_xref_finobt(sc, ino); xchk_inode_xref_finobt(sc, ino);
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
xchk_xref_is_not_shared(sc, agbno, 1); xchk_xref_is_not_shared(sc, agbno, 1);
xchk_inode_xref_bmap(sc, dip); xchk_inode_xref_bmap(sc, dip);

View File

@ -383,7 +383,6 @@ xchk_refcountbt_rec(
STATIC void STATIC void
xchk_refcount_xref_rmap( xchk_refcount_xref_rmap(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xfs_owner_info *oinfo,
xfs_filblks_t cow_blocks) xfs_filblks_t cow_blocks)
{ {
xfs_extlen_t refcbt_blocks = 0; xfs_extlen_t refcbt_blocks = 0;
@ -397,17 +396,16 @@ xchk_refcount_xref_rmap(
error = xfs_btree_count_blocks(sc->sa.refc_cur, &refcbt_blocks); error = xfs_btree_count_blocks(sc->sa.refc_cur, &refcbt_blocks);
if (!xchk_btree_process_error(sc, sc->sa.refc_cur, 0, &error)) if (!xchk_btree_process_error(sc, sc->sa.refc_cur, 0, &error))
return; return;
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo, error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
&blocks); &XFS_RMAP_OINFO_REFC, &blocks);
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
return; return;
if (blocks != refcbt_blocks) if (blocks != refcbt_blocks)
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
/* Check that we saw as many cow blocks as the rmap knows about. */ /* Check that we saw as many cow blocks as the rmap knows about. */
xfs_rmap_ag_owner(oinfo, XFS_RMAP_OWN_COW); error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo, &XFS_RMAP_OINFO_COW, &blocks);
&blocks);
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
return; return;
if (blocks != cow_blocks) if (blocks != cow_blocks)
@ -419,17 +417,15 @@ int
xchk_refcountbt( xchk_refcountbt(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_owner_info oinfo;
xfs_agblock_t cow_blocks = 0; xfs_agblock_t cow_blocks = 0;
int error; int error;
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC);
error = xchk_btree(sc, sc->sa.refc_cur, xchk_refcountbt_rec, error = xchk_btree(sc, sc->sa.refc_cur, xchk_refcountbt_rec,
&oinfo, &cow_blocks); &XFS_RMAP_OINFO_REFC, &cow_blocks);
if (error) if (error)
return error; return error;
xchk_refcount_xref_rmap(sc, &oinfo, cow_blocks); xchk_refcount_xref_rmap(sc, cow_blocks);
return 0; return 0;
} }

View File

@ -299,14 +299,14 @@ xrep_calc_ag_resblks(
/* Allocate a block in an AG. */ /* Allocate a block in an AG. */
int int
xrep_alloc_ag_block( xrep_alloc_ag_block(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
xfs_fsblock_t *fsbno, xfs_fsblock_t *fsbno,
enum xfs_ag_resv_type resv) enum xfs_ag_resv_type resv)
{ {
struct xfs_alloc_arg args = {0}; struct xfs_alloc_arg args = {0};
xfs_agblock_t bno; xfs_agblock_t bno;
int error; int error;
switch (resv) { switch (resv) {
case XFS_AG_RESV_AGFL: case XFS_AG_RESV_AGFL:
@ -505,7 +505,6 @@ xrep_put_freelist(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_agblock_t agbno) xfs_agblock_t agbno)
{ {
struct xfs_owner_info oinfo;
int error; int error;
/* Make sure there's space on the freelist. */ /* Make sure there's space on the freelist. */
@ -518,9 +517,8 @@ xrep_put_freelist(
* create an rmap for the block prior to merging it or else other * create an rmap for the block prior to merging it or else other
* parts will break. * parts will break.
*/ */
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
error = xfs_rmap_alloc(sc->tp, sc->sa.agf_bp, sc->sa.agno, agbno, 1, error = xfs_rmap_alloc(sc->tp, sc->sa.agf_bp, sc->sa.agno, agbno, 1,
&oinfo); &XFS_RMAP_OINFO_AG);
if (error) if (error)
return error; return error;
@ -538,17 +536,17 @@ xrep_put_freelist(
/* Dispose of a single block. */ /* Dispose of a single block. */
STATIC int STATIC int
xrep_reap_block( xrep_reap_block(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_fsblock_t fsbno, xfs_fsblock_t fsbno,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
enum xfs_ag_resv_type resv) enum xfs_ag_resv_type resv)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
struct xfs_buf *agf_bp = NULL; struct xfs_buf *agf_bp = NULL;
xfs_agnumber_t agno; xfs_agnumber_t agno;
xfs_agblock_t agbno; xfs_agblock_t agbno;
bool has_other_rmap; bool has_other_rmap;
int error; int error;
agno = XFS_FSB_TO_AGNO(sc->mp, fsbno); agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno); agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
@ -612,15 +610,15 @@ out_free:
/* Dispose of every block of every extent in the bitmap. */ /* Dispose of every block of every extent in the bitmap. */
int int
xrep_reap_extents( xrep_reap_extents(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xfs_bitmap *bitmap, struct xfs_bitmap *bitmap,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
enum xfs_ag_resv_type type) enum xfs_ag_resv_type type)
{ {
struct xfs_bitmap_range *bmr; struct xfs_bitmap_range *bmr;
struct xfs_bitmap_range *n; struct xfs_bitmap_range *n;
xfs_fsblock_t fsbno; xfs_fsblock_t fsbno;
int error = 0; int error = 0;
ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb)); ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb));

View File

@ -21,8 +21,9 @@ int xrep_roll_ag_trans(struct xfs_scrub *sc);
bool xrep_ag_has_space(struct xfs_perag *pag, xfs_extlen_t nr_blocks, bool xrep_ag_has_space(struct xfs_perag *pag, xfs_extlen_t nr_blocks,
enum xfs_ag_resv_type type); enum xfs_ag_resv_type type);
xfs_extlen_t xrep_calc_ag_resblks(struct xfs_scrub *sc); xfs_extlen_t xrep_calc_ag_resblks(struct xfs_scrub *sc);
int xrep_alloc_ag_block(struct xfs_scrub *sc, struct xfs_owner_info *oinfo, int xrep_alloc_ag_block(struct xfs_scrub *sc,
xfs_fsblock_t *fsbno, enum xfs_ag_resv_type resv); const struct xfs_owner_info *oinfo, xfs_fsblock_t *fsbno,
enum xfs_ag_resv_type resv);
int xrep_init_btblock(struct xfs_scrub *sc, xfs_fsblock_t fsb, int xrep_init_btblock(struct xfs_scrub *sc, xfs_fsblock_t fsb,
struct xfs_buf **bpp, xfs_btnum_t btnum, struct xfs_buf **bpp, xfs_btnum_t btnum,
const struct xfs_buf_ops *ops); const struct xfs_buf_ops *ops);
@ -32,7 +33,7 @@ struct xfs_bitmap;
int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink); int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink);
int xrep_invalidate_blocks(struct xfs_scrub *sc, struct xfs_bitmap *btlist); int xrep_invalidate_blocks(struct xfs_scrub *sc, struct xfs_bitmap *btlist);
int xrep_reap_extents(struct xfs_scrub *sc, struct xfs_bitmap *exlist, int xrep_reap_extents(struct xfs_scrub *sc, struct xfs_bitmap *exlist,
struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type); const struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type);
struct xrep_find_ag_btree { struct xrep_find_ag_btree {
/* in: rmap owner of the btree we're looking for */ /* in: rmap owner of the btree we're looking for */

View File

@ -174,24 +174,21 @@ int
xchk_rmapbt( xchk_rmapbt(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_owner_info oinfo;
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
return xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec, return xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
&oinfo, NULL); &XFS_RMAP_OINFO_AG, NULL);
} }
/* xref check that the extent is owned by a given owner */ /* xref check that the extent is owned by a given owner */
static inline void static inline void
xchk_xref_check_owner( xchk_xref_check_owner(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
bool should_have_rmap) bool should_have_rmap)
{ {
bool has_rmap; bool has_rmap;
int error; int error;
if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
return; return;
@ -207,10 +204,10 @@ xchk_xref_check_owner(
/* xref check that the extent is owned by a given owner */ /* xref check that the extent is owned by a given owner */
void void
xchk_xref_is_owned_by( xchk_xref_is_owned_by(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
xchk_xref_check_owner(sc, bno, len, oinfo, true); xchk_xref_check_owner(sc, bno, len, oinfo, true);
} }
@ -218,10 +215,10 @@ xchk_xref_is_owned_by(
/* xref check that the extent is not owned by a given owner */ /* xref check that the extent is not owned by a given owner */
void void
xchk_xref_is_not_owned_by( xchk_xref_is_not_owned_by(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_agblock_t bno, xfs_agblock_t bno,
xfs_extlen_t len, xfs_extlen_t len,
struct xfs_owner_info *oinfo) const struct xfs_owner_info *oinfo)
{ {
xchk_xref_check_owner(sc, bno, len, oinfo, false); xchk_xref_check_owner(sc, bno, len, oinfo, false);
} }

View File

@ -122,9 +122,9 @@ void xchk_xref_is_not_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
void xchk_xref_is_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno, void xchk_xref_is_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
xfs_extlen_t len); xfs_extlen_t len);
void xchk_xref_is_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno, void xchk_xref_is_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
xfs_extlen_t len, struct xfs_owner_info *oinfo); xfs_extlen_t len, const struct xfs_owner_info *oinfo);
void xchk_xref_is_not_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno, void xchk_xref_is_not_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
xfs_extlen_t len, struct xfs_owner_info *oinfo); xfs_extlen_t len, const struct xfs_owner_info *oinfo);
void xchk_xref_has_no_owner(struct xfs_scrub *sc, xfs_agblock_t agbno, void xchk_xref_has_no_owner(struct xfs_scrub *sc, xfs_agblock_t agbno,
xfs_extlen_t len); xfs_extlen_t len);
void xchk_xref_is_cow_staging(struct xfs_scrub *sc, xfs_agblock_t bno, void xchk_xref_is_cow_staging(struct xfs_scrub *sc, xfs_agblock_t bno,

View File

@ -12,6 +12,71 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include "xfs_bit.h" #include "xfs_bit.h"
/*
* ftrace's __print_symbolic requires that all enum values be wrapped in the
* TRACE_DEFINE_ENUM macro so that the enum value can be encoded in the ftrace
* ring buffer. Somehow this was only worth mentioning in the ftrace sample
* code.
*/
TRACE_DEFINE_ENUM(XFS_BTNUM_BNOi);
TRACE_DEFINE_ENUM(XFS_BTNUM_CNTi);
TRACE_DEFINE_ENUM(XFS_BTNUM_BMAPi);
TRACE_DEFINE_ENUM(XFS_BTNUM_INOi);
TRACE_DEFINE_ENUM(XFS_BTNUM_FINOi);
TRACE_DEFINE_ENUM(XFS_BTNUM_RMAPi);
TRACE_DEFINE_ENUM(XFS_BTNUM_REFCi);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PROBE);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_SB);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_AGF);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_AGFL);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_AGI);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BNOBT);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_CNTBT);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_INOBT);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FINOBT);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RMAPBT);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_REFCNTBT);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_INODE);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BMBTD);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BMBTA);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BMBTC);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_DIR);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_XATTR);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_SYMLINK);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PARENT);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RTBITMAP);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RTSUM);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_UQUOTA);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_GQUOTA);
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PQUOTA);
#define XFS_SCRUB_TYPE_STRINGS \
{ XFS_SCRUB_TYPE_PROBE, "probe" }, \
{ XFS_SCRUB_TYPE_SB, "sb" }, \
{ XFS_SCRUB_TYPE_AGF, "agf" }, \
{ XFS_SCRUB_TYPE_AGFL, "agfl" }, \
{ XFS_SCRUB_TYPE_AGI, "agi" }, \
{ XFS_SCRUB_TYPE_BNOBT, "bnobt" }, \
{ XFS_SCRUB_TYPE_CNTBT, "cntbt" }, \
{ XFS_SCRUB_TYPE_INOBT, "inobt" }, \
{ XFS_SCRUB_TYPE_FINOBT, "finobt" }, \
{ XFS_SCRUB_TYPE_RMAPBT, "rmapbt" }, \
{ XFS_SCRUB_TYPE_REFCNTBT, "refcountbt" }, \
{ XFS_SCRUB_TYPE_INODE, "inode" }, \
{ XFS_SCRUB_TYPE_BMBTD, "bmapbtd" }, \
{ XFS_SCRUB_TYPE_BMBTA, "bmapbta" }, \
{ XFS_SCRUB_TYPE_BMBTC, "bmapbtc" }, \
{ XFS_SCRUB_TYPE_DIR, "directory" }, \
{ XFS_SCRUB_TYPE_XATTR, "xattr" }, \
{ XFS_SCRUB_TYPE_SYMLINK, "symlink" }, \
{ XFS_SCRUB_TYPE_PARENT, "parent" }, \
{ XFS_SCRUB_TYPE_RTBITMAP, "rtbitmap" }, \
{ XFS_SCRUB_TYPE_RTSUM, "rtsummary" }, \
{ XFS_SCRUB_TYPE_UQUOTA, "usrquota" }, \
{ XFS_SCRUB_TYPE_GQUOTA, "grpquota" }, \
{ XFS_SCRUB_TYPE_PQUOTA, "prjquota" }
DECLARE_EVENT_CLASS(xchk_class, DECLARE_EVENT_CLASS(xchk_class,
TP_PROTO(struct xfs_inode *ip, struct xfs_scrub_metadata *sm, TP_PROTO(struct xfs_inode *ip, struct xfs_scrub_metadata *sm,
int error), int error),
@ -36,10 +101,10 @@ DECLARE_EVENT_CLASS(xchk_class,
__entry->flags = sm->sm_flags; __entry->flags = sm->sm_flags;
__entry->error = error; __entry->error = error;
), ),
TP_printk("dev %d:%d ino 0x%llx type %u agno %u inum %llu gen %u flags 0x%x error %d", TP_printk("dev %d:%d ino 0x%llx type %s agno %u inum %llu gen %u flags 0x%x error %d",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino, __entry->ino,
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->agno, __entry->agno,
__entry->inum, __entry->inum,
__entry->gen, __entry->gen,
@ -78,9 +143,9 @@ TRACE_EVENT(xchk_op_error,
__entry->error = error; __entry->error = error;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d type %u agno %u agbno %u error %d ret_ip %pS", TP_printk("dev %d:%d type %s agno %u agbno %u error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->agno, __entry->agno,
__entry->bno, __entry->bno,
__entry->error, __entry->error,
@ -109,11 +174,11 @@ TRACE_EVENT(xchk_file_op_error,
__entry->error = error; __entry->error = error;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d ino 0x%llx fork %d type %u offset %llu error %d ret_ip %pS", TP_printk("dev %d:%d ino 0x%llx fork %d type %s offset %llu error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino, __entry->ino,
__entry->whichfork, __entry->whichfork,
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->offset, __entry->offset,
__entry->error, __entry->error,
__entry->ret_ip) __entry->ret_ip)
@ -144,9 +209,9 @@ DECLARE_EVENT_CLASS(xchk_block_error_class,
__entry->bno = bno; __entry->bno = bno;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d type %u agno %u agbno %u ret_ip %pS", TP_printk("dev %d:%d type %s agno %u agbno %u ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->agno, __entry->agno,
__entry->bno, __entry->bno,
__entry->ret_ip) __entry->ret_ip)
@ -176,10 +241,10 @@ DECLARE_EVENT_CLASS(xchk_ino_error_class,
__entry->type = sc->sm->sm_type; __entry->type = sc->sm->sm_type;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d ino 0x%llx type %u ret_ip %pS", TP_printk("dev %d:%d ino 0x%llx type %s ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino, __entry->ino,
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->ret_ip) __entry->ret_ip)
) )
@ -213,11 +278,11 @@ DECLARE_EVENT_CLASS(xchk_fblock_error_class,
__entry->offset = offset; __entry->offset = offset;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d ino 0x%llx fork %d type %u offset %llu ret_ip %pS", TP_printk("dev %d:%d ino 0x%llx fork %d type %s offset %llu ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino, __entry->ino,
__entry->whichfork, __entry->whichfork,
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->offset, __entry->offset,
__entry->ret_ip) __entry->ret_ip)
); );
@ -244,9 +309,9 @@ TRACE_EVENT(xchk_incomplete,
__entry->type = sc->sm->sm_type; __entry->type = sc->sm->sm_type;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d type %u ret_ip %pS", TP_printk("dev %d:%d type %s ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->ret_ip) __entry->ret_ip)
); );
@ -278,10 +343,10 @@ TRACE_EVENT(xchk_btree_op_error,
__entry->error = error; __entry->error = error;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d type %u btnum %d level %d ptr %d agno %u agbno %u error %d ret_ip %pS", TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->btnum, __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level, __entry->level,
__entry->ptr, __entry->ptr,
__entry->agno, __entry->agno,
@ -321,12 +386,12 @@ TRACE_EVENT(xchk_ifork_btree_op_error,
__entry->error = error; __entry->error = error;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d ino 0x%llx fork %d type %u btnum %d level %d ptr %d agno %u agbno %u error %d ret_ip %pS", TP_printk("dev %d:%d ino 0x%llx fork %d type %s btree %s level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino, __entry->ino,
__entry->whichfork, __entry->whichfork,
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->btnum, __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level, __entry->level,
__entry->ptr, __entry->ptr,
__entry->agno, __entry->agno,
@ -360,10 +425,10 @@ TRACE_EVENT(xchk_btree_error,
__entry->ptr = cur->bc_ptrs[level]; __entry->ptr = cur->bc_ptrs[level];
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d type %u btnum %d level %d ptr %d agno %u agbno %u ret_ip %pS", TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno %u agbno %u ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->btnum, __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level, __entry->level,
__entry->ptr, __entry->ptr,
__entry->agno, __entry->agno,
@ -400,12 +465,12 @@ TRACE_EVENT(xchk_ifork_btree_error,
__entry->ptr = cur->bc_ptrs[level]; __entry->ptr = cur->bc_ptrs[level];
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d ino 0x%llx fork %d type %u btnum %d level %d ptr %d agno %u agbno %u ret_ip %pS", TP_printk("dev %d:%d ino 0x%llx fork %d type %s btree %s level %d ptr %d agno %u agbno %u ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino, __entry->ino,
__entry->whichfork, __entry->whichfork,
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->btnum, __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level, __entry->level,
__entry->ptr, __entry->ptr,
__entry->agno, __entry->agno,
@ -439,10 +504,10 @@ DECLARE_EVENT_CLASS(xchk_sbtree_class,
__entry->nlevels = cur->bc_nlevels; __entry->nlevels = cur->bc_nlevels;
__entry->ptr = cur->bc_ptrs[level]; __entry->ptr = cur->bc_ptrs[level];
), ),
TP_printk("dev %d:%d type %u btnum %d agno %u agbno %u level %d nlevels %d ptr %d", TP_printk("dev %d:%d type %s btree %s agno %u agbno %u level %d nlevels %d ptr %d",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->btnum, __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->agno, __entry->agno,
__entry->bno, __entry->bno,
__entry->level, __entry->level,
@ -473,9 +538,9 @@ TRACE_EVENT(xchk_xref_error,
__entry->error = error; __entry->error = error;
__entry->ret_ip = ret_ip; __entry->ret_ip = ret_ip;
), ),
TP_printk("dev %d:%d type %u xref error %d ret_ip %pF", TP_printk("dev %d:%d type %s xref error %d ret_ip %pS",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->type, __print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
__entry->error, __entry->error,
__entry->ret_ip) __entry->ret_ip)
); );
@ -598,11 +663,11 @@ TRACE_EVENT(xrep_init_btblock,
__entry->agbno = agbno; __entry->agbno = agbno;
__entry->btnum = btnum; __entry->btnum = btnum;
), ),
TP_printk("dev %d:%d agno %u agbno %u btnum %d", TP_printk("dev %d:%d agno %u agbno %u btree %s",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno, __entry->agno,
__entry->agbno, __entry->agbno,
__entry->btnum) __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS))
) )
TRACE_EVENT(xrep_findroot_block, TRACE_EVENT(xrep_findroot_block,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno,

View File

@ -10,6 +10,9 @@ extern struct bio_set xfs_ioend_bioset;
/* /*
* Types of I/O for bmap clustering and I/O completion tracking. * Types of I/O for bmap clustering and I/O completion tracking.
*
* This enum is used in string mapping in xfs_trace.h; please keep the
* TRACE_DEFINE_ENUMs for it up to date.
*/ */
enum { enum {
XFS_IO_HOLE, /* covers region without any block allocation */ XFS_IO_HOLE, /* covers region without any block allocation */

View File

@ -494,7 +494,6 @@ xfs_efi_recover(
int error = 0; int error = 0;
xfs_extent_t *extp; xfs_extent_t *extp;
xfs_fsblock_t startblock_fsb; xfs_fsblock_t startblock_fsb;
struct xfs_owner_info oinfo;
ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)); ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags));
@ -526,11 +525,11 @@ xfs_efi_recover(
return error; return error;
efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
xfs_rmap_any_owner_update(&oinfo);
for (i = 0; i < efip->efi_format.efi_nextents; i++) { for (i = 0; i < efip->efi_format.efi_nextents; i++) {
extp = &efip->efi_format.efi_extents[i]; extp = &efip->efi_format.efi_extents[i];
error = xfs_trans_free_extent(tp, efdp, extp->ext_start, error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
extp->ext_len, &oinfo, false); extp->ext_len,
&XFS_RMAP_OINFO_ANY_OWNER, false);
if (error) if (error)
goto abort_error; goto abort_error;

View File

@ -252,7 +252,7 @@ xfs_growfs_data(
if (mp->m_sb.sb_imax_pct) { if (mp->m_sb.sb_imax_pct) {
uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct; uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
do_div(icount, 100); do_div(icount, 100);
mp->m_maxicount = icount << mp->m_sb.sb_inopblog; mp->m_maxicount = XFS_FSB_TO_INO(mp, icount);
} else } else
mp->m_maxicount = 0; mp->m_maxicount = 0;

View File

@ -2184,8 +2184,6 @@ xfs_ifree_cluster(
struct xfs_icluster *xic) struct xfs_icluster *xic)
{ {
xfs_mount_t *mp = free_ip->i_mount; xfs_mount_t *mp = free_ip->i_mount;
int blks_per_cluster;
int inodes_per_cluster;
int nbufs; int nbufs;
int i, j; int i, j;
int ioffset; int ioffset;
@ -2199,11 +2197,9 @@ xfs_ifree_cluster(
inum = xic->first_ino; inum = xic->first_ino;
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, inum)); pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, inum));
blks_per_cluster = xfs_icluster_size_fsb(mp); nbufs = mp->m_ialloc_blks / mp->m_blocks_per_cluster;
inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog;
nbufs = mp->m_ialloc_blks / blks_per_cluster;
for (j = 0; j < nbufs; j++, inum += inodes_per_cluster) { for (j = 0; j < nbufs; j++, inum += mp->m_inodes_per_cluster) {
/* /*
* The allocation bitmap tells us which inodes of the chunk were * The allocation bitmap tells us which inodes of the chunk were
* physically allocated. Skip the cluster if an inode falls into * physically allocated. Skip the cluster if an inode falls into
@ -2211,7 +2207,7 @@ xfs_ifree_cluster(
*/ */
ioffset = inum - xic->first_ino; ioffset = inum - xic->first_ino;
if ((xic->alloc & XFS_INOBT_MASK(ioffset)) == 0) { if ((xic->alloc & XFS_INOBT_MASK(ioffset)) == 0) {
ASSERT(ioffset % inodes_per_cluster == 0); ASSERT(ioffset % mp->m_inodes_per_cluster == 0);
continue; continue;
} }
@ -2227,7 +2223,7 @@ xfs_ifree_cluster(
* to mark all the active inodes on the buffer stale. * to mark all the active inodes on the buffer stale.
*/ */
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
mp->m_bsize * blks_per_cluster, mp->m_bsize * mp->m_blocks_per_cluster,
XBF_UNMAPPED); XBF_UNMAPPED);
if (!bp) if (!bp)
@ -2242,7 +2238,7 @@ xfs_ifree_cluster(
* want it to fail. We can acheive this by adding a write * want it to fail. We can acheive this by adding a write
* verifier to the buffer. * verifier to the buffer.
*/ */
bp->b_ops = &xfs_inode_buf_ops; bp->b_ops = &xfs_inode_buf_ops;
/* /*
* Walk the inodes already attached to the buffer and mark them * Walk the inodes already attached to the buffer and mark them
@ -2274,7 +2270,7 @@ xfs_ifree_cluster(
* transaction stale above, which means there is no point in * transaction stale above, which means there is no point in
* even trying to lock them. * even trying to lock them.
*/ */
for (i = 0; i < inodes_per_cluster; i++) { for (i = 0; i < mp->m_inodes_per_cluster; i++) {
retry: retry:
rcu_read_lock(); rcu_read_lock();
ip = radix_tree_lookup(&pag->pag_ici_root, ip = radix_tree_lookup(&pag->pag_ici_root,

View File

@ -241,6 +241,32 @@ xfs_compat_ioc_bulkstat(
int done; int done;
int error; int error;
/*
* Output structure handling functions. Depending on the command,
* either the xfs_bstat and xfs_inogrp structures are written out
* to userpace memory via bulkreq.ubuffer. Normally the compat
* functions and structure size are the correct ones to use ...
*/
inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat;
bulkstat_one_pf bs_one_func = xfs_bulkstat_one_compat;
size_t bs_one_size = sizeof(struct compat_xfs_bstat);
#ifdef CONFIG_X86_X32
if (in_x32_syscall()) {
/*
* ... but on x32 the input xfs_fsop_bulkreq has pointers
* which must be handled in the "compat" (32-bit) way, while
* the xfs_bstat and xfs_inogrp structures follow native 64-
* bit layout convention. So adjust accordingly, otherwise
* the data written out in compat layout will not match what
* x32 userspace expects.
*/
inumbers_func = xfs_inumbers_fmt;
bs_one_func = xfs_bulkstat_one;
bs_one_size = sizeof(struct xfs_bstat);
}
#endif
/* done = 1 if there are more stats to get and if bulkstat */ /* done = 1 if there are more stats to get and if bulkstat */
/* should be called again (unused here, but used in dmapi) */ /* should be called again (unused here, but used in dmapi) */
@ -272,15 +298,15 @@ xfs_compat_ioc_bulkstat(
if (cmd == XFS_IOC_FSINUMBERS_32) { if (cmd == XFS_IOC_FSINUMBERS_32) {
error = xfs_inumbers(mp, &inlast, &count, error = xfs_inumbers(mp, &inlast, &count,
bulkreq.ubuffer, xfs_inumbers_fmt_compat); bulkreq.ubuffer, inumbers_func);
} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) { } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
int res; int res;
error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer, error = bs_one_func(mp, inlast, bulkreq.ubuffer,
sizeof(compat_xfs_bstat_t), NULL, &res); bs_one_size, NULL, &res);
} else if (cmd == XFS_IOC_FSBULKSTAT_32) { } else if (cmd == XFS_IOC_FSBULKSTAT_32) {
error = xfs_bulkstat(mp, &inlast, &count, error = xfs_bulkstat(mp, &inlast, &count,
xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t), bs_one_func, bs_one_size,
bulkreq.ubuffer, &done); bulkreq.ubuffer, &done);
} else } else
error = -EINVAL; error = -EINVAL;
@ -336,6 +362,7 @@ xfs_compat_attrlist_by_handle(
{ {
int error; int error;
attrlist_cursor_kern_t *cursor; attrlist_cursor_kern_t *cursor;
compat_xfs_fsop_attrlist_handlereq_t __user *p = arg;
compat_xfs_fsop_attrlist_handlereq_t al_hreq; compat_xfs_fsop_attrlist_handlereq_t al_hreq;
struct dentry *dentry; struct dentry *dentry;
char *kbuf; char *kbuf;
@ -370,6 +397,11 @@ xfs_compat_attrlist_by_handle(
if (error) if (error)
goto out_kfree; goto out_kfree;
if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
error = -EFAULT;
goto out_kfree;
}
if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen)) if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
error = -EFAULT; error = -EFAULT;
@ -547,8 +579,12 @@ xfs_file_compat_ioctl(
case FS_IOC_GETFSMAP: case FS_IOC_GETFSMAP:
case XFS_IOC_SCRUB_METADATA: case XFS_IOC_SCRUB_METADATA:
return xfs_file_ioctl(filp, cmd, p); return xfs_file_ioctl(filp, cmd, p);
#ifndef BROKEN_X86_ALIGNMENT #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
/* These are handled fine if no alignment issues */ /*
* These are handled fine if no alignment issues. To support x32
* which uses native 64-bit alignment we must emit these cases in
* addition to the ia-32 compat set below.
*/
case XFS_IOC_ALLOCSP: case XFS_IOC_ALLOCSP:
case XFS_IOC_FREESP: case XFS_IOC_FREESP:
case XFS_IOC_RESVSP: case XFS_IOC_RESVSP:
@ -561,8 +597,16 @@ xfs_file_compat_ioctl(
case XFS_IOC_FSGROWFSDATA: case XFS_IOC_FSGROWFSDATA:
case XFS_IOC_FSGROWFSRT: case XFS_IOC_FSGROWFSRT:
case XFS_IOC_ZERO_RANGE: case XFS_IOC_ZERO_RANGE:
#ifdef CONFIG_X86_X32
/*
* x32 special: this gets a different cmd number from the ia-32 compat
* case below; the associated data will match native 64-bit alignment.
*/
case XFS_IOC_SWAPEXT:
#endif
return xfs_file_ioctl(filp, cmd, p); return xfs_file_ioctl(filp, cmd, p);
#else #endif
#if defined(BROKEN_X86_ALIGNMENT)
case XFS_IOC_ALLOCSP_32: case XFS_IOC_ALLOCSP_32:
case XFS_IOC_FREESP_32: case XFS_IOC_FREESP_32:
case XFS_IOC_ALLOCSP64_32: case XFS_IOC_ALLOCSP64_32:

View File

@ -167,20 +167,18 @@ xfs_bulkstat_ichunk_ra(
{ {
xfs_agblock_t agbno; xfs_agblock_t agbno;
struct blk_plug plug; struct blk_plug plug;
int blks_per_cluster;
int inodes_per_cluster;
int i; /* inode chunk index */ int i; /* inode chunk index */
agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino); agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino);
blks_per_cluster = xfs_icluster_size_fsb(mp);
inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog;
blk_start_plug(&plug); blk_start_plug(&plug);
for (i = 0; i < XFS_INODES_PER_CHUNK; for (i = 0; i < XFS_INODES_PER_CHUNK;
i += inodes_per_cluster, agbno += blks_per_cluster) { i += mp->m_inodes_per_cluster, agbno += mp->m_blocks_per_cluster) {
if (xfs_inobt_maskn(i, inodes_per_cluster) & ~irec->ir_free) { if (xfs_inobt_maskn(i, mp->m_inodes_per_cluster) &
xfs_btree_reada_bufs(mp, agno, agbno, blks_per_cluster, ~irec->ir_free) {
&xfs_inode_buf_ops); xfs_btree_reada_bufs(mp, agno, agbno,
mp->m_blocks_per_cluster,
&xfs_inode_buf_ops);
} }
} }
blk_finish_plug(&plug); blk_finish_plug(&plug);

View File

@ -3850,7 +3850,6 @@ xlog_recover_do_icreate_pass2(
unsigned int count; unsigned int count;
unsigned int isize; unsigned int isize;
xfs_agblock_t length; xfs_agblock_t length;
int blks_per_cluster;
int bb_per_cluster; int bb_per_cluster;
int cancel_count; int cancel_count;
int nbufs; int nbufs;
@ -3918,14 +3917,13 @@ xlog_recover_do_icreate_pass2(
* buffers for cancellation so we don't overwrite anything written after * buffers for cancellation so we don't overwrite anything written after
* a cancellation. * a cancellation.
*/ */
blks_per_cluster = xfs_icluster_size_fsb(mp); bb_per_cluster = XFS_FSB_TO_BB(mp, mp->m_blocks_per_cluster);
bb_per_cluster = XFS_FSB_TO_BB(mp, blks_per_cluster); nbufs = length / mp->m_blocks_per_cluster;
nbufs = length / blks_per_cluster;
for (i = 0, cancel_count = 0; i < nbufs; i++) { for (i = 0, cancel_count = 0; i < nbufs; i++) {
xfs_daddr_t daddr; xfs_daddr_t daddr;
daddr = XFS_AGB_TO_DADDR(mp, agno, daddr = XFS_AGB_TO_DADDR(mp, agno,
agbno + i * blks_per_cluster); agbno + i * mp->m_blocks_per_cluster);
if (xlog_check_buffer_cancelled(log, daddr, bb_per_cluster, 0)) if (xlog_check_buffer_cancelled(log, daddr, bb_per_cluster, 0))
cancel_count++; cancel_count++;
} }

View File

@ -798,6 +798,10 @@ xfs_mountfs(
if (mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, new_size)) if (mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, new_size))
mp->m_inode_cluster_size = new_size; mp->m_inode_cluster_size = new_size;
} }
mp->m_blocks_per_cluster = xfs_icluster_size_fsb(mp);
mp->m_inodes_per_cluster = XFS_FSB_TO_INO(mp, mp->m_blocks_per_cluster);
mp->m_cluster_align = xfs_ialloc_cluster_alignment(mp);
mp->m_cluster_align_inodes = XFS_FSB_TO_INO(mp, mp->m_cluster_align);
/* /*
* If enabled, sparse inode chunk alignment is expected to match the * If enabled, sparse inode chunk alignment is expected to match the

View File

@ -89,6 +89,13 @@ typedef struct xfs_mount {
int m_logbsize; /* size of each log buffer */ int m_logbsize; /* size of each log buffer */
uint m_rsumlevels; /* rt summary levels */ uint m_rsumlevels; /* rt summary levels */
uint m_rsumsize; /* size of rt summary, bytes */ uint m_rsumsize; /* size of rt summary, bytes */
/*
* Optional cache of rt summary level per bitmap block with the
* invariant that m_rsum_cache[bbno] <= the minimum i for which
* rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip
* inode lock.
*/
uint8_t *m_rsum_cache;
struct xfs_inode *m_rbmip; /* pointer to bitmap inode */ struct xfs_inode *m_rbmip; /* pointer to bitmap inode */
struct xfs_inode *m_rsumip; /* pointer to summary inode */ struct xfs_inode *m_rsumip; /* pointer to summary inode */
struct xfs_inode *m_rootip; /* pointer to root directory */ struct xfs_inode *m_rootip; /* pointer to root directory */
@ -101,6 +108,10 @@ typedef struct xfs_mount {
uint8_t m_agno_log; /* log #ag's */ uint8_t m_agno_log; /* log #ag's */
uint8_t m_agino_log; /* #bits for agino in inum */ uint8_t m_agino_log; /* #bits for agino in inum */
uint m_inode_cluster_size;/* min inode buf size */ uint m_inode_cluster_size;/* min inode buf size */
unsigned int m_inodes_per_cluster;
unsigned int m_blocks_per_cluster;
unsigned int m_cluster_align;
unsigned int m_cluster_align_inodes;
uint m_blockmask; /* sb_blocksize-1 */ uint m_blockmask; /* sb_blocksize-1 */
uint m_blockwsize; /* sb_blocksize in words */ uint m_blockwsize; /* sb_blocksize in words */
uint m_blockwmask; /* blockwsize-1 */ uint m_blockwmask; /* blockwsize-1 */

View File

@ -623,54 +623,47 @@ out:
} }
/* /*
* Remap parts of a file's data fork after a successful CoW. * Remap part of the CoW fork into the data fork.
*
* We aim to remap the range starting at @offset_fsb and ending at @end_fsb
* into the data fork; this function will remap what it can (at the end of the
* range) and update @end_fsb appropriately. Each remap gets its own
* transaction because we can end up merging and splitting bmbt blocks for
* every remap operation and we'd like to keep the block reservation
* requirements as low as possible.
*/ */
int STATIC int
xfs_reflink_end_cow( xfs_reflink_end_cow_extent(
struct xfs_inode *ip, struct xfs_inode *ip,
xfs_off_t offset, xfs_fileoff_t offset_fsb,
xfs_off_t count) xfs_fileoff_t *end_fsb)
{ {
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); struct xfs_bmbt_irec got, del;
struct xfs_bmbt_irec got, del; struct xfs_iext_cursor icur;
struct xfs_trans *tp; struct xfs_mount *mp = ip->i_mount;
xfs_fileoff_t offset_fsb; struct xfs_trans *tp;
xfs_fileoff_t end_fsb; struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
int error; xfs_filblks_t rlen;
unsigned int resblks; unsigned int resblks;
xfs_filblks_t rlen; int error;
struct xfs_iext_cursor icur;
trace_xfs_reflink_end_cow(ip, offset, count);
/* No COW extents? That's easy! */ /* No COW extents? That's easy! */
if (ifp->if_bytes == 0) if (ifp->if_bytes == 0) {
*end_fsb = offset_fsb;
return 0; return 0;
}
offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp);
if (error)
return error;
/* /*
* Start a rolling transaction to switch the mappings. We're * Lock the inode. We have to ijoin without automatic unlock because
* unlikely ever to have to remap 16T worth of single-block * the lead transaction is the refcountbt record deletion; the data
* extents, so just cap the worst case extent count to 2^32-1. * fork update follows as a deferred log item.
* Stick a warning in just in case, and avoid 64-bit division.
*/ */
BUILD_BUG_ON(MAX_RW_COUNT > UINT_MAX);
if (end_fsb - offset_fsb > UINT_MAX) {
error = -EFSCORRUPTED;
xfs_force_shutdown(ip->i_mount, SHUTDOWN_CORRUPT_INCORE);
ASSERT(0);
goto out;
}
resblks = XFS_NEXTENTADD_SPACE_RES(ip->i_mount,
(unsigned int)(end_fsb - offset_fsb),
XFS_DATA_FORK);
error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write,
resblks, 0, XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp);
if (error)
goto out;
xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0); xfs_trans_ijoin(tp, ip, 0);
@ -679,80 +672,131 @@ xfs_reflink_end_cow(
* left by the time I/O completes for the loser of the race. In that * left by the time I/O completes for the loser of the race. In that
* case we are done. * case we are done.
*/ */
if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got)) if (!xfs_iext_lookup_extent_before(ip, ifp, end_fsb, &icur, &got) ||
got.br_startoff + got.br_blockcount <= offset_fsb) {
*end_fsb = offset_fsb;
goto out_cancel;
}
/*
* Structure copy @got into @del, then trim @del to the range that we
* were asked to remap. We preserve @got for the eventual CoW fork
* deletion; from now on @del represents the mapping that we're
* actually remapping.
*/
del = got;
xfs_trim_extent(&del, offset_fsb, *end_fsb - offset_fsb);
ASSERT(del.br_blockcount > 0);
/*
* Only remap real extents that contain data. With AIO, speculative
* preallocations can leak into the range we are called upon, and we
* need to skip them.
*/
if (!xfs_bmap_is_real_extent(&got)) {
*end_fsb = del.br_startoff;
goto out_cancel;
}
/* Unmap the old blocks in the data fork. */
rlen = del.br_blockcount;
error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1);
if (error)
goto out_cancel; goto out_cancel;
/* Walk backwards until we're out of the I/O range... */ /* Trim the extent to whatever got unmapped. */
while (got.br_startoff + got.br_blockcount > offset_fsb) { xfs_trim_extent(&del, del.br_startoff + rlen, del.br_blockcount - rlen);
del = got; trace_xfs_reflink_cow_remap(ip, &del);
xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb);
/* Extent delete may have bumped ext forward */ /* Free the CoW orphan record. */
if (!del.br_blockcount) error = xfs_refcount_free_cow_extent(tp, del.br_startblock,
goto prev_extent; del.br_blockcount);
if (error)
goto out_cancel;
/* /* Map the new blocks into the data fork. */
* Only remap real extent that contain data. With AIO error = xfs_bmap_map_extent(tp, ip, &del);
* speculatively preallocations can leak into the range we if (error)
* are called upon, and we need to skip them. goto out_cancel;
*/
if (!xfs_bmap_is_real_extent(&got))
goto prev_extent;
/* Unmap the old blocks in the data fork. */ /* Charge this new data fork mapping to the on-disk quota. */
ASSERT(tp->t_firstblock == NULLFSBLOCK); xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT,
rlen = del.br_blockcount; (long)del.br_blockcount);
error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1);
if (error)
goto out_cancel;
/* Trim the extent to whatever got unmapped. */ /* Remove the mapping from the CoW fork. */
if (rlen) { xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
xfs_trim_extent(&del, del.br_startoff + rlen,
del.br_blockcount - rlen);
}
trace_xfs_reflink_cow_remap(ip, &del);
/* Free the CoW orphan record. */
error = xfs_refcount_free_cow_extent(tp, del.br_startblock,
del.br_blockcount);
if (error)
goto out_cancel;
/* Map the new blocks into the data fork. */
error = xfs_bmap_map_extent(tp, ip, &del);
if (error)
goto out_cancel;
/* Charge this new data fork mapping to the on-disk quota. */
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT,
(long)del.br_blockcount);
/* Remove the mapping from the CoW fork. */
xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
error = xfs_defer_finish(&tp);
if (error)
goto out_cancel;
if (!xfs_iext_get_extent(ifp, &icur, &got))
break;
continue;
prev_extent:
if (!xfs_iext_prev_extent(ifp, &icur, &got))
break;
}
error = xfs_trans_commit(tp); error = xfs_trans_commit(tp);
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
if (error) if (error)
goto out; return error;
/* Update the caller about how much progress we made. */
*end_fsb = del.br_startoff;
return 0; return 0;
out_cancel: out_cancel:
xfs_trans_cancel(tp); xfs_trans_cancel(tp);
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
out: return error;
trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_); }
/*
* Remap parts of a file's data fork after a successful CoW.
*/
int
xfs_reflink_end_cow(
struct xfs_inode *ip,
xfs_off_t offset,
xfs_off_t count)
{
xfs_fileoff_t offset_fsb;
xfs_fileoff_t end_fsb;
int error = 0;
trace_xfs_reflink_end_cow(ip, offset, count);
offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
/*
* Walk backwards until we're out of the I/O range. The loop function
* repeatedly cycles the ILOCK to allocate one transaction per remapped
* extent.
*
* If we're being called by writeback then the the pages will still
* have PageWriteback set, which prevents races with reflink remapping
* and truncate. Reflink remapping prevents races with writeback by
* taking the iolock and mmaplock before flushing the pages and
* remapping, which means there won't be any further writeback or page
* cache dirtying until the reflink completes.
*
* We should never have two threads issuing writeback for the same file
* region. There are also have post-eof checks in the writeback
* preparation code so that we don't bother writing out pages that are
* about to be truncated.
*
* If we're being called as part of directio write completion, the dio
* count is still elevated, which reflink and truncate will wait for.
* Reflink remapping takes the iolock and mmaplock and waits for
* pending dio to finish, which should prevent any directio until the
* remap completes. Multiple concurrent directio writes to the same
* region are handled by end_cow processing only occurring for the
* threads which succeed; the outcome of multiple overlapping direct
* writes is not well defined anyway.
*
* It's possible that a buffered write and a direct write could collide
* here (the buffered write stumbles in after the dio flushes and
* invalidates the page cache and immediately queues writeback), but we
* have never supported this 100%. If either disk write succeeds the
* blocks will be remapped.
*/
while (end_fsb > offset_fsb && !error)
error = xfs_reflink_end_cow_extent(ip, offset_fsb, &end_fsb);
if (error)
trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_);
return error; return error;
} }

View File

@ -64,8 +64,12 @@ xfs_rtany_summary(
int log; /* loop counter, log2 of ext. size */ int log; /* loop counter, log2 of ext. size */
xfs_suminfo_t sum; /* summary data */ xfs_suminfo_t sum; /* summary data */
/* There are no extents at levels < m_rsum_cache[bbno]. */
if (mp->m_rsum_cache && low < mp->m_rsum_cache[bbno])
low = mp->m_rsum_cache[bbno];
/* /*
* Loop over logs of extent sizes. Order is irrelevant. * Loop over logs of extent sizes.
*/ */
for (log = low; log <= high; log++) { for (log = low; log <= high; log++) {
/* /*
@ -80,13 +84,17 @@ xfs_rtany_summary(
*/ */
if (sum) { if (sum) {
*stat = 1; *stat = 1;
return 0; goto out;
} }
} }
/* /*
* Found nothing, return failure. * Found nothing, return failure.
*/ */
*stat = 0; *stat = 0;
out:
/* There were no extents at levels < log. */
if (mp->m_rsum_cache && log > mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno] = log;
return 0; return 0;
} }
@ -853,6 +861,21 @@ out_trans_cancel:
return error; return error;
} }
static void
xfs_alloc_rsum_cache(
xfs_mount_t *mp, /* file system mount structure */
xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */
{
/*
* The rsum cache is initialized to all zeroes, which is trivially a
* lower bound on the minimum level with any free extents. We can
* continue without the cache if it couldn't be allocated.
*/
mp->m_rsum_cache = kmem_zalloc_large(rbmblocks, KM_SLEEP);
if (!mp->m_rsum_cache)
xfs_warn(mp, "could not allocate realtime summary cache");
}
/* /*
* Visible (exported) functions. * Visible (exported) functions.
*/ */
@ -881,6 +904,7 @@ xfs_growfs_rt(
xfs_extlen_t rsumblocks; /* current number of rt summary blks */ xfs_extlen_t rsumblocks; /* current number of rt summary blks */
xfs_sb_t *sbp; /* old superblock */ xfs_sb_t *sbp; /* old superblock */
xfs_fsblock_t sumbno; /* summary block number */ xfs_fsblock_t sumbno; /* summary block number */
uint8_t *rsum_cache; /* old summary cache */
sbp = &mp->m_sb; sbp = &mp->m_sb;
/* /*
@ -937,6 +961,11 @@ xfs_growfs_rt(
error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip); error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
if (error) if (error)
return error; return error;
rsum_cache = mp->m_rsum_cache;
if (nrbmblocks != sbp->sb_rbmblocks)
xfs_alloc_rsum_cache(mp, nrbmblocks);
/* /*
* Allocate a new (fake) mount/sb. * Allocate a new (fake) mount/sb.
*/ */
@ -1062,6 +1091,20 @@ error_cancel:
*/ */
kmem_free(nmp); kmem_free(nmp);
/*
* If we had to allocate a new rsum_cache, we either need to free the
* old one (if we succeeded) or free the new one and restore the old one
* (if there was an error).
*/
if (rsum_cache != mp->m_rsum_cache) {
if (error) {
kmem_free(mp->m_rsum_cache);
mp->m_rsum_cache = rsum_cache;
} else {
kmem_free(rsum_cache);
}
}
return error; return error;
} }
@ -1187,8 +1230,8 @@ xfs_rtmount_init(
} }
/* /*
* Get the bitmap and summary inodes into the mount structure * Get the bitmap and summary inodes and the summary cache into the mount
* at mount time. * structure at mount time.
*/ */
int /* error */ int /* error */
xfs_rtmount_inodes( xfs_rtmount_inodes(
@ -1198,19 +1241,18 @@ xfs_rtmount_inodes(
xfs_sb_t *sbp; xfs_sb_t *sbp;
sbp = &mp->m_sb; sbp = &mp->m_sb;
if (sbp->sb_rbmino == NULLFSINO)
return 0;
error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip); error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
if (error) if (error)
return error; return error;
ASSERT(mp->m_rbmip != NULL); ASSERT(mp->m_rbmip != NULL);
ASSERT(sbp->sb_rsumino != NULLFSINO);
error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip); error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
if (error) { if (error) {
xfs_irele(mp->m_rbmip); xfs_irele(mp->m_rbmip);
return error; return error;
} }
ASSERT(mp->m_rsumip != NULL); ASSERT(mp->m_rsumip != NULL);
xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
return 0; return 0;
} }
@ -1218,6 +1260,7 @@ void
xfs_rtunmount_inodes( xfs_rtunmount_inodes(
struct xfs_mount *mp) struct xfs_mount *mp)
{ {
kmem_free(mp->m_rsum_cache);
if (mp->m_rbmip) if (mp->m_rbmip)
xfs_irele(mp->m_rbmip); xfs_irele(mp->m_rbmip);
if (mp->m_rsumip) if (mp->m_rsumip)

View File

@ -38,6 +38,7 @@
#include "xfs_refcount_item.h" #include "xfs_refcount_item.h"
#include "xfs_bmap_item.h" #include "xfs_bmap_item.h"
#include "xfs_reflink.h" #include "xfs_reflink.h"
#include "xfs_defer.h"
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/dax.h> #include <linux/dax.h>
@ -607,7 +608,7 @@ xfs_set_inode_alloc(
} }
/* Get the last possible inode in the filesystem */ /* Get the last possible inode in the filesystem */
agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0); agino = XFS_AGB_TO_AGINO(mp, sbp->sb_agblocks - 1);
ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino); ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
/* /*
@ -1149,7 +1150,7 @@ xfs_fs_statfs(
statp->f_bfree = fdblocks - mp->m_alloc_set_aside; statp->f_bfree = fdblocks - mp->m_alloc_set_aside;
statp->f_bavail = statp->f_bfree; statp->f_bavail = statp->f_bfree;
fakeinos = statp->f_bfree << sbp->sb_inopblog; fakeinos = XFS_FSB_TO_INO(mp, statp->f_bfree);
statp->f_files = min(icount + fakeinos, (uint64_t)XFS_MAXINUMBER); statp->f_files = min(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),
@ -2085,11 +2086,6 @@ init_xfs_fs(void)
printk(KERN_INFO XFS_VERSION_STRING " with " printk(KERN_INFO XFS_VERSION_STRING " with "
XFS_BUILD_OPTIONS " enabled\n"); XFS_BUILD_OPTIONS " enabled\n");
xfs_extent_free_init_defer_op();
xfs_rmap_update_init_defer_op();
xfs_refcount_update_init_defer_op();
xfs_bmap_update_init_defer_op();
xfs_dir_startup(); xfs_dir_startup();
error = xfs_init_zones(); error = xfs_init_zones();

View File

@ -192,6 +192,7 @@ xfs_symlink(
pathlen = strlen(target_path); pathlen = strlen(target_path);
if (pathlen >= XFS_SYMLINK_MAXLEN) /* total string too long */ if (pathlen >= XFS_SYMLINK_MAXLEN) /* total string too long */
return -ENAMETOOLONG; return -ENAMETOOLONG;
ASSERT(pathlen > 0);
udqp = gdqp = NULL; udqp = gdqp = NULL;
prid = xfs_get_initial_prid(dp); prid = xfs_get_initial_prid(dp);
@ -378,6 +379,12 @@ out_release_inode:
/* /*
* Free a symlink that has blocks associated with it. * Free a symlink that has blocks associated with it.
*
* Note: zero length symlinks are not allowed to exist. When we set the size to
* zero, also change it to a regular file so that it does not get written to
* disk as a zero length symlink. The inode is on the unlinked list already, so
* userspace cannot find this inode anymore, so this change is not user visible
* but allows us to catch corrupt zero-length symlinks in the verifiers.
*/ */
STATIC int STATIC int
xfs_inactive_symlink_rmt( xfs_inactive_symlink_rmt(
@ -412,13 +419,14 @@ xfs_inactive_symlink_rmt(
xfs_trans_ijoin(tp, ip, 0); xfs_trans_ijoin(tp, ip, 0);
/* /*
* Lock the inode, fix the size, and join it to the transaction. * Lock the inode, fix the size, turn it into a regular file and join it
* Hold it so in the normal path, we still have it locked for * to the transaction. Hold it so in the normal path, we still have it
* the second transaction. In the error paths we need it * locked for the second transaction. In the error paths we need it
* held so the cancel won't rele it, see below. * held so the cancel won't rele it, see below.
*/ */
size = (int)ip->i_d.di_size; size = (int)ip->i_d.di_size;
ip->i_d.di_size = 0; ip->i_d.di_size = 0;
VFS_I(ip)->i_mode = (VFS_I(ip)->i_mode & ~S_IFMT) | S_IFREG;
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
/* /*
* Find the block(s) so we can inval and unmap them. * Find the block(s) so we can inval and unmap them.
@ -494,17 +502,10 @@ xfs_inactive_symlink(
return -EIO; return -EIO;
xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_ilock(ip, XFS_ILOCK_EXCL);
/*
* Zero length symlinks _can_ exist.
*/
pathlen = (int)ip->i_d.di_size; pathlen = (int)ip->i_d.di_size;
if (!pathlen) { ASSERT(pathlen);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
return 0;
}
if (pathlen < 0 || pathlen > XFS_SYMLINK_MAXLEN) { if (pathlen <= 0 || pathlen > XFS_SYMLINK_MAXLEN) {
xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)",
__func__, (unsigned long long)ip->i_ino, pathlen); __func__, (unsigned long long)ip->i_ino, pathlen);
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
@ -512,12 +513,12 @@ xfs_inactive_symlink(
return -EFSCORRUPTED; return -EFSCORRUPTED;
} }
/*
* Inline fork state gets removed by xfs_difree() so we have nothing to
* do here in that case.
*/
if (ip->i_df.if_flags & XFS_IFINLINE) { if (ip->i_df.if_flags & XFS_IFINLINE) {
if (ip->i_df.if_bytes > 0)
xfs_idata_realloc(ip, -(ip->i_df.if_bytes),
XFS_DATA_FORK);
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
ASSERT(ip->i_df.if_bytes == 0);
return 0; return 0;
} }

View File

@ -640,6 +640,16 @@ DEFINE_INODE_EVENT(xfs_inode_set_cowblocks_tag);
DEFINE_INODE_EVENT(xfs_inode_clear_cowblocks_tag); DEFINE_INODE_EVENT(xfs_inode_clear_cowblocks_tag);
DEFINE_INODE_EVENT(xfs_inode_free_cowblocks_invalid); DEFINE_INODE_EVENT(xfs_inode_free_cowblocks_invalid);
/*
* ftrace's __print_symbolic requires that all enum values be wrapped in the
* TRACE_DEFINE_ENUM macro so that the enum value can be encoded in the ftrace
* ring buffer. Somehow this was only worth mentioning in the ftrace sample
* code.
*/
TRACE_DEFINE_ENUM(PE_SIZE_PTE);
TRACE_DEFINE_ENUM(PE_SIZE_PMD);
TRACE_DEFINE_ENUM(PE_SIZE_PUD);
TRACE_EVENT(xfs_filemap_fault, TRACE_EVENT(xfs_filemap_fault,
TP_PROTO(struct xfs_inode *ip, enum page_entry_size pe_size, TP_PROTO(struct xfs_inode *ip, enum page_entry_size pe_size,
bool write_fault), bool write_fault),
@ -1208,6 +1218,12 @@ DEFINE_EVENT(xfs_readpage_class, name, \
DEFINE_READPAGE_EVENT(xfs_vm_readpage); DEFINE_READPAGE_EVENT(xfs_vm_readpage);
DEFINE_READPAGE_EVENT(xfs_vm_readpages); DEFINE_READPAGE_EVENT(xfs_vm_readpages);
TRACE_DEFINE_ENUM(XFS_IO_HOLE);
TRACE_DEFINE_ENUM(XFS_IO_DELALLOC);
TRACE_DEFINE_ENUM(XFS_IO_UNWRITTEN);
TRACE_DEFINE_ENUM(XFS_IO_OVERWRITE);
TRACE_DEFINE_ENUM(XFS_IO_COW);
DECLARE_EVENT_CLASS(xfs_imap_class, DECLARE_EVENT_CLASS(xfs_imap_class,
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
int type, struct xfs_bmbt_irec *irec), int type, struct xfs_bmbt_irec *irec),
@ -1885,11 +1901,11 @@ TRACE_EVENT(xfs_dir2_leafn_moveents,
{ 0, "target" }, \ { 0, "target" }, \
{ 1, "temp" } { 1, "temp" }
#define XFS_INODE_FORMAT_STR \ TRACE_DEFINE_ENUM(XFS_DINODE_FMT_DEV);
{ 0, "invalid" }, \ TRACE_DEFINE_ENUM(XFS_DINODE_FMT_LOCAL);
{ 1, "local" }, \ TRACE_DEFINE_ENUM(XFS_DINODE_FMT_EXTENTS);
{ 2, "extent" }, \ TRACE_DEFINE_ENUM(XFS_DINODE_FMT_BTREE);
{ 3, "btree" } TRACE_DEFINE_ENUM(XFS_DINODE_FMT_UUID);
DECLARE_EVENT_CLASS(xfs_swap_extent_class, DECLARE_EVENT_CLASS(xfs_swap_extent_class,
TP_PROTO(struct xfs_inode *ip, int which), TP_PROTO(struct xfs_inode *ip, int which),
@ -2178,6 +2194,14 @@ DEFINE_DISCARD_EVENT(xfs_discard_exclude);
DEFINE_DISCARD_EVENT(xfs_discard_busy); DEFINE_DISCARD_EVENT(xfs_discard_busy);
/* btree cursor events */ /* btree cursor events */
TRACE_DEFINE_ENUM(XFS_BTNUM_BNOi);
TRACE_DEFINE_ENUM(XFS_BTNUM_CNTi);
TRACE_DEFINE_ENUM(XFS_BTNUM_BMAPi);
TRACE_DEFINE_ENUM(XFS_BTNUM_INOi);
TRACE_DEFINE_ENUM(XFS_BTNUM_FINOi);
TRACE_DEFINE_ENUM(XFS_BTNUM_RMAPi);
TRACE_DEFINE_ENUM(XFS_BTNUM_REFCi);
DECLARE_EVENT_CLASS(xfs_btree_cur_class, DECLARE_EVENT_CLASS(xfs_btree_cur_class,
TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp),
TP_ARGS(cur, level, bp), TP_ARGS(cur, level, bp),
@ -2197,9 +2221,9 @@ DECLARE_EVENT_CLASS(xfs_btree_cur_class,
__entry->ptr = cur->bc_ptrs[level]; __entry->ptr = cur->bc_ptrs[level];
__entry->daddr = bp ? bp->b_bn : -1; __entry->daddr = bp ? bp->b_bn : -1;
), ),
TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx", TP_printk("dev %d:%d btree %s level %d/%d ptr %d daddr 0x%llx",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->btnum, __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
__entry->level, __entry->level,
__entry->nlevels, __entry->nlevels,
__entry->ptr, __entry->ptr,
@ -2276,7 +2300,7 @@ DECLARE_EVENT_CLASS(xfs_defer_pending_class,
), ),
TP_fast_assign( TP_fast_assign(
__entry->dev = mp ? mp->m_super->s_dev : 0; __entry->dev = mp ? mp->m_super->s_dev : 0;
__entry->type = dfp->dfp_type->type; __entry->type = dfp->dfp_type;
__entry->intent = dfp->dfp_intent; __entry->intent = dfp->dfp_intent;
__entry->committed = dfp->dfp_done != NULL; __entry->committed = dfp->dfp_done != NULL;
__entry->nr = dfp->dfp_count; __entry->nr = dfp->dfp_count;
@ -2405,7 +2429,7 @@ DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_agfl_free_deferred);
DECLARE_EVENT_CLASS(xfs_rmap_class, DECLARE_EVENT_CLASS(xfs_rmap_class,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten,
struct xfs_owner_info *oinfo), const struct xfs_owner_info *oinfo),
TP_ARGS(mp, agno, agbno, len, unwritten, oinfo), TP_ARGS(mp, agno, agbno, len, unwritten, oinfo),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(dev_t, dev) __field(dev_t, dev)
@ -2440,7 +2464,7 @@ DECLARE_EVENT_CLASS(xfs_rmap_class,
DEFINE_EVENT(xfs_rmap_class, name, \ DEFINE_EVENT(xfs_rmap_class, name, \
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, \ xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, \
struct xfs_owner_info *oinfo), \ const struct xfs_owner_info *oinfo), \
TP_ARGS(mp, agno, agbno, len, unwritten, oinfo)) TP_ARGS(mp, agno, agbno, len, unwritten, oinfo))
/* simple AG-based error/%ip tracepoint class */ /* simple AG-based error/%ip tracepoint class */
@ -2610,10 +2634,9 @@ DEFINE_AG_ERROR_EVENT(xfs_ag_resv_init_error);
#define DEFINE_AG_EXTENT_EVENT(name) DEFINE_DISCARD_EVENT(name) #define DEFINE_AG_EXTENT_EVENT(name) DEFINE_DISCARD_EVENT(name)
/* ag btree lookup tracepoint class */ /* ag btree lookup tracepoint class */
#define XFS_AG_BTREE_CMP_FORMAT_STR \ TRACE_DEFINE_ENUM(XFS_LOOKUP_EQi);
{ XFS_LOOKUP_EQ, "eq" }, \ TRACE_DEFINE_ENUM(XFS_LOOKUP_LEi);
{ XFS_LOOKUP_LE, "le" }, \ TRACE_DEFINE_ENUM(XFS_LOOKUP_GEi);
{ XFS_LOOKUP_GE, "ge" }
DECLARE_EVENT_CLASS(xfs_ag_btree_lookup_class, DECLARE_EVENT_CLASS(xfs_ag_btree_lookup_class,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agblock_t agbno, xfs_lookup_t dir), xfs_agblock_t agbno, xfs_lookup_t dir),

View File

@ -223,13 +223,13 @@ void xfs_trans_dirty_buf(struct xfs_trans *, struct xfs_buf *);
bool xfs_trans_buf_is_dirty(struct xfs_buf *bp); bool xfs_trans_buf_is_dirty(struct xfs_buf *bp);
void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
void xfs_extent_free_init_defer_op(void);
struct xfs_efd_log_item *xfs_trans_get_efd(struct xfs_trans *, struct xfs_efd_log_item *xfs_trans_get_efd(struct xfs_trans *,
struct xfs_efi_log_item *, struct xfs_efi_log_item *,
uint); uint);
int xfs_trans_free_extent(struct xfs_trans *, int xfs_trans_free_extent(struct xfs_trans *,
struct xfs_efd_log_item *, xfs_fsblock_t, struct xfs_efd_log_item *, xfs_fsblock_t,
xfs_extlen_t, struct xfs_owner_info *, xfs_extlen_t,
const struct xfs_owner_info *,
bool); bool);
int xfs_trans_commit(struct xfs_trans *); int xfs_trans_commit(struct xfs_trans *);
int xfs_trans_roll(struct xfs_trans **); int xfs_trans_roll(struct xfs_trans **);
@ -248,7 +248,6 @@ extern kmem_zone_t *xfs_trans_zone;
/* rmap updates */ /* rmap updates */
enum xfs_rmap_intent_type; enum xfs_rmap_intent_type;
void xfs_rmap_update_init_defer_op(void);
struct xfs_rud_log_item *xfs_trans_get_rud(struct xfs_trans *tp, struct xfs_rud_log_item *xfs_trans_get_rud(struct xfs_trans *tp,
struct xfs_rui_log_item *ruip); struct xfs_rui_log_item *ruip);
int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp, int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
@ -260,7 +259,6 @@ int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
/* refcount updates */ /* refcount updates */
enum xfs_refcount_intent_type; enum xfs_refcount_intent_type;
void xfs_refcount_update_init_defer_op(void);
struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp, struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp,
struct xfs_cui_log_item *cuip); struct xfs_cui_log_item *cuip);
int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp, int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp,
@ -272,7 +270,6 @@ int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp,
/* mapping updates */ /* mapping updates */
enum xfs_bmap_intent_type; enum xfs_bmap_intent_type;
void xfs_bmap_update_init_defer_op(void);
struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp, struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp,
struct xfs_bui_log_item *buip); struct xfs_bui_log_item *buip);
int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp, int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp,

View File

@ -17,6 +17,7 @@
#include "xfs_alloc.h" #include "xfs_alloc.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_defer.h"
/* /*
* This routine is called to allocate a "bmap update done" * This routine is called to allocate a "bmap update done"
@ -220,8 +221,7 @@ xfs_bmap_update_cancel_item(
kmem_free(bmap); kmem_free(bmap);
} }
static const struct xfs_defer_op_type xfs_bmap_update_defer_type = { const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
.type = XFS_DEFER_OPS_TYPE_BMAP,
.max_items = XFS_BUI_MAX_FAST_EXTENTS, .max_items = XFS_BUI_MAX_FAST_EXTENTS,
.diff_items = xfs_bmap_update_diff_items, .diff_items = xfs_bmap_update_diff_items,
.create_intent = xfs_bmap_update_create_intent, .create_intent = xfs_bmap_update_create_intent,
@ -231,10 +231,3 @@ static const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
.finish_item = xfs_bmap_update_finish_item, .finish_item = xfs_bmap_update_finish_item,
.cancel_item = xfs_bmap_update_cancel_item, .cancel_item = xfs_bmap_update_cancel_item,
}; };
/* Register the deferred op type. */
void
xfs_bmap_update_init_defer_op(void)
{
xfs_defer_init_op_type(&xfs_bmap_update_defer_type);
}

View File

@ -18,6 +18,7 @@
#include "xfs_alloc.h" #include "xfs_alloc.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "xfs_trace.h" #include "xfs_trace.h"
#include "xfs_defer.h"
/* /*
* This routine is called to allocate an "extent free done" * This routine is called to allocate an "extent free done"
@ -52,19 +53,20 @@ xfs_trans_get_efd(struct xfs_trans *tp,
*/ */
int int
xfs_trans_free_extent( xfs_trans_free_extent(
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_efd_log_item *efdp, struct xfs_efd_log_item *efdp,
xfs_fsblock_t start_block, xfs_fsblock_t start_block,
xfs_extlen_t ext_len, xfs_extlen_t ext_len,
struct xfs_owner_info *oinfo, const struct xfs_owner_info *oinfo,
bool skip_discard) bool skip_discard)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
uint next_extent; struct xfs_extent *extp;
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, start_block); uint next_extent;
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, start_block); xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, start_block);
struct xfs_extent *extp; xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
int error; start_block);
int error;
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len); trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
@ -206,8 +208,7 @@ xfs_extent_free_cancel_item(
kmem_free(free); kmem_free(free);
} }
static const struct xfs_defer_op_type xfs_extent_free_defer_type = { const struct xfs_defer_op_type xfs_extent_free_defer_type = {
.type = XFS_DEFER_OPS_TYPE_FREE,
.max_items = XFS_EFI_MAX_FAST_EXTENTS, .max_items = XFS_EFI_MAX_FAST_EXTENTS,
.diff_items = xfs_extent_free_diff_items, .diff_items = xfs_extent_free_diff_items,
.create_intent = xfs_extent_free_create_intent, .create_intent = xfs_extent_free_create_intent,
@ -274,8 +275,7 @@ xfs_agfl_free_finish_item(
/* sub-type with special handling for AGFL deferred frees */ /* sub-type with special handling for AGFL deferred frees */
static const struct xfs_defer_op_type xfs_agfl_free_defer_type = { const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
.type = XFS_DEFER_OPS_TYPE_AGFL_FREE,
.max_items = XFS_EFI_MAX_FAST_EXTENTS, .max_items = XFS_EFI_MAX_FAST_EXTENTS,
.diff_items = xfs_extent_free_diff_items, .diff_items = xfs_extent_free_diff_items,
.create_intent = xfs_extent_free_create_intent, .create_intent = xfs_extent_free_create_intent,
@ -285,11 +285,3 @@ static const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
.finish_item = xfs_agfl_free_finish_item, .finish_item = xfs_agfl_free_finish_item,
.cancel_item = xfs_extent_free_cancel_item, .cancel_item = xfs_extent_free_cancel_item,
}; };
/* Register the deferred op type. */
void
xfs_extent_free_init_defer_op(void)
{
xfs_defer_init_op_type(&xfs_extent_free_defer_type);
xfs_defer_init_op_type(&xfs_agfl_free_defer_type);
}

View File

@ -16,6 +16,7 @@
#include "xfs_refcount_item.h" #include "xfs_refcount_item.h"
#include "xfs_alloc.h" #include "xfs_alloc.h"
#include "xfs_refcount.h" #include "xfs_refcount.h"
#include "xfs_defer.h"
/* /*
* This routine is called to allocate a "refcount update done" * This routine is called to allocate a "refcount update done"
@ -227,8 +228,7 @@ xfs_refcount_update_cancel_item(
kmem_free(refc); kmem_free(refc);
} }
static const struct xfs_defer_op_type xfs_refcount_update_defer_type = { const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
.type = XFS_DEFER_OPS_TYPE_REFCOUNT,
.max_items = XFS_CUI_MAX_FAST_EXTENTS, .max_items = XFS_CUI_MAX_FAST_EXTENTS,
.diff_items = xfs_refcount_update_diff_items, .diff_items = xfs_refcount_update_diff_items,
.create_intent = xfs_refcount_update_create_intent, .create_intent = xfs_refcount_update_create_intent,
@ -239,10 +239,3 @@ static const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
.finish_cleanup = xfs_refcount_update_finish_cleanup, .finish_cleanup = xfs_refcount_update_finish_cleanup,
.cancel_item = xfs_refcount_update_cancel_item, .cancel_item = xfs_refcount_update_cancel_item,
}; };
/* Register the deferred op type. */
void
xfs_refcount_update_init_defer_op(void)
{
xfs_defer_init_op_type(&xfs_refcount_update_defer_type);
}

View File

@ -16,6 +16,7 @@
#include "xfs_rmap_item.h" #include "xfs_rmap_item.h"
#include "xfs_alloc.h" #include "xfs_alloc.h"
#include "xfs_rmap.h" #include "xfs_rmap.h"
#include "xfs_defer.h"
/* Set the map extent flags for this reverse mapping. */ /* Set the map extent flags for this reverse mapping. */
static void static void
@ -244,8 +245,7 @@ xfs_rmap_update_cancel_item(
kmem_free(rmap); kmem_free(rmap);
} }
static const struct xfs_defer_op_type xfs_rmap_update_defer_type = { const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
.type = XFS_DEFER_OPS_TYPE_RMAP,
.max_items = XFS_RUI_MAX_FAST_EXTENTS, .max_items = XFS_RUI_MAX_FAST_EXTENTS,
.diff_items = xfs_rmap_update_diff_items, .diff_items = xfs_rmap_update_diff_items,
.create_intent = xfs_rmap_update_create_intent, .create_intent = xfs_rmap_update_create_intent,
@ -256,10 +256,3 @@ static const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
.finish_cleanup = xfs_rmap_update_finish_cleanup, .finish_cleanup = xfs_rmap_update_finish_cleanup,
.cancel_item = xfs_rmap_update_cancel_item, .cancel_item = xfs_rmap_update_cancel_item,
}; };
/* Register the deferred op type. */
void
xfs_rmap_update_init_defer_op(void)
{
xfs_defer_init_op_type(&xfs_rmap_update_defer_type);
}