Loading fs/xfs/xfs_dir2_node.c +202 −156 Original line number Diff line number Diff line Loading @@ -387,28 +387,26 @@ xfs_dir2_leafn_lasthash( } /* * 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. * Look up a leaf entry for space to add a name in a node-format leaf block. * The extrablk in state is a freespace block. */ int xfs_dir2_leafn_lookup_int( STATIC int xfs_dir2_leafn_lookup_for_addname( 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; /* current data/free buffer */ xfs_dir2_db_t curdb; /* current data block number */ xfs_dir2_db_t curfdb; /* current free block number */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_dabuf_t *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 */ int error; /* error return value */ int fi; /* free entry index */ xfs_dir2_free_t *free = NULL; /* free block structure */ int index; /* leaf entry index */ 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_mount_t *mp; /* filesystem mount point */ xfs_dir2_db_t newdb; /* new data block number */ Loading @@ -431,32 +429,19 @@ xfs_dir2_leafn_lookup_int( /* * 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; else curbp = NULL; /* * 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))) curfdb = state->extrablk.blkno; free = curbp->data; 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. */ for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; 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. Loading @@ -471,9 +456,7 @@ xfs_dir2_leafn_lookup_int( * 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 * hash value to ours if there is one with room. */ if (args->addname) { /* * * If this block isn't the data block we already have * in hand, take a look at it. */ Loading @@ -485,8 +468,7 @@ xfs_dir2_leafn_lookup_int( */ newfdb = xfs_dir2_db_to_fdb(mp, newdb); /* * If it's not the one we have in hand, * read it in. * If it's not the one we have in hand, read it in. */ if (newfdb != curfdb) { /* Loading @@ -497,22 +479,18 @@ xfs_dir2_leafn_lookup_int( /* * Read the free block. */ if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newfdb), -1, &curbp, XFS_DATA_FORK))) { error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newfdb), -1, &curbp, XFS_DATA_FORK); if (error) 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); XFS_DIR2_MAX_FREE_BESTS(mp)) == 0); ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb); ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) + ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) + be32_to_cpu(free->hdr.nvalid)); } /* Loading @@ -530,25 +508,94 @@ xfs_dir2_leafn_lookup_int( return XFS_ERROR(EFSCORRUPTED); } curfdb = newfdb; if (be16_to_cpu(free->bests[fi]) >= length) { *indexp = index; 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.blkno = curfdb; state->extrablk.index = fi; state->extrablk.magic = XFS_DIR2_FREE_MAGIC; ASSERT(args->oknoent); return XFS_ERROR(ENOENT); state->extrablk.blkno = curfdb; state->extrablk.magic = XFS_DIR2_FREE_MAGIC; } else { state->extravalid = 0; } /* * Return the index, that will be the insertion point. */ *indexp = index; return XFS_ERROR(ENOENT); } /* * 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; } /* * Not adding a new entry, so we really want to find * the name given to us. * Loop over leaf entries with the right hash value. */ else { 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)); /* * 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 (newdb != curdb) { Loading @@ -560,69 +607,67 @@ xfs_dir2_leafn_lookup_int( /* * Read the data block. */ if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newdb), -1, &curbp, XFS_DATA_FORK))) { 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; } /* * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *) ((char *)curbp->data + dep = (xfs_dir2_data_entry_t *)((char *)curbp->data + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); /* * Compare the entry, return it if it matches. */ if (dep->namelen == args->namelen && dep->name[0] == args->name[0] && memcmp(dep->name, args->name, args->namelen) == 0) { if (dep->namelen == args->namelen && memcmp(dep->name, args->name, args->namelen) == 0) { args->inumber = be64_to_cpu(dep->inumber); *indexp = index; 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.index = (int)((char *)dep - (char *)curbp->data); state->extrablk.magic = XFS_DIR2_DATA_MAGIC; return XFS_ERROR(EEXIST); } } } /* * Didn't find a match. * If we are holding a buffer, give it back in case our caller * finds it useful. */ if ((state->extravalid = (curbp != NULL))) { state->extrablk.bp = curbp; state->extrablk.index = -1; /* * For addname, giving back a free block. */ if (args->addname) { state->extrablk.blkno = curfdb; state->extrablk.magic = XFS_DIR2_FREE_MAGIC; } else { state->extravalid = 0; } /* * For other callers, giving back a data block. * Return the index, that will be the insertion point. */ else { state->extrablk.blkno = curdb; state->extrablk.magic = XFS_DIR2_DATA_MAGIC; } *indexp = index; return XFS_ERROR(error); } /* * Return the final index, that will be the insertion point. * 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. */ *indexp = index; ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent); return XFS_ERROR(ENOENT); 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); } /* Loading Loading @@ -825,7 +870,8 @@ xfs_dir2_leafn_rebalance( 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) { state->inleaf = 1; Loading Loading
fs/xfs/xfs_dir2_node.c +202 −156 Original line number Diff line number Diff line Loading @@ -387,28 +387,26 @@ xfs_dir2_leafn_lasthash( } /* * 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. * Look up a leaf entry for space to add a name in a node-format leaf block. * The extrablk in state is a freespace block. */ int xfs_dir2_leafn_lookup_int( STATIC int xfs_dir2_leafn_lookup_for_addname( 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; /* current data/free buffer */ xfs_dir2_db_t curdb; /* current data block number */ xfs_dir2_db_t curfdb; /* current free block number */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_dabuf_t *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 */ int error; /* error return value */ int fi; /* free entry index */ xfs_dir2_free_t *free = NULL; /* free block structure */ int index; /* leaf entry index */ 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_mount_t *mp; /* filesystem mount point */ xfs_dir2_db_t newdb; /* new data block number */ Loading @@ -431,32 +429,19 @@ xfs_dir2_leafn_lookup_int( /* * 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; else curbp = NULL; /* * 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))) curfdb = state->extrablk.blkno; free = curbp->data; 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. */ for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; 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. Loading @@ -471,9 +456,7 @@ xfs_dir2_leafn_lookup_int( * 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 * hash value to ours if there is one with room. */ if (args->addname) { /* * * If this block isn't the data block we already have * in hand, take a look at it. */ Loading @@ -485,8 +468,7 @@ xfs_dir2_leafn_lookup_int( */ newfdb = xfs_dir2_db_to_fdb(mp, newdb); /* * If it's not the one we have in hand, * read it in. * If it's not the one we have in hand, read it in. */ if (newfdb != curfdb) { /* Loading @@ -497,22 +479,18 @@ xfs_dir2_leafn_lookup_int( /* * Read the free block. */ if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newfdb), -1, &curbp, XFS_DATA_FORK))) { error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newfdb), -1, &curbp, XFS_DATA_FORK); if (error) 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); XFS_DIR2_MAX_FREE_BESTS(mp)) == 0); ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb); ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) + ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) + be32_to_cpu(free->hdr.nvalid)); } /* Loading @@ -530,25 +508,94 @@ xfs_dir2_leafn_lookup_int( return XFS_ERROR(EFSCORRUPTED); } curfdb = newfdb; if (be16_to_cpu(free->bests[fi]) >= length) { *indexp = index; 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.blkno = curfdb; state->extrablk.index = fi; state->extrablk.magic = XFS_DIR2_FREE_MAGIC; ASSERT(args->oknoent); return XFS_ERROR(ENOENT); state->extrablk.blkno = curfdb; state->extrablk.magic = XFS_DIR2_FREE_MAGIC; } else { state->extravalid = 0; } /* * Return the index, that will be the insertion point. */ *indexp = index; return XFS_ERROR(ENOENT); } /* * 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; } /* * Not adding a new entry, so we really want to find * the name given to us. * Loop over leaf entries with the right hash value. */ else { 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)); /* * 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 (newdb != curdb) { Loading @@ -560,69 +607,67 @@ xfs_dir2_leafn_lookup_int( /* * Read the data block. */ if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newdb), -1, &curbp, XFS_DATA_FORK))) { 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; } /* * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *) ((char *)curbp->data + dep = (xfs_dir2_data_entry_t *)((char *)curbp->data + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); /* * Compare the entry, return it if it matches. */ if (dep->namelen == args->namelen && dep->name[0] == args->name[0] && memcmp(dep->name, args->name, args->namelen) == 0) { if (dep->namelen == args->namelen && memcmp(dep->name, args->name, args->namelen) == 0) { args->inumber = be64_to_cpu(dep->inumber); *indexp = index; 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.index = (int)((char *)dep - (char *)curbp->data); state->extrablk.magic = XFS_DIR2_DATA_MAGIC; return XFS_ERROR(EEXIST); } } } /* * Didn't find a match. * If we are holding a buffer, give it back in case our caller * finds it useful. */ if ((state->extravalid = (curbp != NULL))) { state->extrablk.bp = curbp; state->extrablk.index = -1; /* * For addname, giving back a free block. */ if (args->addname) { state->extrablk.blkno = curfdb; state->extrablk.magic = XFS_DIR2_FREE_MAGIC; } else { state->extravalid = 0; } /* * For other callers, giving back a data block. * Return the index, that will be the insertion point. */ else { state->extrablk.blkno = curdb; state->extrablk.magic = XFS_DIR2_DATA_MAGIC; } *indexp = index; return XFS_ERROR(error); } /* * Return the final index, that will be the insertion point. * 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. */ *indexp = index; ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent); return XFS_ERROR(ENOENT); 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); } /* Loading Loading @@ -825,7 +870,8 @@ xfs_dir2_leafn_rebalance( 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) { state->inleaf = 1; Loading