diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2005-10-04 09:01:14 -0400 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-10-04 09:01:14 -0400 |
commit | 69b41e3c0223bd38cf23e3d8f1385963089fbf22 (patch) | |
tree | 6a1fc55f654d6f7cb745bba032115d5590cc5931 /fs/ntfs/attrib.c | |
parent | fd9d63678d42ffd4312815ac720a12920642eb36 (diff) |
NTFS: Change ntfs_attr_find_vcn_nolock() to also take an optional attribute
search context as argument. This allows calling it with the mft
record mapped. Update all callers.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs/attrib.c')
-rw-r--r-- | fs/ntfs/attrib.c | 84 |
1 files changed, 48 insertions, 36 deletions
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index b194197b72f7..2aafc87e9601 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -406,9 +406,9 @@ retry_remap: | |||
406 | 406 | ||
407 | /** | 407 | /** |
408 | * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode | 408 | * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode |
409 | * @ni: ntfs inode describing the runlist to search | 409 | * @ni: ntfs inode describing the runlist to search |
410 | * @vcn: vcn to find | 410 | * @vcn: vcn to find |
411 | * @write_locked: true if the runlist is locked for writing | 411 | * @ctx: active attribute search context if present or NULL if not |
412 | * | 412 | * |
413 | * Find the virtual cluster number @vcn in the runlist described by the ntfs | 413 | * Find the virtual cluster number @vcn in the runlist described by the ntfs |
414 | * inode @ni and return the address of the runlist element containing the @vcn. | 414 | * inode @ni and return the address of the runlist element containing the @vcn. |
@@ -416,9 +416,22 @@ retry_remap: | |||
416 | * If the @vcn is not mapped yet, the attempt is made to map the attribute | 416 | * If the @vcn is not mapped yet, the attempt is made to map the attribute |
417 | * extent containing the @vcn and the vcn to lcn conversion is retried. | 417 | * extent containing the @vcn and the vcn to lcn conversion is retried. |
418 | * | 418 | * |
419 | * If @write_locked is true the caller has locked the runlist for writing and | 419 | * If @ctx is specified, it is an active search context of @ni and its base mft |
420 | * if false for reading. | 420 | * record. This is needed when ntfs_attr_find_vcn_nolock() encounters unmapped |
421 | * runlist fragments and allows their mapping. If you do not have the mft | ||
422 | * record mapped, you can specify @ctx as NULL and ntfs_attr_find_vcn_nolock() | ||
423 | * will perform the necessary mapping and unmapping. | ||
421 | * | 424 | * |
425 | * Note, ntfs_attr_find_vcn_nolock() saves the state of @ctx on entry and | ||
426 | * restores it before returning. Thus, @ctx will be left pointing to the same | ||
427 | * attribute on return as on entry. However, the actual pointers in @ctx may | ||
428 | * point to different memory locations on return, so you must remember to reset | ||
429 | * any cached pointers from the @ctx, i.e. after the call to | ||
430 | * ntfs_attr_find_vcn_nolock(), you will probably want to do: | ||
431 | * m = ctx->mrec; | ||
432 | * a = ctx->attr; | ||
433 | * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that | ||
434 | * you cache ctx->mrec in a variable @m of type MFT_RECORD *. | ||
422 | * Note you need to distinguish between the lcn of the returned runlist element | 435 | * Note you need to distinguish between the lcn of the returned runlist element |
423 | * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on | 436 | * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on |
424 | * read and allocate clusters on write. | 437 | * read and allocate clusters on write. |
@@ -433,22 +446,31 @@ retry_remap: | |||
433 | * -ENOMEM - Not enough memory to map runlist. | 446 | * -ENOMEM - Not enough memory to map runlist. |
434 | * -EIO - Critical error (runlist/file is corrupt, i/o error, etc). | 447 | * -EIO - Critical error (runlist/file is corrupt, i/o error, etc). |
435 | * | 448 | * |
436 | * Locking: - The runlist must be locked on entry and is left locked on return. | 449 | * WARNING: If @ctx is supplied, regardless of whether success or failure is |
437 | * - If @write_locked is FALSE, i.e. the runlist is locked for reading, | 450 | * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx |
438 | * the lock may be dropped inside the function so you cannot rely on | 451 | * is no longer valid, i.e. you need to either call |
439 | * the runlist still being the same when this function returns. | 452 | * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it. |
453 | * In that case PTR_ERR(@ctx->mrec) will give you the error code for | ||
454 | * why the mapping of the old inode failed. | ||
455 | * | ||
456 | * Locking: - The runlist described by @ni must be locked for writing on entry | ||
457 | * and is locked on return. Note the runlist may be modified when | ||
458 | * needed runlist fragments need to be mapped. | ||
459 | * - If @ctx is NULL, the base mft record of @ni must not be mapped on | ||
460 | * entry and it will be left unmapped on return. | ||
461 | * - If @ctx is not NULL, the base mft record must be mapped on entry | ||
462 | * and it will be left mapped on return. | ||
440 | */ | 463 | */ |
441 | runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, | 464 | runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, |
442 | const BOOL write_locked) | 465 | ntfs_attr_search_ctx *ctx) |
443 | { | 466 | { |
444 | unsigned long flags; | 467 | unsigned long flags; |
445 | runlist_element *rl; | 468 | runlist_element *rl; |
446 | int err = 0; | 469 | int err = 0; |
447 | BOOL is_retry = FALSE; | 470 | BOOL is_retry = FALSE; |
448 | 471 | ||
449 | ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.", | 472 | ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, with%s ctx.", |
450 | ni->mft_no, (unsigned long long)vcn, | 473 | ni->mft_no, (unsigned long long)vcn, ctx ? "" : "out"); |
451 | write_locked ? "write" : "read"); | ||
452 | BUG_ON(!ni); | 474 | BUG_ON(!ni); |
453 | BUG_ON(!NInoNonResident(ni)); | 475 | BUG_ON(!NInoNonResident(ni)); |
454 | BUG_ON(vcn < 0); | 476 | BUG_ON(vcn < 0); |
@@ -482,33 +504,22 @@ retry_remap: | |||
482 | } | 504 | } |
483 | if (!err && !is_retry) { | 505 | if (!err && !is_retry) { |
484 | /* | 506 | /* |
485 | * The @vcn is in an unmapped region, map the runlist and | 507 | * If the search context is invalid we cannot map the unmapped |
486 | * retry. | 508 | * region. |
487 | */ | 509 | */ |
488 | if (!write_locked) { | 510 | if (IS_ERR(ctx->mrec)) |
489 | up_read(&ni->runlist.lock); | 511 | err = PTR_ERR(ctx->mrec); |
490 | down_write(&ni->runlist.lock); | 512 | else { |
491 | if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) != | 513 | /* |
492 | LCN_RL_NOT_MAPPED)) { | 514 | * The @vcn is in an unmapped region, map the runlist |
493 | up_write(&ni->runlist.lock); | 515 | * and retry. |
494 | down_read(&ni->runlist.lock); | 516 | */ |
517 | err = ntfs_map_runlist_nolock(ni, vcn, ctx); | ||
518 | if (likely(!err)) { | ||
519 | is_retry = TRUE; | ||
495 | goto retry_remap; | 520 | goto retry_remap; |
496 | } | 521 | } |
497 | } | 522 | } |
498 | err = ntfs_map_runlist_nolock(ni, vcn, NULL); | ||
499 | if (!write_locked) { | ||
500 | up_write(&ni->runlist.lock); | ||
501 | down_read(&ni->runlist.lock); | ||
502 | } | ||
503 | if (likely(!err)) { | ||
504 | is_retry = TRUE; | ||
505 | goto retry_remap; | ||
506 | } | ||
507 | /* | ||
508 | * -EINVAL coming from a failed mapping attempt is equivalent | ||
509 | * to i/o error for us as it should not happen in our code | ||
510 | * paths. | ||
511 | */ | ||
512 | if (err == -EINVAL) | 523 | if (err == -EINVAL) |
513 | err = -EIO; | 524 | err = -EIO; |
514 | } else if (!err) | 525 | } else if (!err) |
@@ -1181,6 +1192,7 @@ int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, | |||
1181 | ntfs_inode *base_ni; | 1192 | ntfs_inode *base_ni; |
1182 | 1193 | ||
1183 | ntfs_debug("Entering."); | 1194 | ntfs_debug("Entering."); |
1195 | BUG_ON(IS_ERR(ctx->mrec)); | ||
1184 | if (ctx->base_ntfs_ino) | 1196 | if (ctx->base_ntfs_ino) |
1185 | base_ni = ctx->base_ntfs_ino; | 1197 | base_ni = ctx->base_ntfs_ino; |
1186 | else | 1198 | else |