Commit eed8b2de authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS: More runlist handling fixes from Richard Russon and myself.

Signed-off-by: default avatarAnton Altaparmakov <aia21@cantab.net>
parent 676d55ae
...@@ -158,17 +158,21 @@ static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst, ...@@ -158,17 +158,21 @@ static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
BUG_ON(!dst); BUG_ON(!dst);
BUG_ON(!src); BUG_ON(!src);
if ((dst->lcn < 0) || (src->lcn < 0)) { /* Are we merging holes? */ /* We can merge unmapped regions even if they are misaligned. */
if (dst->lcn == LCN_HOLE && src->lcn == LCN_HOLE) if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
return TRUE; return TRUE;
/* If the runs are misaligned, we cannot merge them. */
if ((dst->vcn + dst->length) != src->vcn)
return FALSE; return FALSE;
} /* If both runs are non-sparse and contiguous, we can merge them. */
if ((dst->lcn + dst->length) != src->lcn) /* Are the runs contiguous? */ if ((dst->lcn >= 0) && (src->lcn >= 0) &&
return FALSE; ((dst->lcn + dst->length) == src->lcn))
if ((dst->vcn + dst->length) != src->vcn) /* Are the runs misaligned? */ return TRUE;
return FALSE; /* If we are merging two holes, we can merge them. */
if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
return TRUE; return TRUE;
/* Cannot merge. */
return FALSE;
} }
/** /**
...@@ -214,14 +218,15 @@ static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src) ...@@ -214,14 +218,15 @@ static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
static inline runlist_element *ntfs_rl_append(runlist_element *dst, static inline runlist_element *ntfs_rl_append(runlist_element *dst,
int dsize, runlist_element *src, int ssize, int loc) int dsize, runlist_element *src, int ssize, int loc)
{ {
BOOL right; /* Right end of @src needs merging. */ BOOL right = FALSE; /* Right end of @src needs merging. */
int marker; /* End of the inserted runs. */ int marker; /* End of the inserted runs. */
BUG_ON(!dst); BUG_ON(!dst);
BUG_ON(!src); BUG_ON(!src);
/* First, check if the right hand end needs merging. */ /* First, check if the right hand end needs merging. */
right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); if ((loc + 1) < dsize)
right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
/* Space required: @dst size + @src size, less one if we merged. */ /* Space required: @dst size + @src size, less one if we merged. */
dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right); dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right);
...@@ -377,20 +382,21 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, ...@@ -377,20 +382,21 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
int dsize, runlist_element *src, int ssize, int loc) int dsize, runlist_element *src, int ssize, int loc)
{ {
BOOL left = FALSE; /* Left end of @src needs merging. */ BOOL left = FALSE; /* Left end of @src needs merging. */
BOOL right; /* Right end of @src needs merging. */ BOOL right = FALSE; /* Right end of @src needs merging. */
int tail; /* Start of tail of @dst. */ int tail; /* Start of tail of @dst. */
int marker; /* End of the inserted runs. */ int marker; /* End of the inserted runs. */
BUG_ON(!dst); BUG_ON(!dst);
BUG_ON(!src); BUG_ON(!src);
/* First, merge the left and right ends, if necessary. */ /* First, see if the left and right ends need merging. */
right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); if ((loc + 1) < dsize)
right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
if (loc > 0) if (loc > 0)
left = ntfs_are_rl_mergeable(dst + loc - 1, src); left = ntfs_are_rl_mergeable(dst + loc - 1, src);
/* /*
* Allocate some space. We will need less if the left, right, or both * Allocate some space. We will need less if the left, right, or both
* ends were merged. * ends get merged.
*/ */
dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right); dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right);
if (IS_ERR(dst)) if (IS_ERR(dst))
...@@ -399,21 +405,26 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, ...@@ -399,21 +405,26 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
* We are guaranteed to succeed from here so can start modifying the * We are guaranteed to succeed from here so can start modifying the
* original runlists. * original runlists.
*/ */
/* First, merge the left and right ends, if necessary. */
if (right) if (right)
__ntfs_rl_merge(src + ssize - 1, dst + loc + 1); __ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
if (left) if (left)
__ntfs_rl_merge(dst + loc - 1, src); __ntfs_rl_merge(dst + loc - 1, src);
/* /*
* First run of @dst that needs to be moved out of the way to make * Offset of the tail of @dst. This needs to be moved out of the way
* space for the runs to be copied from @src, i.e. the first run of the * to make space for the runs to be copied from @src, i.e. the first
* tail of @dst. * run of the tail of @dst.
* Nominally, @tail equals @loc + 1, i.e. location, skipping the
* replaced run. However, if @right, then one of @dst's runs is
* already merged into @src.
*/ */
tail = loc + right + 1; tail = loc + right + 1;
/* /*
* First run after the @src runs that have been inserted, i.e. where * First run after the @src runs that have been inserted, i.e. where
* the tail of @dst needs to be moved to. * the tail of @dst needs to be moved to.
* Nominally, marker equals @loc + @ssize, i.e. location + number of * Nominally, @marker equals @loc + @ssize, i.e. location + number of
* runs in @src). However, if @left, then the first run in @src has * runs in @src. However, if @left, then the first run in @src has
* been merged with one in @dst. * been merged with one in @dst.
*/ */
marker = loc + ssize - left; marker = loc + ssize - left;
......
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