aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2_leaf.c
diff options
context:
space:
mode:
authorBarry Naujok <bnaujok@sgi.com>2008-05-21 02:41:01 -0400
committerNiv Sardi <xaiki@debian.org>2008-07-28 02:58:36 -0400
commit5163f95a08cbf058ae16452c2242c5600fedc32e (patch)
tree5d6b905f7031144a62fb1fa17ba3106d99268003 /fs/xfs/xfs_dir2_leaf.c
parent68f34d5107dbace3d14a1c2f060fc8941894879c (diff)
[XFS] Name operation vector for hash and compare
Adds two pieces of functionality for the basis of case-insensitive support in XFS: 1. A comparison result enumerated type: xfs_dacmp. It represents an exact match, case-insensitive match or no match at all. This patch only implements different and exact results. 2. xfs_nameops vector for specifying how to perform the hash generation of filenames and comparision methods. In this patch the hash vector points to the existing xfs_da_hashname function and the comparison method does a length compare, and if the same, does a memcmp and return the xfs_dacmp result. All filename functions that use the hash (create, lookup remove, rename, etc) now use the xfs_nameops.hashname function and all directory lookup functions also use the xfs_nameops.compname function. The lookup functions also handle case-insensitive results even though the default comparison function cannot return that. And important aspect of the lookup functions is that an exact match always has precedence over a case-insensitive. So while a case-insensitive match is found, we have to keep looking just in case there is an exact match. In the meantime, the info for the first case-insensitive match is retained if no exact match is found. SGI-PV: 981519 SGI-Modid: xfs-linux-melb:xfs-kern:31205a Signed-off-by: Barry Naujok <bnaujok@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs/xfs/xfs_dir2_leaf.c')
-rw-r--r--fs/xfs/xfs_dir2_leaf.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index e33433408e4a..b52903bc0b14 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -1331,6 +1331,8 @@ xfs_dir2_leaf_lookup_int(
1331 xfs_mount_t *mp; /* filesystem mount point */ 1331 xfs_mount_t *mp; /* filesystem mount point */
1332 xfs_dir2_db_t newdb; /* new data block number */ 1332 xfs_dir2_db_t newdb; /* new data block number */
1333 xfs_trans_t *tp; /* transaction pointer */ 1333 xfs_trans_t *tp; /* transaction pointer */
1334 xfs_dabuf_t *cbp; /* case match data buffer */
1335 enum xfs_dacmp cmp; /* name compare result */
1334 1336
1335 dp = args->dp; 1337 dp = args->dp;
1336 tp = args->trans; 1338 tp = args->trans;
@@ -1354,9 +1356,11 @@ xfs_dir2_leaf_lookup_int(
1354 * Loop over all the entries with the right hash value 1356 * Loop over all the entries with the right hash value
1355 * looking to match the name. 1357 * looking to match the name.
1356 */ 1358 */
1359 cbp = NULL;
1357 for (lep = &leaf->ents[index], dbp = NULL, curdb = -1; 1360 for (lep = &leaf->ents[index], dbp = NULL, curdb = -1;
1358 index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; 1361 index < be16_to_cpu(leaf->hdr.count) &&
1359 lep++, index++) { 1362 be32_to_cpu(lep->hashval) == args->hashval;
1363 lep++, index++) {
1360 /* 1364 /*
1361 * Skip over stale leaf entries. 1365 * Skip over stale leaf entries.
1362 */ 1366 */
@@ -1371,12 +1375,12 @@ xfs_dir2_leaf_lookup_int(
1371 * need to pitch the old one and read the new one. 1375 * need to pitch the old one and read the new one.
1372 */ 1376 */
1373 if (newdb != curdb) { 1377 if (newdb != curdb) {
1374 if (dbp) 1378 if (dbp != cbp)
1375 xfs_da_brelse(tp, dbp); 1379 xfs_da_brelse(tp, dbp);
1376 if ((error = 1380 error = xfs_da_read_buf(tp, dp,
1377 xfs_da_read_buf(tp, dp, 1381 xfs_dir2_db_to_da(mp, newdb),
1378 xfs_dir2_db_to_da(mp, newdb), -1, &dbp, 1382 -1, &dbp, XFS_DATA_FORK);
1379 XFS_DATA_FORK))) { 1383 if (error) {
1380 xfs_da_brelse(tp, lbp); 1384 xfs_da_brelse(tp, lbp);
1381 return error; 1385 return error;
1382 } 1386 }
@@ -1386,24 +1390,46 @@ xfs_dir2_leaf_lookup_int(
1386 /* 1390 /*
1387 * Point to the data entry. 1391 * Point to the data entry.
1388 */ 1392 */
1389 dep = (xfs_dir2_data_entry_t *) 1393 dep = (xfs_dir2_data_entry_t *)((char *)dbp->data +
1390 ((char *)dbp->data + 1394 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
1391 xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
1392 /* 1395 /*
1393 * If it matches then return it. 1396 * Compare name and if it's an exact match, return the index
1397 * and buffer. If it's the first case-insensitive match, store
1398 * the index and buffer and continue looking for an exact match.
1394 */ 1399 */
1395 if (dep->namelen == args->namelen && 1400 cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
1396 dep->name[0] == args->name[0] && 1401 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
1397 memcmp(dep->name, args->name, args->namelen) == 0) { 1402 args->cmpresult = cmp;
1398 *dbpp = dbp;
1399 *indexp = index; 1403 *indexp = index;
1400 return 0; 1404 /*
1405 * case exact match: release the stored CI buffer if it
1406 * exists and return the current buffer.
1407 */
1408 if (cmp == XFS_CMP_EXACT) {
1409 if (cbp && cbp != dbp)
1410 xfs_da_brelse(tp, cbp);
1411 *dbpp = dbp;
1412 return 0;
1413 }
1414 cbp = dbp;
1401 } 1415 }
1402 } 1416 }
1417 ASSERT(args->oknoent);
1418 /*
1419 * Here, we can only be doing a lookup (not a rename or replace).
1420 * If a case-insensitive match was found earlier, release the current
1421 * buffer and return the stored CI matching buffer.
1422 */
1423 if (args->cmpresult == XFS_CMP_CASE) {
1424 if (cbp != dbp)
1425 xfs_da_brelse(tp, dbp);
1426 *dbpp = cbp;
1427 return 0;
1428 }
1403 /* 1429 /*
1404 * No match found, return ENOENT. 1430 * No match found, return ENOENT.
1405 */ 1431 */
1406 ASSERT(args->oknoent); 1432 ASSERT(cbp == NULL);
1407 if (dbp) 1433 if (dbp)
1408 xfs_da_brelse(tp, dbp); 1434 xfs_da_brelse(tp, dbp);
1409 xfs_da_brelse(tp, lbp); 1435 xfs_da_brelse(tp, lbp);