162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * TODO: try to use extents tree (instead of array)
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/blkdev.h>
1062306a36Sopenharmony_ci#include <linux/fs.h>
1162306a36Sopenharmony_ci#include <linux/log2.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "debug.h"
1462306a36Sopenharmony_ci#include "ntfs.h"
1562306a36Sopenharmony_ci#include "ntfs_fs.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/* runs_tree is a continues memory. Try to avoid big size. */
1862306a36Sopenharmony_ci#define NTFS3_RUN_MAX_BYTES 0x10000
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct ntfs_run {
2162306a36Sopenharmony_ci	CLST vcn; /* Virtual cluster number. */
2262306a36Sopenharmony_ci	CLST len; /* Length in clusters. */
2362306a36Sopenharmony_ci	CLST lcn; /* Logical cluster number. */
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/*
2762306a36Sopenharmony_ci * run_lookup - Lookup the index of a MCB entry that is first <= vcn.
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * Case of success it will return non-zero value and set
3062306a36Sopenharmony_ci * @index parameter to index of entry been found.
3162306a36Sopenharmony_ci * Case of entry missing from list 'index' will be set to
3262306a36Sopenharmony_ci * point to insertion position for the entry question.
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_cistatic bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *index)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	size_t min_idx, max_idx, mid_idx;
3762306a36Sopenharmony_ci	struct ntfs_run *r;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	if (!run->count) {
4062306a36Sopenharmony_ci		*index = 0;
4162306a36Sopenharmony_ci		return false;
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	min_idx = 0;
4562306a36Sopenharmony_ci	max_idx = run->count - 1;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* Check boundary cases specially, 'cause they cover the often requests. */
4862306a36Sopenharmony_ci	r = run->runs;
4962306a36Sopenharmony_ci	if (vcn < r->vcn) {
5062306a36Sopenharmony_ci		*index = 0;
5162306a36Sopenharmony_ci		return false;
5262306a36Sopenharmony_ci	}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	if (vcn < r->vcn + r->len) {
5562306a36Sopenharmony_ci		*index = 0;
5662306a36Sopenharmony_ci		return true;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	r += max_idx;
6062306a36Sopenharmony_ci	if (vcn >= r->vcn + r->len) {
6162306a36Sopenharmony_ci		*index = run->count;
6262306a36Sopenharmony_ci		return false;
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (vcn >= r->vcn) {
6662306a36Sopenharmony_ci		*index = max_idx;
6762306a36Sopenharmony_ci		return true;
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	do {
7162306a36Sopenharmony_ci		mid_idx = min_idx + ((max_idx - min_idx) >> 1);
7262306a36Sopenharmony_ci		r = run->runs + mid_idx;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci		if (vcn < r->vcn) {
7562306a36Sopenharmony_ci			max_idx = mid_idx - 1;
7662306a36Sopenharmony_ci			if (!mid_idx)
7762306a36Sopenharmony_ci				break;
7862306a36Sopenharmony_ci		} else if (vcn >= r->vcn + r->len) {
7962306a36Sopenharmony_ci			min_idx = mid_idx + 1;
8062306a36Sopenharmony_ci		} else {
8162306a36Sopenharmony_ci			*index = mid_idx;
8262306a36Sopenharmony_ci			return true;
8362306a36Sopenharmony_ci		}
8462306a36Sopenharmony_ci	} while (min_idx <= max_idx);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	*index = max_idx + 1;
8762306a36Sopenharmony_ci	return false;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/*
9162306a36Sopenharmony_ci * run_consolidate - Consolidate runs starting from a given one.
9262306a36Sopenharmony_ci */
9362306a36Sopenharmony_cistatic void run_consolidate(struct runs_tree *run, size_t index)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	size_t i;
9662306a36Sopenharmony_ci	struct ntfs_run *r = run->runs + index;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	while (index + 1 < run->count) {
9962306a36Sopenharmony_ci		/*
10062306a36Sopenharmony_ci		 * I should merge current run with next
10162306a36Sopenharmony_ci		 * if start of the next run lies inside one being tested.
10262306a36Sopenharmony_ci		 */
10362306a36Sopenharmony_ci		struct ntfs_run *n = r + 1;
10462306a36Sopenharmony_ci		CLST end = r->vcn + r->len;
10562306a36Sopenharmony_ci		CLST dl;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci		/* Stop if runs are not aligned one to another. */
10862306a36Sopenharmony_ci		if (n->vcn > end)
10962306a36Sopenharmony_ci			break;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		dl = end - n->vcn;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci		/*
11462306a36Sopenharmony_ci		 * If range at index overlaps with next one
11562306a36Sopenharmony_ci		 * then I will either adjust it's start position
11662306a36Sopenharmony_ci		 * or (if completely matches) dust remove one from the list.
11762306a36Sopenharmony_ci		 */
11862306a36Sopenharmony_ci		if (dl > 0) {
11962306a36Sopenharmony_ci			if (n->len <= dl)
12062306a36Sopenharmony_ci				goto remove_next_range;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci			n->len -= dl;
12362306a36Sopenharmony_ci			n->vcn += dl;
12462306a36Sopenharmony_ci			if (n->lcn != SPARSE_LCN)
12562306a36Sopenharmony_ci				n->lcn += dl;
12662306a36Sopenharmony_ci			dl = 0;
12762306a36Sopenharmony_ci		}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		/*
13062306a36Sopenharmony_ci		 * Stop if sparse mode does not match
13162306a36Sopenharmony_ci		 * both current and next runs.
13262306a36Sopenharmony_ci		 */
13362306a36Sopenharmony_ci		if ((n->lcn == SPARSE_LCN) != (r->lcn == SPARSE_LCN)) {
13462306a36Sopenharmony_ci			index += 1;
13562306a36Sopenharmony_ci			r = n;
13662306a36Sopenharmony_ci			continue;
13762306a36Sopenharmony_ci		}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci		/*
14062306a36Sopenharmony_ci		 * Check if volume block
14162306a36Sopenharmony_ci		 * of a next run lcn does not match
14262306a36Sopenharmony_ci		 * last volume block of the current run.
14362306a36Sopenharmony_ci		 */
14462306a36Sopenharmony_ci		if (n->lcn != SPARSE_LCN && n->lcn != r->lcn + r->len)
14562306a36Sopenharmony_ci			break;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci		/*
14862306a36Sopenharmony_ci		 * Next and current are siblings.
14962306a36Sopenharmony_ci		 * Eat/join.
15062306a36Sopenharmony_ci		 */
15162306a36Sopenharmony_ci		r->len += n->len - dl;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciremove_next_range:
15462306a36Sopenharmony_ci		i = run->count - (index + 1);
15562306a36Sopenharmony_ci		if (i > 1)
15662306a36Sopenharmony_ci			memmove(n, n + 1, sizeof(*n) * (i - 1));
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci		run->count -= 1;
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/*
16362306a36Sopenharmony_ci * run_is_mapped_full
16462306a36Sopenharmony_ci *
16562306a36Sopenharmony_ci * Return: True if range [svcn - evcn] is mapped.
16662306a36Sopenharmony_ci */
16762306a36Sopenharmony_cibool run_is_mapped_full(const struct runs_tree *run, CLST svcn, CLST evcn)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	size_t i;
17062306a36Sopenharmony_ci	const struct ntfs_run *r, *end;
17162306a36Sopenharmony_ci	CLST next_vcn;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	if (!run_lookup(run, svcn, &i))
17462306a36Sopenharmony_ci		return false;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	end = run->runs + run->count;
17762306a36Sopenharmony_ci	r = run->runs + i;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	for (;;) {
18062306a36Sopenharmony_ci		next_vcn = r->vcn + r->len;
18162306a36Sopenharmony_ci		if (next_vcn > evcn)
18262306a36Sopenharmony_ci			return true;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		if (++r >= end)
18562306a36Sopenharmony_ci			return false;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci		if (r->vcn != next_vcn)
18862306a36Sopenharmony_ci			return false;
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cibool run_lookup_entry(const struct runs_tree *run, CLST vcn, CLST *lcn,
19362306a36Sopenharmony_ci		      CLST *len, size_t *index)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	size_t idx;
19662306a36Sopenharmony_ci	CLST gap;
19762306a36Sopenharmony_ci	struct ntfs_run *r;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	/* Fail immediately if nrun was not touched yet. */
20062306a36Sopenharmony_ci	if (!run->runs)
20162306a36Sopenharmony_ci		return false;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	if (!run_lookup(run, vcn, &idx))
20462306a36Sopenharmony_ci		return false;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	r = run->runs + idx;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (vcn >= r->vcn + r->len)
20962306a36Sopenharmony_ci		return false;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	gap = vcn - r->vcn;
21262306a36Sopenharmony_ci	if (r->len <= gap)
21362306a36Sopenharmony_ci		return false;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	*lcn = r->lcn == SPARSE_LCN ? SPARSE_LCN : (r->lcn + gap);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	if (len)
21862306a36Sopenharmony_ci		*len = r->len - gap;
21962306a36Sopenharmony_ci	if (index)
22062306a36Sopenharmony_ci		*index = idx;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	return true;
22362306a36Sopenharmony_ci}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci/*
22662306a36Sopenharmony_ci * run_truncate_head - Decommit the range before vcn.
22762306a36Sopenharmony_ci */
22862306a36Sopenharmony_civoid run_truncate_head(struct runs_tree *run, CLST vcn)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	size_t index;
23162306a36Sopenharmony_ci	struct ntfs_run *r;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (run_lookup(run, vcn, &index)) {
23462306a36Sopenharmony_ci		r = run->runs + index;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci		if (vcn > r->vcn) {
23762306a36Sopenharmony_ci			CLST dlen = vcn - r->vcn;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci			r->vcn = vcn;
24062306a36Sopenharmony_ci			r->len -= dlen;
24162306a36Sopenharmony_ci			if (r->lcn != SPARSE_LCN)
24262306a36Sopenharmony_ci				r->lcn += dlen;
24362306a36Sopenharmony_ci		}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		if (!index)
24662306a36Sopenharmony_ci			return;
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci	r = run->runs;
24962306a36Sopenharmony_ci	memmove(r, r + index, sizeof(*r) * (run->count - index));
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	run->count -= index;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	if (!run->count) {
25462306a36Sopenharmony_ci		kvfree(run->runs);
25562306a36Sopenharmony_ci		run->runs = NULL;
25662306a36Sopenharmony_ci		run->allocated = 0;
25762306a36Sopenharmony_ci	}
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci/*
26162306a36Sopenharmony_ci * run_truncate - Decommit the range after vcn.
26262306a36Sopenharmony_ci */
26362306a36Sopenharmony_civoid run_truncate(struct runs_tree *run, CLST vcn)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	size_t index;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/*
26862306a36Sopenharmony_ci	 * If I hit the range then
26962306a36Sopenharmony_ci	 * I have to truncate one.
27062306a36Sopenharmony_ci	 * If range to be truncated is becoming empty
27162306a36Sopenharmony_ci	 * then it will entirely be removed.
27262306a36Sopenharmony_ci	 */
27362306a36Sopenharmony_ci	if (run_lookup(run, vcn, &index)) {
27462306a36Sopenharmony_ci		struct ntfs_run *r = run->runs + index;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci		r->len = vcn - r->vcn;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci		if (r->len > 0)
27962306a36Sopenharmony_ci			index += 1;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	/*
28362306a36Sopenharmony_ci	 * At this point 'index' is set to position that
28462306a36Sopenharmony_ci	 * should be thrown away (including index itself)
28562306a36Sopenharmony_ci	 * Simple one - just set the limit.
28662306a36Sopenharmony_ci	 */
28762306a36Sopenharmony_ci	run->count = index;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	/* Do not reallocate array 'runs'. Only free if possible. */
29062306a36Sopenharmony_ci	if (!index) {
29162306a36Sopenharmony_ci		kvfree(run->runs);
29262306a36Sopenharmony_ci		run->runs = NULL;
29362306a36Sopenharmony_ci		run->allocated = 0;
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci/*
29862306a36Sopenharmony_ci * run_truncate_around - Trim head and tail if necessary.
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_civoid run_truncate_around(struct runs_tree *run, CLST vcn)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	run_truncate_head(run, vcn);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	if (run->count >= NTFS3_RUN_MAX_BYTES / sizeof(struct ntfs_run) / 2)
30562306a36Sopenharmony_ci		run_truncate(run, (run->runs + (run->count >> 1))->vcn);
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci/*
30962306a36Sopenharmony_ci * run_add_entry
31062306a36Sopenharmony_ci *
31162306a36Sopenharmony_ci * Sets location to known state.
31262306a36Sopenharmony_ci * Run to be added may overlap with existing location.
31362306a36Sopenharmony_ci *
31462306a36Sopenharmony_ci * Return: false if of memory.
31562306a36Sopenharmony_ci */
31662306a36Sopenharmony_cibool run_add_entry(struct runs_tree *run, CLST vcn, CLST lcn, CLST len,
31762306a36Sopenharmony_ci		   bool is_mft)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	size_t used, index;
32062306a36Sopenharmony_ci	struct ntfs_run *r;
32162306a36Sopenharmony_ci	bool inrange;
32262306a36Sopenharmony_ci	CLST tail_vcn = 0, tail_len = 0, tail_lcn = 0;
32362306a36Sopenharmony_ci	bool should_add_tail = false;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	/*
32662306a36Sopenharmony_ci	 * Lookup the insertion point.
32762306a36Sopenharmony_ci	 *
32862306a36Sopenharmony_ci	 * Execute bsearch for the entry containing
32962306a36Sopenharmony_ci	 * start position question.
33062306a36Sopenharmony_ci	 */
33162306a36Sopenharmony_ci	inrange = run_lookup(run, vcn, &index);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/*
33462306a36Sopenharmony_ci	 * Shortcut here would be case of
33562306a36Sopenharmony_ci	 * range not been found but one been added
33662306a36Sopenharmony_ci	 * continues previous run.
33762306a36Sopenharmony_ci	 * This case I can directly make use of
33862306a36Sopenharmony_ci	 * existing range as my start point.
33962306a36Sopenharmony_ci	 */
34062306a36Sopenharmony_ci	if (!inrange && index > 0) {
34162306a36Sopenharmony_ci		struct ntfs_run *t = run->runs + index - 1;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		if (t->vcn + t->len == vcn &&
34462306a36Sopenharmony_ci		    (t->lcn == SPARSE_LCN) == (lcn == SPARSE_LCN) &&
34562306a36Sopenharmony_ci		    (lcn == SPARSE_LCN || lcn == t->lcn + t->len)) {
34662306a36Sopenharmony_ci			inrange = true;
34762306a36Sopenharmony_ci			index -= 1;
34862306a36Sopenharmony_ci		}
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	/*
35262306a36Sopenharmony_ci	 * At this point 'index' either points to the range
35362306a36Sopenharmony_ci	 * containing start position or to the insertion position
35462306a36Sopenharmony_ci	 * for a new range.
35562306a36Sopenharmony_ci	 * So first let's check if range I'm probing is here already.
35662306a36Sopenharmony_ci	 */
35762306a36Sopenharmony_ci	if (!inrange) {
35862306a36Sopenharmony_cirequires_new_range:
35962306a36Sopenharmony_ci		/*
36062306a36Sopenharmony_ci		 * Range was not found.
36162306a36Sopenharmony_ci		 * Insert at position 'index'
36262306a36Sopenharmony_ci		 */
36362306a36Sopenharmony_ci		used = run->count * sizeof(struct ntfs_run);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci		/*
36662306a36Sopenharmony_ci		 * Check allocated space.
36762306a36Sopenharmony_ci		 * If one is not enough to get one more entry
36862306a36Sopenharmony_ci		 * then it will be reallocated.
36962306a36Sopenharmony_ci		 */
37062306a36Sopenharmony_ci		if (run->allocated < used + sizeof(struct ntfs_run)) {
37162306a36Sopenharmony_ci			size_t bytes;
37262306a36Sopenharmony_ci			struct ntfs_run *new_ptr;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci			/* Use power of 2 for 'bytes'. */
37562306a36Sopenharmony_ci			if (!used) {
37662306a36Sopenharmony_ci				bytes = 64;
37762306a36Sopenharmony_ci			} else if (used <= 16 * PAGE_SIZE) {
37862306a36Sopenharmony_ci				if (is_power_of_2(run->allocated))
37962306a36Sopenharmony_ci					bytes = run->allocated << 1;
38062306a36Sopenharmony_ci				else
38162306a36Sopenharmony_ci					bytes = (size_t)1
38262306a36Sopenharmony_ci						<< (2 + blksize_bits(used));
38362306a36Sopenharmony_ci			} else {
38462306a36Sopenharmony_ci				bytes = run->allocated + (16 * PAGE_SIZE);
38562306a36Sopenharmony_ci			}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci			WARN_ON(!is_mft && bytes > NTFS3_RUN_MAX_BYTES);
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci			new_ptr = kvmalloc(bytes, GFP_KERNEL);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci			if (!new_ptr)
39262306a36Sopenharmony_ci				return false;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci			r = new_ptr + index;
39562306a36Sopenharmony_ci			memcpy(new_ptr, run->runs,
39662306a36Sopenharmony_ci			       index * sizeof(struct ntfs_run));
39762306a36Sopenharmony_ci			memcpy(r + 1, run->runs + index,
39862306a36Sopenharmony_ci			       sizeof(struct ntfs_run) * (run->count - index));
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci			kvfree(run->runs);
40162306a36Sopenharmony_ci			run->runs = new_ptr;
40262306a36Sopenharmony_ci			run->allocated = bytes;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci		} else {
40562306a36Sopenharmony_ci			size_t i = run->count - index;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci			r = run->runs + index;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci			/* memmove appears to be a bottle neck here... */
41062306a36Sopenharmony_ci			if (i > 0)
41162306a36Sopenharmony_ci				memmove(r + 1, r, sizeof(struct ntfs_run) * i);
41262306a36Sopenharmony_ci		}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci		r->vcn = vcn;
41562306a36Sopenharmony_ci		r->lcn = lcn;
41662306a36Sopenharmony_ci		r->len = len;
41762306a36Sopenharmony_ci		run->count += 1;
41862306a36Sopenharmony_ci	} else {
41962306a36Sopenharmony_ci		r = run->runs + index;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci		/*
42262306a36Sopenharmony_ci		 * If one of ranges was not allocated then we
42362306a36Sopenharmony_ci		 * have to split location we just matched and
42462306a36Sopenharmony_ci		 * insert current one.
42562306a36Sopenharmony_ci		 * A common case this requires tail to be reinserted
42662306a36Sopenharmony_ci		 * a recursive call.
42762306a36Sopenharmony_ci		 */
42862306a36Sopenharmony_ci		if (((lcn == SPARSE_LCN) != (r->lcn == SPARSE_LCN)) ||
42962306a36Sopenharmony_ci		    (lcn != SPARSE_LCN && lcn != r->lcn + (vcn - r->vcn))) {
43062306a36Sopenharmony_ci			CLST to_eat = vcn - r->vcn;
43162306a36Sopenharmony_ci			CLST Tovcn = to_eat + len;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci			should_add_tail = Tovcn < r->len;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci			if (should_add_tail) {
43662306a36Sopenharmony_ci				tail_lcn = r->lcn == SPARSE_LCN ?
43762306a36Sopenharmony_ci						   SPARSE_LCN :
43862306a36Sopenharmony_ci						   (r->lcn + Tovcn);
43962306a36Sopenharmony_ci				tail_vcn = r->vcn + Tovcn;
44062306a36Sopenharmony_ci				tail_len = r->len - Tovcn;
44162306a36Sopenharmony_ci			}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci			if (to_eat > 0) {
44462306a36Sopenharmony_ci				r->len = to_eat;
44562306a36Sopenharmony_ci				inrange = false;
44662306a36Sopenharmony_ci				index += 1;
44762306a36Sopenharmony_ci				goto requires_new_range;
44862306a36Sopenharmony_ci			}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci			/* lcn should match one were going to add. */
45162306a36Sopenharmony_ci			r->lcn = lcn;
45262306a36Sopenharmony_ci		}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci		/*
45562306a36Sopenharmony_ci		 * If existing range fits then were done.
45662306a36Sopenharmony_ci		 * Otherwise extend found one and fall back to range jocode.
45762306a36Sopenharmony_ci		 */
45862306a36Sopenharmony_ci		if (r->vcn + r->len < vcn + len)
45962306a36Sopenharmony_ci			r->len += len - ((r->vcn + r->len) - vcn);
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/*
46362306a36Sopenharmony_ci	 * And normalize it starting from insertion point.
46462306a36Sopenharmony_ci	 * It's possible that no insertion needed case if
46562306a36Sopenharmony_ci	 * start point lies within the range of an entry
46662306a36Sopenharmony_ci	 * that 'index' points to.
46762306a36Sopenharmony_ci	 */
46862306a36Sopenharmony_ci	if (inrange && index > 0)
46962306a36Sopenharmony_ci		index -= 1;
47062306a36Sopenharmony_ci	run_consolidate(run, index);
47162306a36Sopenharmony_ci	run_consolidate(run, index + 1);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	/*
47462306a36Sopenharmony_ci	 * A special case.
47562306a36Sopenharmony_ci	 * We have to add extra range a tail.
47662306a36Sopenharmony_ci	 */
47762306a36Sopenharmony_ci	if (should_add_tail &&
47862306a36Sopenharmony_ci	    !run_add_entry(run, tail_vcn, tail_lcn, tail_len, is_mft))
47962306a36Sopenharmony_ci		return false;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	return true;
48262306a36Sopenharmony_ci}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci/* run_collapse_range
48562306a36Sopenharmony_ci *
48662306a36Sopenharmony_ci * Helper for attr_collapse_range(),
48762306a36Sopenharmony_ci * which is helper for fallocate(collapse_range).
48862306a36Sopenharmony_ci */
48962306a36Sopenharmony_cibool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	size_t index, eat;
49262306a36Sopenharmony_ci	struct ntfs_run *r, *e, *eat_start, *eat_end;
49362306a36Sopenharmony_ci	CLST end;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (WARN_ON(!run_lookup(run, vcn, &index)))
49662306a36Sopenharmony_ci		return true; /* Should never be here. */
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	e = run->runs + run->count;
49962306a36Sopenharmony_ci	r = run->runs + index;
50062306a36Sopenharmony_ci	end = vcn + len;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	if (vcn > r->vcn) {
50362306a36Sopenharmony_ci		if (r->vcn + r->len <= end) {
50462306a36Sopenharmony_ci			/* Collapse tail of run .*/
50562306a36Sopenharmony_ci			r->len = vcn - r->vcn;
50662306a36Sopenharmony_ci		} else if (r->lcn == SPARSE_LCN) {
50762306a36Sopenharmony_ci			/* Collapse a middle part of sparsed run. */
50862306a36Sopenharmony_ci			r->len -= len;
50962306a36Sopenharmony_ci		} else {
51062306a36Sopenharmony_ci			/* Collapse a middle part of normal run, split. */
51162306a36Sopenharmony_ci			if (!run_add_entry(run, vcn, SPARSE_LCN, len, false))
51262306a36Sopenharmony_ci				return false;
51362306a36Sopenharmony_ci			return run_collapse_range(run, vcn, len);
51462306a36Sopenharmony_ci		}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci		r += 1;
51762306a36Sopenharmony_ci	}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	eat_start = r;
52062306a36Sopenharmony_ci	eat_end = r;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	for (; r < e; r++) {
52362306a36Sopenharmony_ci		CLST d;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci		if (r->vcn >= end) {
52662306a36Sopenharmony_ci			r->vcn -= len;
52762306a36Sopenharmony_ci			continue;
52862306a36Sopenharmony_ci		}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci		if (r->vcn + r->len <= end) {
53162306a36Sopenharmony_ci			/* Eat this run. */
53262306a36Sopenharmony_ci			eat_end = r + 1;
53362306a36Sopenharmony_ci			continue;
53462306a36Sopenharmony_ci		}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci		d = end - r->vcn;
53762306a36Sopenharmony_ci		if (r->lcn != SPARSE_LCN)
53862306a36Sopenharmony_ci			r->lcn += d;
53962306a36Sopenharmony_ci		r->len -= d;
54062306a36Sopenharmony_ci		r->vcn -= len - d;
54162306a36Sopenharmony_ci	}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	eat = eat_end - eat_start;
54462306a36Sopenharmony_ci	memmove(eat_start, eat_end, (e - eat_end) * sizeof(*r));
54562306a36Sopenharmony_ci	run->count -= eat;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	return true;
54862306a36Sopenharmony_ci}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci/* run_insert_range
55162306a36Sopenharmony_ci *
55262306a36Sopenharmony_ci * Helper for attr_insert_range(),
55362306a36Sopenharmony_ci * which is helper for fallocate(insert_range).
55462306a36Sopenharmony_ci */
55562306a36Sopenharmony_cibool run_insert_range(struct runs_tree *run, CLST vcn, CLST len)
55662306a36Sopenharmony_ci{
55762306a36Sopenharmony_ci	size_t index;
55862306a36Sopenharmony_ci	struct ntfs_run *r, *e;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	if (WARN_ON(!run_lookup(run, vcn, &index)))
56162306a36Sopenharmony_ci		return false; /* Should never be here. */
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	e = run->runs + run->count;
56462306a36Sopenharmony_ci	r = run->runs + index;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (vcn > r->vcn)
56762306a36Sopenharmony_ci		r += 1;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	for (; r < e; r++)
57062306a36Sopenharmony_ci		r->vcn += len;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	r = run->runs + index;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	if (vcn > r->vcn) {
57562306a36Sopenharmony_ci		/* split fragment. */
57662306a36Sopenharmony_ci		CLST len1 = vcn - r->vcn;
57762306a36Sopenharmony_ci		CLST len2 = r->len - len1;
57862306a36Sopenharmony_ci		CLST lcn2 = r->lcn == SPARSE_LCN ? SPARSE_LCN : (r->lcn + len1);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci		r->len = len1;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci		if (!run_add_entry(run, vcn + len, lcn2, len2, false))
58362306a36Sopenharmony_ci			return false;
58462306a36Sopenharmony_ci	}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	if (!run_add_entry(run, vcn, SPARSE_LCN, len, false))
58762306a36Sopenharmony_ci		return false;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	return true;
59062306a36Sopenharmony_ci}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci/*
59362306a36Sopenharmony_ci * run_get_entry - Return index-th mapped region.
59462306a36Sopenharmony_ci */
59562306a36Sopenharmony_cibool run_get_entry(const struct runs_tree *run, size_t index, CLST *vcn,
59662306a36Sopenharmony_ci		   CLST *lcn, CLST *len)
59762306a36Sopenharmony_ci{
59862306a36Sopenharmony_ci	const struct ntfs_run *r;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (index >= run->count)
60162306a36Sopenharmony_ci		return false;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	r = run->runs + index;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	if (!r->len)
60662306a36Sopenharmony_ci		return false;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	if (vcn)
60962306a36Sopenharmony_ci		*vcn = r->vcn;
61062306a36Sopenharmony_ci	if (lcn)
61162306a36Sopenharmony_ci		*lcn = r->lcn;
61262306a36Sopenharmony_ci	if (len)
61362306a36Sopenharmony_ci		*len = r->len;
61462306a36Sopenharmony_ci	return true;
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci/*
61862306a36Sopenharmony_ci * run_packed_size - Calculate the size of packed int64.
61962306a36Sopenharmony_ci */
62062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN
62162306a36Sopenharmony_cistatic inline int run_packed_size(const s64 n)
62262306a36Sopenharmony_ci{
62362306a36Sopenharmony_ci	const u8 *p = (const u8 *)&n + sizeof(n) - 1;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	if (n >= 0) {
62662306a36Sopenharmony_ci		if (p[-7] || p[-6] || p[-5] || p[-4])
62762306a36Sopenharmony_ci			p -= 4;
62862306a36Sopenharmony_ci		if (p[-3] || p[-2])
62962306a36Sopenharmony_ci			p -= 2;
63062306a36Sopenharmony_ci		if (p[-1])
63162306a36Sopenharmony_ci			p -= 1;
63262306a36Sopenharmony_ci		if (p[0] & 0x80)
63362306a36Sopenharmony_ci			p -= 1;
63462306a36Sopenharmony_ci	} else {
63562306a36Sopenharmony_ci		if (p[-7] != 0xff || p[-6] != 0xff || p[-5] != 0xff ||
63662306a36Sopenharmony_ci		    p[-4] != 0xff)
63762306a36Sopenharmony_ci			p -= 4;
63862306a36Sopenharmony_ci		if (p[-3] != 0xff || p[-2] != 0xff)
63962306a36Sopenharmony_ci			p -= 2;
64062306a36Sopenharmony_ci		if (p[-1] != 0xff)
64162306a36Sopenharmony_ci			p -= 1;
64262306a36Sopenharmony_ci		if (!(p[0] & 0x80))
64362306a36Sopenharmony_ci			p -= 1;
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci	return (const u8 *)&n + sizeof(n) - p;
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci/* Full trusted function. It does not check 'size' for errors. */
64962306a36Sopenharmony_cistatic inline void run_pack_s64(u8 *run_buf, u8 size, s64 v)
65062306a36Sopenharmony_ci{
65162306a36Sopenharmony_ci	const u8 *p = (u8 *)&v;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	switch (size) {
65462306a36Sopenharmony_ci	case 8:
65562306a36Sopenharmony_ci		run_buf[7] = p[0];
65662306a36Sopenharmony_ci		fallthrough;
65762306a36Sopenharmony_ci	case 7:
65862306a36Sopenharmony_ci		run_buf[6] = p[1];
65962306a36Sopenharmony_ci		fallthrough;
66062306a36Sopenharmony_ci	case 6:
66162306a36Sopenharmony_ci		run_buf[5] = p[2];
66262306a36Sopenharmony_ci		fallthrough;
66362306a36Sopenharmony_ci	case 5:
66462306a36Sopenharmony_ci		run_buf[4] = p[3];
66562306a36Sopenharmony_ci		fallthrough;
66662306a36Sopenharmony_ci	case 4:
66762306a36Sopenharmony_ci		run_buf[3] = p[4];
66862306a36Sopenharmony_ci		fallthrough;
66962306a36Sopenharmony_ci	case 3:
67062306a36Sopenharmony_ci		run_buf[2] = p[5];
67162306a36Sopenharmony_ci		fallthrough;
67262306a36Sopenharmony_ci	case 2:
67362306a36Sopenharmony_ci		run_buf[1] = p[6];
67462306a36Sopenharmony_ci		fallthrough;
67562306a36Sopenharmony_ci	case 1:
67662306a36Sopenharmony_ci		run_buf[0] = p[7];
67762306a36Sopenharmony_ci	}
67862306a36Sopenharmony_ci}
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci/* Full trusted function. It does not check 'size' for errors. */
68162306a36Sopenharmony_cistatic inline s64 run_unpack_s64(const u8 *run_buf, u8 size, s64 v)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	u8 *p = (u8 *)&v;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	switch (size) {
68662306a36Sopenharmony_ci	case 8:
68762306a36Sopenharmony_ci		p[0] = run_buf[7];
68862306a36Sopenharmony_ci		fallthrough;
68962306a36Sopenharmony_ci	case 7:
69062306a36Sopenharmony_ci		p[1] = run_buf[6];
69162306a36Sopenharmony_ci		fallthrough;
69262306a36Sopenharmony_ci	case 6:
69362306a36Sopenharmony_ci		p[2] = run_buf[5];
69462306a36Sopenharmony_ci		fallthrough;
69562306a36Sopenharmony_ci	case 5:
69662306a36Sopenharmony_ci		p[3] = run_buf[4];
69762306a36Sopenharmony_ci		fallthrough;
69862306a36Sopenharmony_ci	case 4:
69962306a36Sopenharmony_ci		p[4] = run_buf[3];
70062306a36Sopenharmony_ci		fallthrough;
70162306a36Sopenharmony_ci	case 3:
70262306a36Sopenharmony_ci		p[5] = run_buf[2];
70362306a36Sopenharmony_ci		fallthrough;
70462306a36Sopenharmony_ci	case 2:
70562306a36Sopenharmony_ci		p[6] = run_buf[1];
70662306a36Sopenharmony_ci		fallthrough;
70762306a36Sopenharmony_ci	case 1:
70862306a36Sopenharmony_ci		p[7] = run_buf[0];
70962306a36Sopenharmony_ci	}
71062306a36Sopenharmony_ci	return v;
71162306a36Sopenharmony_ci}
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci#else
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_cistatic inline int run_packed_size(const s64 n)
71662306a36Sopenharmony_ci{
71762306a36Sopenharmony_ci	const u8 *p = (const u8 *)&n;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	if (n >= 0) {
72062306a36Sopenharmony_ci		if (p[7] || p[6] || p[5] || p[4])
72162306a36Sopenharmony_ci			p += 4;
72262306a36Sopenharmony_ci		if (p[3] || p[2])
72362306a36Sopenharmony_ci			p += 2;
72462306a36Sopenharmony_ci		if (p[1])
72562306a36Sopenharmony_ci			p += 1;
72662306a36Sopenharmony_ci		if (p[0] & 0x80)
72762306a36Sopenharmony_ci			p += 1;
72862306a36Sopenharmony_ci	} else {
72962306a36Sopenharmony_ci		if (p[7] != 0xff || p[6] != 0xff || p[5] != 0xff ||
73062306a36Sopenharmony_ci		    p[4] != 0xff)
73162306a36Sopenharmony_ci			p += 4;
73262306a36Sopenharmony_ci		if (p[3] != 0xff || p[2] != 0xff)
73362306a36Sopenharmony_ci			p += 2;
73462306a36Sopenharmony_ci		if (p[1] != 0xff)
73562306a36Sopenharmony_ci			p += 1;
73662306a36Sopenharmony_ci		if (!(p[0] & 0x80))
73762306a36Sopenharmony_ci			p += 1;
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	return 1 + p - (const u8 *)&n;
74162306a36Sopenharmony_ci}
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci/* Full trusted function. It does not check 'size' for errors. */
74462306a36Sopenharmony_cistatic inline void run_pack_s64(u8 *run_buf, u8 size, s64 v)
74562306a36Sopenharmony_ci{
74662306a36Sopenharmony_ci	const u8 *p = (u8 *)&v;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	/* memcpy( run_buf, &v, size); Is it faster? */
74962306a36Sopenharmony_ci	switch (size) {
75062306a36Sopenharmony_ci	case 8:
75162306a36Sopenharmony_ci		run_buf[7] = p[7];
75262306a36Sopenharmony_ci		fallthrough;
75362306a36Sopenharmony_ci	case 7:
75462306a36Sopenharmony_ci		run_buf[6] = p[6];
75562306a36Sopenharmony_ci		fallthrough;
75662306a36Sopenharmony_ci	case 6:
75762306a36Sopenharmony_ci		run_buf[5] = p[5];
75862306a36Sopenharmony_ci		fallthrough;
75962306a36Sopenharmony_ci	case 5:
76062306a36Sopenharmony_ci		run_buf[4] = p[4];
76162306a36Sopenharmony_ci		fallthrough;
76262306a36Sopenharmony_ci	case 4:
76362306a36Sopenharmony_ci		run_buf[3] = p[3];
76462306a36Sopenharmony_ci		fallthrough;
76562306a36Sopenharmony_ci	case 3:
76662306a36Sopenharmony_ci		run_buf[2] = p[2];
76762306a36Sopenharmony_ci		fallthrough;
76862306a36Sopenharmony_ci	case 2:
76962306a36Sopenharmony_ci		run_buf[1] = p[1];
77062306a36Sopenharmony_ci		fallthrough;
77162306a36Sopenharmony_ci	case 1:
77262306a36Sopenharmony_ci		run_buf[0] = p[0];
77362306a36Sopenharmony_ci	}
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci/* full trusted function. It does not check 'size' for errors */
77762306a36Sopenharmony_cistatic inline s64 run_unpack_s64(const u8 *run_buf, u8 size, s64 v)
77862306a36Sopenharmony_ci{
77962306a36Sopenharmony_ci	u8 *p = (u8 *)&v;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	/* memcpy( &v, run_buf, size); Is it faster? */
78262306a36Sopenharmony_ci	switch (size) {
78362306a36Sopenharmony_ci	case 8:
78462306a36Sopenharmony_ci		p[7] = run_buf[7];
78562306a36Sopenharmony_ci		fallthrough;
78662306a36Sopenharmony_ci	case 7:
78762306a36Sopenharmony_ci		p[6] = run_buf[6];
78862306a36Sopenharmony_ci		fallthrough;
78962306a36Sopenharmony_ci	case 6:
79062306a36Sopenharmony_ci		p[5] = run_buf[5];
79162306a36Sopenharmony_ci		fallthrough;
79262306a36Sopenharmony_ci	case 5:
79362306a36Sopenharmony_ci		p[4] = run_buf[4];
79462306a36Sopenharmony_ci		fallthrough;
79562306a36Sopenharmony_ci	case 4:
79662306a36Sopenharmony_ci		p[3] = run_buf[3];
79762306a36Sopenharmony_ci		fallthrough;
79862306a36Sopenharmony_ci	case 3:
79962306a36Sopenharmony_ci		p[2] = run_buf[2];
80062306a36Sopenharmony_ci		fallthrough;
80162306a36Sopenharmony_ci	case 2:
80262306a36Sopenharmony_ci		p[1] = run_buf[1];
80362306a36Sopenharmony_ci		fallthrough;
80462306a36Sopenharmony_ci	case 1:
80562306a36Sopenharmony_ci		p[0] = run_buf[0];
80662306a36Sopenharmony_ci	}
80762306a36Sopenharmony_ci	return v;
80862306a36Sopenharmony_ci}
80962306a36Sopenharmony_ci#endif
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci/*
81262306a36Sopenharmony_ci * run_pack - Pack runs into buffer.
81362306a36Sopenharmony_ci *
81462306a36Sopenharmony_ci * packed_vcns - How much runs we have packed.
81562306a36Sopenharmony_ci * packed_size - How much bytes we have used run_buf.
81662306a36Sopenharmony_ci */
81762306a36Sopenharmony_ciint run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf,
81862306a36Sopenharmony_ci	     u32 run_buf_size, CLST *packed_vcns)
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	CLST next_vcn, vcn, lcn;
82162306a36Sopenharmony_ci	CLST prev_lcn = 0;
82262306a36Sopenharmony_ci	CLST evcn1 = svcn + len;
82362306a36Sopenharmony_ci	const struct ntfs_run *r, *r_end;
82462306a36Sopenharmony_ci	int packed_size = 0;
82562306a36Sopenharmony_ci	size_t i;
82662306a36Sopenharmony_ci	s64 dlcn;
82762306a36Sopenharmony_ci	int offset_size, size_size, tmp;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	*packed_vcns = 0;
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	if (!len)
83262306a36Sopenharmony_ci		goto out;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	/* Check all required entries [svcn, encv1) available. */
83562306a36Sopenharmony_ci	if (!run_lookup(run, svcn, &i))
83662306a36Sopenharmony_ci		return -ENOENT;
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	r_end = run->runs + run->count;
83962306a36Sopenharmony_ci	r = run->runs + i;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	for (next_vcn = r->vcn + r->len; next_vcn < evcn1;
84262306a36Sopenharmony_ci	     next_vcn = r->vcn + r->len) {
84362306a36Sopenharmony_ci		if (++r >= r_end || r->vcn != next_vcn)
84462306a36Sopenharmony_ci			return -ENOENT;
84562306a36Sopenharmony_ci	}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	/* Repeat cycle above and pack runs. Assume no errors. */
84862306a36Sopenharmony_ci	r = run->runs + i;
84962306a36Sopenharmony_ci	len = svcn - r->vcn;
85062306a36Sopenharmony_ci	vcn = svcn;
85162306a36Sopenharmony_ci	lcn = r->lcn == SPARSE_LCN ? SPARSE_LCN : (r->lcn + len);
85262306a36Sopenharmony_ci	len = r->len - len;
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	for (;;) {
85562306a36Sopenharmony_ci		next_vcn = vcn + len;
85662306a36Sopenharmony_ci		if (next_vcn > evcn1)
85762306a36Sopenharmony_ci			len = evcn1 - vcn;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci		/* How much bytes required to pack len. */
86062306a36Sopenharmony_ci		size_size = run_packed_size(len);
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci		/* offset_size - How much bytes is packed dlcn. */
86362306a36Sopenharmony_ci		if (lcn == SPARSE_LCN) {
86462306a36Sopenharmony_ci			offset_size = 0;
86562306a36Sopenharmony_ci			dlcn = 0;
86662306a36Sopenharmony_ci		} else {
86762306a36Sopenharmony_ci			/* NOTE: lcn can be less than prev_lcn! */
86862306a36Sopenharmony_ci			dlcn = (s64)lcn - prev_lcn;
86962306a36Sopenharmony_ci			offset_size = run_packed_size(dlcn);
87062306a36Sopenharmony_ci			prev_lcn = lcn;
87162306a36Sopenharmony_ci		}
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci		tmp = run_buf_size - packed_size - 2 - offset_size;
87462306a36Sopenharmony_ci		if (tmp <= 0)
87562306a36Sopenharmony_ci			goto out;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci		/* Can we store this entire run. */
87862306a36Sopenharmony_ci		if (tmp < size_size)
87962306a36Sopenharmony_ci			goto out;
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci		if (run_buf) {
88262306a36Sopenharmony_ci			/* Pack run header. */
88362306a36Sopenharmony_ci			run_buf[0] = ((u8)(size_size | (offset_size << 4)));
88462306a36Sopenharmony_ci			run_buf += 1;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci			/* Pack the length of run. */
88762306a36Sopenharmony_ci			run_pack_s64(run_buf, size_size, len);
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci			run_buf += size_size;
89062306a36Sopenharmony_ci			/* Pack the offset from previous LCN. */
89162306a36Sopenharmony_ci			run_pack_s64(run_buf, offset_size, dlcn);
89262306a36Sopenharmony_ci			run_buf += offset_size;
89362306a36Sopenharmony_ci		}
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci		packed_size += 1 + offset_size + size_size;
89662306a36Sopenharmony_ci		*packed_vcns += len;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci		if (packed_size + 1 >= run_buf_size || next_vcn >= evcn1)
89962306a36Sopenharmony_ci			goto out;
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci		r += 1;
90262306a36Sopenharmony_ci		vcn = r->vcn;
90362306a36Sopenharmony_ci		lcn = r->lcn;
90462306a36Sopenharmony_ci		len = r->len;
90562306a36Sopenharmony_ci	}
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ciout:
90862306a36Sopenharmony_ci	/* Store last zero. */
90962306a36Sopenharmony_ci	if (run_buf)
91062306a36Sopenharmony_ci		run_buf[0] = 0;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	return packed_size + 1;
91362306a36Sopenharmony_ci}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci/*
91662306a36Sopenharmony_ci * run_unpack - Unpack packed runs from @run_buf.
91762306a36Sopenharmony_ci *
91862306a36Sopenharmony_ci * Return: Error if negative, or real used bytes.
91962306a36Sopenharmony_ci */
92062306a36Sopenharmony_ciint run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
92162306a36Sopenharmony_ci	       CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
92262306a36Sopenharmony_ci	       int run_buf_size)
92362306a36Sopenharmony_ci{
92462306a36Sopenharmony_ci	u64 prev_lcn, vcn64, lcn, next_vcn;
92562306a36Sopenharmony_ci	const u8 *run_last, *run_0;
92662306a36Sopenharmony_ci	bool is_mft = ino == MFT_REC_MFT;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	if (run_buf_size < 0)
92962306a36Sopenharmony_ci		return -EINVAL;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	/* Check for empty. */
93262306a36Sopenharmony_ci	if (evcn + 1 == svcn)
93362306a36Sopenharmony_ci		return 0;
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	if (evcn < svcn)
93662306a36Sopenharmony_ci		return -EINVAL;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	run_0 = run_buf;
93962306a36Sopenharmony_ci	run_last = run_buf + run_buf_size;
94062306a36Sopenharmony_ci	prev_lcn = 0;
94162306a36Sopenharmony_ci	vcn64 = svcn;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	/* Read all runs the chain. */
94462306a36Sopenharmony_ci	/* size_size - How much bytes is packed len. */
94562306a36Sopenharmony_ci	while (run_buf < run_last) {
94662306a36Sopenharmony_ci		/* size_size - How much bytes is packed len. */
94762306a36Sopenharmony_ci		u8 size_size = *run_buf & 0xF;
94862306a36Sopenharmony_ci		/* offset_size - How much bytes is packed dlcn. */
94962306a36Sopenharmony_ci		u8 offset_size = *run_buf++ >> 4;
95062306a36Sopenharmony_ci		u64 len;
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci		if (!size_size)
95362306a36Sopenharmony_ci			break;
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci		/*
95662306a36Sopenharmony_ci		 * Unpack runs.
95762306a36Sopenharmony_ci		 * NOTE: Runs are stored little endian order
95862306a36Sopenharmony_ci		 * "len" is unsigned value, "dlcn" is signed.
95962306a36Sopenharmony_ci		 * Large positive number requires to store 5 bytes
96062306a36Sopenharmony_ci		 * e.g.: 05 FF 7E FF FF 00 00 00
96162306a36Sopenharmony_ci		 */
96262306a36Sopenharmony_ci		if (size_size > 8)
96362306a36Sopenharmony_ci			return -EINVAL;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci		len = run_unpack_s64(run_buf, size_size, 0);
96662306a36Sopenharmony_ci		/* Skip size_size. */
96762306a36Sopenharmony_ci		run_buf += size_size;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci		if (!len)
97062306a36Sopenharmony_ci			return -EINVAL;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci		if (!offset_size)
97362306a36Sopenharmony_ci			lcn = SPARSE_LCN64;
97462306a36Sopenharmony_ci		else if (offset_size <= 8) {
97562306a36Sopenharmony_ci			s64 dlcn;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci			/* Initial value of dlcn is -1 or 0. */
97862306a36Sopenharmony_ci			dlcn = (run_buf[offset_size - 1] & 0x80) ? (s64)-1 : 0;
97962306a36Sopenharmony_ci			dlcn = run_unpack_s64(run_buf, offset_size, dlcn);
98062306a36Sopenharmony_ci			/* Skip offset_size. */
98162306a36Sopenharmony_ci			run_buf += offset_size;
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci			if (!dlcn)
98462306a36Sopenharmony_ci				return -EINVAL;
98562306a36Sopenharmony_ci			lcn = prev_lcn + dlcn;
98662306a36Sopenharmony_ci			prev_lcn = lcn;
98762306a36Sopenharmony_ci		} else
98862306a36Sopenharmony_ci			return -EINVAL;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci		next_vcn = vcn64 + len;
99162306a36Sopenharmony_ci		/* Check boundary. */
99262306a36Sopenharmony_ci		if (next_vcn > evcn + 1)
99362306a36Sopenharmony_ci			return -EINVAL;
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci#ifndef CONFIG_NTFS3_64BIT_CLUSTER
99662306a36Sopenharmony_ci		if (next_vcn > 0x100000000ull || (lcn + len) > 0x100000000ull) {
99762306a36Sopenharmony_ci			ntfs_err(
99862306a36Sopenharmony_ci				sbi->sb,
99962306a36Sopenharmony_ci				"This driver is compiled without CONFIG_NTFS3_64BIT_CLUSTER (like windows driver).\n"
100062306a36Sopenharmony_ci				"Volume contains 64 bits run: vcn %llx, lcn %llx, len %llx.\n"
100162306a36Sopenharmony_ci				"Activate CONFIG_NTFS3_64BIT_CLUSTER to process this case",
100262306a36Sopenharmony_ci				vcn64, lcn, len);
100362306a36Sopenharmony_ci			return -EOPNOTSUPP;
100462306a36Sopenharmony_ci		}
100562306a36Sopenharmony_ci#endif
100662306a36Sopenharmony_ci		if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) {
100762306a36Sopenharmony_ci			/* LCN range is out of volume. */
100862306a36Sopenharmony_ci			return -EINVAL;
100962306a36Sopenharmony_ci		}
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci		if (!run)
101262306a36Sopenharmony_ci			; /* Called from check_attr(fslog.c) to check run. */
101362306a36Sopenharmony_ci		else if (run == RUN_DEALLOCATE) {
101462306a36Sopenharmony_ci			/*
101562306a36Sopenharmony_ci			 * Called from ni_delete_all to free clusters
101662306a36Sopenharmony_ci			 * without storing in run.
101762306a36Sopenharmony_ci			 */
101862306a36Sopenharmony_ci			if (lcn != SPARSE_LCN64)
101962306a36Sopenharmony_ci				mark_as_free_ex(sbi, lcn, len, true);
102062306a36Sopenharmony_ci		} else if (vcn64 >= vcn) {
102162306a36Sopenharmony_ci			if (!run_add_entry(run, vcn64, lcn, len, is_mft))
102262306a36Sopenharmony_ci				return -ENOMEM;
102362306a36Sopenharmony_ci		} else if (next_vcn > vcn) {
102462306a36Sopenharmony_ci			u64 dlen = vcn - vcn64;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci			if (!run_add_entry(run, vcn, lcn + dlen, len - dlen,
102762306a36Sopenharmony_ci					   is_mft))
102862306a36Sopenharmony_ci				return -ENOMEM;
102962306a36Sopenharmony_ci		}
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci		vcn64 = next_vcn;
103262306a36Sopenharmony_ci	}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	if (vcn64 != evcn + 1) {
103562306a36Sopenharmony_ci		/* Not expected length of unpacked runs. */
103662306a36Sopenharmony_ci		return -EINVAL;
103762306a36Sopenharmony_ci	}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	return run_buf - run_0;
104062306a36Sopenharmony_ci}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci#ifdef NTFS3_CHECK_FREE_CLST
104362306a36Sopenharmony_ci/*
104462306a36Sopenharmony_ci * run_unpack_ex - Unpack packed runs from "run_buf".
104562306a36Sopenharmony_ci *
104662306a36Sopenharmony_ci * Checks unpacked runs to be used in bitmap.
104762306a36Sopenharmony_ci *
104862306a36Sopenharmony_ci * Return: Error if negative, or real used bytes.
104962306a36Sopenharmony_ci */
105062306a36Sopenharmony_ciint run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
105162306a36Sopenharmony_ci		  CLST svcn, CLST evcn, CLST vcn, const u8 *run_buf,
105262306a36Sopenharmony_ci		  int run_buf_size)
105362306a36Sopenharmony_ci{
105462306a36Sopenharmony_ci	int ret, err;
105562306a36Sopenharmony_ci	CLST next_vcn, lcn, len;
105662306a36Sopenharmony_ci	size_t index;
105762306a36Sopenharmony_ci	bool ok;
105862306a36Sopenharmony_ci	struct wnd_bitmap *wnd;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	ret = run_unpack(run, sbi, ino, svcn, evcn, vcn, run_buf, run_buf_size);
106162306a36Sopenharmony_ci	if (ret <= 0)
106262306a36Sopenharmony_ci		return ret;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	if (!sbi->used.bitmap.sb || !run || run == RUN_DEALLOCATE)
106562306a36Sopenharmony_ci		return ret;
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	if (ino == MFT_REC_BADCLUST)
106862306a36Sopenharmony_ci		return ret;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	next_vcn = vcn = svcn;
107162306a36Sopenharmony_ci	wnd = &sbi->used.bitmap;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	for (ok = run_lookup_entry(run, vcn, &lcn, &len, &index);
107462306a36Sopenharmony_ci	     next_vcn <= evcn;
107562306a36Sopenharmony_ci	     ok = run_get_entry(run, ++index, &vcn, &lcn, &len)) {
107662306a36Sopenharmony_ci		if (!ok || next_vcn != vcn)
107762306a36Sopenharmony_ci			return -EINVAL;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci		next_vcn = vcn + len;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci		if (lcn == SPARSE_LCN)
108262306a36Sopenharmony_ci			continue;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci		if (sbi->flags & NTFS_FLAGS_NEED_REPLAY)
108562306a36Sopenharmony_ci			continue;
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci		down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
108862306a36Sopenharmony_ci		/* Check for free blocks. */
108962306a36Sopenharmony_ci		ok = wnd_is_used(wnd, lcn, len);
109062306a36Sopenharmony_ci		up_read(&wnd->rw_lock);
109162306a36Sopenharmony_ci		if (ok)
109262306a36Sopenharmony_ci			continue;
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci		/* Looks like volume is corrupted. */
109562306a36Sopenharmony_ci		ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci		if (down_write_trylock(&wnd->rw_lock)) {
109862306a36Sopenharmony_ci			/* Mark all zero bits as used in range [lcn, lcn+len). */
109962306a36Sopenharmony_ci			size_t done;
110062306a36Sopenharmony_ci			err = wnd_set_used_safe(wnd, lcn, len, &done);
110162306a36Sopenharmony_ci			up_write(&wnd->rw_lock);
110262306a36Sopenharmony_ci			if (err)
110362306a36Sopenharmony_ci				return err;
110462306a36Sopenharmony_ci		}
110562306a36Sopenharmony_ci	}
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	return ret;
110862306a36Sopenharmony_ci}
110962306a36Sopenharmony_ci#endif
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci/*
111262306a36Sopenharmony_ci * run_get_highest_vcn
111362306a36Sopenharmony_ci *
111462306a36Sopenharmony_ci * Return the highest vcn from a mapping pairs array
111562306a36Sopenharmony_ci * it used while replaying log file.
111662306a36Sopenharmony_ci */
111762306a36Sopenharmony_ciint run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn)
111862306a36Sopenharmony_ci{
111962306a36Sopenharmony_ci	u64 vcn64 = vcn;
112062306a36Sopenharmony_ci	u8 size_size;
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	while ((size_size = *run_buf & 0xF)) {
112362306a36Sopenharmony_ci		u8 offset_size = *run_buf++ >> 4;
112462306a36Sopenharmony_ci		u64 len;
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci		if (size_size > 8 || offset_size > 8)
112762306a36Sopenharmony_ci			return -EINVAL;
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci		len = run_unpack_s64(run_buf, size_size, 0);
113062306a36Sopenharmony_ci		if (!len)
113162306a36Sopenharmony_ci			return -EINVAL;
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci		run_buf += size_size + offset_size;
113462306a36Sopenharmony_ci		vcn64 += len;
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci#ifndef CONFIG_NTFS3_64BIT_CLUSTER
113762306a36Sopenharmony_ci		if (vcn64 > 0x100000000ull)
113862306a36Sopenharmony_ci			return -EINVAL;
113962306a36Sopenharmony_ci#endif
114062306a36Sopenharmony_ci	}
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	*highest_vcn = vcn64 - 1;
114362306a36Sopenharmony_ci	return 0;
114462306a36Sopenharmony_ci}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci/*
114762306a36Sopenharmony_ci * run_clone
114862306a36Sopenharmony_ci *
114962306a36Sopenharmony_ci * Make a copy of run
115062306a36Sopenharmony_ci */
115162306a36Sopenharmony_ciint run_clone(const struct runs_tree *run, struct runs_tree *new_run)
115262306a36Sopenharmony_ci{
115362306a36Sopenharmony_ci	size_t bytes = run->count * sizeof(struct ntfs_run);
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	if (bytes > new_run->allocated) {
115662306a36Sopenharmony_ci		struct ntfs_run *new_ptr = kvmalloc(bytes, GFP_KERNEL);
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci		if (!new_ptr)
115962306a36Sopenharmony_ci			return -ENOMEM;
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci		kvfree(new_run->runs);
116262306a36Sopenharmony_ci		new_run->runs = new_ptr;
116362306a36Sopenharmony_ci		new_run->allocated = bytes;
116462306a36Sopenharmony_ci	}
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	memcpy(new_run->runs, run->runs, bytes);
116762306a36Sopenharmony_ci	new_run->count = run->count;
116862306a36Sopenharmony_ci	return 0;
116962306a36Sopenharmony_ci}
1170