* Check the internal consistency of a leaf1 block.
* Pop an assert if something is wrong.
*/
-void
+STATIC void
xfs_dir2_leaf_check(
xfs_inode_t *dp, /* incore directory inode */
xfs_dabuf_t *bp) /* leaf's buffer */
int ra_index; /* *map index for read-ahead */
int ra_offset; /* map entry offset for ra */
int ra_want; /* readahead count wanted */
- xfs_ino_t ino;
/*
* If the offset is at or past the largest allowed value,
*/
ra_want = howmany(bufsize + mp->m_dirblksize,
mp->m_sb.sb_blocksize) - 1;
+ ASSERT(ra_want >= 0);
/*
* If we don't have as many as we want, and we haven't
continue;
}
- /*
- * Copy the entry into the putargs, and try formatting it.
- */
dep = (xfs_dir2_data_entry_t *)ptr;
-
length = xfs_dir2_data_entsize(dep->namelen);
- ino = be64_to_cpu(dep->inumber);
-#if XFS_BIG_INUMS
- ino += mp->m_inoadd;
-#endif
-
- /*
- * Won't fit. Return to caller.
- */
if (filldir(dirent, dep->name, dep->namelen,
- xfs_dir2_byte_to_dataptr(mp, curoff),
- ino, DT_UNKNOWN))
+ xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff,
+ be64_to_cpu(dep->inumber), DT_UNKNOWN))
break;
/*
*/
ptr += length;
curoff += length;
- bufsize -= length;
+ /* bufsize may have just been a guess; don't go negative */
+ bufsize = bufsize > length ? bufsize - length : 0;
}
/*
* All done. Set output offset value to current offset.
*/
if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
- *offset = XFS_DIR2_MAX_DATAPTR;
+ *offset = XFS_DIR2_MAX_DATAPTR & 0x7fffffff;
else
- *offset = xfs_dir2_byte_to_dataptr(mp, curoff);
+ *offset = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff;
kmem_free(map);
if (bp)
xfs_da_brelse(NULL, bp);
int *indexp, /* out: index in leaf block */
xfs_dabuf_t **dbpp) /* out: data buffer */
{
- xfs_dir2_db_t curdb; /* current data block number */
- xfs_dabuf_t *dbp; /* data buffer */
+ xfs_dir2_db_t curdb = -1; /* current data block number */
+ xfs_dabuf_t *dbp = NULL; /* data buffer */
xfs_dir2_data_entry_t *dep; /* data entry */
xfs_inode_t *dp; /* incore directory inode */
int error; /* error return code */
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_db_t newdb; /* new data block number */
xfs_trans_t *tp; /* transaction pointer */
- xfs_dabuf_t *cbp; /* case match data buffer */
+ xfs_dir2_db_t cidb = -1; /* case match data block no. */
enum xfs_dacmp cmp; /* name compare result */
dp = args->dp;
/*
* Read the leaf block into the buffer.
*/
- if ((error =
- xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
- XFS_DATA_FORK))) {
+ error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
+ XFS_DATA_FORK);
+ if (error)
return error;
- }
*lbpp = lbp;
leaf = lbp->data;
xfs_dir2_leaf_check(dp, lbp);
* Loop over all the entries with the right hash value
* looking to match the name.
*/
- cbp = NULL;
- for (lep = &leaf->ents[index], dbp = NULL, curdb = -1;
- index < be16_to_cpu(leaf->hdr.count) &&
+ for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
be32_to_cpu(lep->hashval) == args->hashval;
lep++, index++) {
/*
* need to pitch the old one and read the new one.
*/
if (newdb != curdb) {
- if (dbp != cbp)
+ if (dbp)
xfs_da_brelse(tp, dbp);
error = xfs_da_read_buf(tp, dp,
xfs_dir2_db_to_da(mp, newdb),
if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
args->cmpresult = cmp;
*indexp = index;
- /*
- * case exact match: release the stored CI buffer if it
- * exists and return the current buffer.
- */
+ /* case exact match: return the current buffer. */
if (cmp == XFS_CMP_EXACT) {
- if (cbp && cbp != dbp)
- xfs_da_brelse(tp, cbp);
*dbpp = dbp;
return 0;
}
- cbp = dbp;
+ cidb = curdb;
}
}
ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
/*
- * Here, we can only be doing a lookup (not a rename or replace).
- * If a case-insensitive match was found earlier, release the current
- * buffer and return the stored CI matching buffer.
+ * Here, we can only be doing a lookup (not a rename or remove).
+ * If a case-insensitive match was found earlier, re-read the
+ * appropriate data block if required and return it.
*/
if (args->cmpresult == XFS_CMP_CASE) {
- if (cbp != dbp)
+ ASSERT(cidb != -1);
+ if (cidb != curdb) {
xfs_da_brelse(tp, dbp);
- *dbpp = cbp;
+ error = xfs_da_read_buf(tp, dp,
+ xfs_dir2_db_to_da(mp, cidb),
+ -1, &dbp, XFS_DATA_FORK);
+ if (error) {
+ xfs_da_brelse(tp, lbp);
+ return error;
+ }
+ }
+ *dbpp = dbp;
return 0;
}
/*
* No match found, return ENOENT.
*/
- ASSERT(cbp == NULL);
+ ASSERT(cidb == -1);
if (dbp)
xfs_da_brelse(tp, dbp);
xfs_da_brelse(tp, lbp);