From a5155b870d687de1a5f07e774b49b1e8ef0f6f50 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Sat, 2 Nov 2019 09:40:53 -0700 Subject: xfs: always log corruption errors Make sure we log something to dmesg whenever we return -EFSCORRUPTED up the call stack. Signed-off-by: Darrick J. Wong Reviewed-by: Carlos Maiolino Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_dir2_node.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 705c4f562758..72d7ed17eef5 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -373,8 +373,10 @@ xfs_dir2_leaf_to_node( leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); if (be32_to_cpu(ltp->bestcount) > - (uint)dp->i_d.di_size / args->geo->blksize) + (uint)dp->i_d.di_size / args->geo->blksize) { + xfs_buf_corruption_error(lbp); return -EFSCORRUPTED; + } /* * Copy freespace entries from the leaf block to the new block. @@ -445,8 +447,10 @@ xfs_dir2_leafn_add( * Quick check just to make sure we are not going to index * into other peoples memory */ - if (index < 0) + if (index < 0) { + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; + } /* * If there are already the maximum number of leaf entries in @@ -739,8 +743,10 @@ xfs_dir2_leafn_lookup_for_entry( ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); - if (leafhdr.count <= 0) + if (leafhdr.count <= 0) { + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; + } /* * Look up the hash value in the leaf entries. -- cgit From 518425560a8b6ec7516505846c1b79623b467148 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:49 -0800 Subject: xfs: devirtualize ->leaf_hdr_from_disk Replace the ->leaf_hdr_from_disk dir ops method with a directly called xfs_dir2_leaf_hdr_from_disk helper that takes care of the differences between the v4 and v5 on-disk format. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 72d7ed17eef5..d4402b491a41 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -45,7 +45,7 @@ xfs_dir3_leafn_check( struct xfs_dir2_leaf *leaf = bp->b_addr; struct xfs_dir3_icleaf_hdr leafhdr; - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) { struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; @@ -440,7 +440,7 @@ xfs_dir2_leafn_add( trace_xfs_dir2_leafn_add(args, index); - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* @@ -538,7 +538,7 @@ xfs_dir2_leaf_lasthash( struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC || @@ -587,7 +587,7 @@ xfs_dir2_leafn_lookup_for_addname( tp = args->trans; mp = dp->i_mount; leaf = bp->b_addr; - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); @@ -739,7 +739,7 @@ xfs_dir2_leafn_lookup_for_entry( tp = args->trans; mp = dp->i_mount; leaf = bp->b_addr; - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); @@ -977,8 +977,8 @@ xfs_dir2_leafn_order( struct xfs_dir3_icleaf_hdr hdr1; struct xfs_dir3_icleaf_hdr hdr2; - dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); - dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2); ents1 = dp->d_ops->leaf_ents_p(leaf1); ents2 = dp->d_ops->leaf_ents_p(leaf2); @@ -1030,8 +1030,8 @@ xfs_dir2_leafn_rebalance( leaf1 = blk1->bp->b_addr; leaf2 = blk2->bp->b_addr; - dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); - dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2); ents1 = dp->d_ops->leaf_ents_p(leaf1); ents2 = dp->d_ops->leaf_ents_p(leaf2); @@ -1228,7 +1228,7 @@ xfs_dir2_leafn_remove( dp = args->dp; tp = args->trans; leaf = bp->b_addr; - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* @@ -1450,7 +1450,7 @@ xfs_dir2_leafn_toosmall( */ blk = &state->path.blk[state->path.active - 1]; leaf = blk->bp->b_addr; - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, blk->bp); @@ -1513,7 +1513,7 @@ xfs_dir2_leafn_toosmall( (state->args->geo->blksize >> 2); leaf = bp->b_addr; - dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf); ents = dp->d_ops->leaf_ents_p(leaf); count += hdr2.count - hdr2.stale; bytes -= count * sizeof(ents[0]); @@ -1576,8 +1576,8 @@ xfs_dir2_leafn_unbalance( drop_leaf = drop_blk->bp->b_addr; save_leaf = save_blk->bp->b_addr; - dp->d_ops->leaf_hdr_from_disk(&savehdr, save_leaf); - dp->d_ops->leaf_hdr_from_disk(&drophdr, drop_leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &savehdr, save_leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &drophdr, drop_leaf); sents = dp->d_ops->leaf_ents_p(save_leaf); dents = dp->d_ops->leaf_ents_p(drop_leaf); -- cgit From 163fbbb3568b6acf762449b8aa7713c764cf860a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:50 -0800 Subject: xfs: devirtualize ->leaf_hdr_to_disk Replace the ->leaf_hdr_to_disk dir ops method with a directly called xfs_dir_leaf_hdr_to_disk helper that takes care of the differences between the v4 and v5 on-disk format. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index d4402b491a41..98cd645a8c99 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -497,7 +497,7 @@ xfs_dir2_leafn_add( lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(args->geo, args->blkno, args->index)); - dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf, &leafhdr); xfs_dir3_leaf_log_header(args, bp); xfs_dir3_leaf_log_ents(args, bp, lfloglow, lfloghigh); xfs_dir3_leaf_check(dp, bp); @@ -1079,8 +1079,8 @@ xfs_dir2_leafn_rebalance( ASSERT(hdr1.stale + hdr2.stale == oldstale); /* log the changes made when moving the entries */ - dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1); - dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2); + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf1, &hdr1); + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf2, &hdr2); xfs_dir3_leaf_log_header(args, blk1->bp); xfs_dir3_leaf_log_header(args, blk2->bp); @@ -1249,7 +1249,7 @@ xfs_dir2_leafn_remove( * Log the leaf block changes. */ leafhdr.stale++; - dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf, &leafhdr); xfs_dir3_leaf_log_header(args, bp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); @@ -1605,8 +1605,8 @@ xfs_dir2_leafn_unbalance( save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval); /* log the changes made when moving the entries */ - dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr); - dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr); + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, save_leaf, &savehdr); + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, drop_leaf, &drophdr); xfs_dir3_leaf_log_header(args, save_blk->bp); xfs_dir3_leaf_log_header(args, drop_blk->bp); -- cgit From 787b0893ad1e315ea014dc3f0e01a5bc9236c623 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:50 -0800 Subject: xfs: add an entries pointer to struct xfs_dir3_icleaf_hdr All callers of the ->node_tree_p dir operation already have a struct xfs_dir3_icleaf_hdr from a previous call to xfs_da_leaf_hdr_from_disk at hand, or just need slight changes to the calling conventions to do so. Add a pointer to the entries to struct xfs_dir3_icleaf_hdr to clean up this pattern. To make this possible the xfs_dir3_leaf_log_ents function grow a new argument to pass the xfs_dir3_icleaf_hdr that call callers already have, and xfs_dir2_leaf_lookup_int returns the xfs_dir3_icleaf_hdr to the callers so that they can later use it. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 64 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 98cd645a8c99..721dd2dcba8d 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -441,7 +441,7 @@ xfs_dir2_leafn_add( trace_xfs_dir2_leafn_add(args, index); xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); - ents = dp->d_ops->leaf_ents_p(leaf); + ents = leafhdr.ents; /* * Quick check just to make sure we are not going to index @@ -499,7 +499,7 @@ xfs_dir2_leafn_add( xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf, &leafhdr); xfs_dir3_leaf_log_header(args, bp); - xfs_dir3_leaf_log_ents(args, bp, lfloglow, lfloghigh); + xfs_dir3_leaf_log_ents(args, &leafhdr, bp, lfloglow, lfloghigh); xfs_dir3_leaf_check(dp, bp); return 0; } @@ -534,11 +534,9 @@ xfs_dir2_leaf_lasthash( struct xfs_buf *bp, /* leaf buffer */ int *count) /* count of entries in leaf */ { - struct xfs_dir2_leaf *leaf = bp->b_addr; - struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; - xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, bp->b_addr); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC || @@ -549,9 +547,7 @@ xfs_dir2_leaf_lasthash( *count = leafhdr.count; if (!leafhdr.count) return 0; - - ents = dp->d_ops->leaf_ents_p(leaf); - return be32_to_cpu(ents[leafhdr.count - 1].hashval); + return be32_to_cpu(leafhdr.ents[leafhdr.count - 1].hashval); } /* @@ -580,7 +576,6 @@ xfs_dir2_leafn_lookup_for_addname( xfs_dir2_db_t newdb; /* new data block number */ xfs_dir2_db_t newfdb; /* new free block number */ xfs_trans_t *tp; /* transaction pointer */ - struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; dp = args->dp; @@ -588,7 +583,6 @@ xfs_dir2_leafn_lookup_for_addname( mp = dp->i_mount; leaf = bp->b_addr; xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf); - ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); ASSERT(leafhdr.count > 0); @@ -612,7 +606,7 @@ xfs_dir2_leafn_lookup_for_addname( /* * Loop over leaf entries with the right hash value. */ - for (lep = &ents[index]; + for (lep = &leafhdr.ents[index]; index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) { /* @@ -732,7 +726,6 @@ xfs_dir2_leafn_lookup_for_entry( xfs_dir2_db_t newdb; /* new data block number */ xfs_trans_t *tp; /* transaction pointer */ enum xfs_dacmp cmp; /* comparison result */ - struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; dp = args->dp; @@ -740,7 +733,6 @@ xfs_dir2_leafn_lookup_for_entry( mp = dp->i_mount; leaf = bp->b_addr; xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf); - ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); if (leafhdr.count <= 0) { @@ -762,7 +754,7 @@ xfs_dir2_leafn_lookup_for_entry( /* * Loop over leaf entries with the right hash value. */ - for (lep = &ents[index]; + for (lep = &leafhdr.ents[index]; index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) { /* @@ -917,7 +909,7 @@ xfs_dir3_leafn_moveents( if (start_d < dhdr->count) { memmove(&dents[start_d + count], &dents[start_d], (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir3_leaf_log_ents(args, bp_d, start_d + count, + xfs_dir3_leaf_log_ents(args, dhdr, bp_d, start_d + count, count + dhdr->count - 1); } /* @@ -939,7 +931,7 @@ xfs_dir3_leafn_moveents( */ memcpy(&dents[start_d], &sents[start_s], count * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir3_leaf_log_ents(args, bp_d, start_d, start_d + count - 1); + xfs_dir3_leaf_log_ents(args, dhdr, bp_d, start_d, start_d + count - 1); /* * If there are source entries after the ones we copied, @@ -948,7 +940,8 @@ xfs_dir3_leafn_moveents( if (start_s + count < shdr->count) { memmove(&sents[start_s], &sents[start_s + count], count * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir3_leaf_log_ents(args, bp_s, start_s, start_s + count - 1); + xfs_dir3_leaf_log_ents(args, shdr, bp_s, start_s, + start_s + count - 1); } /* @@ -979,8 +972,8 @@ xfs_dir2_leafn_order( xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1); xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2); - ents1 = dp->d_ops->leaf_ents_p(leaf1); - ents2 = dp->d_ops->leaf_ents_p(leaf2); + ents1 = hdr1.ents; + ents2 = hdr2.ents; if (hdr1.count > 0 && hdr2.count > 0 && (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) || @@ -1032,8 +1025,8 @@ xfs_dir2_leafn_rebalance( leaf2 = blk2->bp->b_addr; xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1); xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2); - ents1 = dp->d_ops->leaf_ents_p(leaf1); - ents2 = dp->d_ops->leaf_ents_p(leaf2); + ents1 = hdr1.ents; + ents2 = hdr2.ents; oldsum = hdr1.count + hdr2.count; #if defined(DEBUG) || defined(XFS_WARN) @@ -1221,7 +1214,6 @@ xfs_dir2_leafn_remove( xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir2_data_free *bf; /* bestfree table */ struct xfs_dir3_icleaf_hdr leafhdr; - struct xfs_dir2_leaf_entry *ents; trace_xfs_dir2_leafn_remove(args, index); @@ -1229,12 +1221,11 @@ xfs_dir2_leafn_remove( tp = args->trans; leaf = bp->b_addr; xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); - ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the entry we're removing. */ - lep = &ents[index]; + lep = &leafhdr.ents[index]; /* * Extract the data block and offset from the entry. @@ -1253,7 +1244,7 @@ xfs_dir2_leafn_remove( xfs_dir3_leaf_log_header(args, bp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); - xfs_dir3_leaf_log_ents(args, bp, index, index); + xfs_dir3_leaf_log_ents(args, &leafhdr, bp, index, index); /* * Make the data entry free. Keep track of the longest freespace @@ -1350,7 +1341,7 @@ xfs_dir2_leafn_remove( * to justify trying to join it with a neighbor. */ *rval = (dp->d_ops->leaf_hdr_size + - (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < + (uint)sizeof(leafhdr.ents) * (leafhdr.count - leafhdr.stale)) < args->geo->magicpct; return 0; } @@ -1451,7 +1442,7 @@ xfs_dir2_leafn_toosmall( blk = &state->path.blk[state->path.active - 1]; leaf = blk->bp->b_addr; xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); - ents = dp->d_ops->leaf_ents_p(leaf); + ents = leafhdr.ents; xfs_dir3_leaf_check(dp, blk->bp); count = leafhdr.count - leafhdr.stale; @@ -1514,7 +1505,7 @@ xfs_dir2_leafn_toosmall( leaf = bp->b_addr; xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf); - ents = dp->d_ops->leaf_ents_p(leaf); + ents = hdr2.ents; count += hdr2.count - hdr2.stale; bytes -= count * sizeof(ents[0]); @@ -1578,8 +1569,8 @@ xfs_dir2_leafn_unbalance( xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &savehdr, save_leaf); xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &drophdr, drop_leaf); - sents = dp->d_ops->leaf_ents_p(save_leaf); - dents = dp->d_ops->leaf_ents_p(drop_leaf); + sents = savehdr.ents; + dents = drophdr.ents; /* * If there are any stale leaf entries, take this opportunity @@ -2161,8 +2152,6 @@ xfs_dir2_node_replace( int i; /* btree level */ xfs_ino_t inum; /* new inode number */ int ftype; /* new file type */ - xfs_dir2_leaf_t *leaf; /* leaf structure */ - xfs_dir2_leaf_entry_t *lep; /* leaf entry being changed */ int rval; /* internal return value */ xfs_da_state_t *state; /* btree cursor */ @@ -2194,16 +2183,17 @@ xfs_dir2_node_replace( * and locked it. But paranoia is good. */ if (rval == -EEXIST) { - struct xfs_dir2_leaf_entry *ents; + struct xfs_dir3_icleaf_hdr leafhdr; + /* * Find the leaf entry. */ blk = &state->path.blk[state->path.active - 1]; ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); - leaf = blk->bp->b_addr; - ents = args->dp->d_ops->leaf_ents_p(leaf); - lep = &ents[blk->index]; ASSERT(state->extravalid); + + xfs_dir2_leaf_hdr_from_disk(state->mp, &leafhdr, + blk->bp->b_addr); /* * Point to the data entry. */ @@ -2213,7 +2203,7 @@ xfs_dir2_node_replace( dep = (xfs_dir2_data_entry_t *) ((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, - be32_to_cpu(lep->address))); + be32_to_cpu(leafhdr.ents[blk->index].address))); ASSERT(inum != be64_to_cpu(dep->inumber)); /* * Fill in the new inode number and log the entry. -- cgit From 545910bcc875377160b7b669e790865602a006f3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:51 -0800 Subject: xfs: move the dir2 leaf header size to struct xfs_da_geometry Move the leaf header size towards our structure for dir/attr geometry parameters. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 721dd2dcba8d..f7ba4d22165c 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -1340,7 +1340,7 @@ xfs_dir2_leafn_remove( * Return indication of whether this leaf block is empty enough * to justify trying to join it with a neighbor. */ - *rval = (dp->d_ops->leaf_hdr_size + + *rval = (args->geo->leaf_hdr_size + (uint)sizeof(leafhdr.ents) * (leafhdr.count - leafhdr.stale)) < args->geo->magicpct; return 0; @@ -1446,7 +1446,7 @@ xfs_dir2_leafn_toosmall( xfs_dir3_leaf_check(dp, blk->bp); count = leafhdr.count - leafhdr.stale; - bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]); + bytes = state->args->geo->leaf_hdr_size + count * sizeof(ents[0]); if (bytes > (state->args->geo->blksize >> 1)) { /* * Blk over 50%, don't try to join. -- cgit From 478c7835cb8ee28e73e732642866995f8555df7e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:51 -0800 Subject: xfs: move the max dir2 leaf entries count to struct xfs_da_geometry Move the max leaf entries count towards our structure for dir/attr geometry parameters. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index f7ba4d22165c..2c44248b7b4a 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -459,7 +459,7 @@ xfs_dir2_leafn_add( * a compact. */ - if (leafhdr.count == dp->d_ops->leaf_max_ents(args->geo)) { + if (leafhdr.count == args->geo->leaf_max_ents) { if (!leafhdr.stale) return -ENOSPC; compact = leafhdr.stale > 1; -- cgit From 5ba30919a6fcf0d3d52507082ea67fab32c8bb29 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:52 -0800 Subject: xfs: devirtualize ->free_hdr_from_disk Replace the ->free_hdr_from_disk dir ops method with a directly called xfs_dir_free_hdr_from_disk helper that takes care of the differences between the v4 and v5 on-disk format. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 46 +++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 2c44248b7b4a..d337ecd4e3be 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -54,7 +54,7 @@ xfs_dir3_leafn_check( } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC) return __this_address; - return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf); + return xfs_dir3_leaf_check_int(dp->i_mount, &leafhdr, leaf); } static inline void @@ -220,6 +220,30 @@ __xfs_dir3_free_read( return 0; } +void +xfs_dir2_free_hdr_from_disk( + struct xfs_mount *mp, + struct xfs_dir3_icfree_hdr *to, + struct xfs_dir2_free *from) +{ + if (xfs_sb_version_hascrc(&mp->m_sb)) { + struct xfs_dir3_free *from3 = (struct xfs_dir3_free *)from; + + to->magic = be32_to_cpu(from3->hdr.hdr.magic); + to->firstdb = be32_to_cpu(from3->hdr.firstdb); + to->nvalid = be32_to_cpu(from3->hdr.nvalid); + to->nused = be32_to_cpu(from3->hdr.nused); + + ASSERT(to->magic == XFS_DIR3_FREE_MAGIC); + } else { + to->magic = be32_to_cpu(from->hdr.magic); + to->firstdb = be32_to_cpu(from->hdr.firstdb); + to->nvalid = be32_to_cpu(from->hdr.nvalid); + to->nused = be32_to_cpu(from->hdr.nused); + ASSERT(to->magic == XFS_DIR2_FREE_MAGIC); + } +} + int xfs_dir2_free_read( struct xfs_trans *tp, @@ -369,7 +393,7 @@ xfs_dir2_leaf_to_node( return error; free = fbp->b_addr; - dp->d_ops->free_hdr_from_disk(&freehdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); if (be32_to_cpu(ltp->bestcount) > @@ -513,7 +537,7 @@ xfs_dir2_free_hdr_check( { struct xfs_dir3_icfree_hdr hdr; - dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr); + xfs_dir2_free_hdr_from_disk(dp->i_mount, &hdr, bp->b_addr); ASSERT((hdr.firstdb % dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0); @@ -1123,7 +1147,7 @@ xfs_dir3_data_block_free( struct xfs_dir3_icfree_hdr freehdr; struct xfs_inode *dp = args->dp; - dp->d_ops->free_hdr_from_disk(&freehdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); bests = dp->d_ops->free_bests_p(free); if (hdr) { /* @@ -1292,7 +1316,8 @@ xfs_dir2_leafn_remove( #ifdef DEBUG { struct xfs_dir3_icfree_hdr freehdr; - dp->d_ops->free_hdr_from_disk(&freehdr, free); + + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) * (fdb - xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET))); @@ -1686,7 +1711,7 @@ xfs_dir2_node_add_datablk( return error; free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); - dp->d_ops->free_hdr_from_disk(&freehdr, free); + xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); /* Remember the first slot as our empty slot. */ freehdr.firstdb = (fbno - xfs_dir2_byte_to_db(args->geo, @@ -1695,7 +1720,7 @@ xfs_dir2_node_add_datablk( } else { free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); - dp->d_ops->free_hdr_from_disk(&freehdr, free); + xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); } /* Set the freespace block index from the data block number. */ @@ -1764,7 +1789,8 @@ xfs_dir2_node_find_freeblk( if (findex >= 0) { /* caller already found the freespace for us. */ bests = dp->d_ops->free_bests_p(free); - dp->d_ops->free_hdr_from_disk(&freehdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, + free); ASSERT(findex < freehdr.nvalid); ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF); @@ -1813,7 +1839,7 @@ xfs_dir2_node_find_freeblk( free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); - dp->d_ops->free_hdr_from_disk(&freehdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); /* Scan the free entry array for a large enough free space. */ for (findex = freehdr.nvalid - 1; findex >= 0; findex--) { @@ -2266,7 +2292,7 @@ xfs_dir2_node_trim_free( if (!bp) return 0; free = bp->b_addr; - dp->d_ops->free_hdr_from_disk(&freehdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); /* * If there are used entries, there's nothing to do. -- cgit From 200dada70008a1204ddd3d95250d23d6477e20e6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:52 -0800 Subject: xfs: devirtualize ->free_hdr_to_disk Replace the ->free_hdr_to_disk dir ops method with a directly called xfs_dir2_free_hdr_to_disk helper that takes care of the differences between the v4 and v5 on-disk format. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index d337ecd4e3be..4e49ac64a2ff 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -244,6 +244,31 @@ xfs_dir2_free_hdr_from_disk( } } +static void +xfs_dir2_free_hdr_to_disk( + struct xfs_mount *mp, + struct xfs_dir2_free *to, + struct xfs_dir3_icfree_hdr *from) +{ + if (xfs_sb_version_hascrc(&mp->m_sb)) { + struct xfs_dir3_free *to3 = (struct xfs_dir3_free *)to; + + ASSERT(from->magic == XFS_DIR3_FREE_MAGIC); + + to3->hdr.hdr.magic = cpu_to_be32(from->magic); + to3->hdr.firstdb = cpu_to_be32(from->firstdb); + to3->hdr.nvalid = cpu_to_be32(from->nvalid); + to3->hdr.nused = cpu_to_be32(from->nused); + } else { + ASSERT(from->magic == XFS_DIR2_FREE_MAGIC); + + to->hdr.magic = cpu_to_be32(from->magic); + to->hdr.firstdb = cpu_to_be32(from->firstdb); + to->hdr.nvalid = cpu_to_be32(from->nvalid); + to->hdr.nused = cpu_to_be32(from->nused); + } +} + int xfs_dir2_free_read( struct xfs_trans *tp, @@ -302,7 +327,7 @@ xfs_dir3_free_get_buf( uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid); } else hdr.magic = XFS_DIR2_FREE_MAGIC; - dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr); + xfs_dir2_free_hdr_to_disk(mp, bp->b_addr, &hdr); *bpp = bp; return 0; } @@ -420,7 +445,7 @@ xfs_dir2_leaf_to_node( freehdr.nused = n; freehdr.nvalid = be32_to_cpu(ltp->bestcount); - dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); + xfs_dir2_free_hdr_to_disk(dp->i_mount, fbp->b_addr, &freehdr); xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1); xfs_dir2_free_log_header(args, fbp); @@ -1182,7 +1207,7 @@ xfs_dir3_data_block_free( logfree = 1; } - dp->d_ops->free_hdr_to_disk(free, &freehdr); + xfs_dir2_free_hdr_to_disk(dp->i_mount, free, &freehdr); xfs_dir2_free_log_header(args, fbp); /* @@ -1739,7 +1764,7 @@ xfs_dir2_node_add_datablk( */ if (bests[*findex] == cpu_to_be16(NULLDATAOFF)) { freehdr.nused++; - dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); + xfs_dir2_free_hdr_to_disk(mp, fbp->b_addr, &freehdr); xfs_dir2_free_log_header(args, fbp); } -- cgit From 195b0a44ab73f0275683e7a0b1985751ea2ef6ae Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:57:53 -0800 Subject: xfs: make the xfs_dir3_icfree_hdr available to xfs_dir2_node_addname_int Return the xfs_dir3_icfree_hdr used by the helpers called from xfs_dir2_node_addname_int to the main function to prepare for the next round of changes where we'll use the ichdr in xfs_dir3_icfree_hdr to avoid extra operations to find the bests pointers. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 4e49ac64a2ff..6d67ceac48b7 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -1666,14 +1666,13 @@ xfs_dir2_node_add_datablk( xfs_dir2_db_t *dbno, struct xfs_buf **dbpp, struct xfs_buf **fbpp, + struct xfs_dir3_icfree_hdr *hdr, int *findex) { struct xfs_inode *dp = args->dp; struct xfs_trans *tp = args->trans; struct xfs_mount *mp = dp->i_mount; - struct xfs_dir3_icfree_hdr freehdr; struct xfs_dir2_data_free *bf; - struct xfs_dir2_data_hdr *hdr; struct xfs_dir2_free *free = NULL; xfs_dir2_db_t fbno; struct xfs_buf *fbp; @@ -1736,25 +1735,25 @@ xfs_dir2_node_add_datablk( return error; free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); + xfs_dir2_free_hdr_from_disk(mp, hdr, free); /* Remember the first slot as our empty slot. */ - freehdr.firstdb = (fbno - xfs_dir2_byte_to_db(args->geo, + hdr->firstdb = (fbno - xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)) * dp->d_ops->free_max_bests(args->geo); } else { free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); + xfs_dir2_free_hdr_from_disk(mp, hdr, free); } /* Set the freespace block index from the data block number. */ *findex = dp->d_ops->db_to_fdindex(args->geo, *dbno); /* Extend the freespace table if the new data block is off the end. */ - if (*findex >= freehdr.nvalid) { + if (*findex >= hdr->nvalid) { ASSERT(*findex < dp->d_ops->free_max_bests(args->geo)); - freehdr.nvalid = *findex + 1; + hdr->nvalid = *findex + 1; bests[*findex] = cpu_to_be16(NULLDATAOFF); } @@ -1763,14 +1762,13 @@ xfs_dir2_node_add_datablk( * true) then update the header. */ if (bests[*findex] == cpu_to_be16(NULLDATAOFF)) { - freehdr.nused++; - xfs_dir2_free_hdr_to_disk(mp, fbp->b_addr, &freehdr); + hdr->nused++; + xfs_dir2_free_hdr_to_disk(mp, fbp->b_addr, hdr); xfs_dir2_free_log_header(args, fbp); } /* Update the freespace value for the new block in the table. */ - hdr = dbp->b_addr; - bf = dp->d_ops->data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(dbp->b_addr); bests[*findex] = bf[0].length; *dbpp = dbp; @@ -1784,10 +1782,10 @@ xfs_dir2_node_find_freeblk( struct xfs_da_state_blk *fblk, xfs_dir2_db_t *dbnop, struct xfs_buf **fbpp, + struct xfs_dir3_icfree_hdr *hdr, int *findexp, int length) { - struct xfs_dir3_icfree_hdr freehdr; struct xfs_dir2_free *free = NULL; struct xfs_inode *dp = args->dp; struct xfs_trans *tp = args->trans; @@ -1814,13 +1812,12 @@ xfs_dir2_node_find_freeblk( if (findex >= 0) { /* caller already found the freespace for us. */ bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, - free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, free); - ASSERT(findex < freehdr.nvalid); + ASSERT(findex < hdr->nvalid); ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF); ASSERT(be16_to_cpu(bests[findex]) >= length); - dbno = freehdr.firstdb + findex; + dbno = hdr->firstdb + findex; goto found_block; } @@ -1864,13 +1861,13 @@ xfs_dir2_node_find_freeblk( free = fbp->b_addr; bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, free); /* Scan the free entry array for a large enough free space. */ - for (findex = freehdr.nvalid - 1; findex >= 0; findex--) { + for (findex = hdr->nvalid - 1; findex >= 0; findex--) { if (be16_to_cpu(bests[findex]) != NULLDATAOFF && be16_to_cpu(bests[findex]) >= length) { - dbno = freehdr.firstdb + findex; + dbno = hdr->firstdb + findex; goto found_block; } } @@ -1904,6 +1901,7 @@ xfs_dir2_node_addname_int( struct xfs_dir2_free *free = NULL; /* freespace block structure */ struct xfs_trans *tp = args->trans; struct xfs_inode *dp = args->dp; + struct xfs_dir3_icfree_hdr freehdr; struct xfs_buf *dbp; /* data block buffer */ struct xfs_buf *fbp; /* freespace buffer */ xfs_dir2_data_aoff_t aoff; @@ -1918,8 +1916,8 @@ xfs_dir2_node_addname_int( __be16 *bests; length = dp->d_ops->data_entsize(args->namelen); - error = xfs_dir2_node_find_freeblk(args, fblk, &dbno, &fbp, &findex, - length); + error = xfs_dir2_node_find_freeblk(args, fblk, &dbno, &fbp, &freehdr, + &findex, length); if (error) return error; @@ -1941,7 +1939,7 @@ xfs_dir2_node_addname_int( /* we're going to have to log the free block index later */ logfree = 1; error = xfs_dir2_node_add_datablk(args, fblk, &dbno, &dbp, &fbp, - &findex); + &freehdr, &findex); } else { /* Read the data block in. */ error = xfs_dir3_data_read(tp, dp, -- cgit From a84f3d5cb04f7dff1bf6904f0a05bc8df16137fb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 14:58:05 -0800 Subject: xfs: add a bests pointer to struct xfs_dir3_icfree_hdr All but two callers of the ->free_bests_p dir operation already have a struct xfs_dir3_icfree_hdr from a previous call to xfs_dir2_free_hdr_from_disk at hand. Add a pointer to the bests to struct xfs_dir3_icfree_hdr to clean up this pattern. To optimize this pattern, pass the struct xfs_dir3_icfree_hdr to xfs_dir2_free_log_bests instead of recalculating the pointer there. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 97 +++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 59 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 6d67ceac48b7..78900ba3db71 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -233,6 +233,7 @@ xfs_dir2_free_hdr_from_disk( to->firstdb = be32_to_cpu(from3->hdr.firstdb); to->nvalid = be32_to_cpu(from3->hdr.nvalid); to->nused = be32_to_cpu(from3->hdr.nused); + to->bests = from3->bests; ASSERT(to->magic == XFS_DIR3_FREE_MAGIC); } else { @@ -240,6 +241,8 @@ xfs_dir2_free_hdr_from_disk( to->firstdb = be32_to_cpu(from->hdr.firstdb); to->nvalid = be32_to_cpu(from->hdr.nvalid); to->nused = be32_to_cpu(from->hdr.nused); + to->bests = from->bests; + ASSERT(to->magic == XFS_DIR2_FREE_MAGIC); } } @@ -338,21 +341,19 @@ xfs_dir3_free_get_buf( STATIC void xfs_dir2_free_log_bests( struct xfs_da_args *args, + struct xfs_dir3_icfree_hdr *hdr, struct xfs_buf *bp, int first, /* first entry to log */ int last) /* last entry to log */ { - xfs_dir2_free_t *free; /* freespace structure */ - __be16 *bests; + struct xfs_dir2_free *free = bp->b_addr; - free = bp->b_addr; - bests = args->dp->d_ops->free_bests_p(free); ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); xfs_trans_log_buf(args->trans, bp, - (uint)((char *)&bests[first] - (char *)free), - (uint)((char *)&bests[last] - (char *)free + - sizeof(bests[0]) - 1)); + (char *)&hdr->bests[first] - (char *)free, + (char *)&hdr->bests[last] - (char *)free + + sizeof(hdr->bests[0]) - 1); } /* @@ -388,14 +389,12 @@ xfs_dir2_leaf_to_node( int error; /* error return value */ struct xfs_buf *fbp; /* freespace buffer */ xfs_dir2_db_t fdb; /* freespace block number */ - xfs_dir2_free_t *free; /* freespace structure */ __be16 *from; /* pointer to freespace entry */ int i; /* leaf freespace index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ int n; /* count of live freespc ents */ xfs_dir2_data_off_t off; /* freespace entry value */ - __be16 *to; /* pointer to freespace entry */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_dir3_icfree_hdr freehdr; @@ -417,8 +416,7 @@ xfs_dir2_leaf_to_node( if (error) return error; - free = fbp->b_addr; - xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, fbp->b_addr); leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); if (be32_to_cpu(ltp->bestcount) > @@ -432,11 +430,11 @@ xfs_dir2_leaf_to_node( * Count active entries. */ from = xfs_dir2_leaf_bests_p(ltp); - to = dp->d_ops->free_bests_p(free); - for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { - if ((off = be16_to_cpu(*from)) != NULLDATAOFF) + for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++) { + off = be16_to_cpu(*from); + if (off != NULLDATAOFF) n++; - *to = cpu_to_be16(off); + freehdr.bests[i] = cpu_to_be16(off); } /* @@ -446,7 +444,7 @@ xfs_dir2_leaf_to_node( freehdr.nvalid = be32_to_cpu(ltp->bestcount); xfs_dir2_free_hdr_to_disk(dp->i_mount, fbp->b_addr, &freehdr); - xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1); + xfs_dir2_free_log_bests(args, &freehdr, fbp, 0, freehdr.nvalid - 1); xfs_dir2_free_log_header(args, fbp); /* @@ -677,7 +675,7 @@ xfs_dir2_leafn_lookup_for_addname( * in hand, take a look at it. */ if (newdb != curdb) { - __be16 *bests; + struct xfs_dir3_icfree_hdr freehdr; curdb = newdb; /* @@ -712,8 +710,9 @@ xfs_dir2_leafn_lookup_for_addname( /* * If it has room, return it. */ - bests = dp->d_ops->free_bests_p(free); - if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) { + xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); + if (unlikely( + freehdr.bests[fi] == cpu_to_be16(NULLDATAOFF))) { XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", XFS_ERRLEVEL_LOW, mp); if (curfdb != newfdb) @@ -721,7 +720,7 @@ xfs_dir2_leafn_lookup_for_addname( return -EFSCORRUPTED; } curfdb = newfdb; - if (be16_to_cpu(bests[fi]) >= length) + if (be16_to_cpu(freehdr.bests[fi]) >= length) goto out; } } @@ -1168,19 +1167,17 @@ xfs_dir3_data_block_free( int longest) { int logfree = 0; - __be16 *bests; struct xfs_dir3_icfree_hdr freehdr; struct xfs_inode *dp = args->dp; xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); - bests = dp->d_ops->free_bests_p(free); if (hdr) { /* * Data block is not empty, just set the free entry to the new * value. */ - bests[findex] = cpu_to_be16(longest); - xfs_dir2_free_log_bests(args, fbp, findex, findex); + freehdr.bests[findex] = cpu_to_be16(longest); + xfs_dir2_free_log_bests(args, &freehdr, fbp, findex, findex); return 0; } @@ -1196,14 +1193,14 @@ xfs_dir3_data_block_free( int i; /* free entry index */ for (i = findex - 1; i >= 0; i--) { - if (bests[i] != cpu_to_be16(NULLDATAOFF)) + if (freehdr.bests[i] != cpu_to_be16(NULLDATAOFF)) break; } freehdr.nvalid = i + 1; logfree = 0; } else { /* Not the last entry, just punch it out. */ - bests[findex] = cpu_to_be16(NULLDATAOFF); + freehdr.bests[findex] = cpu_to_be16(NULLDATAOFF); logfree = 1; } @@ -1232,7 +1229,7 @@ xfs_dir3_data_block_free( /* Log the free entry that changed, unless we got rid of it. */ if (logfree) - xfs_dir2_free_log_bests(args, fbp, findex, findex); + xfs_dir2_free_log_bests(args, &freehdr, fbp, findex, findex); return 0; } @@ -1673,11 +1670,9 @@ xfs_dir2_node_add_datablk( struct xfs_trans *tp = args->trans; struct xfs_mount *mp = dp->i_mount; struct xfs_dir2_data_free *bf; - struct xfs_dir2_free *free = NULL; xfs_dir2_db_t fbno; struct xfs_buf *fbp; struct xfs_buf *dbp; - __be16 *bests = NULL; int error; /* Not allowed to allocate, return failure. */ @@ -1733,18 +1728,14 @@ xfs_dir2_node_add_datablk( error = xfs_dir3_free_get_buf(args, fbno, &fbp); if (error) return error; - free = fbp->b_addr; - bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(mp, hdr, free); + xfs_dir2_free_hdr_from_disk(mp, hdr, fbp->b_addr); /* Remember the first slot as our empty slot. */ hdr->firstdb = (fbno - xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)) * dp->d_ops->free_max_bests(args->geo); } else { - free = fbp->b_addr; - bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(mp, hdr, free); + xfs_dir2_free_hdr_from_disk(mp, hdr, fbp->b_addr); } /* Set the freespace block index from the data block number. */ @@ -1754,14 +1745,14 @@ xfs_dir2_node_add_datablk( if (*findex >= hdr->nvalid) { ASSERT(*findex < dp->d_ops->free_max_bests(args->geo)); hdr->nvalid = *findex + 1; - bests[*findex] = cpu_to_be16(NULLDATAOFF); + hdr->bests[*findex] = cpu_to_be16(NULLDATAOFF); } /* * If this entry was for an empty data block (this should always be * true) then update the header. */ - if (bests[*findex] == cpu_to_be16(NULLDATAOFF)) { + if (hdr->bests[*findex] == cpu_to_be16(NULLDATAOFF)) { hdr->nused++; xfs_dir2_free_hdr_to_disk(mp, fbp->b_addr, hdr); xfs_dir2_free_log_header(args, fbp); @@ -1769,7 +1760,7 @@ xfs_dir2_node_add_datablk( /* Update the freespace value for the new block in the table. */ bf = dp->d_ops->data_bestfree_p(dbp->b_addr); - bests[*findex] = bf[0].length; + hdr->bests[*findex] = bf[0].length; *dbpp = dbp; *fbpp = fbp; @@ -1786,7 +1777,6 @@ xfs_dir2_node_find_freeblk( int *findexp, int length) { - struct xfs_dir2_free *free = NULL; struct xfs_inode *dp = args->dp; struct xfs_trans *tp = args->trans; struct xfs_buf *fbp = NULL; @@ -1796,7 +1786,6 @@ xfs_dir2_node_find_freeblk( xfs_dir2_db_t dbno = -1; xfs_dir2_db_t fbno; xfs_fileoff_t fo; - __be16 *bests = NULL; int findex = 0; int error; @@ -1807,16 +1796,13 @@ xfs_dir2_node_find_freeblk( */ if (fblk) { fbp = fblk->bp; - free = fbp->b_addr; findex = fblk->index; + xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, fbp->b_addr); if (findex >= 0) { /* caller already found the freespace for us. */ - bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, free); - ASSERT(findex < hdr->nvalid); - ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF); - ASSERT(be16_to_cpu(bests[findex]) >= length); + ASSERT(be16_to_cpu(hdr->bests[findex]) != NULLDATAOFF); + ASSERT(be16_to_cpu(hdr->bests[findex]) >= length); dbno = hdr->firstdb + findex; goto found_block; } @@ -1859,14 +1845,12 @@ xfs_dir2_node_find_freeblk( if (!fbp) continue; - free = fbp->b_addr; - bests = dp->d_ops->free_bests_p(free); - xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, free); + xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, fbp->b_addr); /* Scan the free entry array for a large enough free space. */ for (findex = hdr->nvalid - 1; findex >= 0; findex--) { - if (be16_to_cpu(bests[findex]) != NULLDATAOFF && - be16_to_cpu(bests[findex]) >= length) { + if (be16_to_cpu(hdr->bests[findex]) != NULLDATAOFF && + be16_to_cpu(hdr->bests[findex]) >= length) { dbno = hdr->firstdb + findex; goto found_block; } @@ -1883,7 +1867,6 @@ found_block: return 0; } - /* * Add the data entry for a node-format directory name addition. * The leaf entry is added in xfs_dir2_leafn_add. @@ -1898,7 +1881,6 @@ xfs_dir2_node_addname_int( struct xfs_dir2_data_entry *dep; /* data entry pointer */ struct xfs_dir2_data_hdr *hdr; /* data block header */ struct xfs_dir2_data_free *bf; - struct xfs_dir2_free *free = NULL; /* freespace block structure */ struct xfs_trans *tp = args->trans; struct xfs_inode *dp = args->dp; struct xfs_dir3_icfree_hdr freehdr; @@ -1913,7 +1895,6 @@ xfs_dir2_node_addname_int( int needlog = 0; /* need to log data header */ int needscan = 0; /* need to rescan data frees */ __be16 *tagp; /* data entry tag pointer */ - __be16 *bests; length = dp->d_ops->data_entsize(args->namelen); error = xfs_dir2_node_find_freeblk(args, fblk, &dbno, &fbp, &freehdr, @@ -1984,16 +1965,14 @@ xfs_dir2_node_addname_int( xfs_dir2_data_log_header(args, dbp); /* If the freespace block entry is now wrong, update it. */ - free = fbp->b_addr; - bests = dp->d_ops->free_bests_p(free); - if (bests[findex] != bf[0].length) { - bests[findex] = bf[0].length; + if (freehdr.bests[findex] != bf[0].length) { + freehdr.bests[findex] = bf[0].length; logfree = 1; } /* Log the freespace entry if needed. */ if (logfree) - xfs_dir2_free_log_bests(args, fbp, findex, findex); + xfs_dir2_free_log_bests(args, &freehdr, fbp, findex, findex); /* Return the data block and offset in args. */ args->blkno = (xfs_dablk_t)dbno; -- cgit From ed1d612fbe6ba95a4d16b56bbfb1f90d48a42149 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:01:29 -0800 Subject: xfs: move the dir2 free header size to struct xfs_da_geometry Move the free header size towards our structure for dir/attr geometry parameters. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 78900ba3db71..b9d5f4ae9a8d 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -372,7 +372,7 @@ xfs_dir2_free_log_header( free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); #endif xfs_trans_log_buf(args->trans, bp, 0, - args->dp->d_ops->free_hdr_size - 1); + args->geo->free_hdr_size - 1); } /* -- cgit From 5893e4feb0eac11aab7b93ff9fe7e6e58bcec5ec Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:01:30 -0800 Subject: xfs: move the max dir2 free bests count to struct xfs_da_geometry Move the max free bests count towards our structure for dir/attr geometry parameters. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index b9d5f4ae9a8d..5d35a6d77b56 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -160,10 +160,9 @@ xfs_dir3_free_header_check( struct xfs_buf *bp) { struct xfs_mount *mp = dp->i_mount; + int maxbests = mp->m_dir_geo->free_max_bests; unsigned int firstdb; - int maxbests; - maxbests = dp->d_ops->free_max_bests(mp->m_dir_geo); firstdb = (xfs_dir2_da_to_db(mp->m_dir_geo, fbno) - xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) * maxbests; @@ -562,8 +561,7 @@ xfs_dir2_free_hdr_check( xfs_dir2_free_hdr_from_disk(dp->i_mount, &hdr, bp->b_addr); - ASSERT((hdr.firstdb % - dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0); + ASSERT((hdr.firstdb % dp->i_mount->m_dir_geo->free_max_bests) == 0); ASSERT(hdr.firstdb <= db); ASSERT(db < hdr.firstdb + hdr.nvalid); } @@ -1340,7 +1338,7 @@ xfs_dir2_leafn_remove( struct xfs_dir3_icfree_hdr freehdr; xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); - ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) * + ASSERT(freehdr.firstdb == args->geo->free_max_bests * (fdb - xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET))); } @@ -1733,7 +1731,7 @@ xfs_dir2_node_add_datablk( /* Remember the first slot as our empty slot. */ hdr->firstdb = (fbno - xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET)) * - dp->d_ops->free_max_bests(args->geo); + args->geo->free_max_bests; } else { xfs_dir2_free_hdr_from_disk(mp, hdr, fbp->b_addr); } @@ -1743,7 +1741,7 @@ xfs_dir2_node_add_datablk( /* Extend the freespace table if the new data block is off the end. */ if (*findex >= hdr->nvalid) { - ASSERT(*findex < dp->d_ops->free_max_bests(args->geo)); + ASSERT(*findex < args->geo->free_max_bests); hdr->nvalid = *findex + 1; hdr->bests[*findex] = cpu_to_be16(NULLDATAOFF); } -- cgit From 3d92c93b7065be28eda33f92681d2f1121fbf8bf Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:01:39 -0800 Subject: xfs: devirtualize ->db_to_fdb and ->db_to_fdindex Now that the max bests value is in struct xfs_da_geometry both instances of ->db_to_fdb and ->db_to_fdindex are identical. Replace them with local xfs_dir2_db_to_fdb and xfs_dir2_db_to_fdindex functions in xfs_dir2_node.c. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 5d35a6d77b56..daa9dc7a7762 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -33,6 +33,25 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, int index, xfs_da_state_blk_t *dblk, int *rval); +/* + * Convert data space db to the corresponding free db. + */ +static xfs_dir2_db_t +xfs_dir2_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db) +{ + return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) + + (db / geo->free_max_bests); +} + +/* + * Convert data space db to the corresponding index in a free db. + */ +static int +xfs_dir2_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db) +{ + return db % geo->free_max_bests; +} + /* * Check internal consistency of a leafn block. */ @@ -680,7 +699,7 @@ xfs_dir2_leafn_lookup_for_addname( * Convert the data block to the free block * holding its freespace information. */ - newfdb = dp->d_ops->db_to_fdb(args->geo, newdb); + newfdb = xfs_dir2_db_to_fdb(args->geo, newdb); /* * If it's not the one we have in hand, read it in. */ @@ -704,7 +723,7 @@ xfs_dir2_leafn_lookup_for_addname( /* * Get the index for our entry. */ - fi = dp->d_ops->db_to_fdindex(args->geo, curdb); + fi = xfs_dir2_db_to_fdindex(args->geo, curdb); /* * If it has room, return it. */ @@ -1326,7 +1345,7 @@ xfs_dir2_leafn_remove( * Convert the data block number to a free block, * read in the free block. */ - fdb = dp->d_ops->db_to_fdb(args->geo, db); + fdb = xfs_dir2_db_to_fdb(args->geo, db); error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(args->geo, fdb), &fbp); @@ -1346,7 +1365,7 @@ xfs_dir2_leafn_remove( /* * Calculate which entry we need to fix. */ - findex = dp->d_ops->db_to_fdindex(args->geo, db); + findex = xfs_dir2_db_to_fdindex(args->geo, db); longest = be16_to_cpu(bf[0].length); /* * If the data block is now empty we can get rid of it @@ -1689,7 +1708,7 @@ xfs_dir2_node_add_datablk( * Get the freespace block corresponding to the data block * that was just allocated. */ - fbno = dp->d_ops->db_to_fdb(args->geo, *dbno); + fbno = xfs_dir2_db_to_fdb(args->geo, *dbno); error = xfs_dir2_free_try_read(tp, dp, xfs_dir2_db_to_da(args->geo, fbno), &fbp); if (error) @@ -1704,11 +1723,11 @@ xfs_dir2_node_add_datablk( if (error) return error; - if (dp->d_ops->db_to_fdb(args->geo, *dbno) != fbno) { + if (xfs_dir2_db_to_fdb(args->geo, *dbno) != fbno) { xfs_alert(mp, "%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld", __func__, (unsigned long long)dp->i_ino, - (long long)dp->d_ops->db_to_fdb(args->geo, *dbno), + (long long)xfs_dir2_db_to_fdb(args->geo, *dbno), (long long)*dbno, (long long)fbno); if (fblk) { xfs_alert(mp, @@ -1737,7 +1756,7 @@ xfs_dir2_node_add_datablk( } /* Set the freespace block index from the data block number. */ - *findex = dp->d_ops->db_to_fdindex(args->geo, *dbno); + *findex = xfs_dir2_db_to_fdindex(args->geo, *dbno); /* Extend the freespace table if the new data block is off the end. */ if (*findex >= hdr->nvalid) { -- cgit From fdbb8c5b805c19bc2764aa1b91952e75e4c1c086 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:05:37 -0800 Subject: xfs: devirtualize ->data_entsize Replace the ->data_entsize dir ops method with a directly called xfs_dir2_data_entsize helper that takes care of the differences between the directory format with and without the file type field. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index daa9dc7a7762..ca346c9cc7c8 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -666,7 +666,7 @@ xfs_dir2_leafn_lookup_for_addname( ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); } - length = dp->d_ops->data_entsize(args->namelen); + length = xfs_dir2_data_entsize(mp, args->namelen); /* * Loop over leaf entries with the right hash value. */ @@ -1320,7 +1320,8 @@ xfs_dir2_leafn_remove( longest = be16_to_cpu(bf[0].length); needlog = needscan = 0; xfs_dir2_data_make_free(args, dbp, off, - dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); + xfs_dir2_data_entsize(dp->i_mount, dep->namelen), &needlog, + &needscan); /* * Rescan the data block freespaces for bestfree. * Log the data block header if needed. @@ -1913,7 +1914,7 @@ xfs_dir2_node_addname_int( int needscan = 0; /* need to rescan data frees */ __be16 *tagp; /* data entry tag pointer */ - length = dp->d_ops->data_entsize(args->namelen); + length = xfs_dir2_data_entsize(dp->i_mount, args->namelen); error = xfs_dir2_node_find_freeblk(args, fblk, &dbno, &fbp, &freehdr, &findex, length); if (error) -- cgit From 7e8ae7bd1c5d806316e6b6403ac2dd0be7a1f82b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:05:37 -0800 Subject: xfs: devirtualize ->data_entry_tag_p Replace the ->data_entry_tag_p dir ops method with a directly called xfs_dir2_data_entry_tag_p helper that takes care of the differences between the directory format with and without the file type field. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index ca346c9cc7c8..b758da14cc7b 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -1972,7 +1972,7 @@ xfs_dir2_node_addname_int( dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); dp->d_ops->data_put_ftype(dep, args->filetype); - tagp = dp->d_ops->data_entry_tag_p(dep); + tagp = xfs_dir2_data_entry_tag_p(dp->i_mount, dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); xfs_dir2_data_log_entry(args, dbp, dep); -- cgit From d73e1cee8add0d18d5401b81db2351b9e8af899a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:05:38 -0800 Subject: xfs: move the dir2 data block fixed offsets to struct xfs_da_geometry Move the data block fixed offsets towards our structure for dir/attr geometry parameters. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index b758da14cc7b..80659d009cba 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -1263,6 +1263,7 @@ xfs_dir2_leafn_remove( xfs_da_state_blk_t *dblk, /* data block */ int *rval) /* resulting block needs join */ { + struct xfs_da_geometry *geo = args->geo; xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_db_t db; /* data block number */ struct xfs_buf *dbp; /* data block buffer */ @@ -1293,9 +1294,9 @@ xfs_dir2_leafn_remove( /* * Extract the data block and offset from the entry. */ - db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); + db = xfs_dir2_dataptr_to_db(geo, be32_to_cpu(lep->address)); ASSERT(dblk->blkno == db); - off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)); + off = xfs_dir2_dataptr_to_off(geo, be32_to_cpu(lep->address)); ASSERT(dblk->index == off); /* @@ -1346,9 +1347,8 @@ xfs_dir2_leafn_remove( * Convert the data block number to a free block, * read in the free block. */ - fdb = xfs_dir2_db_to_fdb(args->geo, db); - error = xfs_dir2_free_read(tp, dp, - xfs_dir2_db_to_da(args->geo, fdb), + fdb = xfs_dir2_db_to_fdb(geo, db); + error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(geo, fdb), &fbp); if (error) return error; @@ -1358,22 +1358,20 @@ xfs_dir2_leafn_remove( struct xfs_dir3_icfree_hdr freehdr; xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); - ASSERT(freehdr.firstdb == args->geo->free_max_bests * - (fdb - xfs_dir2_byte_to_db(args->geo, - XFS_DIR2_FREE_OFFSET))); + ASSERT(freehdr.firstdb == geo->free_max_bests * + (fdb - xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET))); } #endif /* * Calculate which entry we need to fix. */ - findex = xfs_dir2_db_to_fdindex(args->geo, db); + findex = xfs_dir2_db_to_fdindex(geo, db); longest = be16_to_cpu(bf[0].length); /* * If the data block is now empty we can get rid of it * (usually). */ - if (longest == args->geo->blksize - - dp->d_ops->data_entry_offset) { + if (longest == geo->blksize - geo->data_entry_offset) { /* * Try to punch out the data block. */ @@ -1405,9 +1403,9 @@ xfs_dir2_leafn_remove( * Return indication of whether this leaf block is empty enough * to justify trying to join it with a neighbor. */ - *rval = (args->geo->leaf_hdr_size + + *rval = (geo->leaf_hdr_size + (uint)sizeof(leafhdr.ents) * (leafhdr.count - leafhdr.stale)) < - args->geo->magicpct; + geo->magicpct; return 0; } -- cgit From 1848b607a9ad084db0180118304b9af2be68384e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:05:39 -0800 Subject: xfs: devirtualize ->data_bestfree_p Replace the ->data_bestfree_p dir ops method with a directly called xfs_dir2_data_bestfree_p helper that takes care of the differences between the v4 and v5 on-disk format. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 80659d009cba..76d19b522e92 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -1317,7 +1317,7 @@ xfs_dir2_leafn_remove( dbp = dblk->bp; hdr = dbp->b_addr; dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); - bf = dp->d_ops->data_bestfree_p(hdr); + bf = xfs_dir2_data_bestfree_p(dp->i_mount, hdr); longest = be16_to_cpu(bf[0].length); needlog = needscan = 0; xfs_dir2_data_make_free(args, dbp, off, @@ -1775,7 +1775,7 @@ xfs_dir2_node_add_datablk( } /* Update the freespace value for the new block in the table. */ - bf = dp->d_ops->data_bestfree_p(dbp->b_addr); + bf = xfs_dir2_data_bestfree_p(mp, dbp->b_addr); hdr->bests[*findex] = bf[0].length; *dbpp = dbp; @@ -1948,7 +1948,7 @@ xfs_dir2_node_addname_int( /* setup for data block up now */ hdr = dbp->b_addr; - bf = dp->d_ops->data_bestfree_p(hdr); + bf = xfs_dir2_data_bestfree_p(dp->i_mount, hdr); ASSERT(be16_to_cpu(bf[0].length) >= length); /* Point to the existing unused space. */ -- cgit From 59b8b465058ec203493c0436f243263051e08f5a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:05:48 -0800 Subject: xfs: devirtualize ->data_get_ftype and ->data_put_ftype Replace the ->data_get_ftype and ->data_put_ftype dir ops methods with directly called xfs_dir2_data_get_ftype and xfs_dir2_data_put_ftype helpers that takes care of the differences between the directory format with and without the file type field. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 76d19b522e92..4ac7518b667d 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -884,7 +884,7 @@ xfs_dir2_leafn_lookup_for_entry( xfs_trans_brelse(tp, state->extrablk.bp); args->cmpresult = cmp; args->inumber = be64_to_cpu(dep->inumber); - args->filetype = dp->d_ops->data_get_ftype(dep); + args->filetype = xfs_dir2_data_get_ftype(mp, dep); *indexp = index; state->extravalid = 1; state->extrablk.bp = curbp; @@ -1969,7 +1969,7 @@ xfs_dir2_node_addname_int( dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); - dp->d_ops->data_put_ftype(dep, args->filetype); + xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype); tagp = xfs_dir2_data_entry_tag_p(dp->i_mount, dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); xfs_dir2_data_log_entry(args, dbp, dep); @@ -2253,7 +2253,7 @@ xfs_dir2_node_replace( * Fill in the new inode number and log the entry. */ dep->inumber = cpu_to_be64(inum); - args->dp->d_ops->data_put_ftype(dep, ftype); + xfs_dir2_data_put_ftype(state->mp, dep, ftype); xfs_dir2_data_log_entry(args, state->extrablk.bp, dep); rval = 0; } -- cgit From ae42976de7f1022e6d83f5560debc072929921a9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 8 Nov 2019 15:06:02 -0800 Subject: xfs: merge xfs_dir2_data_freescan and xfs_dir2_data_freescan_int There is no real need for xfs_dir2_data_freescan wrapper, so rename xfs_dir2_data_freescan_int to xfs_dir2_data_freescan and let the callers dereference the mount pointer from the inode. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 4ac7518b667d..5f30a1953a52 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -1328,7 +1328,7 @@ xfs_dir2_leafn_remove( * Log the data block header if needed. */ if (needscan) - xfs_dir2_data_freescan(dp, hdr, &needlog); + xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(args, dbp); xfs_dir3_data_check(dp, dbp); @@ -1976,7 +1976,7 @@ xfs_dir2_node_addname_int( /* Rescan the freespace and log the data block if needed. */ if (needscan) - xfs_dir2_data_freescan(dp, hdr, &needlog); + xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(args, dbp); -- cgit From a71895c5dad1ab8cf30622e208d148298ab602e5 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 11 Nov 2019 12:53:22 -0800 Subject: xfs: convert open coded corruption check to use XFS_IS_CORRUPT Convert the last of the open coded corruption check and report idioms to use the XFS_IS_CORRUPT macro. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_dir2_node.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 5f30a1953a52..560b7e9d210d 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -728,10 +728,9 @@ xfs_dir2_leafn_lookup_for_addname( * If it has room, return it. */ xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); - if (unlikely( - freehdr.bests[fi] == cpu_to_be16(NULLDATAOFF))) { - XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, + freehdr.bests[fi] == + cpu_to_be16(NULLDATAOFF))) { if (curfdb != newfdb) xfs_trans_brelse(tp, curbp); return -EFSCORRUPTED; @@ -1722,7 +1721,9 @@ xfs_dir2_node_add_datablk( if (error) return error; - if (xfs_dir2_db_to_fdb(args->geo, *dbno) != fbno) { + if (XFS_IS_CORRUPT(mp, + xfs_dir2_db_to_fdb(args->geo, *dbno) != + fbno)) { xfs_alert(mp, "%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld", __func__, (unsigned long long)dp->i_ino, @@ -1736,7 +1737,6 @@ xfs_dir2_node_add_datablk( } else { xfs_alert(mp, " ... fblk is NULL"); } - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } -- cgit From d8d11fc703a22bbe3939e08b08396fa6b816719a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Nov 2019 12:59:26 -0800 Subject: xfs: devirtualize ->m_dirnameops Instead of causing a relatively expensive indirect call for each hashing and comparism of a file name in a directory just use an inline function and a simple branch on the ASCII CI bit. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong [darrick: fix unused variable warning] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 560b7e9d210d..3a8b0625a08b 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -875,7 +875,7 @@ xfs_dir2_leafn_lookup_for_entry( * EEXIST immediately. If it's the first case-insensitive * match, store the block & inode number and continue looking. */ - cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); + cmp = xfs_dir2_compname(args, dep->name, dep->namelen); if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { /* If there is a CI match block, drop it */ if (args->cmpresult != XFS_CMP_DIFFERENT && -- cgit From f3fcb314d16cdcffb6c521564b86b453869300da Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 20 Nov 2019 09:46:03 -0800 Subject: xfs: remove the mappedbno argument to xfs_dir3_leafn_read This argument is always hard coded to -1, so remove it. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 3a8b0625a08b..2e2129fdb6a9 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -1553,8 +1553,7 @@ xfs_dir2_leafn_toosmall( /* * Read the sibling leaf block. */ - error = xfs_dir3_leafn_read(state->args->trans, dp, - blkno, -1, &bp); + error = xfs_dir3_leafn_read(state->args->trans, dp, blkno, &bp); if (error) return error; -- cgit From cd2c9f1b544b8f5e1ca1874032fd669d74946a6d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 20 Nov 2019 09:46:04 -0800 Subject: xfs: remove the mappedbno argument to xfs_da_read_buf Move the code for reading an already mapped block into xfs_da3_node_read_mapped, which is the only caller ever passing a block number in the mappedbno argument and replace the mappedbno argument with the simple xfs_dabuf_get flags. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 2e2129fdb6a9..cc871345a141 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -212,14 +212,14 @@ __xfs_dir3_free_read( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t fbno, - xfs_daddr_t mappedbno, + unsigned int flags, struct xfs_buf **bpp) { xfs_failaddr_t fa; int err; - err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, - XFS_DATA_FORK, &xfs_dir3_free_buf_ops); + err = xfs_da_read_buf(tp, dp, fbno, flags, bpp, XFS_DATA_FORK, + &xfs_dir3_free_buf_ops); if (err || !*bpp) return err; @@ -297,7 +297,7 @@ xfs_dir2_free_read( xfs_dablk_t fbno, struct xfs_buf **bpp) { - return __xfs_dir3_free_read(tp, dp, fbno, -1, bpp); + return __xfs_dir3_free_read(tp, dp, fbno, 0, bpp); } static int @@ -307,7 +307,7 @@ xfs_dir2_free_try_read( xfs_dablk_t fbno, struct xfs_buf **bpp) { - return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp); + return __xfs_dir3_free_read(tp, dp, fbno, XFS_DABUF_MAP_HOLE_OK, bpp); } static int @@ -857,7 +857,7 @@ xfs_dir2_leafn_lookup_for_entry( error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, newdb), - -1, &curbp); + 0, &curbp); if (error) return error; } @@ -1940,7 +1940,7 @@ xfs_dir2_node_addname_int( /* Read the data block in. */ error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(args->geo, dbno), - -1, &dbp); + 0, &dbp); } if (error) return error; -- cgit From 2911edb653b9c64e0aad461f308cae8ce030eb7b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 20 Nov 2019 09:46:05 -0800 Subject: xfs: remove the mappedbno argument to xfs_da_get_buf Use the xfs_da_get_buf_daddr function directly for the two callers that pass a mapped disk address, and then remove the mappedbno argument. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/xfs/libxfs/xfs_dir2_node.c') diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index cc871345a141..a0cc5e240306 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -324,7 +324,7 @@ xfs_dir3_free_get_buf( struct xfs_dir3_icfree_hdr hdr; error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, fbno), - -1, &bp, XFS_DATA_FORK); + &bp, XFS_DATA_FORK); if (error) return error; -- cgit