Commit f9f6dce0 authored by Barry Naujok's avatar Barry Naujok Committed by Niv Sardi

[XFS] Split xfs_dir2_leafn_lookup_int into its two pieces of functionality

SGI-PV: 976035
SGI-Modid: xfs-linux-melb:xfs-kern:30834a
Signed-off-by: default avatarBarry Naujok <bnaujok@sgi.com>
Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
parent c9272c4f
...@@ -387,28 +387,26 @@ xfs_dir2_leafn_lasthash( ...@@ -387,28 +387,26 @@ xfs_dir2_leafn_lasthash(
} }
/* /*
* Look up a leaf entry in a node-format leaf block. * Look up a leaf entry for space to add a name in a node-format leaf block.
* If this is an addname then the extrablk in state is a freespace block, * The extrablk in state is a freespace block.
* otherwise it's a data block.
*/ */
int STATIC int
xfs_dir2_leafn_lookup_int( xfs_dir2_leafn_lookup_for_addname(
xfs_dabuf_t *bp, /* leaf buffer */ xfs_dabuf_t *bp, /* leaf buffer */
xfs_da_args_t *args, /* operation arguments */ xfs_da_args_t *args, /* operation arguments */
int *indexp, /* out: leaf entry index */ int *indexp, /* out: leaf entry index */
xfs_da_state_t *state) /* state to fill in */ xfs_da_state_t *state) /* state to fill in */
{ {
xfs_dabuf_t *curbp; /* current data/free buffer */ xfs_dabuf_t *curbp = NULL; /* current data/free buffer */
xfs_dir2_db_t curdb; /* current data block number */ xfs_dir2_db_t curdb = -1; /* current data block number */
xfs_dir2_db_t curfdb; /* current free block number */ xfs_dir2_db_t curfdb = -1; /* current free block number */
xfs_dir2_data_entry_t *dep; /* data block entry */
xfs_inode_t *dp; /* incore directory inode */ xfs_inode_t *dp; /* incore directory inode */
int error; /* error return value */ int error; /* error return value */
int fi; /* free entry index */ int fi; /* free entry index */
xfs_dir2_free_t *free=NULL; /* free block structure */ xfs_dir2_free_t *free = NULL; /* free block structure */
int index; /* leaf entry index */ int index; /* leaf entry index */
xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_t *leaf; /* leaf structure */
int length=0; /* length of new data entry */ int length; /* length of new data entry */
xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */
xfs_mount_t *mp; /* filesystem mount point */ xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_db_t newdb; /* new data block number */ xfs_dir2_db_t newdb; /* new data block number */
...@@ -431,33 +429,20 @@ xfs_dir2_leafn_lookup_int( ...@@ -431,33 +429,20 @@ xfs_dir2_leafn_lookup_int(
/* /*
* Do we have a buffer coming in? * Do we have a buffer coming in?
*/ */
if (state->extravalid) if (state->extravalid) {
/* If so, it's a free block buffer, get the block number. */
curbp = state->extrablk.bp; curbp = state->extrablk.bp;
else curfdb = state->extrablk.blkno;
curbp = NULL; free = curbp->data;
/* ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
* For addname, it's a free block buffer, get the block number.
*/
if (args->addname) {
curfdb = curbp ? state->extrablk.blkno : -1;
curdb = -1;
length = xfs_dir2_data_entsize(args->namelen);
if ((free = (curbp ? curbp->data : NULL)))
ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
}
/*
* For others, it's a data block buffer, get the block number.
*/
else {
curfdb = -1;
curdb = curbp ? state->extrablk.blkno : -1;
} }
length = xfs_dir2_data_entsize(args->namelen);
/* /*
* Loop over leaf entries with the right hash value. * Loop over leaf entries with the right hash value.
*/ */
for (lep = &leaf->ents[index]; for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; be32_to_cpu(lep->hashval) == args->hashval;
lep++, index++) { lep++, index++) {
/* /*
* Skip stale leaf entries. * Skip stale leaf entries.
*/ */
...@@ -471,158 +456,218 @@ xfs_dir2_leafn_lookup_int( ...@@ -471,158 +456,218 @@ xfs_dir2_leafn_lookup_int(
* For addname, we're looking for a place to put the new entry. * For addname, we're looking for a place to put the new entry.
* We want to use a data block with an entry of equal * We want to use a data block with an entry of equal
* hash value to ours if there is one with room. * hash value to ours if there is one with room.
*
* If this block isn't the data block we already have
* in hand, take a look at it.
*/ */
if (args->addname) { if (newdb != curdb) {
curdb = newdb;
/* /*
* If this block isn't the data block we already have * Convert the data block to the free block
* in hand, take a look at it. * holding its freespace information.
*/ */
if (newdb != curdb) { newfdb = xfs_dir2_db_to_fdb(mp, newdb);
curdb = newdb;
/*
* Convert the data block to the free block
* holding its freespace information.
*/
newfdb = xfs_dir2_db_to_fdb(mp, newdb);
/*
* If it's not the one we have in hand,
* read it in.
*/
if (newfdb != curfdb) {
/*
* If we had one before, drop it.
*/
if (curbp)
xfs_da_brelse(tp, curbp);
/*
* Read the free block.
*/
if ((error = xfs_da_read_buf(tp, dp,
xfs_dir2_db_to_da(mp,
newfdb),
-1, &curbp,
XFS_DATA_FORK))) {
return error;
}
free = curbp->data;
ASSERT(be32_to_cpu(free->hdr.magic) ==
XFS_DIR2_FREE_MAGIC);
ASSERT((be32_to_cpu(free->hdr.firstdb) %
XFS_DIR2_MAX_FREE_BESTS(mp)) ==
0);
ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
ASSERT(curdb <
be32_to_cpu(free->hdr.firstdb) +
be32_to_cpu(free->hdr.nvalid));
}
/*
* Get the index for our entry.
*/
fi = xfs_dir2_db_to_fdindex(mp, curdb);
/*
* If it has room, return it.
*/
if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
XFS_ERRLEVEL_LOW, mp);
if (curfdb != newfdb)
xfs_da_brelse(tp, curbp);
return XFS_ERROR(EFSCORRUPTED);
}
curfdb = newfdb;
if (be16_to_cpu(free->bests[fi]) >= length) {
*indexp = index;
state->extravalid = 1;
state->extrablk.bp = curbp;
state->extrablk.blkno = curfdb;
state->extrablk.index = fi;
state->extrablk.magic =
XFS_DIR2_FREE_MAGIC;
ASSERT(args->oknoent);
return XFS_ERROR(ENOENT);
}
}
}
/*
* Not adding a new entry, so we really want to find
* the name given to us.
*/
else {
/* /*
* If it's a different data block, go get it. * If it's not the one we have in hand, read it in.
*/ */
if (newdb != curdb) { if (newfdb != curfdb) {
/* /*
* If we had a block before, drop it. * If we had one before, drop it.
*/ */
if (curbp) if (curbp)
xfs_da_brelse(tp, curbp); xfs_da_brelse(tp, curbp);
/* /*
* Read the data block. * Read the free block.
*/ */
if ((error = error = xfs_da_read_buf(tp, dp,
xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newfdb),
xfs_dir2_db_to_da(mp, newdb), -1, -1, &curbp, XFS_DATA_FORK);
&curbp, XFS_DATA_FORK))) { if (error)
return error; return error;
} free = curbp->data;
xfs_dir2_data_check(dp, curbp); ASSERT(be32_to_cpu(free->hdr.magic) ==
curdb = newdb; XFS_DIR2_FREE_MAGIC);
ASSERT((be32_to_cpu(free->hdr.firstdb) %
XFS_DIR2_MAX_FREE_BESTS(mp)) == 0);
ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) +
be32_to_cpu(free->hdr.nvalid));
} }
/* /*
* Point to the data entry. * Get the index for our entry.
*/ */
dep = (xfs_dir2_data_entry_t *) fi = xfs_dir2_db_to_fdindex(mp, curdb);
((char *)curbp->data +
xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
/* /*
* Compare the entry, return it if it matches. * If it has room, return it.
*/ */
if (dep->namelen == args->namelen && if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
dep->name[0] == args->name[0] && XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
memcmp(dep->name, args->name, args->namelen) == 0) { XFS_ERRLEVEL_LOW, mp);
args->inumber = be64_to_cpu(dep->inumber); if (curfdb != newfdb)
*indexp = index; xfs_da_brelse(tp, curbp);
state->extravalid = 1; return XFS_ERROR(EFSCORRUPTED);
state->extrablk.bp = curbp;
state->extrablk.blkno = curdb;
state->extrablk.index =
(int)((char *)dep -
(char *)curbp->data);
state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
return XFS_ERROR(EEXIST);
} }
curfdb = newfdb;
if (be16_to_cpu(free->bests[fi]) >= length)
goto out;
} }
} }
/* Didn't find any space */
fi = -1;
out:
ASSERT(args->oknoent);
if (curbp) {
/* Giving back a free block. */
state->extravalid = 1;
state->extrablk.bp = curbp;
state->extrablk.index = fi;
state->extrablk.blkno = curfdb;
state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
} else {
state->extravalid = 0;
}
/* /*
* Didn't find a match. * Return the index, that will be the insertion point.
* If we are holding a buffer, give it back in case our caller
* finds it useful.
*/ */
if ((state->extravalid = (curbp != NULL))) { *indexp = index;
state->extrablk.bp = curbp; return XFS_ERROR(ENOENT);
state->extrablk.index = -1; }
/*
* Look up a leaf entry in a node-format leaf block.
* The extrablk in state a data block.
*/
STATIC int
xfs_dir2_leafn_lookup_for_entry(
xfs_dabuf_t *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 */
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 */
int error; /* error return value */
int di; /* data entry index */
int index; /* leaf entry index */
xfs_dir2_leaf_t *leaf; /* leaf structure */
xfs_dir2_leaf_entry_t *lep; /* leaf entry */
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_db_t newdb; /* new data block number */
xfs_trans_t *tp; /* transaction pointer */
dp = args->dp;
tp = args->trans;
mp = dp->i_mount;
leaf = bp->data;
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
#ifdef __KERNEL__
ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
#endif
xfs_dir2_leafn_check(dp, bp);
/*
* Look up the hash value in the leaf entries.
*/
index = xfs_dir2_leaf_search_hash(args, bp);
/*
* Do we have a buffer coming in?
*/
if (state->extravalid) {
curbp = state->extrablk.bp;
curdb = state->extrablk.blkno;
}
/*
* Loop over leaf entries with the right hash value.
*/
for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
be32_to_cpu(lep->hashval) == args->hashval;
lep++, index++) {
/*
* Skip stale leaf entries.
*/
if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
continue;
/*
* Pull the data block number from the entry.
*/
newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
/* /*
* For addname, giving back a free block. * Not adding a new entry, so we really want to find
* the name given to us.
*
* If it's a different data block, go get it.
*/ */
if (args->addname) { if (newdb != curdb) {
state->extrablk.blkno = curfdb; /*
state->extrablk.magic = XFS_DIR2_FREE_MAGIC; * If we had a block before, drop it.
*/
if (curbp)
xfs_da_brelse(tp, curbp);
/*
* Read the data block.
*/
error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp,
newdb), -1, &curbp, XFS_DATA_FORK);
if (error)
return error;
xfs_dir2_data_check(dp, curbp);
curdb = newdb;
} }
/* /*
* For other callers, giving back a data block. * Point to the data entry.
*/ */
else { dep = (xfs_dir2_data_entry_t *)((char *)curbp->data +
state->extrablk.blkno = curdb; xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
state->extrablk.magic = XFS_DIR2_DATA_MAGIC; /*
* Compare the entry, return it if it matches.
*/
if (dep->namelen == args->namelen && memcmp(dep->name,
args->name, args->namelen) == 0) {
args->inumber = be64_to_cpu(dep->inumber);
di = (int)((char *)dep - (char *)curbp->data);
error = EEXIST;
goto out;
} }
} }
/* Didn't find a match. */
error = ENOENT;
di = -1;
ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent);
out:
if (curbp) {
/* Giving back a data block. */
state->extravalid = 1;
state->extrablk.bp = curbp;
state->extrablk.index = di;
state->extrablk.blkno = curdb;
state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
} else {
state->extravalid = 0;
}
/* /*
* Return the final index, that will be the insertion point. * Return the index, that will be the insertion point.
*/ */
*indexp = index; *indexp = index;
ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent); return XFS_ERROR(error);
return XFS_ERROR(ENOENT); }
/*
* Look up a leaf entry in a node-format leaf block.
* If this is an addname then the extrablk in state is a freespace block,
* otherwise it's a data block.
*/
int
xfs_dir2_leafn_lookup_int(
xfs_dabuf_t *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 */
{
if (args->addname)
return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp,
state);
return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state);
} }
/* /*
...@@ -823,9 +868,10 @@ xfs_dir2_leafn_rebalance( ...@@ -823,9 +868,10 @@ xfs_dir2_leafn_rebalance(
*/ */
if (!state->inleaf) if (!state->inleaf)
blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count);
/* /*
* Finally sanity check just to make sure we are not returning a negative index * Finally sanity check just to make sure we are not returning a
* negative index
*/ */
if(blk2->index < 0) { if(blk2->index < 0) {
state->inleaf = 1; state->inleaf = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment