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>
This commit is contained in:
Anton Altaparmakov 2005-10-04 14:01:14 +01:00
parent fd9d63678d
commit 69b41e3c02
5 changed files with 59 additions and 44 deletions

View file

@ -24,8 +24,10 @@ ToDo/Notes:
2.1.25-WIP 2.1.25-WIP
- Change ntfs_map_runlist_nolock() to also take an optional attribute - Change ntfs_map_runlist_nolock() and ntfs_attr_find_vcn_nolock() to
search context. This allows calling it with the mft record mapped. also take an optional attribute search context as argument. This
allows calling these functions with the mft record mapped. Update
all callers.
2.1.24 - Lots of bug fixes and support more clean journal states. 2.1.24 - Lots of bug fixes and support more clean journal states.

View file

@ -406,9 +406,9 @@ retry_remap:
/** /**
* ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode
* @ni: ntfs inode describing the runlist to search * @ni: ntfs inode describing the runlist to search
* @vcn: vcn to find * @vcn: vcn to find
* @write_locked: true if the runlist is locked for writing * @ctx: active attribute search context if present or NULL if not
* *
* Find the virtual cluster number @vcn in the runlist described by the ntfs * Find the virtual cluster number @vcn in the runlist described by the ntfs
* inode @ni and return the address of the runlist element containing the @vcn. * inode @ni and return the address of the runlist element containing the @vcn.
@ -416,9 +416,22 @@ retry_remap:
* If the @vcn is not mapped yet, the attempt is made to map the attribute * If the @vcn is not mapped yet, the attempt is made to map the attribute
* extent containing the @vcn and the vcn to lcn conversion is retried. * extent containing the @vcn and the vcn to lcn conversion is retried.
* *
* If @write_locked is true the caller has locked the runlist for writing and * If @ctx is specified, it is an active search context of @ni and its base mft
* if false for reading. * record. This is needed when ntfs_attr_find_vcn_nolock() encounters unmapped
* runlist fragments and allows their mapping. If you do not have the mft
* record mapped, you can specify @ctx as NULL and ntfs_attr_find_vcn_nolock()
* will perform the necessary mapping and unmapping.
* *
* Note, ntfs_attr_find_vcn_nolock() saves the state of @ctx on entry and
* restores it before returning. Thus, @ctx will be left pointing to the same
* attribute on return as on entry. However, the actual pointers in @ctx may
* point to different memory locations on return, so you must remember to reset
* any cached pointers from the @ctx, i.e. after the call to
* ntfs_attr_find_vcn_nolock(), you will probably want to do:
* m = ctx->mrec;
* a = ctx->attr;
* Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
* you cache ctx->mrec in a variable @m of type MFT_RECORD *.
* Note you need to distinguish between the lcn of the returned runlist element * Note you need to distinguish between the lcn of the returned runlist element
* being >= 0 and LCN_HOLE. In the later case you have to return zeroes on * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on
* read and allocate clusters on write. * read and allocate clusters on write.
@ -433,22 +446,31 @@ retry_remap:
* -ENOMEM - Not enough memory to map runlist. * -ENOMEM - Not enough memory to map runlist.
* -EIO - Critical error (runlist/file is corrupt, i/o error, etc). * -EIO - Critical error (runlist/file is corrupt, i/o error, etc).
* *
* Locking: - The runlist must be locked on entry and is left locked on return. * WARNING: If @ctx is supplied, regardless of whether success or failure is
* - If @write_locked is FALSE, i.e. the runlist is locked for reading, * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
* the lock may be dropped inside the function so you cannot rely on * is no longer valid, i.e. you need to either call
* the runlist still being the same when this function returns. * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
* In that case PTR_ERR(@ctx->mrec) will give you the error code for
* why the mapping of the old inode failed.
*
* Locking: - The runlist described by @ni must be locked for writing on entry
* and is locked on return. Note the runlist may be modified when
* needed runlist fragments need to be mapped.
* - If @ctx is NULL, the base mft record of @ni must not be mapped on
* entry and it will be left unmapped on return.
* - If @ctx is not NULL, the base mft record must be mapped on entry
* and it will be left mapped on return.
*/ */
runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
const BOOL write_locked) ntfs_attr_search_ctx *ctx)
{ {
unsigned long flags; unsigned long flags;
runlist_element *rl; runlist_element *rl;
int err = 0; int err = 0;
BOOL is_retry = FALSE; BOOL is_retry = FALSE;
ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.", ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, with%s ctx.",
ni->mft_no, (unsigned long long)vcn, ni->mft_no, (unsigned long long)vcn, ctx ? "" : "out");
write_locked ? "write" : "read");
BUG_ON(!ni); BUG_ON(!ni);
BUG_ON(!NInoNonResident(ni)); BUG_ON(!NInoNonResident(ni));
BUG_ON(vcn < 0); BUG_ON(vcn < 0);
@ -482,33 +504,22 @@ retry_remap:
} }
if (!err && !is_retry) { if (!err && !is_retry) {
/* /*
* The @vcn is in an unmapped region, map the runlist and * If the search context is invalid we cannot map the unmapped
* retry. * region.
*/ */
if (!write_locked) { if (IS_ERR(ctx->mrec))
up_read(&ni->runlist.lock); err = PTR_ERR(ctx->mrec);
down_write(&ni->runlist.lock); else {
if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) != /*
LCN_RL_NOT_MAPPED)) { * The @vcn is in an unmapped region, map the runlist
up_write(&ni->runlist.lock); * and retry.
down_read(&ni->runlist.lock); */
err = ntfs_map_runlist_nolock(ni, vcn, ctx);
if (likely(!err)) {
is_retry = TRUE;
goto retry_remap; goto retry_remap;
} }
} }
err = ntfs_map_runlist_nolock(ni, vcn, NULL);
if (!write_locked) {
up_write(&ni->runlist.lock);
down_read(&ni->runlist.lock);
}
if (likely(!err)) {
is_retry = TRUE;
goto retry_remap;
}
/*
* -EINVAL coming from a failed mapping attempt is equivalent
* to i/o error for us as it should not happen in our code
* paths.
*/
if (err == -EINVAL) if (err == -EINVAL)
err = -EIO; err = -EIO;
} else if (!err) } else if (!err)
@ -1181,6 +1192,7 @@ int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
ntfs_inode *base_ni; ntfs_inode *base_ni;
ntfs_debug("Entering."); ntfs_debug("Entering.");
BUG_ON(IS_ERR(ctx->mrec));
if (ctx->base_ntfs_ino) if (ctx->base_ntfs_ino)
base_ni = ctx->base_ntfs_ino; base_ni = ctx->base_ntfs_ino;
else else

View file

@ -68,7 +68,7 @@ extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
const BOOL write_locked); const BOOL write_locked);
extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni,
const VCN vcn, const BOOL write_locked); const VCN vcn, ntfs_attr_search_ctx *ctx);
int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
const u32 name_len, const IGNORE_CASE_BOOL ic, const u32 name_len, const IGNORE_CASE_BOOL ic,

View file

@ -839,7 +839,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
total_freed = real_freed = 0; total_freed = real_freed = 0;
rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, TRUE); rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, NULL);
if (IS_ERR(rl)) { if (IS_ERR(rl)) {
if (!is_rollback) if (!is_rollback)
ntfs_error(vol->sb, "Failed to find first runlist " ntfs_error(vol->sb, "Failed to find first runlist "
@ -893,7 +893,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
/* Attempt to map runlist. */ /* Attempt to map runlist. */
vcn = rl->vcn; vcn = rl->vcn;
rl = ntfs_attr_find_vcn_nolock(ni, vcn, TRUE); rl = ntfs_attr_find_vcn_nolock(ni, vcn, NULL);
if (IS_ERR(rl)) { if (IS_ERR(rl)) {
err = PTR_ERR(rl); err = PTR_ERR(rl);
if (!is_rollback) if (!is_rollback)

View file

@ -49,7 +49,8 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
ntfs_volume *vol = ni->vol; ntfs_volume *vol = ni->vol;
struct inode *mft_vi = vol->mft_ino; struct inode *mft_vi = vol->mft_ino;
struct page *page; struct page *page;
unsigned long index, ofs, end_index; unsigned long index, end_index;
unsigned ofs;
BUG_ON(ni->page); BUG_ON(ni->page);
/* /*
@ -1308,7 +1309,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
ll = mftbmp_ni->allocated_size; ll = mftbmp_ni->allocated_size;
read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); read_unlock_irqrestore(&mftbmp_ni->size_lock, flags);
rl = ntfs_attr_find_vcn_nolock(mftbmp_ni, rl = ntfs_attr_find_vcn_nolock(mftbmp_ni,
(ll - 1) >> vol->cluster_size_bits, TRUE); (ll - 1) >> vol->cluster_size_bits, NULL);
if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
up_write(&mftbmp_ni->runlist.lock); up_write(&mftbmp_ni->runlist.lock);
ntfs_error(vol->sb, "Failed to determine last allocated " ntfs_error(vol->sb, "Failed to determine last allocated "
@ -1738,7 +1739,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
ll = mft_ni->allocated_size; ll = mft_ni->allocated_size;
read_unlock_irqrestore(&mft_ni->size_lock, flags); read_unlock_irqrestore(&mft_ni->size_lock, flags);
rl = ntfs_attr_find_vcn_nolock(mft_ni, rl = ntfs_attr_find_vcn_nolock(mft_ni,
(ll - 1) >> vol->cluster_size_bits, TRUE); (ll - 1) >> vol->cluster_size_bits, NULL);
if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
up_write(&mft_ni->runlist.lock); up_write(&mft_ni->runlist.lock);
ntfs_error(vol->sb, "Failed to determine last allocated " ntfs_error(vol->sb, "Failed to determine last allocated "