aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2_node.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2013-03-31 18:10:34 +0200
committerPatrick McHardy <kaber@trash.net>2013-03-31 18:10:34 +0200
commit70711d223510ba1773cfe1d7770a56141c815ff8 (patch)
tree4a71f38a3a554ddecaa31b7d8c6bc49b7d1705b4 /fs/xfs/xfs_dir2_node.c
parentd53b4ed072d9779cdf53582c46436dec06d0961f (diff)
parent19f949f52599ba7c3f67a5897ac6be14bfcb1200 (diff)
Merge tag 'v3.8' of /home/kaber/src/repos/linux
Linux 3.8 Signed-off-by: Patrick McHardy <kaber@trash.net> Conflicts: include/linux/Kbuild include/linux/netlink.h
Diffstat (limited to 'fs/xfs/xfs_dir2_node.c')
-rw-r--r--fs/xfs/xfs_dir2_node.c518
1 files changed, 282 insertions, 236 deletions
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index b0f26780449..5980f9b7fa9 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -36,40 +36,108 @@
/*
* Function declarations.
*/
-static void xfs_dir2_free_log_header(xfs_trans_t *tp, xfs_dabuf_t *bp);
-static int xfs_dir2_leafn_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index);
+static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args,
+ int index);
#ifdef DEBUG
-static void xfs_dir2_leafn_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
+static void xfs_dir2_leafn_check(struct xfs_inode *dp, struct xfs_buf *bp);
#else
#define xfs_dir2_leafn_check(dp, bp)
#endif
-static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, xfs_dabuf_t *bp_s,
- int start_s, xfs_dabuf_t *bp_d, int start_d,
- int count);
+static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, struct xfs_buf *bp_s,
+ int start_s, struct xfs_buf *bp_d,
+ int start_d, int count);
static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state,
xfs_da_state_blk_t *blk1,
xfs_da_state_blk_t *blk2);
-static int xfs_dir2_leafn_remove(xfs_da_args_t *args, xfs_dabuf_t *bp,
+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);
static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
xfs_da_state_blk_t *fblk);
+static void
+xfs_dir2_free_verify(
+ struct xfs_buf *bp)
+{
+ struct xfs_mount *mp = bp->b_target->bt_mount;
+ struct xfs_dir2_free_hdr *hdr = bp->b_addr;
+ int block_ok = 0;
+
+ block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC);
+ if (!block_ok) {
+ XFS_CORRUPTION_ERROR("xfs_dir2_free_verify magic",
+ XFS_ERRLEVEL_LOW, mp, hdr);
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
+ }
+}
+
+static void
+xfs_dir2_free_read_verify(
+ struct xfs_buf *bp)
+{
+ xfs_dir2_free_verify(bp);
+}
+
+static void
+xfs_dir2_free_write_verify(
+ struct xfs_buf *bp)
+{
+ xfs_dir2_free_verify(bp);
+}
+
+static const struct xfs_buf_ops xfs_dir2_free_buf_ops = {
+ .verify_read = xfs_dir2_free_read_verify,
+ .verify_write = xfs_dir2_free_write_verify,
+};
+
+
+static int
+__xfs_dir2_free_read(
+ struct xfs_trans *tp,
+ struct xfs_inode *dp,
+ xfs_dablk_t fbno,
+ xfs_daddr_t mappedbno,
+ struct xfs_buf **bpp)
+{
+ return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+ XFS_DATA_FORK, &xfs_dir2_free_buf_ops);
+}
+
+int
+xfs_dir2_free_read(
+ struct xfs_trans *tp,
+ struct xfs_inode *dp,
+ xfs_dablk_t fbno,
+ struct xfs_buf **bpp)
+{
+ return __xfs_dir2_free_read(tp, dp, fbno, -1, bpp);
+}
+
+static int
+xfs_dir2_free_try_read(
+ struct xfs_trans *tp,
+ struct xfs_inode *dp,
+ xfs_dablk_t fbno,
+ struct xfs_buf **bpp)
+{
+ return __xfs_dir2_free_read(tp, dp, fbno, -2, bpp);
+}
+
/*
* Log entries from a freespace block.
*/
STATIC void
xfs_dir2_free_log_bests(
- xfs_trans_t *tp, /* transaction pointer */
- xfs_dabuf_t *bp, /* freespace buffer */
+ struct xfs_trans *tp,
+ struct xfs_buf *bp,
int first, /* first entry to log */
int last) /* last entry to log */
{
xfs_dir2_free_t *free; /* freespace structure */
- free = bp->data;
+ free = bp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
- xfs_da_log_buf(tp, bp,
+ xfs_trans_log_buf(tp, bp,
(uint)((char *)&free->bests[first] - (char *)free),
(uint)((char *)&free->bests[last] - (char *)free +
sizeof(free->bests[0]) - 1));
@@ -80,14 +148,14 @@ xfs_dir2_free_log_bests(
*/
static void
xfs_dir2_free_log_header(
- xfs_trans_t *tp, /* transaction pointer */
- xfs_dabuf_t *bp) /* freespace buffer */
+ struct xfs_trans *tp,
+ struct xfs_buf *bp)
{
xfs_dir2_free_t *free; /* freespace structure */
- free = bp->data;
+ free = bp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
- xfs_da_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free),
+ xfs_trans_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free),
(uint)(sizeof(xfs_dir2_free_hdr_t) - 1));
}
@@ -99,11 +167,11 @@ xfs_dir2_free_log_header(
int /* error */
xfs_dir2_leaf_to_node(
xfs_da_args_t *args, /* operation arguments */
- xfs_dabuf_t *lbp) /* leaf buffer */
+ struct xfs_buf *lbp) /* leaf buffer */
{
xfs_inode_t *dp; /* incore directory inode */
int error; /* error return value */
- xfs_dabuf_t *fbp; /* freespace buffer */
+ 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 */
@@ -131,13 +199,14 @@ xfs_dir2_leaf_to_node(
/*
* Get the buffer for the new freespace block.
*/
- if ((error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
- XFS_DATA_FORK))) {
+ error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
+ XFS_DATA_FORK);
+ if (error)
return error;
- }
- ASSERT(fbp != NULL);
- free = fbp->data;
- leaf = lbp->data;
+ fbp->b_ops = &xfs_dir2_free_buf_ops;
+
+ free = fbp->b_addr;
+ leaf = lbp->b_addr;
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
/*
* Initialize the freespace block header.
@@ -157,14 +226,16 @@ xfs_dir2_leaf_to_node(
*to = cpu_to_be16(off);
}
free->hdr.nused = cpu_to_be32(n);
+
+ lbp->b_ops = &xfs_dir2_leafn_buf_ops;
leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
+
/*
* Log everything.
*/
xfs_dir2_leaf_log_header(tp, lbp);
xfs_dir2_free_log_header(tp, fbp);
xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1);
- xfs_da_buf_done(fbp);
xfs_dir2_leafn_check(dp, lbp);
return 0;
}
@@ -175,7 +246,7 @@ xfs_dir2_leaf_to_node(
*/
static int /* error */
xfs_dir2_leafn_add(
- xfs_dabuf_t *bp, /* leaf buffer */
+ struct xfs_buf *bp, /* leaf buffer */
xfs_da_args_t *args, /* operation arguments */
int index) /* insertion pt for new entry */
{
@@ -195,7 +266,7 @@ xfs_dir2_leafn_add(
dp = args->dp;
mp = dp->i_mount;
tp = args->trans;
- leaf = bp->data;
+ leaf = bp->b_addr;
/*
* Quick check just to make sure we are not going to index
@@ -261,15 +332,15 @@ xfs_dir2_leafn_add(
*/
void
xfs_dir2_leafn_check(
- xfs_inode_t *dp, /* incore directory inode */
- xfs_dabuf_t *bp) /* leaf buffer */
+ struct xfs_inode *dp,
+ struct xfs_buf *bp)
{
int i; /* leaf index */
xfs_dir2_leaf_t *leaf; /* leaf structure */
xfs_mount_t *mp; /* filesystem mount point */
int stale; /* count of stale leaves */
- leaf = bp->data;
+ leaf = bp->b_addr;
mp = dp->i_mount;
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
@@ -291,12 +362,12 @@ xfs_dir2_leafn_check(
*/
xfs_dahash_t /* hash value */
xfs_dir2_leafn_lasthash(
- xfs_dabuf_t *bp, /* leaf buffer */
+ struct xfs_buf *bp, /* leaf buffer */
int *count) /* count of entries in leaf */
{
xfs_dir2_leaf_t *leaf; /* leaf structure */
- leaf = bp->data;
+ leaf = bp->b_addr;
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
if (count)
*count = be16_to_cpu(leaf->hdr.count);
@@ -311,12 +382,12 @@ xfs_dir2_leafn_lasthash(
*/
STATIC int
xfs_dir2_leafn_lookup_for_addname(
- xfs_dabuf_t *bp, /* leaf buffer */
+ struct xfs_buf *bp, /* leaf buffer */
xfs_da_args_t *args, /* operation arguments */
int *indexp, /* out: leaf entry index */
xfs_da_state_t *state) /* state to fill in */
{
- xfs_dabuf_t *curbp = NULL; /* current data/free buffer */
+ struct xfs_buf *curbp = NULL; /* current data/free buffer */
xfs_dir2_db_t curdb = -1; /* current data block number */
xfs_dir2_db_t curfdb = -1; /* current free block number */
xfs_inode_t *dp; /* incore directory inode */
@@ -335,7 +406,7 @@ xfs_dir2_leafn_lookup_for_addname(
dp = args->dp;
tp = args->trans;
mp = dp->i_mount;
- leaf = bp->data;
+ leaf = bp->b_addr;
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
#ifdef __KERNEL__
ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
@@ -352,7 +423,7 @@ xfs_dir2_leafn_lookup_for_addname(
/* If so, it's a free block buffer, get the block number. */
curbp = state->extrablk.bp;
curfdb = state->extrablk.blkno;
- free = curbp->data;
+ free = curbp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
}
length = xfs_dir2_data_entsize(args->namelen);
@@ -394,16 +465,14 @@ xfs_dir2_leafn_lookup_for_addname(
* If we had one before, drop it.
*/
if (curbp)
- xfs_da_brelse(tp, curbp);
- /*
- * Read the free block.
- */
- error = xfs_da_read_buf(tp, dp,
+ xfs_trans_brelse(tp, curbp);
+
+ error = xfs_dir2_free_read(tp, dp,
xfs_dir2_db_to_da(mp, newfdb),
- -1, &curbp, XFS_DATA_FORK);
+ &curbp);
if (error)
return error;
- free = curbp->data;
+ free = curbp->b_addr;
ASSERT(be32_to_cpu(free->hdr.magic) ==
XFS_DIR2_FREE_MAGIC);
ASSERT((be32_to_cpu(free->hdr.firstdb) %
@@ -424,7 +493,7 @@ xfs_dir2_leafn_lookup_for_addname(
XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
XFS_ERRLEVEL_LOW, mp);
if (curfdb != newfdb)
- xfs_da_brelse(tp, curbp);
+ xfs_trans_brelse(tp, curbp);
return XFS_ERROR(EFSCORRUPTED);
}
curfdb = newfdb;
@@ -459,12 +528,12 @@ out:
*/
STATIC int
xfs_dir2_leafn_lookup_for_entry(
- xfs_dabuf_t *bp, /* leaf buffer */
+ struct xfs_buf *bp, /* leaf buffer */
xfs_da_args_t *args, /* operation arguments */
int *indexp, /* out: leaf entry index */
xfs_da_state_t *state) /* state to fill in */
{
- xfs_dabuf_t *curbp = NULL; /* current data/free buffer */
+ struct xfs_buf *curbp = NULL; /* current data/free buffer */
xfs_dir2_db_t curdb = -1; /* current data block number */
xfs_dir2_data_entry_t *dep; /* data block entry */
xfs_inode_t *dp; /* incore directory inode */
@@ -480,7 +549,7 @@ xfs_dir2_leafn_lookup_for_entry(
dp = args->dp;
tp = args->trans;
mp = dp->i_mount;
- leaf = bp->data;
+ leaf = bp->b_addr;
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
#ifdef __KERNEL__
ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
@@ -525,7 +594,7 @@ xfs_dir2_leafn_lookup_for_entry(
*/
if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT ||
curdb != state->extrablk.blkno))
- xfs_da_brelse(tp, curbp);
+ xfs_trans_brelse(tp, curbp);
/*
* If needing the block that is saved with a CI match,
* use it otherwise read in the new data block.
@@ -535,9 +604,9 @@ xfs_dir2_leafn_lookup_for_entry(
ASSERT(state->extravalid);
curbp = state->extrablk.bp;
} else {
- error = xfs_da_read_buf(tp, dp,
+ error = xfs_dir2_data_read(tp, dp,
xfs_dir2_db_to_da(mp, newdb),
- -1, &curbp, XFS_DATA_FORK);
+ -1, &curbp);
if (error)
return error;
}
@@ -547,7 +616,7 @@ xfs_dir2_leafn_lookup_for_entry(
/*
* Point to the data entry.
*/
- dep = (xfs_dir2_data_entry_t *)((char *)curbp->data +
+ dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr +
xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
/*
* Compare the entry and if it's an exact match, return
@@ -559,7 +628,7 @@ xfs_dir2_leafn_lookup_for_entry(
/* If there is a CI match block, drop it */
if (args->cmpresult != XFS_CMP_DIFFERENT &&
curdb != state->extrablk.blkno)
- xfs_da_brelse(tp, state->extrablk.bp);
+ xfs_trans_brelse(tp, state->extrablk.bp);
args->cmpresult = cmp;
args->inumber = be64_to_cpu(dep->inumber);
*indexp = index;
@@ -567,8 +636,9 @@ xfs_dir2_leafn_lookup_for_entry(
state->extrablk.bp = curbp;
state->extrablk.blkno = curdb;
state->extrablk.index = (int)((char *)dep -
- (char *)curbp->data);
+ (char *)curbp->b_addr);
state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
+ curbp->b_ops = &xfs_dir2_data_buf_ops;
if (cmp == XFS_CMP_EXACT)
return XFS_ERROR(EEXIST);
}
@@ -583,10 +653,11 @@ xfs_dir2_leafn_lookup_for_entry(
state->extrablk.index = -1;
state->extrablk.blkno = curdb;
state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
+ curbp->b_ops = &xfs_dir2_data_buf_ops;
} else {
/* If the curbp is not the CI match block, drop it */
if (state->extrablk.bp != curbp)
- xfs_da_brelse(tp, curbp);
+ xfs_trans_brelse(tp, curbp);
}
} else {
state->extravalid = 0;
@@ -602,7 +673,7 @@ xfs_dir2_leafn_lookup_for_entry(
*/
int
xfs_dir2_leafn_lookup_int(
- xfs_dabuf_t *bp, /* leaf buffer */
+ struct xfs_buf *bp, /* leaf buffer */
xfs_da_args_t *args, /* operation arguments */
int *indexp, /* out: leaf entry index */
xfs_da_state_t *state) /* state to fill in */
@@ -620,9 +691,9 @@ xfs_dir2_leafn_lookup_int(
static void
xfs_dir2_leafn_moveents(
xfs_da_args_t *args, /* operation arguments */
- xfs_dabuf_t *bp_s, /* source leaf buffer */
+ struct xfs_buf *bp_s, /* source leaf buffer */
int start_s, /* source leaf index */
- xfs_dabuf_t *bp_d, /* destination leaf buffer */
+ struct xfs_buf *bp_d, /* destination leaf buffer */
int start_d, /* destination leaf index */
int count) /* count of leaves to copy */
{
@@ -640,8 +711,8 @@ xfs_dir2_leafn_moveents(
return;
}
tp = args->trans;
- leaf_s = bp_s->data;
- leaf_d = bp_d->data;
+ leaf_s = bp_s->b_addr;
+ leaf_d = bp_d->b_addr;
/*
* If the destination index is not the end of the current
* destination leaf entries, open up a hole in the destination
@@ -702,14 +773,14 @@ xfs_dir2_leafn_moveents(
*/
int /* sort order */
xfs_dir2_leafn_order(
- xfs_dabuf_t *leaf1_bp, /* leaf1 buffer */
- xfs_dabuf_t *leaf2_bp) /* leaf2 buffer */
+ struct xfs_buf *leaf1_bp, /* leaf1 buffer */
+ struct xfs_buf *leaf2_bp) /* leaf2 buffer */
{
xfs_dir2_leaf_t *leaf1; /* leaf1 structure */
xfs_dir2_leaf_t *leaf2; /* leaf2 structure */
- leaf1 = leaf1_bp->data;
- leaf2 = leaf2_bp->data;
+ leaf1 = leaf1_bp->b_addr;
+ leaf2 = leaf2_bp->b_addr;
ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
if (be16_to_cpu(leaf1->hdr.count) > 0 &&
@@ -757,8 +828,8 @@ xfs_dir2_leafn_rebalance(
blk1 = blk2;
blk2 = tmp;
}
- leaf1 = blk1->bp->data;
- leaf2 = blk2->bp->data;
+ leaf1 = blk1->bp->b_addr;
+ leaf2 = blk2->bp->b_addr;
oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count);
#ifdef DEBUG
oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale);
@@ -826,6 +897,77 @@ xfs_dir2_leafn_rebalance(
}
}
+static int
+xfs_dir2_data_block_free(
+ xfs_da_args_t *args,
+ struct xfs_dir2_data_hdr *hdr,
+ struct xfs_dir2_free *free,
+ xfs_dir2_db_t fdb,
+ int findex,
+ struct xfs_buf *fbp,
+ int longest)
+{
+ struct xfs_trans *tp = args->trans;
+ int logfree = 0;
+
+ if (!hdr) {
+ /* One less used entry in the free table. */
+ be32_add_cpu(&free->hdr.nused, -1);
+ xfs_dir2_free_log_header(tp, fbp);
+
+ /*
+ * If this was the last entry in the table, we can trim the
+ * table size back. There might be other entries at the end
+ * referring to non-existent data blocks, get those too.
+ */
+ if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
+ int i; /* free entry index */
+
+ for (i = findex - 1; i >= 0; i--) {
+ if (free->bests[i] != cpu_to_be16(NULLDATAOFF))
+ break;
+ }
+ free->hdr.nvalid = cpu_to_be32(i + 1);
+ logfree = 0;
+ } else {
+ /* Not the last entry, just punch it out. */
+ free->bests[findex] = cpu_to_be16(NULLDATAOFF);
+ logfree = 1;
+ }
+ /*
+ * If there are no useful entries left in the block,
+ * get rid of the block if we can.
+ */
+ if (!free->hdr.nused) {
+ int error;
+
+ error = xfs_dir2_shrink_inode(args, fdb, fbp);
+ if (error == 0) {
+ fbp = NULL;
+ logfree = 0;
+ } else if (error != ENOSPC || args->total != 0)
+ return error;
+ /*
+ * It's possible to get ENOSPC if there is no
+ * space reservation. In this case some one
+ * else will eventually get rid of this block.
+ */
+ }
+ } else {
+ /*
+ * Data block is not empty, just set the free entry to the new
+ * value.
+ */
+ free->bests[findex] = cpu_to_be16(longest);
+ logfree = 1;
+ }
+
+ /* Log the free entry that changed, unless we got rid of it. */
+ if (logfree)
+ xfs_dir2_free_log_bests(tp, fbp, findex, findex);
+ return 0;
+}
+
/*
* Remove an entry from a node directory.
* This removes the leaf entry and the data entry,
@@ -834,14 +976,14 @@ xfs_dir2_leafn_rebalance(
static int /* error */
xfs_dir2_leafn_remove(
xfs_da_args_t *args, /* operation arguments */
- xfs_dabuf_t *bp, /* leaf buffer */
+ struct xfs_buf *bp, /* leaf buffer */
int index, /* leaf entry index */
xfs_da_state_blk_t *dblk, /* data block */
int *rval) /* resulting block needs join */
{
xfs_dir2_data_hdr_t *hdr; /* data block header */
xfs_dir2_db_t db; /* data block number */
- xfs_dabuf_t *dbp; /* data block buffer */
+ struct xfs_buf *dbp; /* data block buffer */
xfs_dir2_data_entry_t *dep; /* data block entry */
xfs_inode_t *dp; /* incore directory inode */
xfs_dir2_leaf_t *leaf; /* leaf structure */
@@ -858,7 +1000,7 @@ xfs_dir2_leafn_remove(
dp = args->dp;
tp = args->trans;
mp = dp->i_mount;
- leaf = bp->data;
+ leaf = bp->b_addr;
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
/*
* Point to the entry we're removing.
@@ -884,7 +1026,7 @@ xfs_dir2_leafn_remove(
* in the data block in case it changes.
*/
dbp = dblk->bp;
- hdr = dbp->data;
+ hdr = dbp->b_addr;
dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
longest = be16_to_cpu(hdr->bestfree[0].length);
needlog = needscan = 0;
@@ -905,22 +1047,21 @@ xfs_dir2_leafn_remove(
*/
if (longest < be16_to_cpu(hdr->bestfree[0].length)) {
int error; /* error return value */
- xfs_dabuf_t *fbp; /* freeblock buffer */
+ struct xfs_buf *fbp; /* freeblock buffer */
xfs_dir2_db_t fdb; /* freeblock block number */
int findex; /* index in freeblock entries */
xfs_dir2_free_t *free; /* freeblock structure */
- int logfree; /* need to log free entry */
/*
* Convert the data block number to a free block,
* read in the free block.
*/
fdb = xfs_dir2_db_to_fdb(mp, db);
- if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb),
- -1, &fbp, XFS_DATA_FORK))) {
+ error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb),
+ &fbp);
+ if (error)
return error;
- }
- free = fbp->data;
+ free = fbp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
ASSERT(be32_to_cpu(free->hdr.firstdb) ==
xfs_dir2_free_max_bests(mp) *
@@ -948,82 +1089,19 @@ xfs_dir2_leafn_remove(
* In this case just drop the buffer and some one else
* will eventually get rid of the empty block.
*/
- else if (error == ENOSPC && args->total == 0)
- xfs_da_buf_done(dbp);
- else
+ else if (!(error == ENOSPC && args->total == 0))
return error;
}
/*
* If we got rid of the data block, we can eliminate that entry
* in the free block.
*/
- if (hdr == NULL) {
- /*
- * One less used entry in the free table.
- */
- be32_add_cpu(&free->hdr.nused, -1);
- xfs_dir2_free_log_header(tp, fbp);
- /*
- * If this was the last entry in the table, we can
- * trim the table size back. There might be other
- * entries at the end referring to non-existent
- * data blocks, get those too.
- */
- if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
- int i; /* free entry index */
-
- for (i = findex - 1;
- i >= 0 &&
- free->bests[i] == cpu_to_be16(NULLDATAOFF);
- i--)
- continue;
- free->hdr.nvalid = cpu_to_be32(i + 1);
- logfree = 0;
- }
- /*
- * Not the last entry, just punch it out.
- */
- else {
- free->bests[findex] = cpu_to_be16(NULLDATAOFF);
- logfree = 1;
- }
- /*
- * If there are no useful entries left in the block,
- * get rid of the block if we can.
- */
- if (!free->hdr.nused) {
- error = xfs_dir2_shrink_inode(args, fdb, fbp);
- if (error == 0) {
- fbp = NULL;
- logfree = 0;
- } else if (error != ENOSPC || args->total != 0)
- return error;
- /*
- * It's possible to get ENOSPC if there is no
- * space reservation. In this case some one
- * else will eventually get rid of this block.
- */
- }
- }
- /*
- * Data block is not empty, just set the free entry to
- * the new value.
- */
- else {
- free->bests[findex] = cpu_to_be16(longest);
- logfree = 1;
- }
- /*
- * Log the free entry that changed, unless we got rid of it.
- */
- if (logfree)
- xfs_dir2_free_log_bests(tp, fbp, findex, findex);
- /*
- * Drop the buffer if we still have it.
- */
- if (fbp)
- xfs_da_buf_done(fbp);
+ error = xfs_dir2_data_block_free(args, hdr, free,
+ fdb, findex, fbp, longest);
+ if (error)
+ return error;
}
+
xfs_dir2_leafn_check(dp, bp);
/*
* Return indication of whether this leaf block is empty enough
@@ -1114,7 +1192,7 @@ xfs_dir2_leafn_toosmall(
{
xfs_da_state_blk_t *blk; /* leaf block */
xfs_dablk_t blkno; /* leaf block number */
- xfs_dabuf_t *bp; /* leaf buffer */
+ struct xfs_buf *bp; /* leaf buffer */
int bytes; /* bytes in use */
int count; /* leaf live entry count */
int error; /* error return value */
@@ -1130,7 +1208,7 @@ xfs_dir2_leafn_toosmall(
* to coalesce with a sibling.
*/
blk = &state->path.blk[state->path.active - 1];
- info = blk->bp->data;
+ info = blk->bp->b_addr;
ASSERT(info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
leaf = (xfs_dir2_leaf_t *)info;
count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
@@ -1177,19 +1255,18 @@ xfs_dir2_leafn_toosmall(
/*
* Read the sibling leaf block.
*/
- if ((error =
- xfs_da_read_buf(state->args->trans, state->args->dp, blkno,
- -1, &bp, XFS_DATA_FORK))) {
+ error = xfs_dir2_leafn_read(state->args->trans, state->args->dp,
+ blkno, -1, &bp);
+ if (error)
return error;
- }
- ASSERT(bp != NULL);
+
/*
* Count bytes in the two blocks combined.
*/
leaf = (xfs_dir2_leaf_t *)info;
count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
bytes = state->blocksize - (state->blocksize >> 2);
- leaf = bp->data;
+ leaf = bp->b_addr;
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
bytes -= count * (uint)sizeof(leaf->ents[0]);
@@ -1198,7 +1275,7 @@ xfs_dir2_leafn_toosmall(
*/
if (bytes >= 0)
break;
- xfs_da_brelse(state->args->trans, bp);
+ xfs_trans_brelse(state->args->trans, bp);
}
/*
* Didn't like either block, give up.
@@ -1207,11 +1284,7 @@ xfs_dir2_leafn_toosmall(
*action = 0;
return 0;
}
- /*
- * Done with the sibling leaf block here, drop the dabuf
- * so path_shift can get it.
- */
- xfs_da_buf_done(bp);
+
/*
* Make altpath point to the block we want to keep (the lower
* numbered block) and path point to the block we want to drop.
@@ -1247,8 +1320,8 @@ xfs_dir2_leafn_unbalance(
args = state->args;
ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC);
- drop_leaf = drop_blk->bp->data;
- save_leaf = save_blk->bp->data;
+ drop_leaf = drop_blk->bp->b_addr;
+ save_leaf = save_blk->bp->b_addr;
ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
/*
@@ -1356,13 +1429,13 @@ xfs_dir2_node_addname_int(
{
xfs_dir2_data_hdr_t *hdr; /* data block header */
xfs_dir2_db_t dbno; /* data block number */
- xfs_dabuf_t *dbp; /* data block buffer */
+ struct xfs_buf *dbp; /* data block buffer */
xfs_dir2_data_entry_t *dep; /* data entry pointer */
xfs_inode_t *dp; /* incore directory inode */
xfs_dir2_data_unused_t *dup; /* data unused entry pointer */
int error; /* error return value */
xfs_dir2_db_t fbno; /* freespace block number */
- xfs_dabuf_t *fbp; /* freespace buffer */
+ struct xfs_buf *fbp; /* freespace buffer */
int findex; /* freespace entry index */
xfs_dir2_free_t *free=NULL; /* freespace block structure */
xfs_dir2_db_t ifbno; /* initial freespace block no */
@@ -1390,7 +1463,7 @@ xfs_dir2_node_addname_int(
* Remember initial freespace block number.
*/
ifbno = fblk->blkno;
- free = fbp->data;
+ free = fbp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
findex = fblk->index;
/*
@@ -1466,15 +1539,14 @@ xfs_dir2_node_addname_int(
* This should be really rare, so there's no reason
* to avoid it.
*/
- if ((error = xfs_da_read_buf(tp, dp,
- xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
- XFS_DATA_FORK))) {
+ error = xfs_dir2_free_try_read(tp, dp,
+ xfs_dir2_db_to_da(mp, fbno),
+ &fbp);
+ if (error)
return error;
- }
- if (unlikely(fbp == NULL)) {
+ if (!fbp)
continue;
- }
- free = fbp->data;
+ free = fbp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
findex = 0;
}
@@ -1492,7 +1564,7 @@ xfs_dir2_node_addname_int(
/*
* Drop the block.
*/
- xfs_da_brelse(tp, fbp);
+ xfs_trans_brelse(tp, fbp);
fbp = NULL;
if (fblk && fblk->bp)
fblk->bp = NULL;
@@ -1507,36 +1579,23 @@ xfs_dir2_node_addname_int(
/*
* Not allowed to allocate, return failure.
*/
- if ((args->op_flags & XFS_DA_OP_JUSTCHECK) ||
- args->total == 0) {
- /*
- * Drop the freespace buffer unless it came from our
- * caller.
- */
- if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
- xfs_da_buf_done(fbp);
+ if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
return XFS_ERROR(ENOSPC);
- }
+
/*
* Allocate and initialize the new data block.
*/
if (unlikely((error = xfs_dir2_grow_inode(args,
XFS_DIR2_DATA_SPACE,
&dbno)) ||
- (error = xfs_dir2_data_init(args, dbno, &dbp)))) {
- /*
- * Drop the freespace buffer unless it came from our
- * caller.
- */
- if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
- xfs_da_buf_done(fbp);
+ (error = xfs_dir2_data_init(args, dbno, &dbp))))
return error;
- }
+
/*
* If (somehow) we have a freespace block, get rid of it.
*/
if (fbp)
- xfs_da_brelse(tp, fbp);
+ xfs_trans_brelse(tp, fbp);
if (fblk && fblk->bp)
fblk->bp = NULL;
@@ -1545,12 +1604,12 @@ xfs_dir2_node_addname_int(
* that was just allocated.
*/
fbno = xfs_dir2_db_to_fdb(mp, dbno);
- if (unlikely(error = xfs_da_read_buf(tp, dp,
- xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
- XFS_DATA_FORK))) {
- xfs_da_buf_done(dbp);
+ error = xfs_dir2_free_try_read(tp, dp,
+ xfs_dir2_db_to_da(mp, fbno),
+ &fbp);
+ if (error)
return error;
- }
+
/*
* If there wasn't a freespace block, the read will
* return a NULL fbp. Allocate and initialize a new one.
@@ -1587,18 +1646,18 @@ xfs_dir2_node_addname_int(
/*
* Get a buffer for the new block.
*/
- if ((error = xfs_da_get_buf(tp, dp,
- xfs_dir2_db_to_da(mp, fbno),
- -1, &fbp, XFS_DATA_FORK))) {
+ error = xfs_da_get_buf(tp, dp,
+ xfs_dir2_db_to_da(mp, fbno),
+ -1, &fbp, XFS_DATA_FORK);
+ if (error)
return error;
- }
- ASSERT(fbp != NULL);
+ fbp->b_ops = &xfs_dir2_free_buf_ops;
/*
* Initialize the new block to be empty, and remember
* its first slot as our empty slot.
*/
- free = fbp->data;
+ free = fbp->b_addr;
free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
free->hdr.firstdb = cpu_to_be32(
(fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
@@ -1606,7 +1665,7 @@ xfs_dir2_node_addname_int(
free->hdr.nvalid = 0;
free->hdr.nused = 0;
} else {
- free = fbp->data;
+ free = fbp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
}
@@ -1639,7 +1698,7 @@ xfs_dir2_node_addname_int(
* We haven't allocated the data entry yet so this will
* change again.
*/
- hdr = dbp->data;
+ hdr = dbp->b_addr;
free->bests[findex] = hdr->bestfree[0].length;
logfree = 1;
}
@@ -1650,22 +1709,17 @@ xfs_dir2_node_addname_int(
/*
* If just checking, we succeeded.
*/
- if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
- if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
- xfs_da_buf_done(fbp);
+ if (args->op_flags & XFS_DA_OP_JUSTCHECK)
return 0;
- }
+
/*
* Read the data block in.
*/
- if (unlikely(
- error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
- -1, &dbp, XFS_DATA_FORK))) {
- if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
- xfs_da_buf_done(fbp);
+ error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno),
+ -1, &dbp);
+ if (error)
return error;
- }
- hdr = dbp->data;
+ hdr = dbp->b_addr;
logfree = 0;
}
ASSERT(be16_to_cpu(hdr->bestfree[0].length) >= length);
@@ -1714,16 +1768,10 @@ xfs_dir2_node_addname_int(
if (logfree)
xfs_dir2_free_log_bests(tp, fbp, findex, findex);
/*
- * If the caller didn't hand us the freespace block, drop it.
- */
- if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
- xfs_da_buf_done(fbp);
- /*
* Return the data block and offset in args, then drop the data block.
*/
args->blkno = (xfs_dablk_t)dbno;
args->index = be16_to_cpu(*tagp);
- xfs_da_buf_done(dbp);
return 0;
}
@@ -1761,22 +1809,23 @@ xfs_dir2_node_lookup(
/* If a CI match, dup the actual name and return EEXIST */
xfs_dir2_data_entry_t *dep;
- dep = (xfs_dir2_data_entry_t *)((char *)state->extrablk.bp->
- data + state->extrablk.index);
+ dep = (xfs_dir2_data_entry_t *)
+ ((char *)state->extrablk.bp->b_addr +
+ state->extrablk.index);
rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
}
/*
* Release the btree blocks and leaf block.
*/
for (i = 0; i < state->path.active; i++) {
- xfs_da_brelse(args->trans, state->path.blk[i].bp);
+ xfs_trans_brelse(args->trans, state->path.blk[i].bp);
state->path.blk[i].bp = NULL;
}
/*
* Release the data block if we have it.
*/
if (state->extravalid && state->extrablk.bp) {
- xfs_da_brelse(args->trans, state->extrablk.bp);
+ xfs_trans_brelse(args->trans, state->extrablk.bp);
state->extrablk.bp = NULL;
}
xfs_da_state_free(state);
@@ -1893,13 +1942,13 @@ xfs_dir2_node_replace(
*/
blk = &state->path.blk[state->path.active - 1];
ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
- leaf = blk->bp->data;
+ leaf = blk->bp->b_addr;
lep = &leaf->ents[blk->index];
ASSERT(state->extravalid);
/*
* Point to the data entry.
*/
- hdr = state->extrablk.bp->data;
+ hdr = state->extrablk.bp->b_addr;
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
dep = (xfs_dir2_data_entry_t *)
((char *)hdr +
@@ -1916,14 +1965,14 @@ xfs_dir2_node_replace(
* Didn't find it, and we're holding a data block. Drop it.
*/
else if (state->extravalid) {
- xfs_da_brelse(args->trans, state->extrablk.bp);
+ xfs_trans_brelse(args->trans, state->extrablk.bp);
state->extrablk.bp = NULL;
}
/*
* Release all the buffers in the cursor.
*/
for (i = 0; i < state->path.active; i++) {
- xfs_da_brelse(args->trans, state->path.blk[i].bp);
+ xfs_trans_brelse(args->trans, state->path.blk[i].bp);
state->path.blk[i].bp = NULL;
}
xfs_da_state_free(state);
@@ -1940,7 +1989,7 @@ xfs_dir2_node_trim_free(
xfs_fileoff_t fo, /* free block number */
int *rvalp) /* out: did something */
{
- xfs_dabuf_t *bp; /* freespace buffer */
+ struct xfs_buf *bp; /* freespace buffer */
xfs_inode_t *dp; /* incore directory inode */
int error; /* error return code */
xfs_dir2_free_t *free; /* freespace structure */
@@ -1953,25 +2002,22 @@ xfs_dir2_node_trim_free(
/*
* Read the freespace block.
*/
- if (unlikely(error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp,
- XFS_DATA_FORK))) {
+ error = xfs_dir2_free_try_read(tp, dp, fo, &bp);
+ if (error)
return error;
- }
-
/*
* There can be holes in freespace. If fo is a hole, there's
* nothing to do.
*/
- if (bp == NULL) {
+ if (!bp)
return 0;
- }
- free = bp->data;
+ free = bp->b_addr;
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
/*
* If there are used entries, there's nothing to do.
*/
if (be32_to_cpu(free->hdr.nused) > 0) {
- xfs_da_brelse(tp, bp);
+ xfs_trans_brelse(tp, bp);
*rvalp = 0;
return 0;
}
@@ -1987,7 +2033,7 @@ xfs_dir2_node_trim_free(
* pieces. This is the last block of an extent.
*/
ASSERT(error != ENOSPC);
- xfs_da_brelse(tp, bp);
+ xfs_trans_brelse(tp, bp);
return error;
}
/*