Commit fc0fa7dc authored by Anton Altaparmakov's avatar Anton Altaparmakov

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: default avatarAnton Altaparmakov <aia21@cantab.net>
parent 511bea5e
...@@ -31,6 +31,12 @@ ToDo/Notes: ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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: ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment