NTFS: - Change ntfs_cluster_alloc() to take an extra boolean parameter
specifying whether the cluster are being allocated to extend an attribute or to fill a hole. - Change ntfs_attr_make_non_resident() to call ntfs_cluster_alloc() with @is_extension set to TRUE and remove the runlist terminator fixup code as this is now done by ntfs_cluster_alloc(). Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
This commit is contained in:
@ -31,6 +31,12 @@ ToDo/Notes:
|
|||||||
- Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock()
|
- Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock()
|
||||||
error handling by passing in the active search context when calling
|
error handling by passing in the active search context when calling
|
||||||
ntfs_cluster_free().
|
ntfs_cluster_free().
|
||||||
|
- Change ntfs_cluster_alloc() to take an extra boolean parameter
|
||||||
|
specifying whether the cluster are being allocated to extend an
|
||||||
|
attribute or to fill a hole.
|
||||||
|
- Change ntfs_attr_make_non_resident() to call ntfs_cluster_alloc()
|
||||||
|
with @is_extension set to TRUE and remove the runlist terminator
|
||||||
|
fixup code as this is now done by ntfs_cluster_alloc().
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
@ -1566,8 +1566,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
|
|||||||
new_size = (i_size_read(vi) + vol->cluster_size - 1) &
|
new_size = (i_size_read(vi) + vol->cluster_size - 1) &
|
||||||
~(vol->cluster_size - 1);
|
~(vol->cluster_size - 1);
|
||||||
if (new_size > 0) {
|
if (new_size > 0) {
|
||||||
runlist_element *rl2;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Will need the page later and since the page lock nests
|
* Will need the page later and since the page lock nests
|
||||||
* outside all ntfs locks, we need to get the page now.
|
* outside all ntfs locks, we need to get the page now.
|
||||||
@ -1578,7 +1576,7 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
/* Start by allocating clusters to hold the attribute value. */
|
/* Start by allocating clusters to hold the attribute value. */
|
||||||
rl = ntfs_cluster_alloc(vol, 0, new_size >>
|
rl = ntfs_cluster_alloc(vol, 0, new_size >>
|
||||||
vol->cluster_size_bits, -1, DATA_ZONE);
|
vol->cluster_size_bits, -1, DATA_ZONE, TRUE);
|
||||||
if (IS_ERR(rl)) {
|
if (IS_ERR(rl)) {
|
||||||
err = PTR_ERR(rl);
|
err = PTR_ERR(rl);
|
||||||
ntfs_debug("Failed to allocate cluster%s, error code "
|
ntfs_debug("Failed to allocate cluster%s, error code "
|
||||||
@ -1587,12 +1585,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
|
|||||||
err);
|
err);
|
||||||
goto page_err_out;
|
goto page_err_out;
|
||||||
}
|
}
|
||||||
/* Change the runlist terminator to LCN_ENOENT. */
|
|
||||||
rl2 = rl;
|
|
||||||
while (rl2->length)
|
|
||||||
rl2++;
|
|
||||||
BUG_ON(rl2->lcn != LCN_RL_NOT_MAPPED);
|
|
||||||
rl2->lcn = LCN_ENOENT;
|
|
||||||
} else {
|
} else {
|
||||||
rl = NULL;
|
rl = NULL;
|
||||||
page = NULL;
|
page = NULL;
|
||||||
|
@ -76,6 +76,7 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
|
|||||||
* @count: number of clusters to allocate
|
* @count: number of clusters to allocate
|
||||||
* @start_lcn: starting lcn at which to allocate the clusters (or -1 if none)
|
* @start_lcn: starting lcn at which to allocate the clusters (or -1 if none)
|
||||||
* @zone: zone from which to allocate the clusters
|
* @zone: zone from which to allocate the clusters
|
||||||
|
* @is_extension: if TRUE, this is an attribute extension
|
||||||
*
|
*
|
||||||
* Allocate @count clusters preferably starting at cluster @start_lcn or at the
|
* Allocate @count clusters preferably starting at cluster @start_lcn or at the
|
||||||
* current allocator position if @start_lcn is -1, on the mounted ntfs volume
|
* current allocator position if @start_lcn is -1, on the mounted ntfs volume
|
||||||
@ -86,6 +87,13 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
|
|||||||
* @start_vcn specifies the vcn of the first allocated cluster. This makes
|
* @start_vcn specifies the vcn of the first allocated cluster. This makes
|
||||||
* merging the resulting runlist with the old runlist easier.
|
* merging the resulting runlist with the old runlist easier.
|
||||||
*
|
*
|
||||||
|
* If @is_extension is TRUE, the caller is allocating clusters to extend an
|
||||||
|
* attribute and if it is FALSE, the caller is allocating clusters to fill a
|
||||||
|
* hole in an attribute. Practically the difference is that if @is_extension
|
||||||
|
* is TRUE the returned runlist will be terminated with LCN_ENOENT and if
|
||||||
|
* @is_extension is FALSE the runlist will be terminated with
|
||||||
|
* LCN_RL_NOT_MAPPED.
|
||||||
|
*
|
||||||
* You need to check the return value with IS_ERR(). If this is false, the
|
* You need to check the return value with IS_ERR(). If this is false, the
|
||||||
* function was successful and the return value is a runlist describing the
|
* function was successful and the return value is a runlist describing the
|
||||||
* allocated cluster(s). If IS_ERR() is true, the function failed and
|
* allocated cluster(s). If IS_ERR() is true, the function failed and
|
||||||
@ -137,7 +145,8 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
|
|||||||
*/
|
*/
|
||||||
runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
|
runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
|
||||||
const s64 count, const LCN start_lcn,
|
const s64 count, const LCN start_lcn,
|
||||||
const NTFS_CLUSTER_ALLOCATION_ZONES zone)
|
const NTFS_CLUSTER_ALLOCATION_ZONES zone,
|
||||||
|
const BOOL is_extension)
|
||||||
{
|
{
|
||||||
LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
|
LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
|
||||||
LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
|
LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
|
||||||
@ -310,7 +319,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bit = 1 << (lcn & 7);
|
bit = 1 << (lcn & 7);
|
||||||
ntfs_debug("bit %i.", bit);
|
ntfs_debug("bit 0x%x.", bit);
|
||||||
/* If the bit is already set, go onto the next one. */
|
/* If the bit is already set, go onto the next one. */
|
||||||
if (*byte & bit) {
|
if (*byte & bit) {
|
||||||
lcn++;
|
lcn++;
|
||||||
@ -729,7 +738,7 @@ out:
|
|||||||
/* Add runlist terminator element. */
|
/* Add runlist terminator element. */
|
||||||
if (likely(rl)) {
|
if (likely(rl)) {
|
||||||
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
|
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
|
||||||
rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
|
rl[rlpos].lcn = is_extension ? LCN_ENOENT : LCN_RL_NOT_MAPPED;
|
||||||
rl[rlpos].length = 0;
|
rl[rlpos].length = 0;
|
||||||
}
|
}
|
||||||
if (likely(page && !IS_ERR(page))) {
|
if (likely(page && !IS_ERR(page))) {
|
||||||
|
@ -42,7 +42,8 @@ typedef enum {
|
|||||||
|
|
||||||
extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
|
extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
|
||||||
const VCN start_vcn, const s64 count, const LCN start_lcn,
|
const VCN start_vcn, const s64 count, const LCN start_lcn,
|
||||||
const NTFS_CLUSTER_ALLOCATION_ZONES zone);
|
const NTFS_CLUSTER_ALLOCATION_ZONES zone,
|
||||||
|
const BOOL is_extension);
|
||||||
|
|
||||||
extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
|
extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
|
||||||
s64 count, ntfs_attr_search_ctx *ctx, const BOOL is_rollback);
|
s64 count, ntfs_attr_search_ctx *ctx, const BOOL is_rollback);
|
||||||
|
@ -1355,7 +1355,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
|
|||||||
up_write(&vol->lcnbmp_lock);
|
up_write(&vol->lcnbmp_lock);
|
||||||
ntfs_unmap_page(page);
|
ntfs_unmap_page(page);
|
||||||
/* Allocate a cluster from the DATA_ZONE. */
|
/* Allocate a cluster from the DATA_ZONE. */
|
||||||
rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);
|
rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE,
|
||||||
|
TRUE);
|
||||||
if (IS_ERR(rl2)) {
|
if (IS_ERR(rl2)) {
|
||||||
up_write(&mftbmp_ni->runlist.lock);
|
up_write(&mftbmp_ni->runlist.lock);
|
||||||
ntfs_error(vol->sb, "Failed to allocate a cluster for "
|
ntfs_error(vol->sb, "Failed to allocate a cluster for "
|
||||||
@ -1780,7 +1781,8 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
|
|||||||
nr > min_nr ? "default" : "minimal", (long long)nr);
|
nr > min_nr ? "default" : "minimal", (long long)nr);
|
||||||
old_last_vcn = rl[1].vcn;
|
old_last_vcn = rl[1].vcn;
|
||||||
do {
|
do {
|
||||||
rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE);
|
rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE,
|
||||||
|
TRUE);
|
||||||
if (likely(!IS_ERR(rl2)))
|
if (likely(!IS_ERR(rl2)))
|
||||||
break;
|
break;
|
||||||
if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) {
|
if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) {
|
||||||
|
Reference in New Issue
Block a user