diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_leaf.c')
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 93 |
1 files changed, 61 insertions, 32 deletions
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index bc52b803d79b..93535992cb60 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -263,20 +263,21 @@ xfs_dir2_leaf_addname( | |||
263 | * If we don't have enough free bytes but we can make enough | 263 | * If we don't have enough free bytes but we can make enough |
264 | * by compacting out stale entries, we'll do that. | 264 | * by compacting out stale entries, we'll do that. |
265 | */ | 265 | */ |
266 | if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < needbytes && | 266 | if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < |
267 | be16_to_cpu(leaf->hdr.stale) > 1) { | 267 | needbytes && be16_to_cpu(leaf->hdr.stale) > 1) { |
268 | compact = 1; | 268 | compact = 1; |
269 | } | 269 | } |
270 | /* | 270 | /* |
271 | * Otherwise if we don't have enough free bytes we need to | 271 | * Otherwise if we don't have enough free bytes we need to |
272 | * convert to node form. | 272 | * convert to node form. |
273 | */ | 273 | */ |
274 | else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < | 274 | else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu( |
275 | needbytes) { | 275 | leaf->hdr.count)] < needbytes) { |
276 | /* | 276 | /* |
277 | * Just checking or no space reservation, give up. | 277 | * Just checking or no space reservation, give up. |
278 | */ | 278 | */ |
279 | if (args->justcheck || args->total == 0) { | 279 | if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || |
280 | args->total == 0) { | ||
280 | xfs_da_brelse(tp, lbp); | 281 | xfs_da_brelse(tp, lbp); |
281 | return XFS_ERROR(ENOSPC); | 282 | return XFS_ERROR(ENOSPC); |
282 | } | 283 | } |
@@ -301,7 +302,7 @@ xfs_dir2_leaf_addname( | |||
301 | * If just checking, then it will fit unless we needed to allocate | 302 | * If just checking, then it will fit unless we needed to allocate |
302 | * a new data block. | 303 | * a new data block. |
303 | */ | 304 | */ |
304 | if (args->justcheck) { | 305 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) { |
305 | xfs_da_brelse(tp, lbp); | 306 | xfs_da_brelse(tp, lbp); |
306 | return use_block == -1 ? XFS_ERROR(ENOSPC) : 0; | 307 | return use_block == -1 ? XFS_ERROR(ENOSPC) : 0; |
307 | } | 308 | } |
@@ -1110,7 +1111,7 @@ xfs_dir2_leaf_getdents( | |||
1110 | *offset = XFS_DIR2_MAX_DATAPTR; | 1111 | *offset = XFS_DIR2_MAX_DATAPTR; |
1111 | else | 1112 | else |
1112 | *offset = xfs_dir2_byte_to_dataptr(mp, curoff); | 1113 | *offset = xfs_dir2_byte_to_dataptr(mp, curoff); |
1113 | kmem_free(map, map_size * sizeof(*map)); | 1114 | kmem_free(map); |
1114 | if (bp) | 1115 | if (bp) |
1115 | xfs_da_brelse(NULL, bp); | 1116 | xfs_da_brelse(NULL, bp); |
1116 | return error; | 1117 | return error; |
@@ -1298,12 +1299,13 @@ xfs_dir2_leaf_lookup( | |||
1298 | ((char *)dbp->data + | 1299 | ((char *)dbp->data + |
1299 | xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address))); | 1300 | xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address))); |
1300 | /* | 1301 | /* |
1301 | * Return the found inode number. | 1302 | * Return the found inode number & CI name if appropriate |
1302 | */ | 1303 | */ |
1303 | args->inumber = be64_to_cpu(dep->inumber); | 1304 | args->inumber = be64_to_cpu(dep->inumber); |
1305 | error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); | ||
1304 | xfs_da_brelse(tp, dbp); | 1306 | xfs_da_brelse(tp, dbp); |
1305 | xfs_da_brelse(tp, lbp); | 1307 | xfs_da_brelse(tp, lbp); |
1306 | return XFS_ERROR(EEXIST); | 1308 | return XFS_ERROR(error); |
1307 | } | 1309 | } |
1308 | 1310 | ||
1309 | /* | 1311 | /* |
@@ -1319,8 +1321,8 @@ xfs_dir2_leaf_lookup_int( | |||
1319 | int *indexp, /* out: index in leaf block */ | 1321 | int *indexp, /* out: index in leaf block */ |
1320 | xfs_dabuf_t **dbpp) /* out: data buffer */ | 1322 | xfs_dabuf_t **dbpp) /* out: data buffer */ |
1321 | { | 1323 | { |
1322 | xfs_dir2_db_t curdb; /* current data block number */ | 1324 | xfs_dir2_db_t curdb = -1; /* current data block number */ |
1323 | xfs_dabuf_t *dbp; /* data buffer */ | 1325 | xfs_dabuf_t *dbp = NULL; /* data buffer */ |
1324 | xfs_dir2_data_entry_t *dep; /* data entry */ | 1326 | xfs_dir2_data_entry_t *dep; /* data entry */ |
1325 | xfs_inode_t *dp; /* incore directory inode */ | 1327 | xfs_inode_t *dp; /* incore directory inode */ |
1326 | int error; /* error return code */ | 1328 | int error; /* error return code */ |
@@ -1331,6 +1333,8 @@ xfs_dir2_leaf_lookup_int( | |||
1331 | xfs_mount_t *mp; /* filesystem mount point */ | 1333 | xfs_mount_t *mp; /* filesystem mount point */ |
1332 | xfs_dir2_db_t newdb; /* new data block number */ | 1334 | xfs_dir2_db_t newdb; /* new data block number */ |
1333 | xfs_trans_t *tp; /* transaction pointer */ | 1335 | xfs_trans_t *tp; /* transaction pointer */ |
1336 | xfs_dir2_db_t cidb = -1; /* case match data block no. */ | ||
1337 | enum xfs_dacmp cmp; /* name compare result */ | ||
1334 | 1338 | ||
1335 | dp = args->dp; | 1339 | dp = args->dp; |
1336 | tp = args->trans; | 1340 | tp = args->trans; |
@@ -1338,11 +1342,10 @@ xfs_dir2_leaf_lookup_int( | |||
1338 | /* | 1342 | /* |
1339 | * Read the leaf block into the buffer. | 1343 | * Read the leaf block into the buffer. |
1340 | */ | 1344 | */ |
1341 | if ((error = | 1345 | error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp, |
1342 | xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp, | 1346 | XFS_DATA_FORK); |
1343 | XFS_DATA_FORK))) { | 1347 | if (error) |
1344 | return error; | 1348 | return error; |
1345 | } | ||
1346 | *lbpp = lbp; | 1349 | *lbpp = lbp; |
1347 | leaf = lbp->data; | 1350 | leaf = lbp->data; |
1348 | xfs_dir2_leaf_check(dp, lbp); | 1351 | xfs_dir2_leaf_check(dp, lbp); |
@@ -1354,9 +1357,9 @@ xfs_dir2_leaf_lookup_int( | |||
1354 | * Loop over all the entries with the right hash value | 1357 | * Loop over all the entries with the right hash value |
1355 | * looking to match the name. | 1358 | * looking to match the name. |
1356 | */ | 1359 | */ |
1357 | for (lep = &leaf->ents[index], dbp = NULL, curdb = -1; | 1360 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && |
1358 | index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; | 1361 | be32_to_cpu(lep->hashval) == args->hashval; |
1359 | lep++, index++) { | 1362 | lep++, index++) { |
1360 | /* | 1363 | /* |
1361 | * Skip over stale leaf entries. | 1364 | * Skip over stale leaf entries. |
1362 | */ | 1365 | */ |
@@ -1373,10 +1376,10 @@ xfs_dir2_leaf_lookup_int( | |||
1373 | if (newdb != curdb) { | 1376 | if (newdb != curdb) { |
1374 | if (dbp) | 1377 | if (dbp) |
1375 | xfs_da_brelse(tp, dbp); | 1378 | xfs_da_brelse(tp, dbp); |
1376 | if ((error = | 1379 | error = xfs_da_read_buf(tp, dp, |
1377 | xfs_da_read_buf(tp, dp, | 1380 | xfs_dir2_db_to_da(mp, newdb), |
1378 | xfs_dir2_db_to_da(mp, newdb), -1, &dbp, | 1381 | -1, &dbp, XFS_DATA_FORK); |
1379 | XFS_DATA_FORK))) { | 1382 | if (error) { |
1380 | xfs_da_brelse(tp, lbp); | 1383 | xfs_da_brelse(tp, lbp); |
1381 | return error; | 1384 | return error; |
1382 | } | 1385 | } |
@@ -1386,24 +1389,50 @@ xfs_dir2_leaf_lookup_int( | |||
1386 | /* | 1389 | /* |
1387 | * Point to the data entry. | 1390 | * Point to the data entry. |
1388 | */ | 1391 | */ |
1389 | dep = (xfs_dir2_data_entry_t *) | 1392 | dep = (xfs_dir2_data_entry_t *)((char *)dbp->data + |
1390 | ((char *)dbp->data + | 1393 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); |
1391 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | ||
1392 | /* | 1394 | /* |
1393 | * If it matches then return it. | 1395 | * Compare name and if it's an exact match, return the index |
1396 | * and buffer. If it's the first case-insensitive match, store | ||
1397 | * the index and buffer and continue looking for an exact match. | ||
1394 | */ | 1398 | */ |
1395 | if (dep->namelen == args->namelen && | 1399 | cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); |
1396 | dep->name[0] == args->name[0] && | 1400 | if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { |
1397 | memcmp(dep->name, args->name, args->namelen) == 0) { | 1401 | args->cmpresult = cmp; |
1398 | *dbpp = dbp; | ||
1399 | *indexp = index; | 1402 | *indexp = index; |
1400 | return 0; | 1403 | /* case exact match: return the current buffer. */ |
1404 | if (cmp == XFS_CMP_EXACT) { | ||
1405 | *dbpp = dbp; | ||
1406 | return 0; | ||
1407 | } | ||
1408 | cidb = curdb; | ||
1401 | } | 1409 | } |
1402 | } | 1410 | } |
1411 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); | ||
1412 | /* | ||
1413 | * Here, we can only be doing a lookup (not a rename or remove). | ||
1414 | * If a case-insensitive match was found earlier, re-read the | ||
1415 | * appropriate data block if required and return it. | ||
1416 | */ | ||
1417 | if (args->cmpresult == XFS_CMP_CASE) { | ||
1418 | ASSERT(cidb != -1); | ||
1419 | if (cidb != curdb) { | ||
1420 | xfs_da_brelse(tp, dbp); | ||
1421 | error = xfs_da_read_buf(tp, dp, | ||
1422 | xfs_dir2_db_to_da(mp, cidb), | ||
1423 | -1, &dbp, XFS_DATA_FORK); | ||
1424 | if (error) { | ||
1425 | xfs_da_brelse(tp, lbp); | ||
1426 | return error; | ||
1427 | } | ||
1428 | } | ||
1429 | *dbpp = dbp; | ||
1430 | return 0; | ||
1431 | } | ||
1403 | /* | 1432 | /* |
1404 | * No match found, return ENOENT. | 1433 | * No match found, return ENOENT. |
1405 | */ | 1434 | */ |
1406 | ASSERT(args->oknoent); | 1435 | ASSERT(cidb == -1); |
1407 | if (dbp) | 1436 | if (dbp) |
1408 | xfs_da_brelse(tp, dbp); | 1437 | xfs_da_brelse(tp, dbp); |
1409 | xfs_da_brelse(tp, lbp); | 1438 | xfs_da_brelse(tp, lbp); |