diff options
-rw-r--r-- | fs/ntfs/ChangeLog | 6 | ||||
-rw-r--r-- | fs/ntfs/attrib.c | 10 | ||||
-rw-r--r-- | fs/ntfs/lcnalloc.c | 15 | ||||
-rw-r--r-- | fs/ntfs/lcnalloc.h | 3 | ||||
-rw-r--r-- | fs/ntfs/mft.c | 6 |
5 files changed, 25 insertions, 15 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 6e4f44eed6fa..aad2a3f2d1f8 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -31,6 +31,12 @@ ToDo/Notes: | |||
31 | - Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock() | 31 | - Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock() |
32 | error handling by passing in the active search context when calling | 32 | error handling by passing in the active search context when calling |
33 | ntfs_cluster_free(). | 33 | ntfs_cluster_free(). |
34 | - Change ntfs_cluster_alloc() to take an extra boolean parameter | ||
35 | specifying whether the cluster are being allocated to extend an | ||
36 | attribute or to fill a hole. | ||
37 | - Change ntfs_attr_make_non_resident() to call ntfs_cluster_alloc() | ||
38 | with @is_extension set to TRUE and remove the runlist terminator | ||
39 | fixup code as this is now done by ntfs_cluster_alloc(). | ||
34 | 40 | ||
35 | 2.1.24 - Lots of bug fixes and support more clean journal states. | 41 | 2.1.24 - Lots of bug fixes and support more clean journal states. |
36 | 42 | ||
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 2aafc87e9601..33e689f82a55 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -1566,8 +1566,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni) | |||
1566 | new_size = (i_size_read(vi) + vol->cluster_size - 1) & | 1566 | new_size = (i_size_read(vi) + vol->cluster_size - 1) & |
1567 | ~(vol->cluster_size - 1); | 1567 | ~(vol->cluster_size - 1); |
1568 | if (new_size > 0) { | 1568 | if (new_size > 0) { |
1569 | runlist_element *rl2; | ||
1570 | |||
1571 | /* | 1569 | /* |
1572 | * Will need the page later and since the page lock nests | 1570 | * Will need the page later and since the page lock nests |
1573 | * outside all ntfs locks, we need to get the page now. | 1571 | * 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 | return -ENOMEM; | 1576 | return -ENOMEM; |
1579 | /* Start by allocating clusters to hold the attribute value. */ | 1577 | /* Start by allocating clusters to hold the attribute value. */ |
1580 | rl = ntfs_cluster_alloc(vol, 0, new_size >> | 1578 | rl = ntfs_cluster_alloc(vol, 0, new_size >> |
1581 | vol->cluster_size_bits, -1, DATA_ZONE); | 1579 | vol->cluster_size_bits, -1, DATA_ZONE, TRUE); |
1582 | if (IS_ERR(rl)) { | 1580 | if (IS_ERR(rl)) { |
1583 | err = PTR_ERR(rl); | 1581 | err = PTR_ERR(rl); |
1584 | ntfs_debug("Failed to allocate cluster%s, error code " | 1582 | ntfs_debug("Failed to allocate cluster%s, error code " |
@@ -1587,12 +1585,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni) | |||
1587 | err); | 1585 | err); |
1588 | goto page_err_out; | 1586 | goto page_err_out; |
1589 | } | 1587 | } |
1590 | /* Change the runlist terminator to LCN_ENOENT. */ | ||
1591 | rl2 = rl; | ||
1592 | while (rl2->length) | ||
1593 | rl2++; | ||
1594 | BUG_ON(rl2->lcn != LCN_RL_NOT_MAPPED); | ||
1595 | rl2->lcn = LCN_ENOENT; | ||
1596 | } else { | 1588 | } else { |
1597 | rl = NULL; | 1589 | rl = NULL; |
1598 | page = NULL; | 1590 | page = NULL; |
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 75313f4307e3..29cabf93d2d2 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c | |||
@@ -76,6 +76,7 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, | |||
76 | * @count: number of clusters to allocate | 76 | * @count: number of clusters to allocate |
77 | * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none) | 77 | * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none) |
78 | * @zone: zone from which to allocate the clusters | 78 | * @zone: zone from which to allocate the clusters |
79 | * @is_extension: if TRUE, this is an attribute extension | ||
79 | * | 80 | * |
80 | * Allocate @count clusters preferably starting at cluster @start_lcn or at the | 81 | * Allocate @count clusters preferably starting at cluster @start_lcn or at the |
81 | * current allocator position if @start_lcn is -1, on the mounted ntfs volume | 82 | * 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 | * @start_vcn specifies the vcn of the first allocated cluster. This makes | 87 | * @start_vcn specifies the vcn of the first allocated cluster. This makes |
87 | * merging the resulting runlist with the old runlist easier. | 88 | * merging the resulting runlist with the old runlist easier. |
88 | * | 89 | * |
90 | * If @is_extension is TRUE, the caller is allocating clusters to extend an | ||
91 | * attribute and if it is FALSE, the caller is allocating clusters to fill a | ||
92 | * hole in an attribute. Practically the difference is that if @is_extension | ||
93 | * is TRUE the returned runlist will be terminated with LCN_ENOENT and if | ||
94 | * @is_extension is FALSE the runlist will be terminated with | ||
95 | * LCN_RL_NOT_MAPPED. | ||
96 | * | ||
89 | * You need to check the return value with IS_ERR(). If this is false, the | 97 | * You need to check the return value with IS_ERR(). If this is false, the |
90 | * function was successful and the return value is a runlist describing the | 98 | * function was successful and the return value is a runlist describing the |
91 | * allocated cluster(s). If IS_ERR() is true, the function failed and | 99 | * 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 | */ | 145 | */ |
138 | runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, | 146 | runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, |
139 | const s64 count, const LCN start_lcn, | 147 | const s64 count, const LCN start_lcn, |
140 | const NTFS_CLUSTER_ALLOCATION_ZONES zone) | 148 | const NTFS_CLUSTER_ALLOCATION_ZONES zone, |
149 | const BOOL is_extension) | ||
141 | { | 150 | { |
142 | LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; | 151 | LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; |
143 | LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size; | 152 | 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 | continue; | 319 | continue; |
311 | } | 320 | } |
312 | bit = 1 << (lcn & 7); | 321 | bit = 1 << (lcn & 7); |
313 | ntfs_debug("bit %i.", bit); | 322 | ntfs_debug("bit 0x%x.", bit); |
314 | /* If the bit is already set, go onto the next one. */ | 323 | /* If the bit is already set, go onto the next one. */ |
315 | if (*byte & bit) { | 324 | if (*byte & bit) { |
316 | lcn++; | 325 | lcn++; |
@@ -729,7 +738,7 @@ out: | |||
729 | /* Add runlist terminator element. */ | 738 | /* Add runlist terminator element. */ |
730 | if (likely(rl)) { | 739 | if (likely(rl)) { |
731 | rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length; | 740 | rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length; |
732 | rl[rlpos].lcn = LCN_RL_NOT_MAPPED; | 741 | rl[rlpos].lcn = is_extension ? LCN_ENOENT : LCN_RL_NOT_MAPPED; |
733 | rl[rlpos].length = 0; | 742 | rl[rlpos].length = 0; |
734 | } | 743 | } |
735 | if (likely(page && !IS_ERR(page))) { | 744 | if (likely(page && !IS_ERR(page))) { |
diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h index aa0518509cd3..72cbca7003b2 100644 --- a/fs/ntfs/lcnalloc.h +++ b/fs/ntfs/lcnalloc.h | |||
@@ -42,7 +42,8 @@ typedef enum { | |||
42 | 42 | ||
43 | extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, | 43 | extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, |
44 | const VCN start_vcn, const s64 count, const LCN start_lcn, | 44 | const VCN start_vcn, const s64 count, const LCN start_lcn, |
45 | const NTFS_CLUSTER_ALLOCATION_ZONES zone); | 45 | const NTFS_CLUSTER_ALLOCATION_ZONES zone, |
46 | const BOOL is_extension); | ||
46 | 47 | ||
47 | extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, | 48 | extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, |
48 | s64 count, ntfs_attr_search_ctx *ctx, const BOOL is_rollback); | 49 | s64 count, ntfs_attr_search_ctx *ctx, const BOOL is_rollback); |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 5577fc6e190f..0c65cbb8c5cf 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
@@ -1355,7 +1355,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
1355 | up_write(&vol->lcnbmp_lock); | 1355 | up_write(&vol->lcnbmp_lock); |
1356 | ntfs_unmap_page(page); | 1356 | ntfs_unmap_page(page); |
1357 | /* Allocate a cluster from the DATA_ZONE. */ | 1357 | /* Allocate a cluster from the DATA_ZONE. */ |
1358 | rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE); | 1358 | rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE, |
1359 | TRUE); | ||
1359 | if (IS_ERR(rl2)) { | 1360 | if (IS_ERR(rl2)) { |
1360 | up_write(&mftbmp_ni->runlist.lock); | 1361 | up_write(&mftbmp_ni->runlist.lock); |
1361 | ntfs_error(vol->sb, "Failed to allocate a cluster for " | 1362 | 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 | nr > min_nr ? "default" : "minimal", (long long)nr); | 1781 | nr > min_nr ? "default" : "minimal", (long long)nr); |
1781 | old_last_vcn = rl[1].vcn; | 1782 | old_last_vcn = rl[1].vcn; |
1782 | do { | 1783 | do { |
1783 | rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE); | 1784 | rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE, |
1785 | TRUE); | ||
1784 | if (likely(!IS_ERR(rl2))) | 1786 | if (likely(!IS_ERR(rl2))) |
1785 | break; | 1787 | break; |
1786 | if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) { | 1788 | if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) { |