summaryrefslogtreecommitdiff
path: root/fs/ntfs3/run.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs3/run.c')
-rw-r--r--fs/ntfs3/run.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c
index 88550085f745..395b20492525 100644
--- a/fs/ntfs3/run.c
+++ b/fs/ntfs3/run.c
@@ -487,7 +487,7 @@ requires_new_range:
* Helper for attr_collapse_range(),
* which is helper for fallocate(collapse_range).
*/
-bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len)
+bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len, CLST sub)
{
size_t index, eat;
struct ntfs_run *r, *e, *eat_start, *eat_end;
@@ -511,7 +511,7 @@ bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len)
/* Collapse a middle part of normal run, split. */
if (!run_add_entry(run, vcn, SPARSE_LCN, len, false))
return false;
- return run_collapse_range(run, vcn, len);
+ return run_collapse_range(run, vcn, len, sub);
}
r += 1;
@@ -545,6 +545,13 @@ bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len)
memmove(eat_start, eat_end, (e - eat_end) * sizeof(*r));
run->count -= eat;
+ if (sub) {
+ e -= eat;
+ for (r = run->runs; r < e; r++) {
+ r->vcn -= sub;
+ }
+ }
+
return true;
}
@@ -984,8 +991,12 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
if (!dlcn)
return -EINVAL;
- if (check_add_overflow(prev_lcn, dlcn, &lcn))
+ /* Check special combination: 0 + SPARSE_LCN64. */
+ if (!prev_lcn && dlcn == SPARSE_LCN64) {
+ lcn = SPARSE_LCN64;
+ } else if (check_add_overflow(prev_lcn, dlcn, &lcn)) {
return -EINVAL;
+ }
prev_lcn = lcn;
} else {
/* The size of 'dlcn' can't be > 8. */