NTFS: - Split ntfs_map_runlist() into ntfs_map_runlist() and a non-locking

helper ntfs_map_runlist_nolock() which is used by ntfs_map_runlist().
	This allows us to map runlist fragments with the runlist lock already
	held without having to drop and reacquire it around the call.  Adapt
	all callers.
      - Change ntfs_find_vcn() to ntfs_find_vcn_nolock() which takes a locked
	runlist.  This allows us to find runlist elements with the runlist
	lock already held without having to drop and reacquire it around the
	call.  Adapt all callers.

Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
This commit is contained in:
Anton Altaparmakov 2005-02-15 10:08:43 +00:00
parent 1a0df15acd
commit b6ad6c52fe
6 changed files with 119 additions and 113 deletions

View file

@ -849,7 +849,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
total_freed = real_freed = 0;
/* This returns with ni->runlist locked for reading on success. */
rl = ntfs_find_vcn(ni, start_vcn, FALSE);
down_read(&ni->runlist.lock);
rl = ntfs_find_vcn_nolock(ni, start_vcn, FALSE);
if (IS_ERR(rl)) {
if (!is_rollback)
ntfs_error(vol->sb, "Failed to find first runlist "
@ -863,7 +864,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
ntfs_error(vol->sb, "First runlist element has "
"invalid lcn, aborting.");
err = -EIO;
goto unl_err_out;
goto err_out;
}
/* Find the starting cluster inside the run that needs freeing. */
delta = start_vcn - rl->vcn;
@ -881,7 +882,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
if (!is_rollback)
ntfs_error(vol->sb, "Failed to clear first run "
"(error %i), aborting.", err);
goto unl_err_out;
goto err_out;
}
/* We have freed @to_free real clusters. */
real_freed = to_free;
@ -901,30 +902,15 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
if (unlikely(rl->lcn < LCN_HOLE)) {
VCN vcn;
/*
* Attempt to map runlist, dropping runlist lock for
* the duration.
*/
/* Attempt to map runlist. */
vcn = rl->vcn;
up_read(&ni->runlist.lock);
err = ntfs_map_runlist(ni, vcn);
if (err) {
if (!is_rollback)
ntfs_error(vol->sb, "Failed to map "
"runlist fragment.");
if (err == -EINVAL || err == -ENOENT)
err = -EIO;
goto err_out;
}
/*
* This returns with ni->runlist locked for reading on
* success.
*/
rl = ntfs_find_vcn(ni, vcn, FALSE);
rl = ntfs_find_vcn_nolock(ni, vcn, FALSE);
if (IS_ERR(rl)) {
err = PTR_ERR(rl);
if (!is_rollback)
ntfs_error(vol->sb, "Failed to find "
ntfs_error(vol->sb, "Failed to map "
"runlist fragment or "
"failed to find "
"subsequent runlist "
"element.");
goto err_out;
@ -937,7 +923,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
(unsigned long long)
rl->lcn);
err = -EIO;
goto unl_err_out;
goto err_out;
}
}
/* The number of clusters in this run that need freeing. */
@ -953,7 +939,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
if (!is_rollback)
ntfs_error(vol->sb, "Failed to clear "
"subsequent run.");
goto unl_err_out;
goto err_out;
}
/* We have freed @to_free real clusters. */
real_freed += to_free;
@ -974,9 +960,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
/* We are done. Return the number of actually freed clusters. */
ntfs_debug("Done.");
return real_freed;
unl_err_out:
up_read(&ni->runlist.lock);
err_out:
up_read(&ni->runlist.lock);
if (is_rollback)
return err;
/* If no real clusters were freed, no need to rollback. */