18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/**
38c2ecf20Sopenharmony_ci * runlist.c - NTFS runlist handling code.  Part of the Linux-NTFS project.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2001-2007 Anton Altaparmakov
68c2ecf20Sopenharmony_ci * Copyright (c) 2002-2005 Richard Russon
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "debug.h"
108c2ecf20Sopenharmony_ci#include "dir.h"
118c2ecf20Sopenharmony_ci#include "endian.h"
128c2ecf20Sopenharmony_ci#include "malloc.h"
138c2ecf20Sopenharmony_ci#include "ntfs.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/**
168c2ecf20Sopenharmony_ci * ntfs_rl_mm - runlist memmove
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlist @base.
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_cistatic inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
218c2ecf20Sopenharmony_ci		int size)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	if (likely((dst != src) && (size > 0)))
248c2ecf20Sopenharmony_ci		memmove(base + dst, base + src, size * sizeof(*base));
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/**
288c2ecf20Sopenharmony_ci * ntfs_rl_mc - runlist memory copy
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @dstbase and
318c2ecf20Sopenharmony_ci * @srcbase.
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_cistatic inline void ntfs_rl_mc(runlist_element *dstbase, int dst,
348c2ecf20Sopenharmony_ci		runlist_element *srcbase, int src, int size)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	if (likely(size > 0))
378c2ecf20Sopenharmony_ci		memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/**
418c2ecf20Sopenharmony_ci * ntfs_rl_realloc - Reallocate memory for runlists
428c2ecf20Sopenharmony_ci * @rl:		original runlist
438c2ecf20Sopenharmony_ci * @old_size:	number of runlist elements in the original runlist @rl
448c2ecf20Sopenharmony_ci * @new_size:	number of runlist elements we need space for
458c2ecf20Sopenharmony_ci *
468c2ecf20Sopenharmony_ci * As the runlists grow, more memory will be required.  To prevent the
478c2ecf20Sopenharmony_ci * kernel having to allocate and reallocate large numbers of small bits of
488c2ecf20Sopenharmony_ci * memory, this function returns an entire page of memory.
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlist @rl.
518c2ecf20Sopenharmony_ci *
528c2ecf20Sopenharmony_ci * N.B.  If the new allocation doesn't require a different number of pages in
538c2ecf20Sopenharmony_ci *       memory, the function will return the original pointer.
548c2ecf20Sopenharmony_ci *
558c2ecf20Sopenharmony_ci * On success, return a pointer to the newly allocated, or recycled, memory.
568c2ecf20Sopenharmony_ci * On error, return -errno. The following error codes are defined:
578c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
588c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_cistatic inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
618c2ecf20Sopenharmony_ci		int old_size, int new_size)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	runlist_element *new_rl;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	old_size = PAGE_ALIGN(old_size * sizeof(*rl));
668c2ecf20Sopenharmony_ci	new_size = PAGE_ALIGN(new_size * sizeof(*rl));
678c2ecf20Sopenharmony_ci	if (old_size == new_size)
688c2ecf20Sopenharmony_ci		return rl;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	new_rl = ntfs_malloc_nofs(new_size);
718c2ecf20Sopenharmony_ci	if (unlikely(!new_rl))
728c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	if (likely(rl != NULL)) {
758c2ecf20Sopenharmony_ci		if (unlikely(old_size > new_size))
768c2ecf20Sopenharmony_ci			old_size = new_size;
778c2ecf20Sopenharmony_ci		memcpy(new_rl, rl, old_size);
788c2ecf20Sopenharmony_ci		ntfs_free(rl);
798c2ecf20Sopenharmony_ci	}
808c2ecf20Sopenharmony_ci	return new_rl;
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci/**
848c2ecf20Sopenharmony_ci * ntfs_rl_realloc_nofail - Reallocate memory for runlists
858c2ecf20Sopenharmony_ci * @rl:		original runlist
868c2ecf20Sopenharmony_ci * @old_size:	number of runlist elements in the original runlist @rl
878c2ecf20Sopenharmony_ci * @new_size:	number of runlist elements we need space for
888c2ecf20Sopenharmony_ci *
898c2ecf20Sopenharmony_ci * As the runlists grow, more memory will be required.  To prevent the
908c2ecf20Sopenharmony_ci * kernel having to allocate and reallocate large numbers of small bits of
918c2ecf20Sopenharmony_ci * memory, this function returns an entire page of memory.
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci * This function guarantees that the allocation will succeed.  It will sleep
948c2ecf20Sopenharmony_ci * for as long as it takes to complete the allocation.
958c2ecf20Sopenharmony_ci *
968c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlist @rl.
978c2ecf20Sopenharmony_ci *
988c2ecf20Sopenharmony_ci * N.B.  If the new allocation doesn't require a different number of pages in
998c2ecf20Sopenharmony_ci *       memory, the function will return the original pointer.
1008c2ecf20Sopenharmony_ci *
1018c2ecf20Sopenharmony_ci * On success, return a pointer to the newly allocated, or recycled, memory.
1028c2ecf20Sopenharmony_ci * On error, return -errno. The following error codes are defined:
1038c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
1048c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
1058c2ecf20Sopenharmony_ci */
1068c2ecf20Sopenharmony_cistatic inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl,
1078c2ecf20Sopenharmony_ci		int old_size, int new_size)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	runlist_element *new_rl;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	old_size = PAGE_ALIGN(old_size * sizeof(*rl));
1128c2ecf20Sopenharmony_ci	new_size = PAGE_ALIGN(new_size * sizeof(*rl));
1138c2ecf20Sopenharmony_ci	if (old_size == new_size)
1148c2ecf20Sopenharmony_ci		return rl;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	new_rl = ntfs_malloc_nofs_nofail(new_size);
1178c2ecf20Sopenharmony_ci	BUG_ON(!new_rl);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	if (likely(rl != NULL)) {
1208c2ecf20Sopenharmony_ci		if (unlikely(old_size > new_size))
1218c2ecf20Sopenharmony_ci			old_size = new_size;
1228c2ecf20Sopenharmony_ci		memcpy(new_rl, rl, old_size);
1238c2ecf20Sopenharmony_ci		ntfs_free(rl);
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci	return new_rl;
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci/**
1298c2ecf20Sopenharmony_ci * ntfs_are_rl_mergeable - test if two runlists can be joined together
1308c2ecf20Sopenharmony_ci * @dst:	original runlist
1318c2ecf20Sopenharmony_ci * @src:	new runlist to test for mergeability with @dst
1328c2ecf20Sopenharmony_ci *
1338c2ecf20Sopenharmony_ci * Test if two runlists can be joined together. For this, their VCNs and LCNs
1348c2ecf20Sopenharmony_ci * must be adjacent.
1358c2ecf20Sopenharmony_ci *
1368c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @dst and @src.
1378c2ecf20Sopenharmony_ci *
1388c2ecf20Sopenharmony_ci * Return: true   Success, the runlists can be merged.
1398c2ecf20Sopenharmony_ci *	   false  Failure, the runlists cannot be merged.
1408c2ecf20Sopenharmony_ci */
1418c2ecf20Sopenharmony_cistatic inline bool ntfs_are_rl_mergeable(runlist_element *dst,
1428c2ecf20Sopenharmony_ci		runlist_element *src)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	BUG_ON(!dst);
1458c2ecf20Sopenharmony_ci	BUG_ON(!src);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	/* We can merge unmapped regions even if they are misaligned. */
1488c2ecf20Sopenharmony_ci	if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
1498c2ecf20Sopenharmony_ci		return true;
1508c2ecf20Sopenharmony_ci	/* If the runs are misaligned, we cannot merge them. */
1518c2ecf20Sopenharmony_ci	if ((dst->vcn + dst->length) != src->vcn)
1528c2ecf20Sopenharmony_ci		return false;
1538c2ecf20Sopenharmony_ci	/* If both runs are non-sparse and contiguous, we can merge them. */
1548c2ecf20Sopenharmony_ci	if ((dst->lcn >= 0) && (src->lcn >= 0) &&
1558c2ecf20Sopenharmony_ci			((dst->lcn + dst->length) == src->lcn))
1568c2ecf20Sopenharmony_ci		return true;
1578c2ecf20Sopenharmony_ci	/* If we are merging two holes, we can merge them. */
1588c2ecf20Sopenharmony_ci	if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
1598c2ecf20Sopenharmony_ci		return true;
1608c2ecf20Sopenharmony_ci	/* Cannot merge. */
1618c2ecf20Sopenharmony_ci	return false;
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/**
1658c2ecf20Sopenharmony_ci * __ntfs_rl_merge - merge two runlists without testing if they can be merged
1668c2ecf20Sopenharmony_ci * @dst:	original, destination runlist
1678c2ecf20Sopenharmony_ci * @src:	new runlist to merge with @dst
1688c2ecf20Sopenharmony_ci *
1698c2ecf20Sopenharmony_ci * Merge the two runlists, writing into the destination runlist @dst. The
1708c2ecf20Sopenharmony_ci * caller must make sure the runlists can be merged or this will corrupt the
1718c2ecf20Sopenharmony_ci * destination runlist.
1728c2ecf20Sopenharmony_ci *
1738c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @dst and @src.
1748c2ecf20Sopenharmony_ci */
1758c2ecf20Sopenharmony_cistatic inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	dst->length += src->length;
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci/**
1818c2ecf20Sopenharmony_ci * ntfs_rl_append - append a runlist after a given element
1828c2ecf20Sopenharmony_ci * @dst:	original runlist to be worked on
1838c2ecf20Sopenharmony_ci * @dsize:	number of elements in @dst (including end marker)
1848c2ecf20Sopenharmony_ci * @src:	runlist to be inserted into @dst
1858c2ecf20Sopenharmony_ci * @ssize:	number of elements in @src (excluding end marker)
1868c2ecf20Sopenharmony_ci * @loc:	append the new runlist @src after this element in @dst
1878c2ecf20Sopenharmony_ci *
1888c2ecf20Sopenharmony_ci * Append the runlist @src after element @loc in @dst.  Merge the right end of
1898c2ecf20Sopenharmony_ci * the new runlist, if necessary. Adjust the size of the hole before the
1908c2ecf20Sopenharmony_ci * appended runlist.
1918c2ecf20Sopenharmony_ci *
1928c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @dst and @src.
1938c2ecf20Sopenharmony_ci *
1948c2ecf20Sopenharmony_ci * On success, return a pointer to the new, combined, runlist. Note, both
1958c2ecf20Sopenharmony_ci * runlists @dst and @src are deallocated before returning so you cannot use
1968c2ecf20Sopenharmony_ci * the pointers for anything any more. (Strictly speaking the returned runlist
1978c2ecf20Sopenharmony_ci * may be the same as @dst but this is irrelevant.)
1988c2ecf20Sopenharmony_ci *
1998c2ecf20Sopenharmony_ci * On error, return -errno. Both runlists are left unmodified. The following
2008c2ecf20Sopenharmony_ci * error codes are defined:
2018c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
2028c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
2038c2ecf20Sopenharmony_ci */
2048c2ecf20Sopenharmony_cistatic inline runlist_element *ntfs_rl_append(runlist_element *dst,
2058c2ecf20Sopenharmony_ci		int dsize, runlist_element *src, int ssize, int loc)
2068c2ecf20Sopenharmony_ci{
2078c2ecf20Sopenharmony_ci	bool right = false;	/* Right end of @src needs merging. */
2088c2ecf20Sopenharmony_ci	int marker;		/* End of the inserted runs. */
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	BUG_ON(!dst);
2118c2ecf20Sopenharmony_ci	BUG_ON(!src);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	/* First, check if the right hand end needs merging. */
2148c2ecf20Sopenharmony_ci	if ((loc + 1) < dsize)
2158c2ecf20Sopenharmony_ci		right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	/* Space required: @dst size + @src size, less one if we merged. */
2188c2ecf20Sopenharmony_ci	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right);
2198c2ecf20Sopenharmony_ci	if (IS_ERR(dst))
2208c2ecf20Sopenharmony_ci		return dst;
2218c2ecf20Sopenharmony_ci	/*
2228c2ecf20Sopenharmony_ci	 * We are guaranteed to succeed from here so can start modifying the
2238c2ecf20Sopenharmony_ci	 * original runlists.
2248c2ecf20Sopenharmony_ci	 */
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	/* First, merge the right hand end, if necessary. */
2278c2ecf20Sopenharmony_ci	if (right)
2288c2ecf20Sopenharmony_ci		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* First run after the @src runs that have been inserted. */
2318c2ecf20Sopenharmony_ci	marker = loc + ssize + 1;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	/* Move the tail of @dst out of the way, then copy in @src. */
2348c2ecf20Sopenharmony_ci	ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - (loc + 1 + right));
2358c2ecf20Sopenharmony_ci	ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	/* Adjust the size of the preceding hole. */
2388c2ecf20Sopenharmony_ci	dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	/* We may have changed the length of the file, so fix the end marker */
2418c2ecf20Sopenharmony_ci	if (dst[marker].lcn == LCN_ENOENT)
2428c2ecf20Sopenharmony_ci		dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	return dst;
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci/**
2488c2ecf20Sopenharmony_ci * ntfs_rl_insert - insert a runlist into another
2498c2ecf20Sopenharmony_ci * @dst:	original runlist to be worked on
2508c2ecf20Sopenharmony_ci * @dsize:	number of elements in @dst (including end marker)
2518c2ecf20Sopenharmony_ci * @src:	new runlist to be inserted
2528c2ecf20Sopenharmony_ci * @ssize:	number of elements in @src (excluding end marker)
2538c2ecf20Sopenharmony_ci * @loc:	insert the new runlist @src before this element in @dst
2548c2ecf20Sopenharmony_ci *
2558c2ecf20Sopenharmony_ci * Insert the runlist @src before element @loc in the runlist @dst. Merge the
2568c2ecf20Sopenharmony_ci * left end of the new runlist, if necessary. Adjust the size of the hole
2578c2ecf20Sopenharmony_ci * after the inserted runlist.
2588c2ecf20Sopenharmony_ci *
2598c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @dst and @src.
2608c2ecf20Sopenharmony_ci *
2618c2ecf20Sopenharmony_ci * On success, return a pointer to the new, combined, runlist. Note, both
2628c2ecf20Sopenharmony_ci * runlists @dst and @src are deallocated before returning so you cannot use
2638c2ecf20Sopenharmony_ci * the pointers for anything any more. (Strictly speaking the returned runlist
2648c2ecf20Sopenharmony_ci * may be the same as @dst but this is irrelevant.)
2658c2ecf20Sopenharmony_ci *
2668c2ecf20Sopenharmony_ci * On error, return -errno. Both runlists are left unmodified. The following
2678c2ecf20Sopenharmony_ci * error codes are defined:
2688c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
2698c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
2708c2ecf20Sopenharmony_ci */
2718c2ecf20Sopenharmony_cistatic inline runlist_element *ntfs_rl_insert(runlist_element *dst,
2728c2ecf20Sopenharmony_ci		int dsize, runlist_element *src, int ssize, int loc)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	bool left = false;	/* Left end of @src needs merging. */
2758c2ecf20Sopenharmony_ci	bool disc = false;	/* Discontinuity between @dst and @src. */
2768c2ecf20Sopenharmony_ci	int marker;		/* End of the inserted runs. */
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	BUG_ON(!dst);
2798c2ecf20Sopenharmony_ci	BUG_ON(!src);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	/*
2828c2ecf20Sopenharmony_ci	 * disc => Discontinuity between the end of @dst and the start of @src.
2838c2ecf20Sopenharmony_ci	 *	   This means we might need to insert a "not mapped" run.
2848c2ecf20Sopenharmony_ci	 */
2858c2ecf20Sopenharmony_ci	if (loc == 0)
2868c2ecf20Sopenharmony_ci		disc = (src[0].vcn > 0);
2878c2ecf20Sopenharmony_ci	else {
2888c2ecf20Sopenharmony_ci		s64 merged_length;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci		left = ntfs_are_rl_mergeable(dst + loc - 1, src);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci		merged_length = dst[loc - 1].length;
2938c2ecf20Sopenharmony_ci		if (left)
2948c2ecf20Sopenharmony_ci			merged_length += src->length;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci		disc = (src[0].vcn > dst[loc - 1].vcn + merged_length);
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci	/*
2998c2ecf20Sopenharmony_ci	 * Space required: @dst size + @src size, less one if we merged, plus
3008c2ecf20Sopenharmony_ci	 * one if there was a discontinuity.
3018c2ecf20Sopenharmony_ci	 */
3028c2ecf20Sopenharmony_ci	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc);
3038c2ecf20Sopenharmony_ci	if (IS_ERR(dst))
3048c2ecf20Sopenharmony_ci		return dst;
3058c2ecf20Sopenharmony_ci	/*
3068c2ecf20Sopenharmony_ci	 * We are guaranteed to succeed from here so can start modifying the
3078c2ecf20Sopenharmony_ci	 * original runlist.
3088c2ecf20Sopenharmony_ci	 */
3098c2ecf20Sopenharmony_ci	if (left)
3108c2ecf20Sopenharmony_ci		__ntfs_rl_merge(dst + loc - 1, src);
3118c2ecf20Sopenharmony_ci	/*
3128c2ecf20Sopenharmony_ci	 * First run after the @src runs that have been inserted.
3138c2ecf20Sopenharmony_ci	 * Nominally,  @marker equals @loc + @ssize, i.e. location + number of
3148c2ecf20Sopenharmony_ci	 * runs in @src.  However, if @left, then the first run in @src has
3158c2ecf20Sopenharmony_ci	 * been merged with one in @dst.  And if @disc, then @dst and @src do
3168c2ecf20Sopenharmony_ci	 * not meet and we need an extra run to fill the gap.
3178c2ecf20Sopenharmony_ci	 */
3188c2ecf20Sopenharmony_ci	marker = loc + ssize - left + disc;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* Move the tail of @dst out of the way, then copy in @src. */
3218c2ecf20Sopenharmony_ci	ntfs_rl_mm(dst, marker, loc, dsize - loc);
3228c2ecf20Sopenharmony_ci	ntfs_rl_mc(dst, loc + disc, src, left, ssize - left);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	/* Adjust the VCN of the first run after the insertion... */
3258c2ecf20Sopenharmony_ci	dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
3268c2ecf20Sopenharmony_ci	/* ... and the length. */
3278c2ecf20Sopenharmony_ci	if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED)
3288c2ecf20Sopenharmony_ci		dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/* Writing beyond the end of the file and there is a discontinuity. */
3318c2ecf20Sopenharmony_ci	if (disc) {
3328c2ecf20Sopenharmony_ci		if (loc > 0) {
3338c2ecf20Sopenharmony_ci			dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
3348c2ecf20Sopenharmony_ci			dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
3358c2ecf20Sopenharmony_ci		} else {
3368c2ecf20Sopenharmony_ci			dst[loc].vcn = 0;
3378c2ecf20Sopenharmony_ci			dst[loc].length = dst[loc + 1].vcn;
3388c2ecf20Sopenharmony_ci		}
3398c2ecf20Sopenharmony_ci		dst[loc].lcn = LCN_RL_NOT_MAPPED;
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci	return dst;
3428c2ecf20Sopenharmony_ci}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci/**
3458c2ecf20Sopenharmony_ci * ntfs_rl_replace - overwrite a runlist element with another runlist
3468c2ecf20Sopenharmony_ci * @dst:	original runlist to be worked on
3478c2ecf20Sopenharmony_ci * @dsize:	number of elements in @dst (including end marker)
3488c2ecf20Sopenharmony_ci * @src:	new runlist to be inserted
3498c2ecf20Sopenharmony_ci * @ssize:	number of elements in @src (excluding end marker)
3508c2ecf20Sopenharmony_ci * @loc:	index in runlist @dst to overwrite with @src
3518c2ecf20Sopenharmony_ci *
3528c2ecf20Sopenharmony_ci * Replace the runlist element @dst at @loc with @src. Merge the left and
3538c2ecf20Sopenharmony_ci * right ends of the inserted runlist, if necessary.
3548c2ecf20Sopenharmony_ci *
3558c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @dst and @src.
3568c2ecf20Sopenharmony_ci *
3578c2ecf20Sopenharmony_ci * On success, return a pointer to the new, combined, runlist. Note, both
3588c2ecf20Sopenharmony_ci * runlists @dst and @src are deallocated before returning so you cannot use
3598c2ecf20Sopenharmony_ci * the pointers for anything any more. (Strictly speaking the returned runlist
3608c2ecf20Sopenharmony_ci * may be the same as @dst but this is irrelevant.)
3618c2ecf20Sopenharmony_ci *
3628c2ecf20Sopenharmony_ci * On error, return -errno. Both runlists are left unmodified. The following
3638c2ecf20Sopenharmony_ci * error codes are defined:
3648c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
3658c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
3668c2ecf20Sopenharmony_ci */
3678c2ecf20Sopenharmony_cistatic inline runlist_element *ntfs_rl_replace(runlist_element *dst,
3688c2ecf20Sopenharmony_ci		int dsize, runlist_element *src, int ssize, int loc)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	signed delta;
3718c2ecf20Sopenharmony_ci	bool left = false;	/* Left end of @src needs merging. */
3728c2ecf20Sopenharmony_ci	bool right = false;	/* Right end of @src needs merging. */
3738c2ecf20Sopenharmony_ci	int tail;		/* Start of tail of @dst. */
3748c2ecf20Sopenharmony_ci	int marker;		/* End of the inserted runs. */
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	BUG_ON(!dst);
3778c2ecf20Sopenharmony_ci	BUG_ON(!src);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	/* First, see if the left and right ends need merging. */
3808c2ecf20Sopenharmony_ci	if ((loc + 1) < dsize)
3818c2ecf20Sopenharmony_ci		right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
3828c2ecf20Sopenharmony_ci	if (loc > 0)
3838c2ecf20Sopenharmony_ci		left = ntfs_are_rl_mergeable(dst + loc - 1, src);
3848c2ecf20Sopenharmony_ci	/*
3858c2ecf20Sopenharmony_ci	 * Allocate some space.  We will need less if the left, right, or both
3868c2ecf20Sopenharmony_ci	 * ends get merged.  The -1 accounts for the run being replaced.
3878c2ecf20Sopenharmony_ci	 */
3888c2ecf20Sopenharmony_ci	delta = ssize - 1 - left - right;
3898c2ecf20Sopenharmony_ci	if (delta > 0) {
3908c2ecf20Sopenharmony_ci		dst = ntfs_rl_realloc(dst, dsize, dsize + delta);
3918c2ecf20Sopenharmony_ci		if (IS_ERR(dst))
3928c2ecf20Sopenharmony_ci			return dst;
3938c2ecf20Sopenharmony_ci	}
3948c2ecf20Sopenharmony_ci	/*
3958c2ecf20Sopenharmony_ci	 * We are guaranteed to succeed from here so can start modifying the
3968c2ecf20Sopenharmony_ci	 * original runlists.
3978c2ecf20Sopenharmony_ci	 */
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	/* First, merge the left and right ends, if necessary. */
4008c2ecf20Sopenharmony_ci	if (right)
4018c2ecf20Sopenharmony_ci		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
4028c2ecf20Sopenharmony_ci	if (left)
4038c2ecf20Sopenharmony_ci		__ntfs_rl_merge(dst + loc - 1, src);
4048c2ecf20Sopenharmony_ci	/*
4058c2ecf20Sopenharmony_ci	 * Offset of the tail of @dst.  This needs to be moved out of the way
4068c2ecf20Sopenharmony_ci	 * to make space for the runs to be copied from @src, i.e. the first
4078c2ecf20Sopenharmony_ci	 * run of the tail of @dst.
4088c2ecf20Sopenharmony_ci	 * Nominally, @tail equals @loc + 1, i.e. location, skipping the
4098c2ecf20Sopenharmony_ci	 * replaced run.  However, if @right, then one of @dst's runs is
4108c2ecf20Sopenharmony_ci	 * already merged into @src.
4118c2ecf20Sopenharmony_ci	 */
4128c2ecf20Sopenharmony_ci	tail = loc + right + 1;
4138c2ecf20Sopenharmony_ci	/*
4148c2ecf20Sopenharmony_ci	 * First run after the @src runs that have been inserted, i.e. where
4158c2ecf20Sopenharmony_ci	 * the tail of @dst needs to be moved to.
4168c2ecf20Sopenharmony_ci	 * Nominally, @marker equals @loc + @ssize, i.e. location + number of
4178c2ecf20Sopenharmony_ci	 * runs in @src.  However, if @left, then the first run in @src has
4188c2ecf20Sopenharmony_ci	 * been merged with one in @dst.
4198c2ecf20Sopenharmony_ci	 */
4208c2ecf20Sopenharmony_ci	marker = loc + ssize - left;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	/* Move the tail of @dst out of the way, then copy in @src. */
4238c2ecf20Sopenharmony_ci	ntfs_rl_mm(dst, marker, tail, dsize - tail);
4248c2ecf20Sopenharmony_ci	ntfs_rl_mc(dst, loc, src, left, ssize - left);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	/* We may have changed the length of the file, so fix the end marker. */
4278c2ecf20Sopenharmony_ci	if (dsize - tail > 0 && dst[marker].lcn == LCN_ENOENT)
4288c2ecf20Sopenharmony_ci		dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
4298c2ecf20Sopenharmony_ci	return dst;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci/**
4338c2ecf20Sopenharmony_ci * ntfs_rl_split - insert a runlist into the centre of a hole
4348c2ecf20Sopenharmony_ci * @dst:	original runlist to be worked on
4358c2ecf20Sopenharmony_ci * @dsize:	number of elements in @dst (including end marker)
4368c2ecf20Sopenharmony_ci * @src:	new runlist to be inserted
4378c2ecf20Sopenharmony_ci * @ssize:	number of elements in @src (excluding end marker)
4388c2ecf20Sopenharmony_ci * @loc:	index in runlist @dst at which to split and insert @src
4398c2ecf20Sopenharmony_ci *
4408c2ecf20Sopenharmony_ci * Split the runlist @dst at @loc into two and insert @new in between the two
4418c2ecf20Sopenharmony_ci * fragments. No merging of runlists is necessary. Adjust the size of the
4428c2ecf20Sopenharmony_ci * holes either side.
4438c2ecf20Sopenharmony_ci *
4448c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @dst and @src.
4458c2ecf20Sopenharmony_ci *
4468c2ecf20Sopenharmony_ci * On success, return a pointer to the new, combined, runlist. Note, both
4478c2ecf20Sopenharmony_ci * runlists @dst and @src are deallocated before returning so you cannot use
4488c2ecf20Sopenharmony_ci * the pointers for anything any more. (Strictly speaking the returned runlist
4498c2ecf20Sopenharmony_ci * may be the same as @dst but this is irrelevant.)
4508c2ecf20Sopenharmony_ci *
4518c2ecf20Sopenharmony_ci * On error, return -errno. Both runlists are left unmodified. The following
4528c2ecf20Sopenharmony_ci * error codes are defined:
4538c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
4548c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
4558c2ecf20Sopenharmony_ci */
4568c2ecf20Sopenharmony_cistatic inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
4578c2ecf20Sopenharmony_ci		runlist_element *src, int ssize, int loc)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	BUG_ON(!dst);
4608c2ecf20Sopenharmony_ci	BUG_ON(!src);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	/* Space required: @dst size + @src size + one new hole. */
4638c2ecf20Sopenharmony_ci	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1);
4648c2ecf20Sopenharmony_ci	if (IS_ERR(dst))
4658c2ecf20Sopenharmony_ci		return dst;
4668c2ecf20Sopenharmony_ci	/*
4678c2ecf20Sopenharmony_ci	 * We are guaranteed to succeed from here so can start modifying the
4688c2ecf20Sopenharmony_ci	 * original runlists.
4698c2ecf20Sopenharmony_ci	 */
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	/* Move the tail of @dst out of the way, then copy in @src. */
4728c2ecf20Sopenharmony_ci	ntfs_rl_mm(dst, loc + 1 + ssize, loc, dsize - loc);
4738c2ecf20Sopenharmony_ci	ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* Adjust the size of the holes either size of @src. */
4768c2ecf20Sopenharmony_ci	dst[loc].length		= dst[loc+1].vcn       - dst[loc].vcn;
4778c2ecf20Sopenharmony_ci	dst[loc+ssize+1].vcn    = dst[loc+ssize].vcn   + dst[loc+ssize].length;
4788c2ecf20Sopenharmony_ci	dst[loc+ssize+1].length = dst[loc+ssize+2].vcn - dst[loc+ssize+1].vcn;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	return dst;
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci/**
4848c2ecf20Sopenharmony_ci * ntfs_runlists_merge - merge two runlists into one
4858c2ecf20Sopenharmony_ci * @drl:	original runlist to be worked on
4868c2ecf20Sopenharmony_ci * @srl:	new runlist to be merged into @drl
4878c2ecf20Sopenharmony_ci *
4888c2ecf20Sopenharmony_ci * First we sanity check the two runlists @srl and @drl to make sure that they
4898c2ecf20Sopenharmony_ci * are sensible and can be merged. The runlist @srl must be either after the
4908c2ecf20Sopenharmony_ci * runlist @drl or completely within a hole (or unmapped region) in @drl.
4918c2ecf20Sopenharmony_ci *
4928c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlists @drl and @srl.
4938c2ecf20Sopenharmony_ci *
4948c2ecf20Sopenharmony_ci * Merging of runlists is necessary in two cases:
4958c2ecf20Sopenharmony_ci *   1. When attribute lists are used and a further extent is being mapped.
4968c2ecf20Sopenharmony_ci *   2. When new clusters are allocated to fill a hole or extend a file.
4978c2ecf20Sopenharmony_ci *
4988c2ecf20Sopenharmony_ci * There are four possible ways @srl can be merged. It can:
4998c2ecf20Sopenharmony_ci *	- be inserted at the beginning of a hole,
5008c2ecf20Sopenharmony_ci *	- split the hole in two and be inserted between the two fragments,
5018c2ecf20Sopenharmony_ci *	- be appended at the end of a hole, or it can
5028c2ecf20Sopenharmony_ci *	- replace the whole hole.
5038c2ecf20Sopenharmony_ci * It can also be appended to the end of the runlist, which is just a variant
5048c2ecf20Sopenharmony_ci * of the insert case.
5058c2ecf20Sopenharmony_ci *
5068c2ecf20Sopenharmony_ci * On success, return a pointer to the new, combined, runlist. Note, both
5078c2ecf20Sopenharmony_ci * runlists @drl and @srl are deallocated before returning so you cannot use
5088c2ecf20Sopenharmony_ci * the pointers for anything any more. (Strictly speaking the returned runlist
5098c2ecf20Sopenharmony_ci * may be the same as @dst but this is irrelevant.)
5108c2ecf20Sopenharmony_ci *
5118c2ecf20Sopenharmony_ci * On error, return -errno. Both runlists are left unmodified. The following
5128c2ecf20Sopenharmony_ci * error codes are defined:
5138c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
5148c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
5158c2ecf20Sopenharmony_ci *	-ERANGE	- The runlists overlap and cannot be merged.
5168c2ecf20Sopenharmony_ci */
5178c2ecf20Sopenharmony_cirunlist_element *ntfs_runlists_merge(runlist_element *drl,
5188c2ecf20Sopenharmony_ci		runlist_element *srl)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	int di, si;		/* Current index into @[ds]rl. */
5218c2ecf20Sopenharmony_ci	int sstart;		/* First index with lcn > LCN_RL_NOT_MAPPED. */
5228c2ecf20Sopenharmony_ci	int dins;		/* Index into @drl at which to insert @srl. */
5238c2ecf20Sopenharmony_ci	int dend, send;		/* Last index into @[ds]rl. */
5248c2ecf20Sopenharmony_ci	int dfinal, sfinal;	/* The last index into @[ds]rl with
5258c2ecf20Sopenharmony_ci				   lcn >= LCN_HOLE. */
5268c2ecf20Sopenharmony_ci	int marker = 0;
5278c2ecf20Sopenharmony_ci	VCN marker_vcn = 0;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci#ifdef DEBUG
5308c2ecf20Sopenharmony_ci	ntfs_debug("dst:");
5318c2ecf20Sopenharmony_ci	ntfs_debug_dump_runlist(drl);
5328c2ecf20Sopenharmony_ci	ntfs_debug("src:");
5338c2ecf20Sopenharmony_ci	ntfs_debug_dump_runlist(srl);
5348c2ecf20Sopenharmony_ci#endif
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	/* Check for silly calling... */
5378c2ecf20Sopenharmony_ci	if (unlikely(!srl))
5388c2ecf20Sopenharmony_ci		return drl;
5398c2ecf20Sopenharmony_ci	if (IS_ERR(srl) || IS_ERR(drl))
5408c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/* Check for the case where the first mapping is being done now. */
5438c2ecf20Sopenharmony_ci	if (unlikely(!drl)) {
5448c2ecf20Sopenharmony_ci		drl = srl;
5458c2ecf20Sopenharmony_ci		/* Complete the source runlist if necessary. */
5468c2ecf20Sopenharmony_ci		if (unlikely(drl[0].vcn)) {
5478c2ecf20Sopenharmony_ci			/* Scan to the end of the source runlist. */
5488c2ecf20Sopenharmony_ci			for (dend = 0; likely(drl[dend].length); dend++)
5498c2ecf20Sopenharmony_ci				;
5508c2ecf20Sopenharmony_ci			dend++;
5518c2ecf20Sopenharmony_ci			drl = ntfs_rl_realloc(drl, dend, dend + 1);
5528c2ecf20Sopenharmony_ci			if (IS_ERR(drl))
5538c2ecf20Sopenharmony_ci				return drl;
5548c2ecf20Sopenharmony_ci			/* Insert start element at the front of the runlist. */
5558c2ecf20Sopenharmony_ci			ntfs_rl_mm(drl, 1, 0, dend);
5568c2ecf20Sopenharmony_ci			drl[0].vcn = 0;
5578c2ecf20Sopenharmony_ci			drl[0].lcn = LCN_RL_NOT_MAPPED;
5588c2ecf20Sopenharmony_ci			drl[0].length = drl[1].vcn;
5598c2ecf20Sopenharmony_ci		}
5608c2ecf20Sopenharmony_ci		goto finished;
5618c2ecf20Sopenharmony_ci	}
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	si = di = 0;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	/* Skip any unmapped start element(s) in the source runlist. */
5668c2ecf20Sopenharmony_ci	while (srl[si].length && srl[si].lcn < LCN_HOLE)
5678c2ecf20Sopenharmony_ci		si++;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	/* Can't have an entirely unmapped source runlist. */
5708c2ecf20Sopenharmony_ci	BUG_ON(!srl[si].length);
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	/* Record the starting points. */
5738c2ecf20Sopenharmony_ci	sstart = si;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/*
5768c2ecf20Sopenharmony_ci	 * Skip forward in @drl until we reach the position where @srl needs to
5778c2ecf20Sopenharmony_ci	 * be inserted. If we reach the end of @drl, @srl just needs to be
5788c2ecf20Sopenharmony_ci	 * appended to @drl.
5798c2ecf20Sopenharmony_ci	 */
5808c2ecf20Sopenharmony_ci	for (; drl[di].length; di++) {
5818c2ecf20Sopenharmony_ci		if (drl[di].vcn + drl[di].length > srl[sstart].vcn)
5828c2ecf20Sopenharmony_ci			break;
5838c2ecf20Sopenharmony_ci	}
5848c2ecf20Sopenharmony_ci	dins = di;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	/* Sanity check for illegal overlaps. */
5878c2ecf20Sopenharmony_ci	if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) &&
5888c2ecf20Sopenharmony_ci			(srl[si].lcn >= 0)) {
5898c2ecf20Sopenharmony_ci		ntfs_error(NULL, "Run lists overlap. Cannot merge!");
5908c2ecf20Sopenharmony_ci		return ERR_PTR(-ERANGE);
5918c2ecf20Sopenharmony_ci	}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	/* Scan to the end of both runlists in order to know their sizes. */
5948c2ecf20Sopenharmony_ci	for (send = si; srl[send].length; send++)
5958c2ecf20Sopenharmony_ci		;
5968c2ecf20Sopenharmony_ci	for (dend = di; drl[dend].length; dend++)
5978c2ecf20Sopenharmony_ci		;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	if (srl[send].lcn == LCN_ENOENT)
6008c2ecf20Sopenharmony_ci		marker_vcn = srl[marker = send].vcn;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	/* Scan to the last element with lcn >= LCN_HOLE. */
6038c2ecf20Sopenharmony_ci	for (sfinal = send; sfinal >= 0 && srl[sfinal].lcn < LCN_HOLE; sfinal--)
6048c2ecf20Sopenharmony_ci		;
6058c2ecf20Sopenharmony_ci	for (dfinal = dend; dfinal >= 0 && drl[dfinal].lcn < LCN_HOLE; dfinal--)
6068c2ecf20Sopenharmony_ci		;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	{
6098c2ecf20Sopenharmony_ci	bool start;
6108c2ecf20Sopenharmony_ci	bool finish;
6118c2ecf20Sopenharmony_ci	int ds = dend + 1;		/* Number of elements in drl & srl */
6128c2ecf20Sopenharmony_ci	int ss = sfinal - sstart + 1;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	start  = ((drl[dins].lcn <  LCN_RL_NOT_MAPPED) ||    /* End of file   */
6158c2ecf20Sopenharmony_ci		  (drl[dins].vcn == srl[sstart].vcn));	     /* Start of hole */
6168c2ecf20Sopenharmony_ci	finish = ((drl[dins].lcn >= LCN_RL_NOT_MAPPED) &&    /* End of file   */
6178c2ecf20Sopenharmony_ci		 ((drl[dins].vcn + drl[dins].length) <=      /* End of hole   */
6188c2ecf20Sopenharmony_ci		  (srl[send - 1].vcn + srl[send - 1].length)));
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	/* Or we will lose an end marker. */
6218c2ecf20Sopenharmony_ci	if (finish && !drl[dins].length)
6228c2ecf20Sopenharmony_ci		ss++;
6238c2ecf20Sopenharmony_ci	if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))
6248c2ecf20Sopenharmony_ci		finish = false;
6258c2ecf20Sopenharmony_ci#if 0
6268c2ecf20Sopenharmony_ci	ntfs_debug("dfinal = %i, dend = %i", dfinal, dend);
6278c2ecf20Sopenharmony_ci	ntfs_debug("sstart = %i, sfinal = %i, send = %i", sstart, sfinal, send);
6288c2ecf20Sopenharmony_ci	ntfs_debug("start = %i, finish = %i", start, finish);
6298c2ecf20Sopenharmony_ci	ntfs_debug("ds = %i, ss = %i, dins = %i", ds, ss, dins);
6308c2ecf20Sopenharmony_ci#endif
6318c2ecf20Sopenharmony_ci	if (start) {
6328c2ecf20Sopenharmony_ci		if (finish)
6338c2ecf20Sopenharmony_ci			drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins);
6348c2ecf20Sopenharmony_ci		else
6358c2ecf20Sopenharmony_ci			drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins);
6368c2ecf20Sopenharmony_ci	} else {
6378c2ecf20Sopenharmony_ci		if (finish)
6388c2ecf20Sopenharmony_ci			drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins);
6398c2ecf20Sopenharmony_ci		else
6408c2ecf20Sopenharmony_ci			drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins);
6418c2ecf20Sopenharmony_ci	}
6428c2ecf20Sopenharmony_ci	if (IS_ERR(drl)) {
6438c2ecf20Sopenharmony_ci		ntfs_error(NULL, "Merge failed.");
6448c2ecf20Sopenharmony_ci		return drl;
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci	ntfs_free(srl);
6478c2ecf20Sopenharmony_ci	if (marker) {
6488c2ecf20Sopenharmony_ci		ntfs_debug("Triggering marker code.");
6498c2ecf20Sopenharmony_ci		for (ds = dend; drl[ds].length; ds++)
6508c2ecf20Sopenharmony_ci			;
6518c2ecf20Sopenharmony_ci		/* We only need to care if @srl ended after @drl. */
6528c2ecf20Sopenharmony_ci		if (drl[ds].vcn <= marker_vcn) {
6538c2ecf20Sopenharmony_ci			int slots = 0;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci			if (drl[ds].vcn == marker_vcn) {
6568c2ecf20Sopenharmony_ci				ntfs_debug("Old marker = 0x%llx, replacing "
6578c2ecf20Sopenharmony_ci						"with LCN_ENOENT.",
6588c2ecf20Sopenharmony_ci						(unsigned long long)
6598c2ecf20Sopenharmony_ci						drl[ds].lcn);
6608c2ecf20Sopenharmony_ci				drl[ds].lcn = LCN_ENOENT;
6618c2ecf20Sopenharmony_ci				goto finished;
6628c2ecf20Sopenharmony_ci			}
6638c2ecf20Sopenharmony_ci			/*
6648c2ecf20Sopenharmony_ci			 * We need to create an unmapped runlist element in
6658c2ecf20Sopenharmony_ci			 * @drl or extend an existing one before adding the
6668c2ecf20Sopenharmony_ci			 * ENOENT terminator.
6678c2ecf20Sopenharmony_ci			 */
6688c2ecf20Sopenharmony_ci			if (drl[ds].lcn == LCN_ENOENT) {
6698c2ecf20Sopenharmony_ci				ds--;
6708c2ecf20Sopenharmony_ci				slots = 1;
6718c2ecf20Sopenharmony_ci			}
6728c2ecf20Sopenharmony_ci			if (drl[ds].lcn != LCN_RL_NOT_MAPPED) {
6738c2ecf20Sopenharmony_ci				/* Add an unmapped runlist element. */
6748c2ecf20Sopenharmony_ci				if (!slots) {
6758c2ecf20Sopenharmony_ci					drl = ntfs_rl_realloc_nofail(drl, ds,
6768c2ecf20Sopenharmony_ci							ds + 2);
6778c2ecf20Sopenharmony_ci					slots = 2;
6788c2ecf20Sopenharmony_ci				}
6798c2ecf20Sopenharmony_ci				ds++;
6808c2ecf20Sopenharmony_ci				/* Need to set vcn if it isn't set already. */
6818c2ecf20Sopenharmony_ci				if (slots != 1)
6828c2ecf20Sopenharmony_ci					drl[ds].vcn = drl[ds - 1].vcn +
6838c2ecf20Sopenharmony_ci							drl[ds - 1].length;
6848c2ecf20Sopenharmony_ci				drl[ds].lcn = LCN_RL_NOT_MAPPED;
6858c2ecf20Sopenharmony_ci				/* We now used up a slot. */
6868c2ecf20Sopenharmony_ci				slots--;
6878c2ecf20Sopenharmony_ci			}
6888c2ecf20Sopenharmony_ci			drl[ds].length = marker_vcn - drl[ds].vcn;
6898c2ecf20Sopenharmony_ci			/* Finally add the ENOENT terminator. */
6908c2ecf20Sopenharmony_ci			ds++;
6918c2ecf20Sopenharmony_ci			if (!slots)
6928c2ecf20Sopenharmony_ci				drl = ntfs_rl_realloc_nofail(drl, ds, ds + 1);
6938c2ecf20Sopenharmony_ci			drl[ds].vcn = marker_vcn;
6948c2ecf20Sopenharmony_ci			drl[ds].lcn = LCN_ENOENT;
6958c2ecf20Sopenharmony_ci			drl[ds].length = (s64)0;
6968c2ecf20Sopenharmony_ci		}
6978c2ecf20Sopenharmony_ci	}
6988c2ecf20Sopenharmony_ci	}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_cifinished:
7018c2ecf20Sopenharmony_ci	/* The merge was completed successfully. */
7028c2ecf20Sopenharmony_ci	ntfs_debug("Merged runlist:");
7038c2ecf20Sopenharmony_ci	ntfs_debug_dump_runlist(drl);
7048c2ecf20Sopenharmony_ci	return drl;
7058c2ecf20Sopenharmony_ci}
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci/**
7088c2ecf20Sopenharmony_ci * ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist
7098c2ecf20Sopenharmony_ci * @vol:	ntfs volume on which the attribute resides
7108c2ecf20Sopenharmony_ci * @attr:	attribute record whose mapping pairs array to decompress
7118c2ecf20Sopenharmony_ci * @old_rl:	optional runlist in which to insert @attr's runlist
7128c2ecf20Sopenharmony_ci *
7138c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlist @old_rl.
7148c2ecf20Sopenharmony_ci *
7158c2ecf20Sopenharmony_ci * Decompress the attribute @attr's mapping pairs array into a runlist. On
7168c2ecf20Sopenharmony_ci * success, return the decompressed runlist.
7178c2ecf20Sopenharmony_ci *
7188c2ecf20Sopenharmony_ci * If @old_rl is not NULL, decompressed runlist is inserted into the
7198c2ecf20Sopenharmony_ci * appropriate place in @old_rl and the resultant, combined runlist is
7208c2ecf20Sopenharmony_ci * returned. The original @old_rl is deallocated.
7218c2ecf20Sopenharmony_ci *
7228c2ecf20Sopenharmony_ci * On error, return -errno. @old_rl is left unmodified in that case.
7238c2ecf20Sopenharmony_ci *
7248c2ecf20Sopenharmony_ci * The following error codes are defined:
7258c2ecf20Sopenharmony_ci *	-ENOMEM	- Not enough memory to allocate runlist array.
7268c2ecf20Sopenharmony_ci *	-EIO	- Corrupt runlist.
7278c2ecf20Sopenharmony_ci *	-EINVAL	- Invalid parameters were passed in.
7288c2ecf20Sopenharmony_ci *	-ERANGE	- The two runlists overlap.
7298c2ecf20Sopenharmony_ci *
7308c2ecf20Sopenharmony_ci * FIXME: For now we take the conceptionally simplest approach of creating the
7318c2ecf20Sopenharmony_ci * new runlist disregarding the already existing one and then splicing the
7328c2ecf20Sopenharmony_ci * two into one, if that is possible (we check for overlap and discard the new
7338c2ecf20Sopenharmony_ci * runlist if overlap present before returning ERR_PTR(-ERANGE)).
7348c2ecf20Sopenharmony_ci */
7358c2ecf20Sopenharmony_cirunlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
7368c2ecf20Sopenharmony_ci		const ATTR_RECORD *attr, runlist_element *old_rl)
7378c2ecf20Sopenharmony_ci{
7388c2ecf20Sopenharmony_ci	VCN vcn;		/* Current vcn. */
7398c2ecf20Sopenharmony_ci	LCN lcn;		/* Current lcn. */
7408c2ecf20Sopenharmony_ci	s64 deltaxcn;		/* Change in [vl]cn. */
7418c2ecf20Sopenharmony_ci	runlist_element *rl;	/* The output runlist. */
7428c2ecf20Sopenharmony_ci	u8 *buf;		/* Current position in mapping pairs array. */
7438c2ecf20Sopenharmony_ci	u8 *attr_end;		/* End of attribute. */
7448c2ecf20Sopenharmony_ci	int rlsize;		/* Size of runlist buffer. */
7458c2ecf20Sopenharmony_ci	u16 rlpos;		/* Current runlist position in units of
7468c2ecf20Sopenharmony_ci				   runlist_elements. */
7478c2ecf20Sopenharmony_ci	u8 b;			/* Current byte offset in buf. */
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci#ifdef DEBUG
7508c2ecf20Sopenharmony_ci	/* Make sure attr exists and is non-resident. */
7518c2ecf20Sopenharmony_ci	if (!attr || !attr->non_resident || sle64_to_cpu(
7528c2ecf20Sopenharmony_ci			attr->data.non_resident.lowest_vcn) < (VCN)0) {
7538c2ecf20Sopenharmony_ci		ntfs_error(vol->sb, "Invalid arguments.");
7548c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci#endif
7578c2ecf20Sopenharmony_ci	/* Start at vcn = lowest_vcn and lcn 0. */
7588c2ecf20Sopenharmony_ci	vcn = sle64_to_cpu(attr->data.non_resident.lowest_vcn);
7598c2ecf20Sopenharmony_ci	lcn = 0;
7608c2ecf20Sopenharmony_ci	/* Get start of the mapping pairs array. */
7618c2ecf20Sopenharmony_ci	buf = (u8*)attr + le16_to_cpu(
7628c2ecf20Sopenharmony_ci			attr->data.non_resident.mapping_pairs_offset);
7638c2ecf20Sopenharmony_ci	attr_end = (u8*)attr + le32_to_cpu(attr->length);
7648c2ecf20Sopenharmony_ci	if (unlikely(buf < (u8*)attr || buf > attr_end)) {
7658c2ecf20Sopenharmony_ci		ntfs_error(vol->sb, "Corrupt attribute.");
7668c2ecf20Sopenharmony_ci		return ERR_PTR(-EIO);
7678c2ecf20Sopenharmony_ci	}
7688c2ecf20Sopenharmony_ci	/* If the mapping pairs array is valid but empty, nothing to do. */
7698c2ecf20Sopenharmony_ci	if (!vcn && !*buf)
7708c2ecf20Sopenharmony_ci		return old_rl;
7718c2ecf20Sopenharmony_ci	/* Current position in runlist array. */
7728c2ecf20Sopenharmony_ci	rlpos = 0;
7738c2ecf20Sopenharmony_ci	/* Allocate first page and set current runlist size to one page. */
7748c2ecf20Sopenharmony_ci	rl = ntfs_malloc_nofs(rlsize = PAGE_SIZE);
7758c2ecf20Sopenharmony_ci	if (unlikely(!rl))
7768c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
7778c2ecf20Sopenharmony_ci	/* Insert unmapped starting element if necessary. */
7788c2ecf20Sopenharmony_ci	if (vcn) {
7798c2ecf20Sopenharmony_ci		rl->vcn = 0;
7808c2ecf20Sopenharmony_ci		rl->lcn = LCN_RL_NOT_MAPPED;
7818c2ecf20Sopenharmony_ci		rl->length = vcn;
7828c2ecf20Sopenharmony_ci		rlpos++;
7838c2ecf20Sopenharmony_ci	}
7848c2ecf20Sopenharmony_ci	while (buf < attr_end && *buf) {
7858c2ecf20Sopenharmony_ci		/*
7868c2ecf20Sopenharmony_ci		 * Allocate more memory if needed, including space for the
7878c2ecf20Sopenharmony_ci		 * not-mapped and terminator elements. ntfs_malloc_nofs()
7888c2ecf20Sopenharmony_ci		 * operates on whole pages only.
7898c2ecf20Sopenharmony_ci		 */
7908c2ecf20Sopenharmony_ci		if (((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
7918c2ecf20Sopenharmony_ci			runlist_element *rl2;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci			rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
7948c2ecf20Sopenharmony_ci			if (unlikely(!rl2)) {
7958c2ecf20Sopenharmony_ci				ntfs_free(rl);
7968c2ecf20Sopenharmony_ci				return ERR_PTR(-ENOMEM);
7978c2ecf20Sopenharmony_ci			}
7988c2ecf20Sopenharmony_ci			memcpy(rl2, rl, rlsize);
7998c2ecf20Sopenharmony_ci			ntfs_free(rl);
8008c2ecf20Sopenharmony_ci			rl = rl2;
8018c2ecf20Sopenharmony_ci			rlsize += PAGE_SIZE;
8028c2ecf20Sopenharmony_ci		}
8038c2ecf20Sopenharmony_ci		/* Enter the current vcn into the current runlist element. */
8048c2ecf20Sopenharmony_ci		rl[rlpos].vcn = vcn;
8058c2ecf20Sopenharmony_ci		/*
8068c2ecf20Sopenharmony_ci		 * Get the change in vcn, i.e. the run length in clusters.
8078c2ecf20Sopenharmony_ci		 * Doing it this way ensures that we signextend negative values.
8088c2ecf20Sopenharmony_ci		 * A negative run length doesn't make any sense, but hey, I
8098c2ecf20Sopenharmony_ci		 * didn't make up the NTFS specs and Windows NT4 treats the run
8108c2ecf20Sopenharmony_ci		 * length as a signed value so that's how it is...
8118c2ecf20Sopenharmony_ci		 */
8128c2ecf20Sopenharmony_ci		b = *buf & 0xf;
8138c2ecf20Sopenharmony_ci		if (b) {
8148c2ecf20Sopenharmony_ci			if (unlikely(buf + b > attr_end))
8158c2ecf20Sopenharmony_ci				goto io_error;
8168c2ecf20Sopenharmony_ci			for (deltaxcn = (s8)buf[b--]; b; b--)
8178c2ecf20Sopenharmony_ci				deltaxcn = (deltaxcn << 8) + buf[b];
8188c2ecf20Sopenharmony_ci		} else { /* The length entry is compulsory. */
8198c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Missing length entry in mapping "
8208c2ecf20Sopenharmony_ci					"pairs array.");
8218c2ecf20Sopenharmony_ci			deltaxcn = (s64)-1;
8228c2ecf20Sopenharmony_ci		}
8238c2ecf20Sopenharmony_ci		/*
8248c2ecf20Sopenharmony_ci		 * Assume a negative length to indicate data corruption and
8258c2ecf20Sopenharmony_ci		 * hence clean-up and return NULL.
8268c2ecf20Sopenharmony_ci		 */
8278c2ecf20Sopenharmony_ci		if (unlikely(deltaxcn < 0)) {
8288c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Invalid length in mapping pairs "
8298c2ecf20Sopenharmony_ci					"array.");
8308c2ecf20Sopenharmony_ci			goto err_out;
8318c2ecf20Sopenharmony_ci		}
8328c2ecf20Sopenharmony_ci		/*
8338c2ecf20Sopenharmony_ci		 * Enter the current run length into the current runlist
8348c2ecf20Sopenharmony_ci		 * element.
8358c2ecf20Sopenharmony_ci		 */
8368c2ecf20Sopenharmony_ci		rl[rlpos].length = deltaxcn;
8378c2ecf20Sopenharmony_ci		/* Increment the current vcn by the current run length. */
8388c2ecf20Sopenharmony_ci		vcn += deltaxcn;
8398c2ecf20Sopenharmony_ci		/*
8408c2ecf20Sopenharmony_ci		 * There might be no lcn change at all, as is the case for
8418c2ecf20Sopenharmony_ci		 * sparse clusters on NTFS 3.0+, in which case we set the lcn
8428c2ecf20Sopenharmony_ci		 * to LCN_HOLE.
8438c2ecf20Sopenharmony_ci		 */
8448c2ecf20Sopenharmony_ci		if (!(*buf & 0xf0))
8458c2ecf20Sopenharmony_ci			rl[rlpos].lcn = LCN_HOLE;
8468c2ecf20Sopenharmony_ci		else {
8478c2ecf20Sopenharmony_ci			/* Get the lcn change which really can be negative. */
8488c2ecf20Sopenharmony_ci			u8 b2 = *buf & 0xf;
8498c2ecf20Sopenharmony_ci			b = b2 + ((*buf >> 4) & 0xf);
8508c2ecf20Sopenharmony_ci			if (buf + b > attr_end)
8518c2ecf20Sopenharmony_ci				goto io_error;
8528c2ecf20Sopenharmony_ci			for (deltaxcn = (s8)buf[b--]; b > b2; b--)
8538c2ecf20Sopenharmony_ci				deltaxcn = (deltaxcn << 8) + buf[b];
8548c2ecf20Sopenharmony_ci			/* Change the current lcn to its new value. */
8558c2ecf20Sopenharmony_ci			lcn += deltaxcn;
8568c2ecf20Sopenharmony_ci#ifdef DEBUG
8578c2ecf20Sopenharmony_ci			/*
8588c2ecf20Sopenharmony_ci			 * On NTFS 1.2-, apparently can have lcn == -1 to
8598c2ecf20Sopenharmony_ci			 * indicate a hole. But we haven't verified ourselves
8608c2ecf20Sopenharmony_ci			 * whether it is really the lcn or the deltaxcn that is
8618c2ecf20Sopenharmony_ci			 * -1. So if either is found give us a message so we
8628c2ecf20Sopenharmony_ci			 * can investigate it further!
8638c2ecf20Sopenharmony_ci			 */
8648c2ecf20Sopenharmony_ci			if (vol->major_ver < 3) {
8658c2ecf20Sopenharmony_ci				if (unlikely(deltaxcn == (LCN)-1))
8668c2ecf20Sopenharmony_ci					ntfs_error(vol->sb, "lcn delta == -1");
8678c2ecf20Sopenharmony_ci				if (unlikely(lcn == (LCN)-1))
8688c2ecf20Sopenharmony_ci					ntfs_error(vol->sb, "lcn == -1");
8698c2ecf20Sopenharmony_ci			}
8708c2ecf20Sopenharmony_ci#endif
8718c2ecf20Sopenharmony_ci			/* Check lcn is not below -1. */
8728c2ecf20Sopenharmony_ci			if (unlikely(lcn < (LCN)-1)) {
8738c2ecf20Sopenharmony_ci				ntfs_error(vol->sb, "Invalid LCN < -1 in "
8748c2ecf20Sopenharmony_ci						"mapping pairs array.");
8758c2ecf20Sopenharmony_ci				goto err_out;
8768c2ecf20Sopenharmony_ci			}
8778c2ecf20Sopenharmony_ci			/* Enter the current lcn into the runlist element. */
8788c2ecf20Sopenharmony_ci			rl[rlpos].lcn = lcn;
8798c2ecf20Sopenharmony_ci		}
8808c2ecf20Sopenharmony_ci		/* Get to the next runlist element. */
8818c2ecf20Sopenharmony_ci		rlpos++;
8828c2ecf20Sopenharmony_ci		/* Increment the buffer position to the next mapping pair. */
8838c2ecf20Sopenharmony_ci		buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
8848c2ecf20Sopenharmony_ci	}
8858c2ecf20Sopenharmony_ci	if (unlikely(buf >= attr_end))
8868c2ecf20Sopenharmony_ci		goto io_error;
8878c2ecf20Sopenharmony_ci	/*
8888c2ecf20Sopenharmony_ci	 * If there is a highest_vcn specified, it must be equal to the final
8898c2ecf20Sopenharmony_ci	 * vcn in the runlist - 1, or something has gone badly wrong.
8908c2ecf20Sopenharmony_ci	 */
8918c2ecf20Sopenharmony_ci	deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn);
8928c2ecf20Sopenharmony_ci	if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) {
8938c2ecf20Sopenharmony_cimpa_err:
8948c2ecf20Sopenharmony_ci		ntfs_error(vol->sb, "Corrupt mapping pairs array in "
8958c2ecf20Sopenharmony_ci				"non-resident attribute.");
8968c2ecf20Sopenharmony_ci		goto err_out;
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci	/* Setup not mapped runlist element if this is the base extent. */
8998c2ecf20Sopenharmony_ci	if (!attr->data.non_resident.lowest_vcn) {
9008c2ecf20Sopenharmony_ci		VCN max_cluster;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci		max_cluster = ((sle64_to_cpu(
9038c2ecf20Sopenharmony_ci				attr->data.non_resident.allocated_size) +
9048c2ecf20Sopenharmony_ci				vol->cluster_size - 1) >>
9058c2ecf20Sopenharmony_ci				vol->cluster_size_bits) - 1;
9068c2ecf20Sopenharmony_ci		/*
9078c2ecf20Sopenharmony_ci		 * A highest_vcn of zero means this is a single extent
9088c2ecf20Sopenharmony_ci		 * attribute so simply terminate the runlist with LCN_ENOENT).
9098c2ecf20Sopenharmony_ci		 */
9108c2ecf20Sopenharmony_ci		if (deltaxcn) {
9118c2ecf20Sopenharmony_ci			/*
9128c2ecf20Sopenharmony_ci			 * If there is a difference between the highest_vcn and
9138c2ecf20Sopenharmony_ci			 * the highest cluster, the runlist is either corrupt
9148c2ecf20Sopenharmony_ci			 * or, more likely, there are more extents following
9158c2ecf20Sopenharmony_ci			 * this one.
9168c2ecf20Sopenharmony_ci			 */
9178c2ecf20Sopenharmony_ci			if (deltaxcn < max_cluster) {
9188c2ecf20Sopenharmony_ci				ntfs_debug("More extents to follow; deltaxcn "
9198c2ecf20Sopenharmony_ci						"= 0x%llx, max_cluster = "
9208c2ecf20Sopenharmony_ci						"0x%llx",
9218c2ecf20Sopenharmony_ci						(unsigned long long)deltaxcn,
9228c2ecf20Sopenharmony_ci						(unsigned long long)
9238c2ecf20Sopenharmony_ci						max_cluster);
9248c2ecf20Sopenharmony_ci				rl[rlpos].vcn = vcn;
9258c2ecf20Sopenharmony_ci				vcn += rl[rlpos].length = max_cluster -
9268c2ecf20Sopenharmony_ci						deltaxcn;
9278c2ecf20Sopenharmony_ci				rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
9288c2ecf20Sopenharmony_ci				rlpos++;
9298c2ecf20Sopenharmony_ci			} else if (unlikely(deltaxcn > max_cluster)) {
9308c2ecf20Sopenharmony_ci				ntfs_error(vol->sb, "Corrupt attribute.  "
9318c2ecf20Sopenharmony_ci						"deltaxcn = 0x%llx, "
9328c2ecf20Sopenharmony_ci						"max_cluster = 0x%llx",
9338c2ecf20Sopenharmony_ci						(unsigned long long)deltaxcn,
9348c2ecf20Sopenharmony_ci						(unsigned long long)
9358c2ecf20Sopenharmony_ci						max_cluster);
9368c2ecf20Sopenharmony_ci				goto mpa_err;
9378c2ecf20Sopenharmony_ci			}
9388c2ecf20Sopenharmony_ci		}
9398c2ecf20Sopenharmony_ci		rl[rlpos].lcn = LCN_ENOENT;
9408c2ecf20Sopenharmony_ci	} else /* Not the base extent. There may be more extents to follow. */
9418c2ecf20Sopenharmony_ci		rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	/* Setup terminating runlist element. */
9448c2ecf20Sopenharmony_ci	rl[rlpos].vcn = vcn;
9458c2ecf20Sopenharmony_ci	rl[rlpos].length = (s64)0;
9468c2ecf20Sopenharmony_ci	/* If no existing runlist was specified, we are done. */
9478c2ecf20Sopenharmony_ci	if (!old_rl) {
9488c2ecf20Sopenharmony_ci		ntfs_debug("Mapping pairs array successfully decompressed:");
9498c2ecf20Sopenharmony_ci		ntfs_debug_dump_runlist(rl);
9508c2ecf20Sopenharmony_ci		return rl;
9518c2ecf20Sopenharmony_ci	}
9528c2ecf20Sopenharmony_ci	/* Now combine the new and old runlists checking for overlaps. */
9538c2ecf20Sopenharmony_ci	old_rl = ntfs_runlists_merge(old_rl, rl);
9548c2ecf20Sopenharmony_ci	if (!IS_ERR(old_rl))
9558c2ecf20Sopenharmony_ci		return old_rl;
9568c2ecf20Sopenharmony_ci	ntfs_free(rl);
9578c2ecf20Sopenharmony_ci	ntfs_error(vol->sb, "Failed to merge runlists.");
9588c2ecf20Sopenharmony_ci	return old_rl;
9598c2ecf20Sopenharmony_ciio_error:
9608c2ecf20Sopenharmony_ci	ntfs_error(vol->sb, "Corrupt attribute.");
9618c2ecf20Sopenharmony_cierr_out:
9628c2ecf20Sopenharmony_ci	ntfs_free(rl);
9638c2ecf20Sopenharmony_ci	return ERR_PTR(-EIO);
9648c2ecf20Sopenharmony_ci}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci/**
9678c2ecf20Sopenharmony_ci * ntfs_rl_vcn_to_lcn - convert a vcn into a lcn given a runlist
9688c2ecf20Sopenharmony_ci * @rl:		runlist to use for conversion
9698c2ecf20Sopenharmony_ci * @vcn:	vcn to convert
9708c2ecf20Sopenharmony_ci *
9718c2ecf20Sopenharmony_ci * Convert the virtual cluster number @vcn of an attribute into a logical
9728c2ecf20Sopenharmony_ci * cluster number (lcn) of a device using the runlist @rl to map vcns to their
9738c2ecf20Sopenharmony_ci * corresponding lcns.
9748c2ecf20Sopenharmony_ci *
9758c2ecf20Sopenharmony_ci * It is up to the caller to serialize access to the runlist @rl.
9768c2ecf20Sopenharmony_ci *
9778c2ecf20Sopenharmony_ci * Since lcns must be >= 0, we use negative return codes with special meaning:
9788c2ecf20Sopenharmony_ci *
9798c2ecf20Sopenharmony_ci * Return code		Meaning / Description
9808c2ecf20Sopenharmony_ci * ==================================================
9818c2ecf20Sopenharmony_ci *  LCN_HOLE		Hole / not allocated on disk.
9828c2ecf20Sopenharmony_ci *  LCN_RL_NOT_MAPPED	This is part of the runlist which has not been
9838c2ecf20Sopenharmony_ci *			inserted into the runlist yet.
9848c2ecf20Sopenharmony_ci *  LCN_ENOENT		There is no such vcn in the attribute.
9858c2ecf20Sopenharmony_ci *
9868c2ecf20Sopenharmony_ci * Locking: - The caller must have locked the runlist (for reading or writing).
9878c2ecf20Sopenharmony_ci *	    - This function does not touch the lock, nor does it modify the
9888c2ecf20Sopenharmony_ci *	      runlist.
9898c2ecf20Sopenharmony_ci */
9908c2ecf20Sopenharmony_ciLCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
9918c2ecf20Sopenharmony_ci{
9928c2ecf20Sopenharmony_ci	int i;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	BUG_ON(vcn < 0);
9958c2ecf20Sopenharmony_ci	/*
9968c2ecf20Sopenharmony_ci	 * If rl is NULL, assume that we have found an unmapped runlist. The
9978c2ecf20Sopenharmony_ci	 * caller can then attempt to map it and fail appropriately if
9988c2ecf20Sopenharmony_ci	 * necessary.
9998c2ecf20Sopenharmony_ci	 */
10008c2ecf20Sopenharmony_ci	if (unlikely(!rl))
10018c2ecf20Sopenharmony_ci		return LCN_RL_NOT_MAPPED;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	/* Catch out of lower bounds vcn. */
10048c2ecf20Sopenharmony_ci	if (unlikely(vcn < rl[0].vcn))
10058c2ecf20Sopenharmony_ci		return LCN_ENOENT;
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	for (i = 0; likely(rl[i].length); i++) {
10088c2ecf20Sopenharmony_ci		if (unlikely(vcn < rl[i+1].vcn)) {
10098c2ecf20Sopenharmony_ci			if (likely(rl[i].lcn >= (LCN)0))
10108c2ecf20Sopenharmony_ci				return rl[i].lcn + (vcn - rl[i].vcn);
10118c2ecf20Sopenharmony_ci			return rl[i].lcn;
10128c2ecf20Sopenharmony_ci		}
10138c2ecf20Sopenharmony_ci	}
10148c2ecf20Sopenharmony_ci	/*
10158c2ecf20Sopenharmony_ci	 * The terminator element is setup to the correct value, i.e. one of
10168c2ecf20Sopenharmony_ci	 * LCN_HOLE, LCN_RL_NOT_MAPPED, or LCN_ENOENT.
10178c2ecf20Sopenharmony_ci	 */
10188c2ecf20Sopenharmony_ci	if (likely(rl[i].lcn < (LCN)0))
10198c2ecf20Sopenharmony_ci		return rl[i].lcn;
10208c2ecf20Sopenharmony_ci	/* Just in case... We could replace this with BUG() some day. */
10218c2ecf20Sopenharmony_ci	return LCN_ENOENT;
10228c2ecf20Sopenharmony_ci}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci#ifdef NTFS_RW
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci/**
10278c2ecf20Sopenharmony_ci * ntfs_rl_find_vcn_nolock - find a vcn in a runlist
10288c2ecf20Sopenharmony_ci * @rl:		runlist to search
10298c2ecf20Sopenharmony_ci * @vcn:	vcn to find
10308c2ecf20Sopenharmony_ci *
10318c2ecf20Sopenharmony_ci * Find the virtual cluster number @vcn in the runlist @rl and return the
10328c2ecf20Sopenharmony_ci * address of the runlist element containing the @vcn on success.
10338c2ecf20Sopenharmony_ci *
10348c2ecf20Sopenharmony_ci * Return NULL if @rl is NULL or @vcn is in an unmapped part/out of bounds of
10358c2ecf20Sopenharmony_ci * the runlist.
10368c2ecf20Sopenharmony_ci *
10378c2ecf20Sopenharmony_ci * Locking: The runlist must be locked on entry.
10388c2ecf20Sopenharmony_ci */
10398c2ecf20Sopenharmony_cirunlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, const VCN vcn)
10408c2ecf20Sopenharmony_ci{
10418c2ecf20Sopenharmony_ci	BUG_ON(vcn < 0);
10428c2ecf20Sopenharmony_ci	if (unlikely(!rl || vcn < rl[0].vcn))
10438c2ecf20Sopenharmony_ci		return NULL;
10448c2ecf20Sopenharmony_ci	while (likely(rl->length)) {
10458c2ecf20Sopenharmony_ci		if (unlikely(vcn < rl[1].vcn)) {
10468c2ecf20Sopenharmony_ci			if (likely(rl->lcn >= LCN_HOLE))
10478c2ecf20Sopenharmony_ci				return rl;
10488c2ecf20Sopenharmony_ci			return NULL;
10498c2ecf20Sopenharmony_ci		}
10508c2ecf20Sopenharmony_ci		rl++;
10518c2ecf20Sopenharmony_ci	}
10528c2ecf20Sopenharmony_ci	if (likely(rl->lcn == LCN_ENOENT))
10538c2ecf20Sopenharmony_ci		return rl;
10548c2ecf20Sopenharmony_ci	return NULL;
10558c2ecf20Sopenharmony_ci}
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci/**
10588c2ecf20Sopenharmony_ci * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number
10598c2ecf20Sopenharmony_ci * @n:		number for which to get the number of bytes for
10608c2ecf20Sopenharmony_ci *
10618c2ecf20Sopenharmony_ci * Return the number of bytes required to store @n unambiguously as
10628c2ecf20Sopenharmony_ci * a signed number.
10638c2ecf20Sopenharmony_ci *
10648c2ecf20Sopenharmony_ci * This is used in the context of the mapping pairs array to determine how
10658c2ecf20Sopenharmony_ci * many bytes will be needed in the array to store a given logical cluster
10668c2ecf20Sopenharmony_ci * number (lcn) or a specific run length.
10678c2ecf20Sopenharmony_ci *
10688c2ecf20Sopenharmony_ci * Return the number of bytes written.  This function cannot fail.
10698c2ecf20Sopenharmony_ci */
10708c2ecf20Sopenharmony_cistatic inline int ntfs_get_nr_significant_bytes(const s64 n)
10718c2ecf20Sopenharmony_ci{
10728c2ecf20Sopenharmony_ci	s64 l = n;
10738c2ecf20Sopenharmony_ci	int i;
10748c2ecf20Sopenharmony_ci	s8 j;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	i = 0;
10778c2ecf20Sopenharmony_ci	do {
10788c2ecf20Sopenharmony_ci		l >>= 8;
10798c2ecf20Sopenharmony_ci		i++;
10808c2ecf20Sopenharmony_ci	} while (l != 0 && l != -1);
10818c2ecf20Sopenharmony_ci	j = (n >> 8 * (i - 1)) & 0xff;
10828c2ecf20Sopenharmony_ci	/* If the sign bit is wrong, we need an extra byte. */
10838c2ecf20Sopenharmony_ci	if ((n < 0 && j >= 0) || (n > 0 && j < 0))
10848c2ecf20Sopenharmony_ci		i++;
10858c2ecf20Sopenharmony_ci	return i;
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci/**
10898c2ecf20Sopenharmony_ci * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array
10908c2ecf20Sopenharmony_ci * @vol:	ntfs volume (needed for the ntfs version)
10918c2ecf20Sopenharmony_ci * @rl:		locked runlist to determine the size of the mapping pairs of
10928c2ecf20Sopenharmony_ci * @first_vcn:	first vcn which to include in the mapping pairs array
10938c2ecf20Sopenharmony_ci * @last_vcn:	last vcn which to include in the mapping pairs array
10948c2ecf20Sopenharmony_ci *
10958c2ecf20Sopenharmony_ci * Walk the locked runlist @rl and calculate the size in bytes of the mapping
10968c2ecf20Sopenharmony_ci * pairs array corresponding to the runlist @rl, starting at vcn @first_vcn and
10978c2ecf20Sopenharmony_ci * finishing with vcn @last_vcn.
10988c2ecf20Sopenharmony_ci *
10998c2ecf20Sopenharmony_ci * A @last_vcn of -1 means end of runlist and in that case the size of the
11008c2ecf20Sopenharmony_ci * mapping pairs array corresponding to the runlist starting at vcn @first_vcn
11018c2ecf20Sopenharmony_ci * and finishing at the end of the runlist is determined.
11028c2ecf20Sopenharmony_ci *
11038c2ecf20Sopenharmony_ci * This for example allows us to allocate a buffer of the right size when
11048c2ecf20Sopenharmony_ci * building the mapping pairs array.
11058c2ecf20Sopenharmony_ci *
11068c2ecf20Sopenharmony_ci * If @rl is NULL, just return 1 (for the single terminator byte).
11078c2ecf20Sopenharmony_ci *
11088c2ecf20Sopenharmony_ci * Return the calculated size in bytes on success.  On error, return -errno.
11098c2ecf20Sopenharmony_ci * The following error codes are defined:
11108c2ecf20Sopenharmony_ci *	-EINVAL	- Run list contains unmapped elements.  Make sure to only pass
11118c2ecf20Sopenharmony_ci *		  fully mapped runlists to this function.
11128c2ecf20Sopenharmony_ci *	-EIO	- The runlist is corrupt.
11138c2ecf20Sopenharmony_ci *
11148c2ecf20Sopenharmony_ci * Locking: @rl must be locked on entry (either for reading or writing), it
11158c2ecf20Sopenharmony_ci *	    remains locked throughout, and is left locked upon return.
11168c2ecf20Sopenharmony_ci */
11178c2ecf20Sopenharmony_ciint ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
11188c2ecf20Sopenharmony_ci		const runlist_element *rl, const VCN first_vcn,
11198c2ecf20Sopenharmony_ci		const VCN last_vcn)
11208c2ecf20Sopenharmony_ci{
11218c2ecf20Sopenharmony_ci	LCN prev_lcn;
11228c2ecf20Sopenharmony_ci	int rls;
11238c2ecf20Sopenharmony_ci	bool the_end = false;
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	BUG_ON(first_vcn < 0);
11268c2ecf20Sopenharmony_ci	BUG_ON(last_vcn < -1);
11278c2ecf20Sopenharmony_ci	BUG_ON(last_vcn >= 0 && first_vcn > last_vcn);
11288c2ecf20Sopenharmony_ci	if (!rl) {
11298c2ecf20Sopenharmony_ci		BUG_ON(first_vcn);
11308c2ecf20Sopenharmony_ci		BUG_ON(last_vcn > 0);
11318c2ecf20Sopenharmony_ci		return 1;
11328c2ecf20Sopenharmony_ci	}
11338c2ecf20Sopenharmony_ci	/* Skip to runlist element containing @first_vcn. */
11348c2ecf20Sopenharmony_ci	while (rl->length && first_vcn >= rl[1].vcn)
11358c2ecf20Sopenharmony_ci		rl++;
11368c2ecf20Sopenharmony_ci	if (unlikely((!rl->length && first_vcn > rl->vcn) ||
11378c2ecf20Sopenharmony_ci			first_vcn < rl->vcn))
11388c2ecf20Sopenharmony_ci		return -EINVAL;
11398c2ecf20Sopenharmony_ci	prev_lcn = 0;
11408c2ecf20Sopenharmony_ci	/* Always need the termining zero byte. */
11418c2ecf20Sopenharmony_ci	rls = 1;
11428c2ecf20Sopenharmony_ci	/* Do the first partial run if present. */
11438c2ecf20Sopenharmony_ci	if (first_vcn > rl->vcn) {
11448c2ecf20Sopenharmony_ci		s64 delta, length = rl->length;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci		/* We know rl->length != 0 already. */
11478c2ecf20Sopenharmony_ci		if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
11488c2ecf20Sopenharmony_ci			goto err_out;
11498c2ecf20Sopenharmony_ci		/*
11508c2ecf20Sopenharmony_ci		 * If @stop_vcn is given and finishes inside this run, cap the
11518c2ecf20Sopenharmony_ci		 * run length.
11528c2ecf20Sopenharmony_ci		 */
11538c2ecf20Sopenharmony_ci		if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
11548c2ecf20Sopenharmony_ci			s64 s1 = last_vcn + 1;
11558c2ecf20Sopenharmony_ci			if (unlikely(rl[1].vcn > s1))
11568c2ecf20Sopenharmony_ci				length = s1 - rl->vcn;
11578c2ecf20Sopenharmony_ci			the_end = true;
11588c2ecf20Sopenharmony_ci		}
11598c2ecf20Sopenharmony_ci		delta = first_vcn - rl->vcn;
11608c2ecf20Sopenharmony_ci		/* Header byte + length. */
11618c2ecf20Sopenharmony_ci		rls += 1 + ntfs_get_nr_significant_bytes(length - delta);
11628c2ecf20Sopenharmony_ci		/*
11638c2ecf20Sopenharmony_ci		 * If the logical cluster number (lcn) denotes a hole and we
11648c2ecf20Sopenharmony_ci		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
11658c2ecf20Sopenharmony_ci		 * zero space.  On earlier NTFS versions we just store the lcn.
11668c2ecf20Sopenharmony_ci		 * Note: this assumes that on NTFS 1.2-, holes are stored with
11678c2ecf20Sopenharmony_ci		 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
11688c2ecf20Sopenharmony_ci		 */
11698c2ecf20Sopenharmony_ci		if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
11708c2ecf20Sopenharmony_ci			prev_lcn = rl->lcn;
11718c2ecf20Sopenharmony_ci			if (likely(rl->lcn >= 0))
11728c2ecf20Sopenharmony_ci				prev_lcn += delta;
11738c2ecf20Sopenharmony_ci			/* Change in lcn. */
11748c2ecf20Sopenharmony_ci			rls += ntfs_get_nr_significant_bytes(prev_lcn);
11758c2ecf20Sopenharmony_ci		}
11768c2ecf20Sopenharmony_ci		/* Go to next runlist element. */
11778c2ecf20Sopenharmony_ci		rl++;
11788c2ecf20Sopenharmony_ci	}
11798c2ecf20Sopenharmony_ci	/* Do the full runs. */
11808c2ecf20Sopenharmony_ci	for (; rl->length && !the_end; rl++) {
11818c2ecf20Sopenharmony_ci		s64 length = rl->length;
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci		if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
11848c2ecf20Sopenharmony_ci			goto err_out;
11858c2ecf20Sopenharmony_ci		/*
11868c2ecf20Sopenharmony_ci		 * If @stop_vcn is given and finishes inside this run, cap the
11878c2ecf20Sopenharmony_ci		 * run length.
11888c2ecf20Sopenharmony_ci		 */
11898c2ecf20Sopenharmony_ci		if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
11908c2ecf20Sopenharmony_ci			s64 s1 = last_vcn + 1;
11918c2ecf20Sopenharmony_ci			if (unlikely(rl[1].vcn > s1))
11928c2ecf20Sopenharmony_ci				length = s1 - rl->vcn;
11938c2ecf20Sopenharmony_ci			the_end = true;
11948c2ecf20Sopenharmony_ci		}
11958c2ecf20Sopenharmony_ci		/* Header byte + length. */
11968c2ecf20Sopenharmony_ci		rls += 1 + ntfs_get_nr_significant_bytes(length);
11978c2ecf20Sopenharmony_ci		/*
11988c2ecf20Sopenharmony_ci		 * If the logical cluster number (lcn) denotes a hole and we
11998c2ecf20Sopenharmony_ci		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
12008c2ecf20Sopenharmony_ci		 * zero space.  On earlier NTFS versions we just store the lcn.
12018c2ecf20Sopenharmony_ci		 * Note: this assumes that on NTFS 1.2-, holes are stored with
12028c2ecf20Sopenharmony_ci		 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
12038c2ecf20Sopenharmony_ci		 */
12048c2ecf20Sopenharmony_ci		if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
12058c2ecf20Sopenharmony_ci			/* Change in lcn. */
12068c2ecf20Sopenharmony_ci			rls += ntfs_get_nr_significant_bytes(rl->lcn -
12078c2ecf20Sopenharmony_ci					prev_lcn);
12088c2ecf20Sopenharmony_ci			prev_lcn = rl->lcn;
12098c2ecf20Sopenharmony_ci		}
12108c2ecf20Sopenharmony_ci	}
12118c2ecf20Sopenharmony_ci	return rls;
12128c2ecf20Sopenharmony_cierr_out:
12138c2ecf20Sopenharmony_ci	if (rl->lcn == LCN_RL_NOT_MAPPED)
12148c2ecf20Sopenharmony_ci		rls = -EINVAL;
12158c2ecf20Sopenharmony_ci	else
12168c2ecf20Sopenharmony_ci		rls = -EIO;
12178c2ecf20Sopenharmony_ci	return rls;
12188c2ecf20Sopenharmony_ci}
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci/**
12218c2ecf20Sopenharmony_ci * ntfs_write_significant_bytes - write the significant bytes of a number
12228c2ecf20Sopenharmony_ci * @dst:	destination buffer to write to
12238c2ecf20Sopenharmony_ci * @dst_max:	pointer to last byte of destination buffer for bounds checking
12248c2ecf20Sopenharmony_ci * @n:		number whose significant bytes to write
12258c2ecf20Sopenharmony_ci *
12268c2ecf20Sopenharmony_ci * Store in @dst, the minimum bytes of the number @n which are required to
12278c2ecf20Sopenharmony_ci * identify @n unambiguously as a signed number, taking care not to exceed
12288c2ecf20Sopenharmony_ci * @dest_max, the maximum position within @dst to which we are allowed to
12298c2ecf20Sopenharmony_ci * write.
12308c2ecf20Sopenharmony_ci *
12318c2ecf20Sopenharmony_ci * This is used when building the mapping pairs array of a runlist to compress
12328c2ecf20Sopenharmony_ci * a given logical cluster number (lcn) or a specific run length to the minimum
12338c2ecf20Sopenharmony_ci * size possible.
12348c2ecf20Sopenharmony_ci *
12358c2ecf20Sopenharmony_ci * Return the number of bytes written on success.  On error, i.e. the
12368c2ecf20Sopenharmony_ci * destination buffer @dst is too small, return -ENOSPC.
12378c2ecf20Sopenharmony_ci */
12388c2ecf20Sopenharmony_cistatic inline int ntfs_write_significant_bytes(s8 *dst, const s8 *dst_max,
12398c2ecf20Sopenharmony_ci		const s64 n)
12408c2ecf20Sopenharmony_ci{
12418c2ecf20Sopenharmony_ci	s64 l = n;
12428c2ecf20Sopenharmony_ci	int i;
12438c2ecf20Sopenharmony_ci	s8 j;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	i = 0;
12468c2ecf20Sopenharmony_ci	do {
12478c2ecf20Sopenharmony_ci		if (unlikely(dst > dst_max))
12488c2ecf20Sopenharmony_ci			goto err_out;
12498c2ecf20Sopenharmony_ci		*dst++ = l & 0xffll;
12508c2ecf20Sopenharmony_ci		l >>= 8;
12518c2ecf20Sopenharmony_ci		i++;
12528c2ecf20Sopenharmony_ci	} while (l != 0 && l != -1);
12538c2ecf20Sopenharmony_ci	j = (n >> 8 * (i - 1)) & 0xff;
12548c2ecf20Sopenharmony_ci	/* If the sign bit is wrong, we need an extra byte. */
12558c2ecf20Sopenharmony_ci	if (n < 0 && j >= 0) {
12568c2ecf20Sopenharmony_ci		if (unlikely(dst > dst_max))
12578c2ecf20Sopenharmony_ci			goto err_out;
12588c2ecf20Sopenharmony_ci		i++;
12598c2ecf20Sopenharmony_ci		*dst = (s8)-1;
12608c2ecf20Sopenharmony_ci	} else if (n > 0 && j < 0) {
12618c2ecf20Sopenharmony_ci		if (unlikely(dst > dst_max))
12628c2ecf20Sopenharmony_ci			goto err_out;
12638c2ecf20Sopenharmony_ci		i++;
12648c2ecf20Sopenharmony_ci		*dst = (s8)0;
12658c2ecf20Sopenharmony_ci	}
12668c2ecf20Sopenharmony_ci	return i;
12678c2ecf20Sopenharmony_cierr_out:
12688c2ecf20Sopenharmony_ci	return -ENOSPC;
12698c2ecf20Sopenharmony_ci}
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci/**
12728c2ecf20Sopenharmony_ci * ntfs_mapping_pairs_build - build the mapping pairs array from a runlist
12738c2ecf20Sopenharmony_ci * @vol:	ntfs volume (needed for the ntfs version)
12748c2ecf20Sopenharmony_ci * @dst:	destination buffer to which to write the mapping pairs array
12758c2ecf20Sopenharmony_ci * @dst_len:	size of destination buffer @dst in bytes
12768c2ecf20Sopenharmony_ci * @rl:		locked runlist for which to build the mapping pairs array
12778c2ecf20Sopenharmony_ci * @first_vcn:	first vcn which to include in the mapping pairs array
12788c2ecf20Sopenharmony_ci * @last_vcn:	last vcn which to include in the mapping pairs array
12798c2ecf20Sopenharmony_ci * @stop_vcn:	first vcn outside destination buffer on success or -ENOSPC
12808c2ecf20Sopenharmony_ci *
12818c2ecf20Sopenharmony_ci * Create the mapping pairs array from the locked runlist @rl, starting at vcn
12828c2ecf20Sopenharmony_ci * @first_vcn and finishing with vcn @last_vcn and save the array in @dst.
12838c2ecf20Sopenharmony_ci * @dst_len is the size of @dst in bytes and it should be at least equal to the
12848c2ecf20Sopenharmony_ci * value obtained by calling ntfs_get_size_for_mapping_pairs().
12858c2ecf20Sopenharmony_ci *
12868c2ecf20Sopenharmony_ci * A @last_vcn of -1 means end of runlist and in that case the mapping pairs
12878c2ecf20Sopenharmony_ci * array corresponding to the runlist starting at vcn @first_vcn and finishing
12888c2ecf20Sopenharmony_ci * at the end of the runlist is created.
12898c2ecf20Sopenharmony_ci *
12908c2ecf20Sopenharmony_ci * If @rl is NULL, just write a single terminator byte to @dst.
12918c2ecf20Sopenharmony_ci *
12928c2ecf20Sopenharmony_ci * On success or -ENOSPC error, if @stop_vcn is not NULL, *@stop_vcn is set to
12938c2ecf20Sopenharmony_ci * the first vcn outside the destination buffer.  Note that on error, @dst has
12948c2ecf20Sopenharmony_ci * been filled with all the mapping pairs that will fit, thus it can be treated
12958c2ecf20Sopenharmony_ci * as partial success, in that a new attribute extent needs to be created or
12968c2ecf20Sopenharmony_ci * the next extent has to be used and the mapping pairs build has to be
12978c2ecf20Sopenharmony_ci * continued with @first_vcn set to *@stop_vcn.
12988c2ecf20Sopenharmony_ci *
12998c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error.  The following error codes are
13008c2ecf20Sopenharmony_ci * defined:
13018c2ecf20Sopenharmony_ci *	-EINVAL	- Run list contains unmapped elements.  Make sure to only pass
13028c2ecf20Sopenharmony_ci *		  fully mapped runlists to this function.
13038c2ecf20Sopenharmony_ci *	-EIO	- The runlist is corrupt.
13048c2ecf20Sopenharmony_ci *	-ENOSPC	- The destination buffer is too small.
13058c2ecf20Sopenharmony_ci *
13068c2ecf20Sopenharmony_ci * Locking: @rl must be locked on entry (either for reading or writing), it
13078c2ecf20Sopenharmony_ci *	    remains locked throughout, and is left locked upon return.
13088c2ecf20Sopenharmony_ci */
13098c2ecf20Sopenharmony_ciint ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
13108c2ecf20Sopenharmony_ci		const int dst_len, const runlist_element *rl,
13118c2ecf20Sopenharmony_ci		const VCN first_vcn, const VCN last_vcn, VCN *const stop_vcn)
13128c2ecf20Sopenharmony_ci{
13138c2ecf20Sopenharmony_ci	LCN prev_lcn;
13148c2ecf20Sopenharmony_ci	s8 *dst_max, *dst_next;
13158c2ecf20Sopenharmony_ci	int err = -ENOSPC;
13168c2ecf20Sopenharmony_ci	bool the_end = false;
13178c2ecf20Sopenharmony_ci	s8 len_len, lcn_len;
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	BUG_ON(first_vcn < 0);
13208c2ecf20Sopenharmony_ci	BUG_ON(last_vcn < -1);
13218c2ecf20Sopenharmony_ci	BUG_ON(last_vcn >= 0 && first_vcn > last_vcn);
13228c2ecf20Sopenharmony_ci	BUG_ON(dst_len < 1);
13238c2ecf20Sopenharmony_ci	if (!rl) {
13248c2ecf20Sopenharmony_ci		BUG_ON(first_vcn);
13258c2ecf20Sopenharmony_ci		BUG_ON(last_vcn > 0);
13268c2ecf20Sopenharmony_ci		if (stop_vcn)
13278c2ecf20Sopenharmony_ci			*stop_vcn = 0;
13288c2ecf20Sopenharmony_ci		/* Terminator byte. */
13298c2ecf20Sopenharmony_ci		*dst = 0;
13308c2ecf20Sopenharmony_ci		return 0;
13318c2ecf20Sopenharmony_ci	}
13328c2ecf20Sopenharmony_ci	/* Skip to runlist element containing @first_vcn. */
13338c2ecf20Sopenharmony_ci	while (rl->length && first_vcn >= rl[1].vcn)
13348c2ecf20Sopenharmony_ci		rl++;
13358c2ecf20Sopenharmony_ci	if (unlikely((!rl->length && first_vcn > rl->vcn) ||
13368c2ecf20Sopenharmony_ci			first_vcn < rl->vcn))
13378c2ecf20Sopenharmony_ci		return -EINVAL;
13388c2ecf20Sopenharmony_ci	/*
13398c2ecf20Sopenharmony_ci	 * @dst_max is used for bounds checking in
13408c2ecf20Sopenharmony_ci	 * ntfs_write_significant_bytes().
13418c2ecf20Sopenharmony_ci	 */
13428c2ecf20Sopenharmony_ci	dst_max = dst + dst_len - 1;
13438c2ecf20Sopenharmony_ci	prev_lcn = 0;
13448c2ecf20Sopenharmony_ci	/* Do the first partial run if present. */
13458c2ecf20Sopenharmony_ci	if (first_vcn > rl->vcn) {
13468c2ecf20Sopenharmony_ci		s64 delta, length = rl->length;
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci		/* We know rl->length != 0 already. */
13498c2ecf20Sopenharmony_ci		if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
13508c2ecf20Sopenharmony_ci			goto err_out;
13518c2ecf20Sopenharmony_ci		/*
13528c2ecf20Sopenharmony_ci		 * If @stop_vcn is given and finishes inside this run, cap the
13538c2ecf20Sopenharmony_ci		 * run length.
13548c2ecf20Sopenharmony_ci		 */
13558c2ecf20Sopenharmony_ci		if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
13568c2ecf20Sopenharmony_ci			s64 s1 = last_vcn + 1;
13578c2ecf20Sopenharmony_ci			if (unlikely(rl[1].vcn > s1))
13588c2ecf20Sopenharmony_ci				length = s1 - rl->vcn;
13598c2ecf20Sopenharmony_ci			the_end = true;
13608c2ecf20Sopenharmony_ci		}
13618c2ecf20Sopenharmony_ci		delta = first_vcn - rl->vcn;
13628c2ecf20Sopenharmony_ci		/* Write length. */
13638c2ecf20Sopenharmony_ci		len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
13648c2ecf20Sopenharmony_ci				length - delta);
13658c2ecf20Sopenharmony_ci		if (unlikely(len_len < 0))
13668c2ecf20Sopenharmony_ci			goto size_err;
13678c2ecf20Sopenharmony_ci		/*
13688c2ecf20Sopenharmony_ci		 * If the logical cluster number (lcn) denotes a hole and we
13698c2ecf20Sopenharmony_ci		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
13708c2ecf20Sopenharmony_ci		 * zero space.  On earlier NTFS versions we just write the lcn
13718c2ecf20Sopenharmony_ci		 * change.  FIXME: Do we need to write the lcn change or just
13728c2ecf20Sopenharmony_ci		 * the lcn in that case?  Not sure as I have never seen this
13738c2ecf20Sopenharmony_ci		 * case on NT4. - We assume that we just need to write the lcn
13748c2ecf20Sopenharmony_ci		 * change until someone tells us otherwise... (AIA)
13758c2ecf20Sopenharmony_ci		 */
13768c2ecf20Sopenharmony_ci		if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
13778c2ecf20Sopenharmony_ci			prev_lcn = rl->lcn;
13788c2ecf20Sopenharmony_ci			if (likely(rl->lcn >= 0))
13798c2ecf20Sopenharmony_ci				prev_lcn += delta;
13808c2ecf20Sopenharmony_ci			/* Write change in lcn. */
13818c2ecf20Sopenharmony_ci			lcn_len = ntfs_write_significant_bytes(dst + 1 +
13828c2ecf20Sopenharmony_ci					len_len, dst_max, prev_lcn);
13838c2ecf20Sopenharmony_ci			if (unlikely(lcn_len < 0))
13848c2ecf20Sopenharmony_ci				goto size_err;
13858c2ecf20Sopenharmony_ci		} else
13868c2ecf20Sopenharmony_ci			lcn_len = 0;
13878c2ecf20Sopenharmony_ci		dst_next = dst + len_len + lcn_len + 1;
13888c2ecf20Sopenharmony_ci		if (unlikely(dst_next > dst_max))
13898c2ecf20Sopenharmony_ci			goto size_err;
13908c2ecf20Sopenharmony_ci		/* Update header byte. */
13918c2ecf20Sopenharmony_ci		*dst = lcn_len << 4 | len_len;
13928c2ecf20Sopenharmony_ci		/* Position at next mapping pairs array element. */
13938c2ecf20Sopenharmony_ci		dst = dst_next;
13948c2ecf20Sopenharmony_ci		/* Go to next runlist element. */
13958c2ecf20Sopenharmony_ci		rl++;
13968c2ecf20Sopenharmony_ci	}
13978c2ecf20Sopenharmony_ci	/* Do the full runs. */
13988c2ecf20Sopenharmony_ci	for (; rl->length && !the_end; rl++) {
13998c2ecf20Sopenharmony_ci		s64 length = rl->length;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci		if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
14028c2ecf20Sopenharmony_ci			goto err_out;
14038c2ecf20Sopenharmony_ci		/*
14048c2ecf20Sopenharmony_ci		 * If @stop_vcn is given and finishes inside this run, cap the
14058c2ecf20Sopenharmony_ci		 * run length.
14068c2ecf20Sopenharmony_ci		 */
14078c2ecf20Sopenharmony_ci		if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
14088c2ecf20Sopenharmony_ci			s64 s1 = last_vcn + 1;
14098c2ecf20Sopenharmony_ci			if (unlikely(rl[1].vcn > s1))
14108c2ecf20Sopenharmony_ci				length = s1 - rl->vcn;
14118c2ecf20Sopenharmony_ci			the_end = true;
14128c2ecf20Sopenharmony_ci		}
14138c2ecf20Sopenharmony_ci		/* Write length. */
14148c2ecf20Sopenharmony_ci		len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
14158c2ecf20Sopenharmony_ci				length);
14168c2ecf20Sopenharmony_ci		if (unlikely(len_len < 0))
14178c2ecf20Sopenharmony_ci			goto size_err;
14188c2ecf20Sopenharmony_ci		/*
14198c2ecf20Sopenharmony_ci		 * If the logical cluster number (lcn) denotes a hole and we
14208c2ecf20Sopenharmony_ci		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
14218c2ecf20Sopenharmony_ci		 * zero space.  On earlier NTFS versions we just write the lcn
14228c2ecf20Sopenharmony_ci		 * change.  FIXME: Do we need to write the lcn change or just
14238c2ecf20Sopenharmony_ci		 * the lcn in that case?  Not sure as I have never seen this
14248c2ecf20Sopenharmony_ci		 * case on NT4. - We assume that we just need to write the lcn
14258c2ecf20Sopenharmony_ci		 * change until someone tells us otherwise... (AIA)
14268c2ecf20Sopenharmony_ci		 */
14278c2ecf20Sopenharmony_ci		if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
14288c2ecf20Sopenharmony_ci			/* Write change in lcn. */
14298c2ecf20Sopenharmony_ci			lcn_len = ntfs_write_significant_bytes(dst + 1 +
14308c2ecf20Sopenharmony_ci					len_len, dst_max, rl->lcn - prev_lcn);
14318c2ecf20Sopenharmony_ci			if (unlikely(lcn_len < 0))
14328c2ecf20Sopenharmony_ci				goto size_err;
14338c2ecf20Sopenharmony_ci			prev_lcn = rl->lcn;
14348c2ecf20Sopenharmony_ci		} else
14358c2ecf20Sopenharmony_ci			lcn_len = 0;
14368c2ecf20Sopenharmony_ci		dst_next = dst + len_len + lcn_len + 1;
14378c2ecf20Sopenharmony_ci		if (unlikely(dst_next > dst_max))
14388c2ecf20Sopenharmony_ci			goto size_err;
14398c2ecf20Sopenharmony_ci		/* Update header byte. */
14408c2ecf20Sopenharmony_ci		*dst = lcn_len << 4 | len_len;
14418c2ecf20Sopenharmony_ci		/* Position at next mapping pairs array element. */
14428c2ecf20Sopenharmony_ci		dst = dst_next;
14438c2ecf20Sopenharmony_ci	}
14448c2ecf20Sopenharmony_ci	/* Success. */
14458c2ecf20Sopenharmony_ci	err = 0;
14468c2ecf20Sopenharmony_cisize_err:
14478c2ecf20Sopenharmony_ci	/* Set stop vcn. */
14488c2ecf20Sopenharmony_ci	if (stop_vcn)
14498c2ecf20Sopenharmony_ci		*stop_vcn = rl->vcn;
14508c2ecf20Sopenharmony_ci	/* Add terminator byte. */
14518c2ecf20Sopenharmony_ci	*dst = 0;
14528c2ecf20Sopenharmony_ci	return err;
14538c2ecf20Sopenharmony_cierr_out:
14548c2ecf20Sopenharmony_ci	if (rl->lcn == LCN_RL_NOT_MAPPED)
14558c2ecf20Sopenharmony_ci		err = -EINVAL;
14568c2ecf20Sopenharmony_ci	else
14578c2ecf20Sopenharmony_ci		err = -EIO;
14588c2ecf20Sopenharmony_ci	return err;
14598c2ecf20Sopenharmony_ci}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci/**
14628c2ecf20Sopenharmony_ci * ntfs_rl_truncate_nolock - truncate a runlist starting at a specified vcn
14638c2ecf20Sopenharmony_ci * @vol:	ntfs volume (needed for error output)
14648c2ecf20Sopenharmony_ci * @runlist:	runlist to truncate
14658c2ecf20Sopenharmony_ci * @new_length:	the new length of the runlist in VCNs
14668c2ecf20Sopenharmony_ci *
14678c2ecf20Sopenharmony_ci * Truncate the runlist described by @runlist as well as the memory buffer
14688c2ecf20Sopenharmony_ci * holding the runlist elements to a length of @new_length VCNs.
14698c2ecf20Sopenharmony_ci *
14708c2ecf20Sopenharmony_ci * If @new_length lies within the runlist, the runlist elements with VCNs of
14718c2ecf20Sopenharmony_ci * @new_length and above are discarded.  As a special case if @new_length is
14728c2ecf20Sopenharmony_ci * zero, the runlist is discarded and set to NULL.
14738c2ecf20Sopenharmony_ci *
14748c2ecf20Sopenharmony_ci * If @new_length lies beyond the runlist, a sparse runlist element is added to
14758c2ecf20Sopenharmony_ci * the end of the runlist @runlist or if the last runlist element is a sparse
14768c2ecf20Sopenharmony_ci * one already, this is extended.
14778c2ecf20Sopenharmony_ci *
14788c2ecf20Sopenharmony_ci * Note, no checking is done for unmapped runlist elements.  It is assumed that
14798c2ecf20Sopenharmony_ci * the caller has mapped any elements that need to be mapped already.
14808c2ecf20Sopenharmony_ci *
14818c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error.
14828c2ecf20Sopenharmony_ci *
14838c2ecf20Sopenharmony_ci * Locking: The caller must hold @runlist->lock for writing.
14848c2ecf20Sopenharmony_ci */
14858c2ecf20Sopenharmony_ciint ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
14868c2ecf20Sopenharmony_ci		const s64 new_length)
14878c2ecf20Sopenharmony_ci{
14888c2ecf20Sopenharmony_ci	runlist_element *rl;
14898c2ecf20Sopenharmony_ci	int old_size;
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	ntfs_debug("Entering for new_length 0x%llx.", (long long)new_length);
14928c2ecf20Sopenharmony_ci	BUG_ON(!runlist);
14938c2ecf20Sopenharmony_ci	BUG_ON(new_length < 0);
14948c2ecf20Sopenharmony_ci	rl = runlist->rl;
14958c2ecf20Sopenharmony_ci	if (!new_length) {
14968c2ecf20Sopenharmony_ci		ntfs_debug("Freeing runlist.");
14978c2ecf20Sopenharmony_ci		runlist->rl = NULL;
14988c2ecf20Sopenharmony_ci		if (rl)
14998c2ecf20Sopenharmony_ci			ntfs_free(rl);
15008c2ecf20Sopenharmony_ci		return 0;
15018c2ecf20Sopenharmony_ci	}
15028c2ecf20Sopenharmony_ci	if (unlikely(!rl)) {
15038c2ecf20Sopenharmony_ci		/*
15048c2ecf20Sopenharmony_ci		 * Create a runlist consisting of a sparse runlist element of
15058c2ecf20Sopenharmony_ci		 * length @new_length followed by a terminator runlist element.
15068c2ecf20Sopenharmony_ci		 */
15078c2ecf20Sopenharmony_ci		rl = ntfs_malloc_nofs(PAGE_SIZE);
15088c2ecf20Sopenharmony_ci		if (unlikely(!rl)) {
15098c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Not enough memory to allocate "
15108c2ecf20Sopenharmony_ci					"runlist element buffer.");
15118c2ecf20Sopenharmony_ci			return -ENOMEM;
15128c2ecf20Sopenharmony_ci		}
15138c2ecf20Sopenharmony_ci		runlist->rl = rl;
15148c2ecf20Sopenharmony_ci		rl[1].length = rl->vcn = 0;
15158c2ecf20Sopenharmony_ci		rl->lcn = LCN_HOLE;
15168c2ecf20Sopenharmony_ci		rl[1].vcn = rl->length = new_length;
15178c2ecf20Sopenharmony_ci		rl[1].lcn = LCN_ENOENT;
15188c2ecf20Sopenharmony_ci		return 0;
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci	BUG_ON(new_length < rl->vcn);
15218c2ecf20Sopenharmony_ci	/* Find @new_length in the runlist. */
15228c2ecf20Sopenharmony_ci	while (likely(rl->length && new_length >= rl[1].vcn))
15238c2ecf20Sopenharmony_ci		rl++;
15248c2ecf20Sopenharmony_ci	/*
15258c2ecf20Sopenharmony_ci	 * If not at the end of the runlist we need to shrink it.
15268c2ecf20Sopenharmony_ci	 * If at the end of the runlist we need to expand it.
15278c2ecf20Sopenharmony_ci	 */
15288c2ecf20Sopenharmony_ci	if (rl->length) {
15298c2ecf20Sopenharmony_ci		runlist_element *trl;
15308c2ecf20Sopenharmony_ci		bool is_end;
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci		ntfs_debug("Shrinking runlist.");
15338c2ecf20Sopenharmony_ci		/* Determine the runlist size. */
15348c2ecf20Sopenharmony_ci		trl = rl + 1;
15358c2ecf20Sopenharmony_ci		while (likely(trl->length))
15368c2ecf20Sopenharmony_ci			trl++;
15378c2ecf20Sopenharmony_ci		old_size = trl - runlist->rl + 1;
15388c2ecf20Sopenharmony_ci		/* Truncate the run. */
15398c2ecf20Sopenharmony_ci		rl->length = new_length - rl->vcn;
15408c2ecf20Sopenharmony_ci		/*
15418c2ecf20Sopenharmony_ci		 * If a run was partially truncated, make the following runlist
15428c2ecf20Sopenharmony_ci		 * element a terminator.
15438c2ecf20Sopenharmony_ci		 */
15448c2ecf20Sopenharmony_ci		is_end = false;
15458c2ecf20Sopenharmony_ci		if (rl->length) {
15468c2ecf20Sopenharmony_ci			rl++;
15478c2ecf20Sopenharmony_ci			if (!rl->length)
15488c2ecf20Sopenharmony_ci				is_end = true;
15498c2ecf20Sopenharmony_ci			rl->vcn = new_length;
15508c2ecf20Sopenharmony_ci			rl->length = 0;
15518c2ecf20Sopenharmony_ci		}
15528c2ecf20Sopenharmony_ci		rl->lcn = LCN_ENOENT;
15538c2ecf20Sopenharmony_ci		/* Reallocate memory if necessary. */
15548c2ecf20Sopenharmony_ci		if (!is_end) {
15558c2ecf20Sopenharmony_ci			int new_size = rl - runlist->rl + 1;
15568c2ecf20Sopenharmony_ci			rl = ntfs_rl_realloc(runlist->rl, old_size, new_size);
15578c2ecf20Sopenharmony_ci			if (IS_ERR(rl))
15588c2ecf20Sopenharmony_ci				ntfs_warning(vol->sb, "Failed to shrink "
15598c2ecf20Sopenharmony_ci						"runlist buffer.  This just "
15608c2ecf20Sopenharmony_ci						"wastes a bit of memory "
15618c2ecf20Sopenharmony_ci						"temporarily so we ignore it "
15628c2ecf20Sopenharmony_ci						"and return success.");
15638c2ecf20Sopenharmony_ci			else
15648c2ecf20Sopenharmony_ci				runlist->rl = rl;
15658c2ecf20Sopenharmony_ci		}
15668c2ecf20Sopenharmony_ci	} else if (likely(/* !rl->length && */ new_length > rl->vcn)) {
15678c2ecf20Sopenharmony_ci		ntfs_debug("Expanding runlist.");
15688c2ecf20Sopenharmony_ci		/*
15698c2ecf20Sopenharmony_ci		 * If there is a previous runlist element and it is a sparse
15708c2ecf20Sopenharmony_ci		 * one, extend it.  Otherwise need to add a new, sparse runlist
15718c2ecf20Sopenharmony_ci		 * element.
15728c2ecf20Sopenharmony_ci		 */
15738c2ecf20Sopenharmony_ci		if ((rl > runlist->rl) && ((rl - 1)->lcn == LCN_HOLE))
15748c2ecf20Sopenharmony_ci			(rl - 1)->length = new_length - (rl - 1)->vcn;
15758c2ecf20Sopenharmony_ci		else {
15768c2ecf20Sopenharmony_ci			/* Determine the runlist size. */
15778c2ecf20Sopenharmony_ci			old_size = rl - runlist->rl + 1;
15788c2ecf20Sopenharmony_ci			/* Reallocate memory if necessary. */
15798c2ecf20Sopenharmony_ci			rl = ntfs_rl_realloc(runlist->rl, old_size,
15808c2ecf20Sopenharmony_ci					old_size + 1);
15818c2ecf20Sopenharmony_ci			if (IS_ERR(rl)) {
15828c2ecf20Sopenharmony_ci				ntfs_error(vol->sb, "Failed to expand runlist "
15838c2ecf20Sopenharmony_ci						"buffer, aborting.");
15848c2ecf20Sopenharmony_ci				return PTR_ERR(rl);
15858c2ecf20Sopenharmony_ci			}
15868c2ecf20Sopenharmony_ci			runlist->rl = rl;
15878c2ecf20Sopenharmony_ci			/*
15888c2ecf20Sopenharmony_ci			 * Set @rl to the same runlist element in the new
15898c2ecf20Sopenharmony_ci			 * runlist as before in the old runlist.
15908c2ecf20Sopenharmony_ci			 */
15918c2ecf20Sopenharmony_ci			rl += old_size - 1;
15928c2ecf20Sopenharmony_ci			/* Add a new, sparse runlist element. */
15938c2ecf20Sopenharmony_ci			rl->lcn = LCN_HOLE;
15948c2ecf20Sopenharmony_ci			rl->length = new_length - rl->vcn;
15958c2ecf20Sopenharmony_ci			/* Add a new terminator runlist element. */
15968c2ecf20Sopenharmony_ci			rl++;
15978c2ecf20Sopenharmony_ci			rl->length = 0;
15988c2ecf20Sopenharmony_ci		}
15998c2ecf20Sopenharmony_ci		rl->vcn = new_length;
16008c2ecf20Sopenharmony_ci		rl->lcn = LCN_ENOENT;
16018c2ecf20Sopenharmony_ci	} else /* if (unlikely(!rl->length && new_length == rl->vcn)) */ {
16028c2ecf20Sopenharmony_ci		/* Runlist already has same size as requested. */
16038c2ecf20Sopenharmony_ci		rl->lcn = LCN_ENOENT;
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci	ntfs_debug("Done.");
16068c2ecf20Sopenharmony_ci	return 0;
16078c2ecf20Sopenharmony_ci}
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci/**
16108c2ecf20Sopenharmony_ci * ntfs_rl_punch_nolock - punch a hole into a runlist
16118c2ecf20Sopenharmony_ci * @vol:	ntfs volume (needed for error output)
16128c2ecf20Sopenharmony_ci * @runlist:	runlist to punch a hole into
16138c2ecf20Sopenharmony_ci * @start:	starting VCN of the hole to be created
16148c2ecf20Sopenharmony_ci * @length:	size of the hole to be created in units of clusters
16158c2ecf20Sopenharmony_ci *
16168c2ecf20Sopenharmony_ci * Punch a hole into the runlist @runlist starting at VCN @start and of size
16178c2ecf20Sopenharmony_ci * @length clusters.
16188c2ecf20Sopenharmony_ci *
16198c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error, in which case @runlist has not been
16208c2ecf20Sopenharmony_ci * modified.
16218c2ecf20Sopenharmony_ci *
16228c2ecf20Sopenharmony_ci * If @start and/or @start + @length are outside the runlist return error code
16238c2ecf20Sopenharmony_ci * -ENOENT.
16248c2ecf20Sopenharmony_ci *
16258c2ecf20Sopenharmony_ci * If the runlist contains unmapped or error elements between @start and @start
16268c2ecf20Sopenharmony_ci * + @length return error code -EINVAL.
16278c2ecf20Sopenharmony_ci *
16288c2ecf20Sopenharmony_ci * Locking: The caller must hold @runlist->lock for writing.
16298c2ecf20Sopenharmony_ci */
16308c2ecf20Sopenharmony_ciint ntfs_rl_punch_nolock(const ntfs_volume *vol, runlist *const runlist,
16318c2ecf20Sopenharmony_ci		const VCN start, const s64 length)
16328c2ecf20Sopenharmony_ci{
16338c2ecf20Sopenharmony_ci	const VCN end = start + length;
16348c2ecf20Sopenharmony_ci	s64 delta;
16358c2ecf20Sopenharmony_ci	runlist_element *rl, *rl_end, *rl_real_end, *trl;
16368c2ecf20Sopenharmony_ci	int old_size;
16378c2ecf20Sopenharmony_ci	bool lcn_fixup = false;
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	ntfs_debug("Entering for start 0x%llx, length 0x%llx.",
16408c2ecf20Sopenharmony_ci			(long long)start, (long long)length);
16418c2ecf20Sopenharmony_ci	BUG_ON(!runlist);
16428c2ecf20Sopenharmony_ci	BUG_ON(start < 0);
16438c2ecf20Sopenharmony_ci	BUG_ON(length < 0);
16448c2ecf20Sopenharmony_ci	BUG_ON(end < 0);
16458c2ecf20Sopenharmony_ci	rl = runlist->rl;
16468c2ecf20Sopenharmony_ci	if (unlikely(!rl)) {
16478c2ecf20Sopenharmony_ci		if (likely(!start && !length))
16488c2ecf20Sopenharmony_ci			return 0;
16498c2ecf20Sopenharmony_ci		return -ENOENT;
16508c2ecf20Sopenharmony_ci	}
16518c2ecf20Sopenharmony_ci	/* Find @start in the runlist. */
16528c2ecf20Sopenharmony_ci	while (likely(rl->length && start >= rl[1].vcn))
16538c2ecf20Sopenharmony_ci		rl++;
16548c2ecf20Sopenharmony_ci	rl_end = rl;
16558c2ecf20Sopenharmony_ci	/* Find @end in the runlist. */
16568c2ecf20Sopenharmony_ci	while (likely(rl_end->length && end >= rl_end[1].vcn)) {
16578c2ecf20Sopenharmony_ci		/* Verify there are no unmapped or error elements. */
16588c2ecf20Sopenharmony_ci		if (unlikely(rl_end->lcn < LCN_HOLE))
16598c2ecf20Sopenharmony_ci			return -EINVAL;
16608c2ecf20Sopenharmony_ci		rl_end++;
16618c2ecf20Sopenharmony_ci	}
16628c2ecf20Sopenharmony_ci	/* Check the last element. */
16638c2ecf20Sopenharmony_ci	if (unlikely(rl_end->length && rl_end->lcn < LCN_HOLE))
16648c2ecf20Sopenharmony_ci		return -EINVAL;
16658c2ecf20Sopenharmony_ci	/* This covers @start being out of bounds, too. */
16668c2ecf20Sopenharmony_ci	if (!rl_end->length && end > rl_end->vcn)
16678c2ecf20Sopenharmony_ci		return -ENOENT;
16688c2ecf20Sopenharmony_ci	if (!length)
16698c2ecf20Sopenharmony_ci		return 0;
16708c2ecf20Sopenharmony_ci	if (!rl->length)
16718c2ecf20Sopenharmony_ci		return -ENOENT;
16728c2ecf20Sopenharmony_ci	rl_real_end = rl_end;
16738c2ecf20Sopenharmony_ci	/* Determine the runlist size. */
16748c2ecf20Sopenharmony_ci	while (likely(rl_real_end->length))
16758c2ecf20Sopenharmony_ci		rl_real_end++;
16768c2ecf20Sopenharmony_ci	old_size = rl_real_end - runlist->rl + 1;
16778c2ecf20Sopenharmony_ci	/* If @start is in a hole simply extend the hole. */
16788c2ecf20Sopenharmony_ci	if (rl->lcn == LCN_HOLE) {
16798c2ecf20Sopenharmony_ci		/*
16808c2ecf20Sopenharmony_ci		 * If both @start and @end are in the same sparse run, we are
16818c2ecf20Sopenharmony_ci		 * done.
16828c2ecf20Sopenharmony_ci		 */
16838c2ecf20Sopenharmony_ci		if (end <= rl[1].vcn) {
16848c2ecf20Sopenharmony_ci			ntfs_debug("Done (requested hole is already sparse).");
16858c2ecf20Sopenharmony_ci			return 0;
16868c2ecf20Sopenharmony_ci		}
16878c2ecf20Sopenharmony_ciextend_hole:
16888c2ecf20Sopenharmony_ci		/* Extend the hole. */
16898c2ecf20Sopenharmony_ci		rl->length = end - rl->vcn;
16908c2ecf20Sopenharmony_ci		/* If @end is in a hole, merge it with the current one. */
16918c2ecf20Sopenharmony_ci		if (rl_end->lcn == LCN_HOLE) {
16928c2ecf20Sopenharmony_ci			rl_end++;
16938c2ecf20Sopenharmony_ci			rl->length = rl_end->vcn - rl->vcn;
16948c2ecf20Sopenharmony_ci		}
16958c2ecf20Sopenharmony_ci		/* We have done the hole.  Now deal with the remaining tail. */
16968c2ecf20Sopenharmony_ci		rl++;
16978c2ecf20Sopenharmony_ci		/* Cut out all runlist elements up to @end. */
16988c2ecf20Sopenharmony_ci		if (rl < rl_end)
16998c2ecf20Sopenharmony_ci			memmove(rl, rl_end, (rl_real_end - rl_end + 1) *
17008c2ecf20Sopenharmony_ci					sizeof(*rl));
17018c2ecf20Sopenharmony_ci		/* Adjust the beginning of the tail if necessary. */
17028c2ecf20Sopenharmony_ci		if (end > rl->vcn) {
17038c2ecf20Sopenharmony_ci			delta = end - rl->vcn;
17048c2ecf20Sopenharmony_ci			rl->vcn = end;
17058c2ecf20Sopenharmony_ci			rl->length -= delta;
17068c2ecf20Sopenharmony_ci			/* Only adjust the lcn if it is real. */
17078c2ecf20Sopenharmony_ci			if (rl->lcn >= 0)
17088c2ecf20Sopenharmony_ci				rl->lcn += delta;
17098c2ecf20Sopenharmony_ci		}
17108c2ecf20Sopenharmony_cishrink_allocation:
17118c2ecf20Sopenharmony_ci		/* Reallocate memory if the allocation changed. */
17128c2ecf20Sopenharmony_ci		if (rl < rl_end) {
17138c2ecf20Sopenharmony_ci			rl = ntfs_rl_realloc(runlist->rl, old_size,
17148c2ecf20Sopenharmony_ci					old_size - (rl_end - rl));
17158c2ecf20Sopenharmony_ci			if (IS_ERR(rl))
17168c2ecf20Sopenharmony_ci				ntfs_warning(vol->sb, "Failed to shrink "
17178c2ecf20Sopenharmony_ci						"runlist buffer.  This just "
17188c2ecf20Sopenharmony_ci						"wastes a bit of memory "
17198c2ecf20Sopenharmony_ci						"temporarily so we ignore it "
17208c2ecf20Sopenharmony_ci						"and return success.");
17218c2ecf20Sopenharmony_ci			else
17228c2ecf20Sopenharmony_ci				runlist->rl = rl;
17238c2ecf20Sopenharmony_ci		}
17248c2ecf20Sopenharmony_ci		ntfs_debug("Done (extend hole).");
17258c2ecf20Sopenharmony_ci		return 0;
17268c2ecf20Sopenharmony_ci	}
17278c2ecf20Sopenharmony_ci	/*
17288c2ecf20Sopenharmony_ci	 * If @start is at the beginning of a run things are easier as there is
17298c2ecf20Sopenharmony_ci	 * no need to split the first run.
17308c2ecf20Sopenharmony_ci	 */
17318c2ecf20Sopenharmony_ci	if (start == rl->vcn) {
17328c2ecf20Sopenharmony_ci		/*
17338c2ecf20Sopenharmony_ci		 * @start is at the beginning of a run.
17348c2ecf20Sopenharmony_ci		 *
17358c2ecf20Sopenharmony_ci		 * If the previous run is sparse, extend its hole.
17368c2ecf20Sopenharmony_ci		 *
17378c2ecf20Sopenharmony_ci		 * If @end is not in the same run, switch the run to be sparse
17388c2ecf20Sopenharmony_ci		 * and extend the newly created hole.
17398c2ecf20Sopenharmony_ci		 *
17408c2ecf20Sopenharmony_ci		 * Thus both of these cases reduce the problem to the above
17418c2ecf20Sopenharmony_ci		 * case of "@start is in a hole".
17428c2ecf20Sopenharmony_ci		 */
17438c2ecf20Sopenharmony_ci		if (rl > runlist->rl && (rl - 1)->lcn == LCN_HOLE) {
17448c2ecf20Sopenharmony_ci			rl--;
17458c2ecf20Sopenharmony_ci			goto extend_hole;
17468c2ecf20Sopenharmony_ci		}
17478c2ecf20Sopenharmony_ci		if (end >= rl[1].vcn) {
17488c2ecf20Sopenharmony_ci			rl->lcn = LCN_HOLE;
17498c2ecf20Sopenharmony_ci			goto extend_hole;
17508c2ecf20Sopenharmony_ci		}
17518c2ecf20Sopenharmony_ci		/*
17528c2ecf20Sopenharmony_ci		 * The final case is when @end is in the same run as @start.
17538c2ecf20Sopenharmony_ci		 * For this need to split the run into two.  One run for the
17548c2ecf20Sopenharmony_ci		 * sparse region between the beginning of the old run, i.e.
17558c2ecf20Sopenharmony_ci		 * @start, and @end and one for the remaining non-sparse
17568c2ecf20Sopenharmony_ci		 * region, i.e. between @end and the end of the old run.
17578c2ecf20Sopenharmony_ci		 */
17588c2ecf20Sopenharmony_ci		trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1);
17598c2ecf20Sopenharmony_ci		if (IS_ERR(trl))
17608c2ecf20Sopenharmony_ci			goto enomem_out;
17618c2ecf20Sopenharmony_ci		old_size++;
17628c2ecf20Sopenharmony_ci		if (runlist->rl != trl) {
17638c2ecf20Sopenharmony_ci			rl = trl + (rl - runlist->rl);
17648c2ecf20Sopenharmony_ci			rl_end = trl + (rl_end - runlist->rl);
17658c2ecf20Sopenharmony_ci			rl_real_end = trl + (rl_real_end - runlist->rl);
17668c2ecf20Sopenharmony_ci			runlist->rl = trl;
17678c2ecf20Sopenharmony_ci		}
17688c2ecf20Sopenharmony_cisplit_end:
17698c2ecf20Sopenharmony_ci		/* Shift all the runs up by one. */
17708c2ecf20Sopenharmony_ci		memmove(rl + 1, rl, (rl_real_end - rl + 1) * sizeof(*rl));
17718c2ecf20Sopenharmony_ci		/* Finally, setup the two split runs. */
17728c2ecf20Sopenharmony_ci		rl->lcn = LCN_HOLE;
17738c2ecf20Sopenharmony_ci		rl->length = length;
17748c2ecf20Sopenharmony_ci		rl++;
17758c2ecf20Sopenharmony_ci		rl->vcn += length;
17768c2ecf20Sopenharmony_ci		/* Only adjust the lcn if it is real. */
17778c2ecf20Sopenharmony_ci		if (rl->lcn >= 0 || lcn_fixup)
17788c2ecf20Sopenharmony_ci			rl->lcn += length;
17798c2ecf20Sopenharmony_ci		rl->length -= length;
17808c2ecf20Sopenharmony_ci		ntfs_debug("Done (split one).");
17818c2ecf20Sopenharmony_ci		return 0;
17828c2ecf20Sopenharmony_ci	}
17838c2ecf20Sopenharmony_ci	/*
17848c2ecf20Sopenharmony_ci	 * @start is neither in a hole nor at the beginning of a run.
17858c2ecf20Sopenharmony_ci	 *
17868c2ecf20Sopenharmony_ci	 * If @end is in a hole, things are easier as simply truncating the run
17878c2ecf20Sopenharmony_ci	 * @start is in to end at @start - 1, deleting all runs after that up
17888c2ecf20Sopenharmony_ci	 * to @end, and finally extending the beginning of the run @end is in
17898c2ecf20Sopenharmony_ci	 * to be @start is all that is needed.
17908c2ecf20Sopenharmony_ci	 */
17918c2ecf20Sopenharmony_ci	if (rl_end->lcn == LCN_HOLE) {
17928c2ecf20Sopenharmony_ci		/* Truncate the run containing @start. */
17938c2ecf20Sopenharmony_ci		rl->length = start - rl->vcn;
17948c2ecf20Sopenharmony_ci		rl++;
17958c2ecf20Sopenharmony_ci		/* Cut out all runlist elements up to @end. */
17968c2ecf20Sopenharmony_ci		if (rl < rl_end)
17978c2ecf20Sopenharmony_ci			memmove(rl, rl_end, (rl_real_end - rl_end + 1) *
17988c2ecf20Sopenharmony_ci					sizeof(*rl));
17998c2ecf20Sopenharmony_ci		/* Extend the beginning of the run @end is in to be @start. */
18008c2ecf20Sopenharmony_ci		rl->vcn = start;
18018c2ecf20Sopenharmony_ci		rl->length = rl[1].vcn - start;
18028c2ecf20Sopenharmony_ci		goto shrink_allocation;
18038c2ecf20Sopenharmony_ci	}
18048c2ecf20Sopenharmony_ci	/*
18058c2ecf20Sopenharmony_ci	 * If @end is not in a hole there are still two cases to distinguish.
18068c2ecf20Sopenharmony_ci	 * Either @end is or is not in the same run as @start.
18078c2ecf20Sopenharmony_ci	 *
18088c2ecf20Sopenharmony_ci	 * The second case is easier as it can be reduced to an already solved
18098c2ecf20Sopenharmony_ci	 * problem by truncating the run @start is in to end at @start - 1.
18108c2ecf20Sopenharmony_ci	 * Then, if @end is in the next run need to split the run into a sparse
18118c2ecf20Sopenharmony_ci	 * run followed by a non-sparse run (already covered above) and if @end
18128c2ecf20Sopenharmony_ci	 * is not in the next run switching it to be sparse, again reduces the
18138c2ecf20Sopenharmony_ci	 * problem to the already covered case of "@start is in a hole".
18148c2ecf20Sopenharmony_ci	 */
18158c2ecf20Sopenharmony_ci	if (end >= rl[1].vcn) {
18168c2ecf20Sopenharmony_ci		/*
18178c2ecf20Sopenharmony_ci		 * If @end is not in the next run, reduce the problem to the
18188c2ecf20Sopenharmony_ci		 * case of "@start is in a hole".
18198c2ecf20Sopenharmony_ci		 */
18208c2ecf20Sopenharmony_ci		if (rl[1].length && end >= rl[2].vcn) {
18218c2ecf20Sopenharmony_ci			/* Truncate the run containing @start. */
18228c2ecf20Sopenharmony_ci			rl->length = start - rl->vcn;
18238c2ecf20Sopenharmony_ci			rl++;
18248c2ecf20Sopenharmony_ci			rl->vcn = start;
18258c2ecf20Sopenharmony_ci			rl->lcn = LCN_HOLE;
18268c2ecf20Sopenharmony_ci			goto extend_hole;
18278c2ecf20Sopenharmony_ci		}
18288c2ecf20Sopenharmony_ci		trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1);
18298c2ecf20Sopenharmony_ci		if (IS_ERR(trl))
18308c2ecf20Sopenharmony_ci			goto enomem_out;
18318c2ecf20Sopenharmony_ci		old_size++;
18328c2ecf20Sopenharmony_ci		if (runlist->rl != trl) {
18338c2ecf20Sopenharmony_ci			rl = trl + (rl - runlist->rl);
18348c2ecf20Sopenharmony_ci			rl_end = trl + (rl_end - runlist->rl);
18358c2ecf20Sopenharmony_ci			rl_real_end = trl + (rl_real_end - runlist->rl);
18368c2ecf20Sopenharmony_ci			runlist->rl = trl;
18378c2ecf20Sopenharmony_ci		}
18388c2ecf20Sopenharmony_ci		/* Truncate the run containing @start. */
18398c2ecf20Sopenharmony_ci		rl->length = start - rl->vcn;
18408c2ecf20Sopenharmony_ci		rl++;
18418c2ecf20Sopenharmony_ci		/*
18428c2ecf20Sopenharmony_ci		 * @end is in the next run, reduce the problem to the case
18438c2ecf20Sopenharmony_ci		 * where "@start is at the beginning of a run and @end is in
18448c2ecf20Sopenharmony_ci		 * the same run as @start".
18458c2ecf20Sopenharmony_ci		 */
18468c2ecf20Sopenharmony_ci		delta = rl->vcn - start;
18478c2ecf20Sopenharmony_ci		rl->vcn = start;
18488c2ecf20Sopenharmony_ci		if (rl->lcn >= 0) {
18498c2ecf20Sopenharmony_ci			rl->lcn -= delta;
18508c2ecf20Sopenharmony_ci			/* Need this in case the lcn just became negative. */
18518c2ecf20Sopenharmony_ci			lcn_fixup = true;
18528c2ecf20Sopenharmony_ci		}
18538c2ecf20Sopenharmony_ci		rl->length += delta;
18548c2ecf20Sopenharmony_ci		goto split_end;
18558c2ecf20Sopenharmony_ci	}
18568c2ecf20Sopenharmony_ci	/*
18578c2ecf20Sopenharmony_ci	 * The first case from above, i.e. @end is in the same run as @start.
18588c2ecf20Sopenharmony_ci	 * We need to split the run into three.  One run for the non-sparse
18598c2ecf20Sopenharmony_ci	 * region between the beginning of the old run and @start, one for the
18608c2ecf20Sopenharmony_ci	 * sparse region between @start and @end, and one for the remaining
18618c2ecf20Sopenharmony_ci	 * non-sparse region, i.e. between @end and the end of the old run.
18628c2ecf20Sopenharmony_ci	 */
18638c2ecf20Sopenharmony_ci	trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 2);
18648c2ecf20Sopenharmony_ci	if (IS_ERR(trl))
18658c2ecf20Sopenharmony_ci		goto enomem_out;
18668c2ecf20Sopenharmony_ci	old_size += 2;
18678c2ecf20Sopenharmony_ci	if (runlist->rl != trl) {
18688c2ecf20Sopenharmony_ci		rl = trl + (rl - runlist->rl);
18698c2ecf20Sopenharmony_ci		rl_end = trl + (rl_end - runlist->rl);
18708c2ecf20Sopenharmony_ci		rl_real_end = trl + (rl_real_end - runlist->rl);
18718c2ecf20Sopenharmony_ci		runlist->rl = trl;
18728c2ecf20Sopenharmony_ci	}
18738c2ecf20Sopenharmony_ci	/* Shift all the runs up by two. */
18748c2ecf20Sopenharmony_ci	memmove(rl + 2, rl, (rl_real_end - rl + 1) * sizeof(*rl));
18758c2ecf20Sopenharmony_ci	/* Finally, setup the three split runs. */
18768c2ecf20Sopenharmony_ci	rl->length = start - rl->vcn;
18778c2ecf20Sopenharmony_ci	rl++;
18788c2ecf20Sopenharmony_ci	rl->vcn = start;
18798c2ecf20Sopenharmony_ci	rl->lcn = LCN_HOLE;
18808c2ecf20Sopenharmony_ci	rl->length = length;
18818c2ecf20Sopenharmony_ci	rl++;
18828c2ecf20Sopenharmony_ci	delta = end - rl->vcn;
18838c2ecf20Sopenharmony_ci	rl->vcn = end;
18848c2ecf20Sopenharmony_ci	rl->lcn += delta;
18858c2ecf20Sopenharmony_ci	rl->length -= delta;
18868c2ecf20Sopenharmony_ci	ntfs_debug("Done (split both).");
18878c2ecf20Sopenharmony_ci	return 0;
18888c2ecf20Sopenharmony_cienomem_out:
18898c2ecf20Sopenharmony_ci	ntfs_error(vol->sb, "Not enough memory to extend runlist buffer.");
18908c2ecf20Sopenharmony_ci	return -ENOMEM;
18918c2ecf20Sopenharmony_ci}
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_ci#endif /* NTFS_RW */
1894