1/*
2 * ntfs_attr_list.c - NTFS kernel attribute list attribute operations.
3 *
4 * Copyright (c) 2006-2008 Anton Altaparmakov.  All Rights Reserved.
5 * Portions Copyright (c) 2006-2008 Apple Inc.  All Rights Reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 *    this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 *    this list of conditions and the following disclaimer in the documentation
14 *    and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its
16 *    contributors may be used to endorse or promote products derived from this
17 *    software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * ALTERNATIVELY, provided that this notice and licensing terms are retained in
31 * full, this file may be redistributed and/or modified under the terms of the
32 * GNU General Public License (GPL) Version 2, in which case the provisions of
33 * that version of the GPL will apply to you instead of the license terms
34 * above.  You can obtain a copy of the GPL Version 2 at
35 * http://developer.apple.com/opensource/licenses/gpl-2.txt.
36 */
37
38#include <sys/errno.h>
39
40#include <string.h>
41
42#include <libkern/OSMalloc.h>
43
44#include <kern/sched_prim.h>
45
46#include "ntfs.h"
47#include "ntfs_attr.h"
48#include "ntfs_attr_list.h"
49#include "ntfs_debug.h"
50#include "ntfs_endian.h"
51#include "ntfs_inode.h"
52#include "ntfs_layout.h"
53#include "ntfs_lcnalloc.h"
54#include "ntfs_mft.h"
55#include "ntfs_types.h"
56#include "ntfs_unistr.h"
57#include "ntfs_volume.h"
58
59/**
60 * ntfs_attr_list_is_needed - check if attribute list attribute is still needed
61 * @ni:				base ntfs inode to check
62 * @skip_entry:			attribute list entry to skip when checking
63 * @attr_list_is_needed:	pointer in which to return the result
64 *
65 * Check the attribute list attribute of the base ntfs inode @ni.  If there are
66 * no attribute list attribute entries other than @skip_entry which reference
67 * extent mft records it means the attribute list attribute is no longer needed
68 * thus we set *@attr_list_is_needed to false and return success.
69 *
70 * If there are attribute list attribute entries other than @skip_entry which
71 * reference extent mft records the attribute list attribute is still needed
72 * thus we set *@attr_list_is_needed to true and return success.
73 *
74 * Return 0 on success and errno on error.  On success *@attr_list_is_needed is
75 * set to true if the attribute list attribute is still needed and to false if
76 * it is no longer needed (and hence can be deleted).  On error
77 * *@attr_list_is_needed is not defined.
78 */
79errno_t ntfs_attr_list_is_needed(ntfs_inode *ni, ATTR_LIST_ENTRY *skip_entry,
80		BOOL *attr_list_is_needed)
81{
82	leMFT_REF base_mref;
83	ATTR_LIST_ENTRY *entry;
84	u8 *al, *al_end;
85
86	ntfs_debug("Entering for base mft_no 0x%llx.",
87			(unsigned long long)ni->mft_no);
88	/* Scan all entries in the attribute list attribute. */
89	base_mref = MK_LE_MREF(ni->mft_no, ni->seq_no);
90	*attr_list_is_needed = FALSE;
91	al = ni->attr_list;
92	entry = (ATTR_LIST_ENTRY*)al;
93	al_end = (u8*)al + ni->attr_list_size;
94	for (;; entry = (ATTR_LIST_ENTRY*)((u8*)entry +
95			le16_to_cpu(entry->length))) {
96		/* Out of bounds check. */
97		if ((u8*)entry < al || (u8*)entry > al_end)
98			goto err;
99		/* Catch the end of the attribute list. */
100		if ((u8*)entry == al_end)
101			break;
102		/* More sanity checks. */
103		if (!entry->length || (u8*)entry + sizeof(*entry) > al_end)
104			goto err;
105		/*
106		 * If there is an entry to be skipped and the current entry
107		 * matches it, then skip this entry.  We do not need to check
108		 * whether @skip_entry is NULL because @entry cannot be NULL so
109		 * this condition would never be true in @skip_entry is NULL.
110		 */
111		if (entry == skip_entry)
112			continue;
113		/*
114		 * If this entry references an extent mft record no need to
115		 * search any further, we know there is at least one extent mft
116		 * record in use thus the attribute list attribute is still
117		 * needed.
118		 */
119		if (entry->mft_reference != base_mref) {
120			*attr_list_is_needed = TRUE;
121			break;
122		}
123	}
124	ntfs_debug("Done for mft_no 0x%llx, attribute list attribute is "
125			"%s needed.", (unsigned long long)ni->mft_no,
126			(*attr_list_is_needed) ? "still" : "no longer");
127	return 0;
128err:
129	ntfs_error(ni->vol->mp, "Attribute list attribute of mft_no 0x%llx is "
130			"corrupt.  Unmount and run chkdsk.",
131			(unsigned long long)ni->mft_no);
132	NVolSetErrors(ni->vol);
133	return EIO;
134}
135
136/**
137 * ntfs_attr_list_delete - delete the attribute list attribute of an ntfs inode
138 * @ni:		base ntfs inode whose attribute list attribugte to delete
139 * @ctx:	initialized attribute search context
140 *
141 * Delete the attribute list attribute of the base ntfs inode @ni.
142 *
143 * @ctx is an initialized, ready to use attribute search context that we use to
144 * look up the attribute list attribute in the mapped, base mft record.
145 *
146 * This function assumes that the caller has ensured that the attribute list
147 * attribute is no longer needed by calling ntfs_attr_list_is_needed().
148 *
149 * Return 0 on success and errno on error.
150 */
151errno_t ntfs_attr_list_delete(ntfs_inode *ni, ntfs_attr_search_ctx *ctx)
152{
153	errno_t err;
154
155	ntfs_debug("Entering for base mft_no 0x%llx.",
156			(unsigned long long)ni->mft_no);
157	/* Find the attribute list attribute in the base mft record. */
158	err = ntfs_attr_find_in_mft_record(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
159			NULL, 0, ctx);
160	if (err)
161		goto err;
162	/*
163	 * If the attribute list attribute is non-resident we need to free the
164	 * allocated clusters and runlist.
165	 */
166	if (ctx->a->non_resident) {
167		/* Free the allocated clusters. */
168		err = ntfs_cluster_free_from_rl(ni->vol, ni->attr_list_rl.rl,
169				0, -1, NULL);
170		if (err) {
171			ntfs_warning(ni->vol->mp, "Failed to free some "
172					"allocated clusters belonging to the "
173					"attribute list attribute of mft_no "
174					"0x%llx (error %d).  Continuing "
175					"regardless.  Unmount and run chkdsk "
176					"to recover the lost space.",
177					(unsigned long long)ni->mft_no, err);
178			NVolSetErrors(ni->vol);
179		}
180		/* Free the runlist of the attribute list attribute. */
181		OSFree(ni->attr_list_rl.rl, ni->attr_list_rl.alloc,
182				ntfs_malloc_tag);
183		ni->attr_list_rl.alloc = 0;
184	}
185	/* Delete the attribute list attribute record. */
186	ntfs_attr_record_delete_internal(ctx->m, ctx->a);
187	/* Make sure the modified base mft record is written out. */
188	NInoSetMrecNeedsDirtying(ni);
189	/* Update the in-memory base inode and free memory. */
190	ni->attr_list_size = 0;
191	OSFree(ni->attr_list, ni->attr_list_alloc, ntfs_malloc_tag);
192	ni->attr_list_alloc = 0;
193	NInoClearAttrList(ni);
194	ntfs_debug("Done.");
195	return 0;
196err:
197	ntfs_error(ni->vol->mp, "Failed to find attribute list attribute in "
198			"base mft_no 0x%llx (error %d).  Unmount and run "
199			"chkdsk.", (unsigned long long)ni->mft_no, err);
200	NVolSetErrors(ni->vol);
201	return EIO;
202}
203
204/**
205 * ntfs_attr_list_add - add an attribute list attribute to an inode
206 * @base_ni:	base ntfs inode to which to add an attribute list attribute
207 * @m:		base mft record of the base ntfs inode @base_ni
208 * @ctx:	attribute search context describing attribute being resized
209 *
210 * Add an attribute list attribute to the base ntfs inode @base_ni with mapped
211 * base mft record @m.
212 *
213 * @ctx (if not NULL) is an attribute search context describing the attribute
214 * being resized which is causing the attribute list attribute to be added.
215 * The pointers in the search context are updated with the new location of the
216 * attribute in the mft record.  @ctx is also updated to reflect that this is
217 * now a search in an attribute list attribute containing inode.
218 *
219 * Return 0 on success and the negative error code on error.
220 *
221 * WARNING: If @ctx is supplied, regardless of whether success or failure is
222 *	    returned, you need to check @ctx->is_error and if 1 the @ctx is no
223 *	    longer valid, i.e. you need to either call
224 *	    ntfs_attr_search_ctx_reinit() or ntfs_attr_search_ctx_put() on it.
225 *	    In that case @ctx->error will give you the error code for why the
226 *	    mapping of the inode failed.
227 */
228errno_t ntfs_attr_list_add(ntfs_inode *base_ni, MFT_RECORD *m,
229		ntfs_attr_search_ctx *ctx)
230{
231	leMFT_REF mref;
232	ntfs_volume *vol;
233	ATTR_RECORD *a;
234	u8 *al, *al_end;
235	ATTR_LIST_ENTRY *al_entry;
236	unsigned al_alloc, al_size, bytes_free, attr_len, mp_size = 0;
237	errno_t err, err2;
238	BOOL for_mft, have_std_info, have_idx_root, insert_resident;
239	ntfs_attr_search_ctx al_ctx;
240
241	vol = base_ni->vol;
242	for_mft = FALSE;
243	if (base_ni == vol->mft_ni)
244		for_mft = TRUE;
245	ntfs_debug("Entering for mft_no 0x%llx%s.",
246			(unsigned long long)base_ni->mft_no,
247			for_mft ? ", for $MFT" : "");
248	lck_rw_lock_exclusive(&base_ni->attr_list_rl.lock);
249	if (NInoAttrList(base_ni))
250		panic("%s(): NInoAttrList(base_ni)\n", __FUNCTION__);
251	if (!m)
252		panic("%s(): !m\n", __FUNCTION__);
253	if (ctx && m != ctx->m)
254		panic("%s(): ctx && m != ctx->m\n", __FUNCTION__);
255	if (base_ni->attr_list_alloc)
256		panic("%s(): base_ni->attr_list_alloc\n", __FUNCTION__);
257	if (base_ni->attr_list_rl.alloc)
258		panic("%s(): base_ni->attr_list_rl.alloc\n", __FUNCTION__);
259	if (base_ni->attr_list_rl.elements)
260		panic("%s(): base_ni->attr_list_rl.elements\n", __FUNCTION__);
261	have_idx_root = have_std_info = FALSE;
262	/*
263	 * Iterate over all the attribute records in the base mft record and
264	 * build the attribute list attribute up in memory.
265	 */
266	al_alloc = NTFS_ALLOC_BLOCK;
267	al = OSMalloc(NTFS_ALLOC_BLOCK, ntfs_malloc_tag);
268	if (!al) {
269		ntfs_error(vol->mp, "Not enough memory to allocate buffer for "
270				"attribute list attribute.");
271		lck_rw_unlock_exclusive(&base_ni->attr_list_rl.lock);
272		return ENOMEM;
273	}
274	al_end = al + NTFS_ALLOC_BLOCK;
275	al_entry = (ATTR_LIST_ENTRY*)al;
276	ntfs_attr_search_ctx_init(&al_ctx, base_ni, m);
277	al_ctx.is_iteration = 1;
278	mref = MK_LE_MREF(base_ni->mft_no, base_ni->seq_no);
279	/* Maximum number of usable bytes in the mft record. */
280	bytes_free = le32_to_cpu(m->bytes_allocated) -
281			le16_to_cpu(m->attrs_offset);
282	do {
283		unsigned al_entry_len, len;
284
285		/* Get the next attribute in the mft record. */
286		err = ntfs_attr_find_in_mft_record(AT_UNUSED, NULL, 0, NULL, 0,
287				&al_ctx);
288		if (err) {
289			/*
290			 * If we reached the end we now have all the attribute
291			 * records in the attribute list attribute buffer.
292			 */
293			if (err == ENOENT)
294				break;
295			ntfs_error(vol->mp, "Failed to iterate over "
296					"attribute records in base mft record "
297					"(error %d).", err);
298			goto free_err;
299		}
300		a = al_ctx.a;
301		if (a->type == AT_ATTRIBUTE_LIST) {
302			ntfs_error(vol->mp, "Failed to add attribute list "
303					"attribute as it already exists.");
304			err = EIO;
305			goto free_err;
306		}
307		if (a->non_resident && a->lowest_vcn)
308			panic("%s(): a->non_resident && a->lowest_vcn\n",
309					__FUNCTION__);
310		/*
311		 * Just some book keeping for later.  If the current attribute
312		 * cannot be moved out of the base mft record subtract its size
313		 * from the amount of free space.
314		 */
315		if (a->type == AT_STANDARD_INFORMATION ||
316				a->type == AT_INDEX_ROOT) {
317			bytes_free -= le32_to_cpu(a->length);
318			if (a->type == AT_STANDARD_INFORMATION)
319				have_std_info = TRUE;
320			else
321				have_idx_root = TRUE;
322		}
323		/*
324		 * If we are adding the attribute list attribute to the $MFT
325		 * system file, we cannot move out the $DATA attribute to make
326		 * space although we could shrink it so that it contains only
327		 * enough clusters in its mapping pairs array as to get us to
328		 * the next fragment.  However given everything is currently in
329		 * the base mft record this means we can at least move out the
330		 * filename attribute and the bitmap attribute which is
331		 * guaranteed to give us enough space to add a non-resident
332		 * attribute list attribute so we do not bother implementing
333		 * such truncation here as it cannot be required.
334		 */
335		if (for_mft) {
336			if (a->type == AT_DATA && !a->name_length)
337				bytes_free -= le32_to_cpu(a->length);
338		}
339		/*
340		 * If the current attribute is the attribute to be resized
341		 * record its attribute list entry in @ctx->al_entry so we do
342		 * not have to look it up later.
343		 */
344		if (ctx && ctx->a == a)
345			ctx->al_entry = al_entry;
346		len = offsetof(ATTR_LIST_ENTRY, name) +
347				(a->name_length * sizeof(ntfschar));
348		/*
349		 * Attribute list attribute entries must be aligned to 8-byte
350		 * boundaries.
351		 */
352		al_entry_len = (len + 7) & ~7;
353		/*
354		 * A single mft record cannot have enough attribute records to
355		 * overflow a whole NTFS_ALLOC_BLOCK bytes worth of attribute
356		 * list attribute entries.
357		 */
358		if ((u8*)al_entry + al_entry_len > al_end)
359			panic("%s(): (u8*)al_entry + al_entry_len > al_end\n",
360					__FUNCTION__);
361		/*
362		 * Create the attribute list entry for the current attribute
363		 * record.
364		 */
365		*al_entry = (ATTR_LIST_ENTRY) {
366			.type = a->type,
367			.length = cpu_to_le16(al_entry_len),
368			.name_length = a->name_length,
369			.name_offset = offsetof(ATTR_LIST_ENTRY, name),
370			.lowest_vcn = 0,
371			.mft_reference = mref,
372			.instance = a->instance,
373		};
374		/* Copy the name if the attribute is named. */
375		if (a->name_length)
376			memcpy(&al_entry->name,
377					(u8*)a + le16_to_cpu(a->name_offset),
378					a->name_length * sizeof(ntfschar));
379		/* Zero the padding area at the end if it exists. */
380		if (al_entry_len - len > 0)
381			memset((u8*)al_entry + len, 0, al_entry_len - len);
382		/*
383		 * We are done with this attribute list entry, switch to the
384		 * next one.
385		 */
386		al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry + al_entry_len);
387	} while (1);
388	al_size = (u8*)al_entry - al;
389	/*
390	 * We now have built the attribute list attribute value in @al.
391	 *
392	 * Determine the size needed for the attribute list attribute if it is
393	 * resident.
394	 */
395	attr_len = offsetof(ATTR_RECORD, reservedR) + sizeof(a->reservedR) +
396			al_size;
397	/*
398	 * If the size is greater than the maximum size possible to insert into
399	 * the mft record then insert the attribute list attribute as a
400	 * non-resident attribute record.
401	 */
402	if (attr_len > bytes_free) {
403		insert_resident = FALSE;
404		goto insert;
405	}
406	/*
407	 * If we do not have enough space to insert the attribute list
408	 * attribute as a resident attribute record try to make enough space
409	 * available by making other attributes non-resident and/or moving
410	 * other attributes to extent mft records.
411	 */
412	insert_resident = TRUE;
413	ntfs_attr_search_ctx_reinit(&al_ctx);
414	al_ctx.is_iteration = 1;
415	for (al_entry = (ATTR_LIST_ENTRY*)al;
416			attr_len > le32_to_cpu(m->bytes_allocated) -
417			le32_to_cpu(m->bytes_in_use);
418			al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
419			le16_to_cpu(al_entry->length))) {
420		/* Get the next attribute in the mft record. */
421		err = ntfs_attr_find_in_mft_record(AT_UNUSED, NULL, 0, NULL, 0,
422				&al_ctx);
423		if (err) {
424			/*
425			 * We reached the end and we still do not have enough
426			 * space to insert the attribute list attribute as a
427			 * resident attribute record thus try to insert it as a
428			 * non-resident attribute record.
429			 */
430			if (err == ENOENT) {
431				insert_resident = FALSE;
432				break;
433			}
434			ntfs_error(vol->mp, "Failed to iterate over "
435					"attribute records in base mft record "
436					"(error %d).", err);
437			goto undo;
438		}
439		a = al_ctx.a;
440		/*
441		 * We already checked above that the attribute list attribute
442		 * does not exist yet.
443		 */
444		if (a->type == AT_ATTRIBUTE_LIST)
445			panic("%s(): a->type == AT_ATTRIBUTE_LIST\n",
446					__FUNCTION__);
447		/*
448		 * Do not touch standard information and index root attributes
449		 * at this stage.  They will be moved out to extent mft records
450		 * further below if really necessary.
451		 *
452		 * TODO: Probably want to add unnamed data attributes to this
453		 * as well.
454		 */
455		if (a->type == AT_STANDARD_INFORMATION ||
456				a->type == AT_INDEX_ROOT)
457			continue;
458		/*
459		 * If we are working on the $MFT system file, do not touch the
460		 * unnamed $DATA attribute.
461		 */
462		if (for_mft) {
463			if (a->type == AT_DATA && !a->name_length)
464				continue;
465		}
466		/*
467		 * If the attribute is resident and we can expect the
468		 * non-resident form to be smaller than the resident form
469		 * switch the attribute to non-resident now.
470		 *
471		 * FIXME: We cannot do this at present unless the attribute is
472		 * the attribute being resized as there could be an ntfs inode
473		 * matching this attribute in memory and it would become out of
474		 * date with its metadata if we touch its attribute record.
475		 *
476		 * FIXME: We do not need to do this if this is the attribute
477		 * being resized as the caller will have already tried to make
478		 * the attribute non-resident and this will not have worked or
479		 * we would never have gotten here in the first place.
480		 */
481		/*
482		 * Move the attribute out to an extent mft record and update
483		 * its attribute list entry.  If it is the attribute to be
484		 * resized, also update the attribute search context to match
485		 * the new attribute.  If it is not the attribute to be resized
486		 * but it is in front of the attribute to be resized update the
487		 * attribute search context to account for the removed
488		 * attribute record.
489		 */
490		err = ntfs_attr_record_move_for_attr_list_attribute(&al_ctx,
491				al_entry, ctx, NULL);
492		if (err) {
493			ntfs_error(vol->mp, "Failed to move attribute type "
494					"0x%x out of base mft record 0x%llx "
495					"and into an extent mft record (error "
496					"%d).", (unsigned)le32_to_cpu(a->type),
497					(unsigned long long)base_ni->mft_no,
498					err);
499			goto undo;
500		}
501	}
502insert:
503	/*
504	 * Find the location at which to insert the attribute list attribute
505	 * record in the base mft record.
506	 */
507	ntfs_attr_search_ctx_reinit(&al_ctx);
508	err = ntfs_attr_find_in_mft_record(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
509			NULL, 0, &al_ctx);
510	if (!err || err != ENOENT) {
511		/*
512		 * We already checked above that the attribute list attribute
513		 * does not exist yet.
514		 */
515		if (!err)
516			panic("%s(): !err\n", __FUNCTION__);
517		ntfs_error(vol->mp, "Failed to find location at which to "
518				"insert attribute list attribute (error %d).",
519				err);
520		goto undo;
521	}
522	a = al_ctx.a;
523	/*
524	 * If @insert_resident is true try to insert the attribute list
525	 * attribute as a resident attribute record.
526	 */
527	if (insert_resident) {
528		err = ntfs_resident_attr_record_insert_internal(m, a,
529				AT_ATTRIBUTE_LIST, NULL, 0, al_size);
530		if (!err) {
531			memcpy((u8*)a + le16_to_cpu(a->value_offset), al,
532					al_size);
533			/*
534			 * If we already allocated some clusters in a previous
535			 * iteration need to free them now.
536			 *
537			 * Note we warn about errors and schedule the volume
538			 * for chkdsk but otherwise we ignore the error as it
539			 * does not in any way affect anything we are doing.
540			 * The volume just ends up having some clusters marked
541			 * in use but nothing is referencing them.  Running
542			 * chkdsk will clear those bits in the bitmap thus
543			 * causing the clusters to be made available for use
544			 * again.
545			 */
546			if (base_ni->attr_list_rl.elements) {
547				err = ntfs_cluster_free_from_rl(vol,
548						base_ni->attr_list_rl.rl,
549						0, -1, NULL);
550				if (err) {
551					ntfs_warning(vol->mp, "Failed to "
552							"release no longer "
553							"needed allocated "
554							"cluster(s) (error "
555							"%d).  Run chkdsk to "
556							"recover the lost "
557							"cluster(s).", err);
558					NVolSetErrors(vol);
559				}
560				OSFree(base_ni->attr_list_rl.rl,
561						base_ni->attr_list_rl.alloc,
562						ntfs_malloc_tag);
563				base_ni->attr_list_rl.elements = 0;
564				base_ni->attr_list_rl.alloc = 0;
565			}
566			goto done;
567		}
568		if (err != ENOSPC)
569			panic("%s(): err != ENOSPC\n", __FUNCTION__);
570	}
571	/*
572	 * Attempt to insert the attribute list attribute as a non-resident
573	 * atribute record.
574	 *
575	 * First allocate enough clusters to store the attribute list attribute
576	 * data.
577	 */
578	if (!base_ni->attr_list_rl.elements) {
579		attr_len = (al_size + vol->cluster_size_mask) &
580				~vol->cluster_size_mask;
581		err = ntfs_cluster_alloc(vol, 0, attr_len / vol->cluster_size,
582				-1, DATA_ZONE, TRUE, &base_ni->attr_list_rl);
583		if (err) {
584			ntfs_error(vol->mp, "Failed to allocate clusters for "
585					"the non-resident attribute list "
586					"attribute (error %d).", err);
587			goto undo;
588		}
589		/* Determine the size of the mapping pairs array. */
590		err = ntfs_get_size_for_mapping_pairs(vol,
591				base_ni->attr_list_rl.rl, 0, -1, &mp_size);
592		if (err)
593			panic("%s(): err (ntfs_get_size_for_mapping_pairs())\n",
594					__FUNCTION__);
595	}
596	/*
597	 * As the attribute is unnamed the mapping pairs array is placed
598	 * immediately after the non-resident attribute record itself.
599	 *
600	 * To determine the size of the attribute record take the offset to the
601	 * mapping pairs array and add the size of the mapping pairs array in
602	 * bytes aligned to an 8-byte boundary.  Note we do not need to do the
603	 * alignment as ntfs_attr_record_make_space() does it anyway.
604	 */
605	err = ntfs_attr_record_make_space(m, a, offsetof(ATTR_RECORD,
606		       compressed_size) + mp_size);
607	if (err) {
608		ntfschar *a_name;
609		le32 type;
610
611		if (err != ENOSPC)
612			panic("%s(): err != ENOSPC\n", __FUNCTION__);
613		if (!have_std_info && !have_idx_root) {
614			/*
615			 * We moved all attributes out of the base mft record
616			 * and we still do not have enough space to add the
617			 * attribute list attribute.
618			 *
619			 * TODO: The only thing that can help is to defragment
620			 * the attribute list attribute and/or other fragmented
621			 * attributes.  The former would make the runlist of
622			 * the attribute list attribute directly smaller thus
623			 * it may then fit and the latter would reduce the
624			 * number of extent attributes and thus the number of
625			 * attribute list attribute entries which would
626			 * indirectly make the runlist of the attribute list
627			 * attribute smaller.  For now we do not implement
628			 * defragmentation so there is nothing we can do when
629			 * this case occurs.  It should be very, very hard to
630			 * trigger this case though and I doubt even the
631			 * Windows NTFS driver deals with it so we are not
632			 * doing any worse than Windows so I think leaving
633			 * things as they are is acceptable.
634			 */
635out_of_space:
636			ntfs_error(vol->mp, "The runlist of the attribute "
637					"list attribute is too large to fit "
638					"in the base mft record.  You need to "
639					"defragment your volume and then try "
640					"again.");
641			err = ENOSPC;
642			goto undo;
643		}
644		/*
645		 * Start with the index root(s) if present then do the standard
646		 * information attribute.
647		 *
648		 * TODO: Need to get these cases triggered and then need to run
649		 * chkdsk to check for validity of moving these attributes out
650		 * of the base mft record.
651		 */
652		if (have_idx_root)
653			type = AT_INDEX_ROOT;
654		else {
655try_std_info:
656			type = AT_STANDARD_INFORMATION;
657			have_std_info = FALSE;
658		}
659		/*
660		 * Find the attribute in the base mft record.  Note for the
661		 * index root there can be several index root attributes so we
662		 * can get here multiple times once for each index root.
663		 */
664		ntfs_attr_search_ctx_reinit(&al_ctx);
665		al_ctx.is_iteration = 1;
666		err = ntfs_attr_find_in_mft_record(type, NULL, 0, NULL, 0,
667				&al_ctx);
668		if (err) {
669			/*
670			 * The mft record cannot be corrupt given we have fully
671			 * managed to parse it when generating the attribute
672			 * list attribute entries.
673			 */
674			if (err != ENOENT)
675				panic("%s(): err != ENOENT\n", __FUNCTION__);
676			/*
677			 * We should never get here for the standard
678			 * information attribute.
679			 */
680			if (type != AT_INDEX_ROOT)
681				panic("%s(): type != AT_INDEX_ROOT\n",
682						__FUNCTION__);
683			if (!have_idx_root)
684				panic("%s(): !have_idx_root\n", __FUNCTION__);
685			/*
686			 * We have done the index root attribute(s).  Now try
687			 * the standard information attribute if present.
688			 */
689			have_idx_root = FALSE;
690			if (have_std_info)
691				goto try_std_info;
692			/* We have really run out of space. */
693			goto out_of_space;
694		}
695		a = al_ctx.a;
696		/*
697		 * If the attribute is resident and we can expect the
698		 * non-resident form to be smaller than the resident form
699		 * switch the attribute to non-resident now.
700		 *
701		 * FIXME: We cannot do this at present unless the attribute is
702		 * the attribute being resized as there could be an ntfs inode
703		 * matching this attribute in memory and it would become out of
704		 * date with its metadata if we touch its attribute record.
705		 *
706		 * FIXME: We do not need to do this if this is the attribute
707		 * being resized as the caller will have already tried to make
708		 * the attribute non-resident and this will not have worked or
709		 * we would never have gotten here in the first place.
710		 */
711		/*
712		 * Move the attribute out to an extent mft record and update
713		 * its attribute list entry.  If it is the attribute to be
714		 * resized, also update the attribute search context to match
715		 * the new attribute.  If it is not the attribute to be resized
716		 * but it is in front of the attribute to be resized update the
717		 * attribute search context to account for the removed
718		 * attribute record.
719		 *
720		 * But first find the attribute list entry matching the
721		 * attribute record so it can be updated.
722		 */
723		a_name = (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset));
724		al_entry = (ATTR_LIST_ENTRY*)base_ni->attr_list;
725		do {
726			/*
727			 * We only just generated the attribute list thus it
728			 * cannot be corrupt.
729			 */
730			if ((u8*)al_entry >= al_end || !al_entry->length)
731				panic("%s(): (u8*)al_entry >= al_end || "
732						"!al_entry->length\n",
733						__FUNCTION__);
734			if (al_entry->mft_reference == mref &&
735					al_entry->instance == a->instance) {
736				/*
737				 * We found the entry, stop looking but first
738				 * perform a quick sanity check that we really
739				 * do have the correct attribute record.
740				 */
741				if (al_entry->type != a->type)
742					panic("%s(): al_entry->type != "
743							"a->type\n",
744							__FUNCTION__);
745				if (!ntfs_are_names_equal(
746						(ntfschar*)((u8*)al_entry +
747						al_entry->name_offset),
748						al_entry->name_length, a_name,
749						a->name_length, TRUE,
750						vol->upcase, vol->upcase_len))
751					panic("%s(): !ntfs_are_named_equal()\n",
752							__FUNCTION__);
753				break;
754			}
755			/* Go to the next attribute list entry. */
756			al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
757					le16_to_cpu(al_entry->length));
758		} while (1);
759		err = ntfs_attr_record_move_for_attr_list_attribute(&al_ctx,
760				al_entry, ctx, NULL);
761		if (err) {
762			ntfs_error(vol->mp, "Failed to move attribute type "
763					"0x%x out of base mft record 0x%llx "
764					"and into an extent mft record (error "
765					"%d).", (unsigned)le32_to_cpu(a->type),
766					(unsigned long long)base_ni->mft_no,
767					err);
768			goto undo;
769		}
770		/*
771		 * We moved an attribute out of the base mft record so retry to
772		 * insert the attribute list attribute now that we have more
773		 * space in the base mft record.
774		 */
775		goto insert;
776	}
777	/*
778	 * Now setup the new non-resident attribute list attribute record.  The
779	 * entire attribute has been zeroed and the length of the attribute
780	 * record has been already set up by ntfs_attr_record_make_space().
781	 */
782	a->type = AT_ATTRIBUTE_LIST;
783	a->non_resident = 1;
784	a->mapping_pairs_offset = a->name_offset = const_cpu_to_le16(
785			offsetof(ATTR_RECORD, compressed_size));
786	a->instance = m->next_attr_instance;
787	/*
788	 * Increment the next attribute instance number in the mft record as we
789	 * consumed the old one.
790	 */
791	m->next_attr_instance = cpu_to_le16(
792			(le16_to_cpu(m->next_attr_instance) + 1) & 0xffff);
793	a->highest_vcn = cpu_to_sle64((attr_len / vol->cluster_size) - 1);
794	a->allocated_size = cpu_to_sle64(attr_len);
795	a->initialized_size = a->data_size = cpu_to_sle64(al_size);
796	/*
797	 * Generate the mapping pairs array into place.  This cannot fail as we
798	 * determined how much space we need and then made that much space
799	 * available.  So unless we did something wrong we must have enough
800	 * space available and the runlist must be in order.
801	 */
802	err = ntfs_mapping_pairs_build(vol, (s8*)a + offsetof(ATTR_RECORD,
803			compressed_size), mp_size, base_ni->attr_list_rl.rl, 0,
804			-1, NULL);
805	if (err)
806		panic("%s(): err (ntfs_mapping_pairs_build())\n", __FUNCTION__);
807done:
808	/* Ensure the changes make it to disk later. */
809	NInoSetMrecNeedsDirtying(base_ni);
810	/*
811	 * If we inserted the attribute list attribute as a non-resident
812	 * attribute, write it out to disk now.
813	 */
814	if (a->non_resident) {
815		err = ntfs_rl_write(vol, al, al_size, &base_ni->attr_list_rl,
816				0, 0);
817		if (err) {
818			ntfs_error(vol->mp, "Failed to write non-resident "
819					"attribute list attribute value to "
820					"disk (error %d).", err);
821			goto rm_undo;
822		}
823	}
824	/*
825	 * Set the base ntfs inode up to reflect that it now has an attribute
826	 * list attribute.
827	 */
828	base_ni->attr_list = al;
829	base_ni->attr_list_size = al_size;
830	base_ni->attr_list_alloc = al_alloc;
831	NInoSetAttrList(base_ni);
832	lck_rw_unlock_exclusive(&base_ni->attr_list_rl.lock);
833	/*
834	 * Update @ctx if the attribute it describes is still in the base mft
835	 * record to reflect that the attribute list attribute was inserted in
836	 * front of it.
837	 */
838	if (ctx) {
839		if (ctx->ni == base_ni) {
840			if ((u8*)a <= (u8*)ctx->a)
841				ctx->a = (ATTR_RECORD*)((u8*)ctx->a +
842						le32_to_cpu(a->length));
843		} else {
844			MFT_RECORD *em;
845
846			/*
847			 * @ctx is not in the base mft record, map the extent
848			 * inode it is in and if it is mapped at a different
849			 * address than before update the pointers in @ctx.
850			 */
851retry_map:
852			err2 = ntfs_mft_record_map(ctx->ni, &em);
853			if (err2) {
854				/*
855				 * Something bad has happened.  If out of
856				 * memory retry till it succeeds.  Any other
857				 * errors are fatal and we return the error
858				 * code in @ctx->m.  We cannot undo as we would
859				 * need to map the mft record to be able to
860				 * move the attribute back into the base mft
861				 * record and exactly that operation has just
862				 * failed.
863				 *
864				 * We just need to fudge things so the caller
865				 * can reinit and/or put the search context
866				 * safely.
867				 */
868				if (err2 == ENOMEM) {
869					(void)thread_block(
870							THREAD_CONTINUE_NULL);
871					goto retry_map;
872				}
873				ctx->is_error = 1;
874				ctx->error = err2;
875				ctx->ni = base_ni;
876			}
877			if (!ctx->is_error && em != ctx->m) {
878				ctx->a = (ATTR_RECORD*)((u8*)em +
879						((u8*)ctx->a - (u8*)ctx->m));
880				ctx->m = em;
881			}
882		}
883		/*
884		 * Finally, update @ctx to reflect the fact that it now is the
885		 * result of a search inside an inode with an attribute list
886		 * attribute.
887		 */
888		ctx->base_ni = base_ni;
889		ctx->base_m = m;
890		ctx->base_a = (ATTR_RECORD*)((u8*)m +
891				le16_to_cpu(m->attrs_offset));
892	}
893	ntfs_debug("Done.");
894	return 0;
895rm_undo:
896	/*
897	 * Need to delete the added attribute list attribute record from the
898	 * base mft record.
899	 */
900	ntfs_attr_record_delete_internal(m, a);
901undo:
902	/*
903	 * If we already allocated some clusters for the non-resident attribute
904	 * list attribute need to free them now.
905	 */
906	if (base_ni->attr_list_rl.elements) {
907		err2 = ntfs_cluster_free_from_rl(vol, base_ni->attr_list_rl.rl,
908				0, -1, NULL);
909		if (err2) {
910			ntfs_error(vol->mp, "Failed to release allocated "
911					"cluster(s) in error code path (error "
912					"%d).  Run chkdsk to recover the lost "
913					"cluster(s).", err2);
914			NVolSetErrors(vol);
915		}
916		OSFree(base_ni->attr_list_rl.rl, base_ni->attr_list_rl.alloc,
917				ntfs_malloc_tag);
918		base_ni->attr_list_rl.elements = 0;
919		base_ni->attr_list_rl.alloc = 0;
920	}
921	/*
922	 * Move any attribute records that we moved out of the base mft record
923	 * back into the base mft record and free the extent mft records we
924	 * allocated for them.
925	 */
926	al_end = al + al_size;
927	for (al_entry = (ATTR_LIST_ENTRY*)al; (u8*)al_entry < al_end;
928			al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
929			le16_to_cpu(al_entry->length))) {
930		ntfs_inode *ni;
931		ntfschar *a_name;
932		u8 *val;
933		unsigned val_len;
934
935		/* Skip all attributes that are in the base mft record. */
936		if (al_entry->mft_reference == mref)
937			continue;
938retry_undo_map:
939		/* Find the extent record in the base ntfs inode. */
940		err2 = ntfs_extent_mft_record_map(base_ni,
941				le64_to_cpu(al_entry->mft_reference), &ni, &m);
942		if (err2) {
943			if (err2 == ENOMEM)
944				goto retry_undo_map;
945			/*
946			 * There is nothing we can do to get this attribute
947			 * back into the base mft record thus we simply skip
948			 * it and continue with the next one.
949			 *
950			 * Note we do not free the extent mft record as that
951			 * would confuse our mft allocator as we would leave
952			 * the mft record itself marked in use.
953			 */
954			ntfs_error(vol->mp, "Failed to undo move of attribute "
955					"type 0x%x in mft_no 0x%llx in error "
956					"code path because mapping the extent "
957					"mft record 0x%llx faled (error %d).  "
958					"Leaving corrupt metadata.  Run "
959					"chkdsk.",
960					(unsigned)le32_to_cpu(al_entry->type),
961					(unsigned long long)base_ni->mft_no,
962					(unsigned long long)
963					MREF_LE(al_entry->mft_reference), err2);
964			NVolSetErrors(vol);
965			/*
966			 * Proceed with the next one as we may be able to move
967			 * others back.
968			 */
969			continue;
970		}
971		/* Find the attribute record that needs moving back. */
972		a = (ATTR_RECORD*)((u8*)m + le16_to_cpu(m->attrs_offset));
973		if (a->type == AT_END)
974			panic("%s(): a->type == AT_END\n", __FUNCTION__);
975		while (a->instance != al_entry->instance) {
976			a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length));
977			if (a->type == AT_END)
978				panic("%s(): a->type == AT_END\n",
979						__FUNCTION__);
980		}
981		/* We must have found the right one. */
982		if (al_entry->type != a->type)
983			panic("%s(): al_entry->type != a->type\n",
984					__FUNCTION__);
985		a_name = (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset));
986		if (!ntfs_are_names_equal((ntfschar*)((u8*)al_entry +
987				al_entry->name_offset), al_entry->name_length,
988				a_name, a->name_length, TRUE, vol->upcase,
989				vol->upcase_len))
990			panic("%s(): !ntfs_are_names_equal()\n", __FUNCTION__);
991		/*
992		 * Find the location at which the attribute needs to be
993		 * reinserted in the base mft record.
994		 *
995		 * As there can be multiple otherwise identical filename
996		 * attributes we need to search using the attribute value in
997		 * this case so we find the correct place to insert the
998		 * attribute.
999		 */
1000		if (a->type == AT_FILENAME) {
1001			val = (u8*)a + le16_to_cpu(a->value_offset);
1002			val_len = le32_to_cpu(a->value_length);
1003		} else {
1004			val = NULL;
1005			val_len = 0;
1006		}
1007		ntfs_attr_search_ctx_reinit(&al_ctx);
1008		err2 = ntfs_attr_find_in_mft_record(a->type, a_name,
1009				a->name_length, val, val_len, &al_ctx);
1010		/* The attribute cannot be there already. */
1011		if (!err2)
1012			panic("%s(): !err2\n", __FUNCTION__);
1013		/*
1014		 * The mft record cannot be corrupt given we have fully managed
1015		 * to parse it when generating the attribute list attribute
1016		 * entries.
1017		 */
1018		if (err2 != ENOENT)
1019			panic("%s(): err2 != ENOENT\n", __FUNCTION__);
1020		attr_len = le32_to_cpu(a->length);
1021		/* Make space for the attribute and copy it into place. */
1022		err2 = ntfs_attr_record_make_space(al_ctx.m, al_ctx.a,
1023				attr_len);
1024		/*
1025		 * This cannot fail as the base mft record must have enough
1026		 * space to hold the attribute record given it fitted before we
1027		 * moved it out.
1028		 */
1029		if (err2)
1030			panic("%s(): err2\n", __FUNCTION__);
1031		memcpy(al_ctx.a, a, attr_len);
1032		/*
1033		 * Assign a new instance number to the copied attribute record
1034		 * as it now has moved into the base mft record.
1035		 */
1036		a->instance = al_ctx.m->next_attr_instance;
1037		/*
1038		 * Increment the next attribute instance number in the mft
1039		 * record as we consumed the old one.
1040		 */
1041		al_ctx.m->next_attr_instance = cpu_to_le16((le16_to_cpu(
1042				al_ctx.m->next_attr_instance) + 1) & 0xffff);
1043		/*
1044		 * If this is the only attribute in the extent mft record, free
1045		 * the extent mft record and disconnect it from the base ntfs
1046		 * inode.
1047		 *
1048		 * If this is not the only attribute in the extent mft record,
1049		 * delete the attribute record from the extent mft record.
1050		 */
1051		if (ntfs_attr_record_is_only_one(m, a)) {
1052			err2 = ntfs_extent_mft_record_free(base_ni, ni, m);
1053			if (err2) {
1054				ntfs_error(vol->mp, "Failed to free extent "
1055						"mft record 0x%llx after "
1056						"moving back attribute type "
1057						"0x%x in mft_no 0x%llx in "
1058						"error code path (error %d).  "
1059						"Leaving corrupt metadata.  "
1060						"Run chkdsk.",
1061						(unsigned long long)ni->mft_no,
1062						(unsigned)le32_to_cpu(a->type),
1063						(unsigned long long)
1064						base_ni->mft_no, err2);
1065				NVolSetErrors(vol);
1066				/*
1067				 * Fall back to at least deleting the attribute
1068				 * record from the extent mft record to
1069				 * maintain some consistency.
1070				 */
1071				goto delete_err;
1072			}
1073		} else {
1074delete_err:
1075			ntfs_attr_record_delete_internal(m, a);
1076			NInoSetMrecNeedsDirtying(ni);
1077			ntfs_extent_mft_record_unmap(ni);
1078		}
1079	}
1080	/* Finally mark the fully restored base mft record dirty. */
1081	NInoSetMrecNeedsDirtying(base_ni);
1082free_err:
1083	lck_rw_unlock_exclusive(&base_ni->attr_list_rl.lock);
1084	OSFree(al, al_alloc, ntfs_malloc_tag);
1085	return err;
1086}
1087
1088/**
1089 * ntfs_attr_list_sync_shrink - update the attribute list of an ntfs inode
1090 * @ni:		base ntfs inode whose attribute list attribugte to update
1091 * @start_ofs:	byte offset into attribute list attribute from which to write
1092 * @ctx:	initialized attribute search context
1093 *
1094 * Update the on-disk attribute list attribute of the base ntfs inode @ni.  The
1095 * caller has updated the attribute list attribute value that is cached in the
1096 * ntfs inode @ni and this function takes the updated value and resizes the
1097 * attribute record if necessary and then writes out the modified value
1098 * starting at offset @start_ofs bytes into the attribute value.
1099 *
1100 * This function only works for shrinking the attribute list attribute or if
1101 * the size has not changed.
1102 *
1103 * @ctx is an initialized, ready to use attribute search context that we use to
1104 * look up the attribute list attribute in the mapped, base mft record.
1105 *
1106 * Return 0 on success and errno on error.
1107 */
1108errno_t ntfs_attr_list_sync_shrink(ntfs_inode *ni, const unsigned start_ofs,
1109		ntfs_attr_search_ctx *ctx)
1110{
1111	s64 size, alloc_size;
1112	ntfs_volume *vol;
1113	ATTR_RECORD *a;
1114	unsigned mp_size;
1115	errno_t err;
1116	BOOL dirty_mft;
1117	static const char es[] = "  Leaving inconsistent metadata.  Unmount "
1118			"and run chkdsk.";
1119
1120	ntfs_debug("Entering for base mft_no 0x%llx.",
1121			(unsigned long long)ni->mft_no);
1122	/*
1123	 * We currently do not implement adding the attribute list attribute.
1124	 *
1125	 * Use ntfs_attr_list_add() instead.
1126	 */
1127	if (!NInoAttrList(ni))
1128		panic("%s(): !NInoAttrList(ni)\n", __FUNCTION__);
1129	if (start_ofs > ni->attr_list_size)
1130		panic("%s(): start_ofs > ni->attr_list_size\n", __FUNCTION__);
1131	/*
1132	 * We should never have allowed the attribute list attribute to grow
1133	 * above its maximum size.
1134	 */
1135	if (ni->attr_list_size > NTFS_MAX_ATTR_LIST_SIZE)
1136		panic("%s(): ni->attr_list_size > NTFS_MAX_ATTR_LIST_SIZE\n",
1137				__FUNCTION__);
1138	vol = ni->vol;
1139	dirty_mft = FALSE;
1140	/* Find the attribute list attribute in the base mft record. */
1141	err = ntfs_attr_find_in_mft_record(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
1142			NULL, 0, ctx);
1143	if (err) {
1144		ntfs_error(vol->mp, "Failed to find attribute list attribute "
1145				"in base mft_no 0x%llx (error %d).  Unmount "
1146				"and run chkdsk.",
1147				(unsigned long long)ni->mft_no, err);
1148		NVolSetErrors(vol);
1149		return EIO;
1150	}
1151	a = ctx->a;
1152	size = ntfs_attr_size(a);
1153	/*
1154	 * We currently only implement shrinking the attribute list attribute.
1155	 *
1156	 * Use ntfs_attr_list_sync_extend() when extending it.
1157	 */
1158	if (ni->attr_list_size > size)
1159		panic("%s(): ni->attr_list_size > size\n", __FUNCTION__);
1160	/*
1161	 * If the size has not changed skip the resize and go straight onto the
1162	 * data update.
1163	 */
1164	if (ni->attr_list_size == size) {
1165		if (!a->non_resident)
1166			goto update_resident;
1167		goto update_non_resident;
1168	}
1169	/* Shrink the attribute list attribute. */
1170	if (!a->non_resident) {
1171		/*
1172		 * The attribute list attribute is resident, shrink the
1173		 * attribute record and value.
1174		 */
1175		err = ntfs_resident_attr_value_resize(ctx->m, a,
1176				ni->attr_list_size);
1177		/* Shrinking the attribute record cannot fail. */
1178		if (err)
1179			panic("%s(): err (resident)\n", __FUNCTION__);
1180		dirty_mft = TRUE;
1181update_resident:
1182		/* Update the part of the attribute value that has changed. */
1183		if (start_ofs < ni->attr_list_size) {
1184			memcpy((u8*)a + le16_to_cpu(a->value_offset) +
1185					start_ofs, ni->attr_list + start_ofs,
1186					ni->attr_list_size - start_ofs);
1187			dirty_mft = TRUE;
1188		}
1189		goto done;
1190	}
1191	/*
1192	 * The attribute list attribute is non-resident, as we are shrinking it
1193	 * we need to update the attribute sizes first.
1194	 */
1195	lck_rw_lock_exclusive(&ni->attr_list_rl.lock);
1196	/* Update the attribute sizes. */
1197	if (ni->attr_list_size < sle64_to_cpu(a->initialized_size))
1198		a->initialized_size = cpu_to_sle64(ni->attr_list_size);
1199	a->data_size = cpu_to_sle64(ni->attr_list_size);
1200	dirty_mft = TRUE;
1201	alloc_size = (ni->attr_list_size + vol->cluster_size_mask) &
1202			~vol->cluster_size_mask;
1203	if (alloc_size > sle64_to_cpu(a->allocated_size))
1204		panic("%s(): alloc_size > sle64_to_cpu(a->allocated_size)\n",
1205				__FUNCTION__);
1206	/*
1207	 * If the attribute allocation has not changed we are done with the
1208	 * resize and go straight onto the data update.
1209	 */
1210	if (alloc_size == sle64_to_cpu(a->allocated_size))
1211		goto update_non_resident;
1212	/*
1213	 * The allocated size has shrunk by at least one cluster thus we need
1214	 * to free the no longer in-use clusters and truncate the runlist
1215	 * accordingly.  We then also need to update the mapping pairs array in
1216	 * the attribute record as well as the allocated size and the highest
1217	 * vcn.
1218	 */
1219	err = ntfs_cluster_free_from_rl(vol, ni->attr_list_rl.rl,
1220			alloc_size >> vol->cluster_size_shift, -1, NULL);
1221	if (err) {
1222		ntfs_warning(vol->mp, "Failed to free some allocated clusters "
1223				"belonging to the attribute list attribute of "
1224				"mft_no 0x%llx (error %d).  Unmount and run "
1225				"chkdsk to recover the lost space.",
1226				(unsigned long long)ni->mft_no, err);
1227		NVolSetErrors(vol);
1228	}
1229	err = ntfs_rl_truncate_nolock(vol, &ni->attr_list_rl,
1230			alloc_size >> vol->cluster_size_shift);
1231	if (err) {
1232		ntfs_warning(vol->mp, "Failed to truncate attribute list "
1233				"attribute runlist of mft_no 0x%llx (error "
1234				"%d).%s", (unsigned long long)ni->mft_no, err,
1235				es);
1236		goto err;
1237	}
1238	err = ntfs_get_size_for_mapping_pairs(vol, ni->attr_list_rl.rl, 0, -1,
1239			&mp_size);
1240	if (err) {
1241		ntfs_error(vol->mp, "Cannot shrink attribute list attribute "
1242				"of mft_no 0x%llx because determining the "
1243				"size for the mapping pairs failed (error "
1244				"%d).%s", (unsigned long long)ni->mft_no, err,
1245				es);
1246		goto err;
1247	}
1248	err = ntfs_mapping_pairs_build(vol, (s8*)a +
1249			le16_to_cpu(a->mapping_pairs_offset), mp_size,
1250			ni->attr_list_rl.rl, 0, -1, NULL);
1251	if (err) {
1252		ntfs_error(vol->mp, "Cannot shrink attribute list attribute "
1253				"of mft_no 0x%llx because building the "
1254				"mapping pairs failed (error %d).%s",
1255				(unsigned long long)ni->mft_no, err, es);
1256		goto err;
1257	}
1258	a->allocated_size = cpu_to_sle64(alloc_size);
1259	a->highest_vcn = cpu_to_sle64((alloc_size >> vol->cluster_size_shift) -
1260			1);
1261	err = ntfs_attr_record_resize(ctx->m, a,
1262			le16_to_cpu(a->mapping_pairs_offset) + mp_size);
1263	/* Shrinking the attribute record cannot fail. */
1264	if (err)
1265		panic("%s(): err (non-resident)\n", __FUNCTION__);
1266update_non_resident:
1267	/* Write the modified attribute list attribute value to disk. */
1268	err = ntfs_rl_write(vol, ni->attr_list, ni->attr_list_size,
1269			&ni->attr_list_rl, start_ofs, 0);
1270	if (err) {
1271		ntfs_error(vol->mp, "Failed to update attribute list "
1272				"attribute of mft_no 0x%llx (error %d).%s",
1273				(unsigned long long)ni->mft_no, err, es);
1274		goto err;
1275	}
1276	lck_rw_unlock_exclusive(&ni->attr_list_rl.lock);
1277done:
1278	ntfs_debug("Done.");
1279out:
1280	/* Make sure the modified mft record is written out. */
1281	if (dirty_mft)
1282		NInoSetMrecNeedsDirtying(ni);
1283	return err;
1284err:
1285	lck_rw_unlock_exclusive(&ni->attr_list_rl.lock);
1286	NVolSetErrors(vol);
1287	err = EIO;
1288	goto out;
1289}
1290
1291/**
1292 * ntfs_attr_list_sync_extend - sync an inode's attribute list attribute
1293 * @base_ni:	base ntfs inode whose attribute list attribute to sync
1294 * @base_m:	base mft record of the ntfs inode @base_ni
1295 * @al_ofs:	offset into attribute list attribute at which to begin syncing
1296 * @ctx:	attribute search context describing attribute being resized
1297 *
1298 * Sync the attribute list attribute of the base ntfs inode @base_ni with mft
1299 * record @base_m by extending it to fit the cached attribute list attribute
1300 * value, then copying the modified, cached attribute list value into place in
1301 * the extended attribute list attribute value starting at offset @al_ofs into
1302 * the attribute list attribute.
1303 *
1304 * @ctx is an attribute search context describing the attribute being resized
1305 * which is causing the attribute list attribute to be added.  The search
1306 * context describes a mapped mft record and this is unmapped as needed and
1307 * then mapped again.  Also the pointers in the search context are updated with
1308 * the new location of the attribute in the mft record if it is moved and with
1309 * the new location in memory of the re-mapped mft record if it is re-mapped at
1310 * a different virtual address.
1311 *
1312 * Return 0 on success and errno on error.
1313 *
1314 * WARNING: If @ctx is supplied, regardless of whether success or failure is
1315 *	    returned, you need to check @ctx->is_error and if 1 the @ctx is no
1316 *	    longer valid, i.e. you need to either call
1317 *	    ntfs_attr_search_ctx_reinit() or ntfs_attr_search_ctx_put() on it.
1318 *	    In that case @ctx->error will give you the error code for why the
1319 *	    mapping of the inode failed.
1320 *
1321 * NOTE: When this function fails it is very likely that the attribute list
1322 *	 attribute value both in memory and on-disk has been modified but it is
1323 *	 also very likely that a disparity is left between the in-memory and
1324 *	 the on-disk value thus the caller should undo their extension to the
1325 *	 attribute list attribute value and then rewrite the complete attribute
1326 *	 list attribute starting at offset zero bytes to ensure everything is
1327 *	 made consistent.
1328 */
1329errno_t ntfs_attr_list_sync_extend(ntfs_inode *base_ni, MFT_RECORD *base_m,
1330		unsigned al_ofs, ntfs_attr_search_ctx *ctx)
1331{
1332	leMFT_REF mref;
1333	LCN lcn;
1334	ntfs_volume *vol;
1335	ATTR_RECORD *al_a, *a;
1336	ATTR_LIST_ENTRY *al_entry;
1337	u8 *al_end;
1338	unsigned bytes_needed, bytes_free, alloc_size, name_ofs;
1339	unsigned mp_size, mp_ofs, arec_size, old_arec_size;
1340	errno_t err, err2;
1341	le32 type;
1342	BOOL dirty_mft, remap_needed;
1343	ntfs_attr_search_ctx al_ctx, actx;
1344	ntfs_runlist runlist;
1345
1346	ntfs_debug("Entering for base mft_no 0x%llx, offset 0x%x.",
1347			(unsigned long long)base_ni->mft_no, al_ofs);
1348	if (!NInoAttrList(base_ni))
1349		panic("%s(): !NInoAttrList(base_ni)\n", __FUNCTION__);
1350	if (al_ofs > base_ni->attr_list_size)
1351		panic("%s(): al_ofs > base_ni->attr_list_size\n",
1352				__FUNCTION__);
1353	/*
1354	 * We should never have allowed the attribute list attribute to grow
1355	 * above its maximum size.
1356	 */
1357	if (base_ni->attr_list_size > NTFS_MAX_ATTR_LIST_SIZE)
1358		panic("%s(): base_ni->attr_list_size > "
1359				"NTFS_MAX_ATTR_LIST_SIZE\n", __FUNCTION__);
1360	vol = base_ni->vol;
1361	remap_needed = dirty_mft = FALSE;
1362	/* Find the attribute list attribute record in the base mft record. */
1363	ntfs_attr_search_ctx_init(&al_ctx, base_ni, base_m);
1364	err = ntfs_attr_find_in_mft_record(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
1365			NULL, 0, &al_ctx);
1366	if (err) {
1367		ntfs_error(vol->mp, "Failed to look up attribute list "
1368				"attribute in base mft_no 0x%llx (error %d).",
1369				(unsigned long long)base_ni->mft_no, err);
1370		return err;
1371	}
1372	al_a = al_ctx.a;
1373	arec_size = ntfs_attr_size(al_a);
1374	/*
1375	 * We currently only implement extending the attribute list attribute.
1376	 *
1377	 * Use ntfs_attr_list_sync_shrink() when shrinking it.
1378	 */
1379	if (base_ni->attr_list_size < arec_size)
1380		panic("%s(): base_ni->attr_list_size < arec_size\n",
1381				__FUNCTION__);
1382	/*
1383	 * If the size has not changed skip the resize and go straight onto the
1384	 * data update.
1385	 */
1386	if (base_ni->attr_list_size == arec_size) {
1387		if (!al_a->non_resident)
1388			goto update_resident;
1389		lck_rw_lock_exclusive(&base_ni->attr_list_rl.lock);
1390		goto update_non_resident;
1391	}
1392	mref = MK_LE_MREF(base_ni->mft_no, base_ni->seq_no);
1393	if (al_a->non_resident)
1394		goto non_resident;
1395	arec_size = le32_to_cpu(al_a->length);
1396	/* Extend the attribute list attribute record value. */
1397	err = ntfs_resident_attr_value_resize(al_ctx.m, al_a,
1398			base_ni->attr_list_size);
1399	if (!err) {
1400		/*
1401		 * Update the pointer in @ctx because the attribute has now
1402		 * moved inside the mft record.
1403		 */
1404		if (ctx->ni == base_ni && (u8*)al_a <= (u8*)ctx->a)
1405			ctx->a = (ATTR_RECORD*)((u8*)ctx->a + (signed)
1406					((signed)le32_to_cpu(al_a->length) -
1407					(signed)arec_size));
1408update_resident:
1409		dirty_mft = TRUE;
1410		/*
1411		 * Update the part of the attribute list attribute record value
1412		 * that has changed.
1413		 */
1414		memcpy((u8*)al_a + le16_to_cpu(al_a->value_offset) + al_ofs,
1415				base_ni->attr_list + al_ofs,
1416				base_ni->attr_list_size - al_ofs);
1417		goto done;
1418	}
1419	if (err != ENOSPC)
1420		panic("%s(): err != ENOSPC\n", __FUNCTION__);
1421	/*
1422	 * There was not enough space in the mft record to extend the attribute
1423	 * list attribute record.  Deal with this by making other attributes
1424	 * non-resident and/or moving other attributes out to extent mft
1425	 * records and if that is not enough make the attribute list attribute
1426	 * non-resident.
1427	 */
1428	bytes_needed = ((base_ni->attr_list_size + 7) & ~7) -
1429			((le32_to_cpu(al_a->value_length) + 7) & ~7);
1430	/* Maximum number of usable bytes in the mft record. */
1431	bytes_free = le32_to_cpu(base_m->bytes_allocated) -
1432			le16_to_cpu(base_m->attrs_offset);
1433	/*
1434	 * If the attribute list attribute has become bigger than fits in an
1435	 * mft record switch it to a non-resident attribute record.
1436	 */
1437	if (bytes_needed > bytes_free)
1438		goto make_non_resident;
1439	/*
1440	 * Need to unmap the extent mft record for now which means we have to
1441	 * mark it dirty first.
1442	 */
1443	if (ctx->ni != base_ni) {
1444		NInoSetMrecNeedsDirtying(ctx->ni);
1445		ntfs_extent_mft_record_unmap(ctx->ni);
1446		remap_needed = TRUE;
1447	}
1448	ntfs_attr_search_ctx_init(&actx, base_ni, base_m);
1449	actx.is_iteration = 1;
1450	while (bytes_needed > le32_to_cpu(base_m->bytes_allocated) -
1451			le32_to_cpu(base_m->bytes_in_use)) {
1452		ntfschar *a_name;
1453
1454		/* Get the next attribute in the mft record. */
1455		err = ntfs_attr_find_in_mft_record(AT_UNUSED, NULL, 0, NULL, 0,
1456				&actx);
1457		if (err) {
1458			/*
1459			 * We reached the end and we still do not have enough
1460			 * space to extend the attribute list attribute as a
1461			 * resident attribute record thus try to switch it to a
1462			 * non-resident attribute record.
1463			 */
1464			if (err == ENOENT)
1465				goto make_non_resident;
1466			/*
1467			 * The base mft record is corrupt.  There is nothing we
1468			 * can do just bail out.  Note we are leaving the
1469			 * in-memory attribute list attribute out of sync with
1470			 * the on-disk attribute list attribute after possibly
1471			 * having moved some attributes out of the base mft
1472			 * record.  We hope the caller will manage to undo the
1473			 * extension it did in memory and then write out the
1474			 * attribute list attribute to disk.  This would bring
1475			 * back in sync any changes we just made and if it
1476			 * fails the caller will then display appropriate
1477			 * corruption announcing error messages.
1478			 */
1479			ntfs_error(vol->mp, "Failed to iterate over attribute "
1480					"records in base mft record 0x%llx "
1481					"(error %d).%s",
1482					(unsigned long long)base_ni->mft_no,
1483					err, dirty_mft ? "  Run chkdsk." : "");
1484			if (dirty_mft)
1485				NVolSetErrors(vol);
1486			goto done;
1487		}
1488		a = actx.a;
1489		/*
1490		 * Skip the attribute list attribute itself as that is not
1491		 * represented inside itself and it must stay in the base mft
1492		 * record.
1493		 */
1494		if (a->type == AT_ATTRIBUTE_LIST)
1495			continue;
1496		/*
1497		 * Do not touch standard information and index root attributes
1498		 * at this stage.  They will be moved out to extent mft records
1499		 * further below if really necessary.
1500		 *
1501		 * TODO: Probably want to add unnamed data attributes to this
1502		 * as well.
1503		 */
1504		if (a->type == AT_STANDARD_INFORMATION ||
1505				a->type == AT_INDEX_ROOT) {
1506			/*
1507			 * If the attribute list attribute has become bigger
1508			 * than fits in the mft record switch it to a
1509			 * non-resident attribute record.
1510			 */
1511			bytes_free -= le32_to_cpu(a->length);
1512			if (bytes_needed > bytes_free)
1513				goto make_non_resident;
1514			continue;
1515		}
1516		/*
1517		 * If the attribute is resident and we can expect the
1518		 * non-resident form to be smaller than the resident form
1519		 * switch the attribute to non-resident now.
1520		 *
1521		 * FIXME: We cannot do this at present unless the attribute is
1522		 * the attribute being resized as there could be an ntfs inode
1523		 * matching this attribute in memory and it would become out of
1524		 * date with its metadata if we touch its attribute record.
1525		 *
1526		 * FIXME: We do not need to do this if this is the attribute
1527		 * being resized as the caller will have already tried to make
1528		 * the attribute non-resident and this will not have worked or
1529		 * we would never have gotten here in the first place.
1530		 */
1531		/*
1532		 * Move the attribute out to an extent mft record and update
1533		 * its attribute list entry.  If it is the attribute to be
1534		 * resized, also update the attribute search context to match
1535		 * the new attribute.  If it is not the attribute to be resized
1536		 * but it is in front of the attribute to be resized update the
1537		 * attribute search context to account for the removed
1538		 * attribute record.
1539		 *
1540		 * But first find the attribute list entry matching the
1541		 * attribute record so it can be updated.
1542		 */
1543		a_name = (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset));
1544		al_entry = (ATTR_LIST_ENTRY*)base_ni->attr_list;
1545		al_end = base_ni->attr_list + base_ni->attr_list_size;
1546		do {
1547			/*
1548			 * The attribute must be present in the attribute list
1549			 * attribute or something is corrupt.
1550			 */
1551			if ((u8*)al_entry >= al_end || !al_entry->length) {
1552				ntfs_error(vol->mp, "Attribute type 0x%x not "
1553						"found in attribute list "
1554						"attribute of base mft record "
1555						"0x%llx.  Run chkdsk.",
1556						(unsigned)le32_to_cpu(a->type),
1557						(unsigned long long)
1558						base_ni->mft_no);
1559				NVolSetErrors(vol);
1560				err = EIO;
1561				goto done;
1562			}
1563			if (al_entry->mft_reference == mref &&
1564					al_entry->instance == a->instance) {
1565				/*
1566				 * We found the entry, stop looking but first
1567				 * perform a quick sanity check that we really
1568				 * do have the correct attribute record.
1569				 */
1570				if (al_entry->type == a->type &&
1571						ntfs_are_names_equal(
1572						(ntfschar*)((u8*)al_entry +
1573						al_entry->name_offset),
1574						al_entry->name_length, a_name,
1575						a->name_length, TRUE,
1576						vol->upcase, vol->upcase_len))
1577					break;
1578				ntfs_error(vol->mp, "Found corrupt attribute "
1579						"list attribute when looking "
1580						"for attribute type 0x%x in "
1581						"attribute list attribute of "
1582						"base mft record 0x%llx.  Run "
1583						"chkdsk.",
1584						(unsigned)le32_to_cpu(a->type),
1585						(unsigned long long)
1586						base_ni->mft_no);
1587				NVolSetErrors(vol);
1588				err = EIO;
1589				goto done;
1590			}
1591			/* Go to the next attribute list entry. */
1592			al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
1593					le16_to_cpu(al_entry->length));
1594		} while (1);
1595		err = ntfs_attr_record_move_for_attr_list_attribute(&actx,
1596				al_entry, ctx, &remap_needed);
1597		if (err) {
1598			ntfs_error(vol->mp, "Failed to move attribute type "
1599					"0x%x out of base mft record 0x%llx "
1600					"and into an extent mft record (error "
1601					"%d).%s",
1602					(unsigned)le32_to_cpu(a->type),
1603					(unsigned long long)base_ni->mft_no,
1604					err, dirty_mft ? "  Run chkdsk." : "");
1605			if (dirty_mft)
1606				NVolSetErrors(vol);
1607			goto done;
1608		}
1609		/* We modified the base mft record. */
1610		dirty_mft = TRUE;
1611		/*
1612		 * If the modified attribute list entry is before the current
1613		 * start of attribute list modification we need to sync this
1614		 * entry as well.  For simplicity we just set @al_ofs to the
1615		 * new value thus syncing everything starting at that offset.
1616		 */
1617		if ((u8*)al_entry - base_ni->attr_list < (long)al_ofs)
1618			al_ofs = (u8*)al_entry - base_ni->attr_list;
1619	}
1620	/*
1621	 * Find the attribute list attribute record in the base mft record
1622	 * again in case it has moved.  This cannot fail as we looked it up
1623	 * successfully above.
1624	 */
1625	ntfs_attr_search_ctx_reinit(&al_ctx);
1626	err = ntfs_attr_find_in_mft_record(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
1627			NULL, 0, &al_ctx);
1628	if (err)
1629		panic("%s(): err (attribute list attribute not found)\n",
1630				__FUNCTION__);
1631	al_a = al_ctx.a;
1632	arec_size = le32_to_cpu(al_a->length);
1633	/* Try to extend the attribute list attribute record value. */
1634	err = ntfs_resident_attr_value_resize(base_m, al_a,
1635			base_ni->attr_list_size);
1636	if (!err) {
1637		dirty_mft = TRUE;
1638		/*
1639		 * Update the part of the attribute list attribute record value
1640		 * that has changed.
1641		 */
1642		memcpy((u8*)al_a + le16_to_cpu(al_a->value_offset) + al_ofs,
1643				base_ni->attr_list + al_ofs,
1644				base_ni->attr_list_size - al_ofs);
1645		/*
1646		 * Update the pointer in @ctx because the attribute has now
1647		 * moved inside the mft record.
1648		 */
1649		if (ctx->ni == base_ni && (u8*)al_a <= (u8*)ctx->a)
1650			ctx->a = (ATTR_RECORD*)((u8*)ctx->a + (signed)(
1651					(signed)le32_to_cpu(al_a->length) -
1652					(signed)arec_size));
1653		goto done;
1654	}
1655	if (err != ENOSPC)
1656		panic("%s(): err != ENOSPC\n", __FUNCTION__);
1657	/*
1658	 * There was not enough space in the mft record to extend the attribute
1659	 * list attribute record.  Deal with this by making the attribute list
1660	 * attribute non-resident and then extending it.
1661	 */
1662make_non_resident:
1663	/* Work out the new allocated size we need. */
1664	alloc_size = (base_ni->attr_list_size + vol->cluster_size_mask) &
1665			~vol->cluster_size_mask;
1666	if (!alloc_size)
1667		panic("%s(): !alloc_size\n", __FUNCTION__);
1668	lck_rw_lock_exclusive(&base_ni->attr_list_rl.lock);
1669	if (al_a->non_resident)
1670		panic("%s(): al_a->non_resident\n", __FUNCTION__);
1671	if (base_ni->attr_list_rl.rl)
1672		panic("%s(): base_ni->attr_list_rl.rl\n", __FUNCTION__);
1673	/*
1674	 * Start by allocating clusters to hold the attribute list attribute
1675	 * value.
1676	 */
1677	err = ntfs_cluster_alloc(vol, 0, alloc_size >> vol->cluster_size_shift,
1678			-1, DATA_ZONE, TRUE, &base_ni->attr_list_rl);
1679	if (err) {
1680		ntfs_error(vol->mp, "Failed to allocate cluster%s for "
1681				"non-resident attribute list attribute in "
1682				"base mft record 0x%llx (error %d).",
1683				(alloc_size >> vol->cluster_size_shift) > 1 ?
1684				"s" : "", (unsigned long long)base_ni->mft_no,
1685				err);
1686		goto unl_done;
1687	}
1688	/*
1689	 * Determine the size of the mapping pairs array.
1690	 *
1691	 * This cannot fail as we just allocated the runlist so it must be ok.
1692	 */
1693	err = ntfs_get_size_for_mapping_pairs(vol, base_ni->attr_list_rl.rl, 0,
1694			-1, &mp_size);
1695	if (err)
1696		panic("%s(): err (ntfs_get_size_for_mapping_pairs(), "
1697				"resident)\n", __FUNCTION__);
1698	/* Calculate new offsets for the name and the mapping pairs array. */
1699	name_ofs = (offsetof(ATTR_REC, compressed_size) + 7) & ~7;
1700	mp_ofs = (name_ofs + 7) & ~7;
1701	/*
1702	 * Determine the size of the resident part of the now non-resident
1703	 * attribute record.
1704	 */
1705	old_arec_size = le32_to_cpu(al_a->length);
1706	arec_size = (mp_ofs + mp_size + 7) & ~7;
1707	/*
1708	 * Resize the resident part of the attribute record.
1709	 *
1710	 * This cannot fail because the attribute list attribute must already
1711	 * contain at least three entries, one for the compulsory standard
1712	 * information attribute, one for the compulsory filename attribute,
1713	 * and one for the compulsory data or index root attribute and a
1714	 * resident attribute record containing three attribute list attribute
1715	 * entries in its attribute value is larger than the number of bytes
1716	 * needed to create a maximum length non-resident attribute record that
1717	 * can possibly be created here.  And if the inode is corrupt we would
1718	 * never have gotten here as this case would be detected when the inode
1719	 * is read in.
1720	 */
1721	err = ntfs_attr_record_resize(base_m, al_a, arec_size);
1722	if (err)
1723		panic("%s(): err (ntfs_attr_record_resize())\n", __FUNCTION__);
1724	/*
1725	 * Convert the resident part of the attribute record to describe a
1726	 * non-resident attribute.
1727	 */
1728	al_a->non_resident = 1;
1729	al_a->name_offset = cpu_to_le16(name_ofs);
1730	/* The flags should be zero already but re-set them anyway. */
1731	al_a->flags = 0;
1732	/* Setup the fields specific to non-resident attributes. */
1733	al_a->lowest_vcn = 0;
1734	al_a->mapping_pairs_offset = cpu_to_le16(mp_ofs);
1735	al_a->compression_unit = 0;
1736	memset(&al_a->reservedN, 0, sizeof(al_a->reservedN));
1737	/* We need to write the whole attribute list attribute. */
1738	al_ofs = 0;
1739	goto write_non_resident;
1740non_resident:
1741	/* The attribute list attribute is non-resident. */
1742	lck_rw_lock_exclusive(&base_ni->attr_list_rl.lock);
1743	if (!al_a->non_resident)
1744		panic("%s(): !al_a->non_resident\n", __FUNCTION__);
1745	/* Allocate more disk space if needed. */
1746	if (base_ni->attr_list_size <= sle64_to_cpu(al_a->allocated_size))
1747		goto skip_alloc;
1748	/* Work out the new allocated size we need. */
1749	alloc_size = (base_ni->attr_list_size + vol->cluster_size_mask) &
1750			~vol->cluster_size_mask;
1751	if (!alloc_size)
1752		panic("%s(): !alloc_size\n", __FUNCTION__);
1753	/* Find the last allocated cluster of the existing runlist. */
1754	lcn = -1;
1755	if (al_a->allocated_size) {
1756		ntfs_rl_element *rl;
1757
1758		if (!base_ni->attr_list_rl.elements)
1759			panic("%s(): !base_ni->attr_list_rl.elements\n",
1760					__FUNCTION__);
1761		rl = &base_ni->attr_list_rl.rl[base_ni->attr_list_rl.elements -
1762				1];
1763		while (rl->lcn < 0 && rl > base_ni->attr_list_rl.rl)
1764			rl--;
1765		if (rl->lcn >= 0)
1766			lcn = rl->lcn + rl->length;
1767	}
1768	/*
1769	 * Allocate clusters for the extension of the attribute list attribute
1770	 * value.
1771	 */
1772	runlist.rl = NULL;
1773	runlist.alloc = runlist.elements = 0;
1774	err = ntfs_cluster_alloc(vol, sle64_to_cpu(al_a->allocated_size) >>
1775			vol->cluster_size_shift, (alloc_size -
1776			sle64_to_cpu(al_a->allocated_size)) >>
1777			vol->cluster_size_shift, lcn, DATA_ZONE, TRUE,
1778			&runlist);
1779	if (err) {
1780		ntfs_error(vol->mp, "Failed to allocate cluster%s to extend "
1781				"non-resident attribute list attribute in "
1782				"base mft record 0x%llx (error %d).",
1783				((alloc_size -
1784				sle64_to_cpu(al_a->allocated_size)) >>
1785				vol->cluster_size_shift) > 1 ? "s" : "",
1786				(unsigned long long)base_ni->mft_no, err);
1787		goto unl_done;
1788	}
1789	err = ntfs_rl_merge(&base_ni->attr_list_rl, &runlist);
1790	if (err) {
1791		ntfs_error(vol->mp, "Failed to extend attribute list "
1792				"attribute in base mft record 0x%llx because "
1793				"the runlist merge failed (error %d).",
1794				(unsigned long long)base_ni->mft_no, err);
1795		err2 = ntfs_cluster_free_from_rl(vol, runlist.rl, 0, -1, NULL);
1796		if (err2) {
1797			ntfs_warning(vol->mp, "Failed to release allocated "
1798					"cluster(s) in error code path (error "
1799					"%d).  Run chkdsk to recover the lost "
1800					"cluster(s).", err2);
1801			NVolSetErrors(vol);
1802		}
1803		OSFree(runlist.rl, runlist.alloc, ntfs_malloc_tag);
1804		goto unl_done;
1805	}
1806	/* Determine the size of the mapping pairs array. */
1807	err = ntfs_get_size_for_mapping_pairs(vol, base_ni->attr_list_rl.rl, 0,
1808			-1, &mp_size);
1809	if (err)
1810		panic("%s(): err (ntfs_get_size_for_mapping_pairs(), "
1811				"non-resident)\n", __FUNCTION__);
1812	mp_ofs = le16_to_cpu(al_a->mapping_pairs_offset);
1813	old_arec_size = le32_to_cpu(al_a->length);
1814	/* Extend the attribute record to fit the bigger mapping pairs array. */
1815	err = ntfs_attr_record_resize(base_m, al_a, mp_ofs + mp_size);
1816	if (!err)
1817		goto write_non_resident;
1818	if (err != ENOSPC)
1819		panic("%s(): err != ENOSPC\n", __FUNCTION__);
1820	/*
1821	 * Need to unmap the extent mft record for now which means we have to
1822	 * mark it dirty first.
1823	 */
1824	if (ctx->ni != base_ni) {
1825		NInoSetMrecNeedsDirtying(ctx->ni);
1826		ntfs_extent_mft_record_unmap(ctx->ni);
1827		remap_needed = TRUE;
1828	}
1829	bytes_needed = ((mp_ofs + mp_size + 7) & ~7) - old_arec_size;
1830	type = AT_UNUSED;
1831next_pass:
1832	ntfs_attr_search_ctx_init(&actx, base_ni, base_m);
1833	actx.is_iteration = 1;
1834	while (bytes_needed > le32_to_cpu(base_m->bytes_allocated) -
1835			le32_to_cpu(base_m->bytes_in_use)) {
1836		ntfschar *a_name;
1837
1838		/* Get the next attribute in the mft record. */
1839		err = ntfs_attr_find_in_mft_record(type, NULL, 0, NULL, 0,
1840				&actx);
1841		if (err) {
1842			if (err == ENOENT) {
1843				/*
1844				 * If we have more passes to go do the next
1845				 * pass which will try harder to move things
1846				 * out of the way.
1847				 */
1848				if (type == AT_UNUSED) {
1849					type = AT_DATA;
1850					goto next_pass;
1851				}
1852				/*
1853				 * TODO: Need to get these cases triggerred and
1854				 * then need to run chkdsk to check for
1855				 * validity of moving these attributes out of
1856				 * the base mft record.
1857				 */
1858				if (type == AT_DATA) {
1859					type = AT_INDEX_ROOT;
1860					goto next_pass;
1861				}
1862				if (type == AT_INDEX_ROOT) {
1863					type = AT_STANDARD_INFORMATION;
1864					goto next_pass;
1865				}
1866				/*
1867				 * We moved all attributes out of the base mft
1868				 * record and we still do not have enough space
1869				 * to extend the attribute list attribute.
1870				 *
1871				 * TODO: The only thing that can help is to
1872				 * defragment the attribute list attribute
1873				 * and/or other fragmented attributes.  The
1874				 * former would make the runlist of the
1875				 * attribute list attribute directly smaller
1876				 * thus it may then fit and the latter would
1877				 * reduce the number of extent attributes and
1878				 * thus the number of attribute list attribute
1879				 * entries which would indirectly make the
1880				 * runlist of the attribute list attribute
1881				 * smaller.  For now we do not implement
1882				 * defragmentation so there is nothing we can
1883				 * do when this case occurs.  It should be
1884				 * very, very hard to trigger this case though
1885				 * and I doubt even the Windows NTFS driver
1886				 * deals with it so we are not doing any worse
1887				 * than Windows so I think leaving things as
1888				 * they are is acceptable.
1889				 *
1890				 * The caller will hopefully undo what they did
1891				 * thus shrinking the attribute list attribute
1892				 * again which will then fit and they will then
1893				 * rewrite it which will fix everything we have
1894				 * failed to do nicely.
1895				 */
1896				ntfs_error(vol->mp, "The runlist of the "
1897						"attribute list attribute of "
1898						"mft_no 0x%llx is too large to "
1899						"fit in the base mft record.  "
1900						"You need to defragment your "
1901						"volume and then try again.%s",
1902						(unsigned long long)
1903						base_ni->mft_no, dirty_mft ?
1904						"  Run chkdsk." : "");
1905				if (dirty_mft)
1906					NVolSetErrors(vol);
1907				err = ENOSPC;
1908				goto unl_done;
1909			}
1910			/*
1911			 * The base mft record is corrupt.  There is nothing we
1912			 * can do just bail out.  Note we are leaving the
1913			 * in-memory attribute list attribute out of sync with
1914			 * the on-disk attribute list attribute after possibly
1915			 * having moved some attributes out of the base mft
1916			 * record.  We hope the caller will manage to undo the
1917			 * extension it did in memory and then write out the
1918			 * attribute list attribute to disk.  This would bring
1919			 * back in sync any changes we just made and if it
1920			 * fails the caller will then display appropriate
1921			 * corruption announcing error messages.
1922			 */
1923			ntfs_error(vol->mp, "Failed to iterate over attribute "
1924					"records in base mft record 0x%llx "
1925					"(error %d).%s",
1926					(unsigned long long)base_ni->mft_no,
1927					err, dirty_mft ? "  Run chkdsk." : "");
1928			if (dirty_mft)
1929				NVolSetErrors(vol);
1930			goto unl_done;
1931		}
1932		a = actx.a;
1933		if (type == AT_UNUSED) {
1934			/*
1935			 * Skip the attribute list attribute itself as that is
1936			 * not represented inside itself and we cannot move it
1937			 * out anyway.
1938			 *
1939			 * Also, do not touch standard information, index root,
1940			 * and unnamed $DATA attributes.  They will be moved
1941			 * out to extent mft records in later passes if really
1942			 * necessary.
1943			 */
1944			if (a->type == AT_ATTRIBUTE_LIST ||
1945					a->type == AT_STANDARD_INFORMATION ||
1946					a->type == AT_INDEX_ROOT ||
1947					(a->type == AT_DATA &&
1948					!a->name_length))
1949				continue;
1950		}
1951		/*
1952		 * If the attribute is resident and we can expect the
1953		 * non-resident form to be smaller than the resident form
1954		 * switch the attribute to non-resident now.
1955		 *
1956		 * FIXME: We cannot do this at present unless the attribute is
1957		 * the attribute being resized as there could be an ntfs inode
1958		 * matching this attribute in memory and it would become out of
1959		 * date with its metadata if we touch its attribute record.
1960		 *
1961		 * FIXME: We do not need to do this if this is the attribute
1962		 * being resized as the caller will have already tried to make
1963		 * the attribute non-resident and this will not have worked or
1964		 * we would never have gotten here in the first place.
1965		 */
1966		/*
1967		 * Move the attribute out to an extent mft record and update
1968		 * its attribute list entry.  If it is the attribute to be
1969		 * resized, also update the attribute search context to match
1970		 * the new attribute.  If it is not the attribute to be resized
1971		 * but it is in front of the attribute to be resized update the
1972		 * attribute search context to account for the removed
1973		 * attribute record.
1974		 *
1975		 * But first find the attribute list entry matching the
1976		 * attribute record so it can be updated.
1977		 */
1978		a_name = (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset));
1979		al_entry = (ATTR_LIST_ENTRY*)base_ni->attr_list;
1980		al_end = base_ni->attr_list + base_ni->attr_list_size;
1981		do {
1982			/*
1983			 * The attribute must be present in the attribute list
1984			 * attribute or something is corrupt.
1985			 */
1986			if ((u8*)al_entry >= al_end || !al_entry->length) {
1987				ntfs_error(vol->mp, "Attribute type 0x%x not "
1988						"found in attribute list "
1989						"attribute of base mft record "
1990						"0x%llx.  Run chkdsk.",
1991						(unsigned)le32_to_cpu(a->type),
1992						(unsigned long long)
1993						base_ni->mft_no);
1994				NVolSetErrors(vol);
1995				err = EIO;
1996				goto unl_done;
1997			}
1998			if (al_entry->mft_reference == mref &&
1999					al_entry->instance == a->instance) {
2000				/*
2001				 * We found the entry, stop looking but first
2002				 * perform a quick sanity check that we really
2003				 * do have the correct attribute record.
2004				 */
2005				if (al_entry->type == a->type &&
2006						ntfs_are_names_equal(
2007						(ntfschar*)((u8*)al_entry +
2008						al_entry->name_offset),
2009						al_entry->name_length, a_name,
2010						a->name_length, TRUE,
2011						vol->upcase, vol->upcase_len))
2012					break;
2013				ntfs_error(vol->mp, "Found corrupt attribute "
2014						"list attribute when looking "
2015						"for attribute type 0x%x in "
2016						"attribute list attribute of "
2017						"base mft record 0x%llx.  Run "
2018						"chkdsk.",
2019						(unsigned)le32_to_cpu(a->type),
2020						(unsigned long long)
2021						base_ni->mft_no);
2022				NVolSetErrors(vol);
2023				err = EIO;
2024				goto unl_done;
2025			}
2026			/* Go to the next attribute list entry. */
2027			al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
2028					le16_to_cpu(al_entry->length));
2029		} while (1);
2030		err = ntfs_attr_record_move_for_attr_list_attribute(&actx,
2031				al_entry, ctx, &remap_needed);
2032		if (err) {
2033			ntfs_error(vol->mp, "Failed to move attribute type "
2034					"0x%x out of base mft record 0x%llx "
2035					"and into an extent mft record (error "
2036					"%d).%s",
2037					(unsigned)le32_to_cpu(a->type),
2038					(unsigned long long)base_ni->mft_no,
2039					err, dirty_mft ? "  Run chkdsk." : "");
2040			if (dirty_mft)
2041				NVolSetErrors(vol);
2042			goto unl_done;
2043		}
2044		/* We modified the base mft record. */
2045		dirty_mft = TRUE;
2046		/*
2047		 * If the modified attribute list entry is before the current
2048		 * start of attribute list modification we need to sync this
2049		 * entry as well.  For simplicity we just set @al_ofs to the
2050		 * new value thus syncing everything starting at that offset.
2051		 */
2052		if ((u8*)al_entry - base_ni->attr_list < (long)al_ofs)
2053			al_ofs = (u8*)al_entry - base_ni->attr_list;
2054	}
2055	/*
2056	 * Find the attribute list attribute record in the base mft record
2057	 * again in case it has moved.  This cannot fail as we looked it up
2058	 * successfully above.
2059	 */
2060	ntfs_attr_search_ctx_reinit(&al_ctx);
2061	err = ntfs_attr_find_in_mft_record(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
2062			NULL, 0, &al_ctx);
2063	if (err)
2064		panic("%s(): err (attribute list attribute not found 2)\n",
2065				__FUNCTION__);
2066	al_a = al_ctx.a;
2067	/*
2068	 * Extend the attribute record to fit the bigger mapping pairs array.
2069	 * This cannot fail as we only get here if we managed to create enough
2070	 * space.
2071	 */
2072	err = ntfs_attr_record_resize(base_m, al_a, mp_ofs + mp_size);
2073	if (err)
2074		panic("%s(): err (ntfs_attr_record_resize())\n", __FUNCTION__);
2075write_non_resident:
2076	dirty_mft = TRUE;
2077	/*
2078	 * Update the pointer in @ctx because the attribute has now moved
2079	 * inside the mft record.
2080	 */
2081	if (ctx->ni == base_ni && (u8*)al_a <= (u8*)ctx->a)
2082		ctx->a = (ATTR_RECORD*)((u8*)ctx->a +
2083				(signed)((signed)le32_to_cpu(al_a->length) -
2084				(signed)old_arec_size));
2085	/*
2086	 * Generate the mapping pairs array in place.  This cannot fail as we
2087	 * determined the amount of space we need already and have ensured that
2088	 * we have enough space available.
2089	 */
2090	err = ntfs_mapping_pairs_build(vol, (s8*)al_a + mp_ofs,
2091			le32_to_cpu(al_a->length) - mp_ofs,
2092			base_ni->attr_list_rl.rl, 0, -1, NULL);
2093	if (err)
2094		panic("%s(): err (ntfs_mapping_pairs_build())\n", __FUNCTION__);
2095	/* Update the highest_vcn. */
2096	al_a->highest_vcn = cpu_to_sle64((alloc_size - 1) >>
2097			vol->cluster_size_shift);
2098	al_a->allocated_size = cpu_to_sle64(alloc_size);
2099skip_alloc:
2100	/* Update the data size. */
2101	dirty_mft = TRUE;
2102	al_a->data_size = cpu_to_sle64(base_ni->attr_list_size);
2103update_non_resident:
2104	/*
2105	 * Write the modified part of the attribute list attribute to disk.
2106	 *
2107	 * ntfs_rl_write() will mark the volume dirty and ask the user to run
2108	 * chkdsk.
2109	 */
2110	err = ntfs_rl_write(vol, base_ni->attr_list, base_ni->attr_list_size,
2111			&base_ni->attr_list_rl, al_ofs, 0);
2112	if (err)
2113		ntfs_error(vol->mp, "Failed to update on-disk attribute list "
2114				"attribute of mft_no 0x%llx (error %d).",
2115				(unsigned long long)base_ni->mft_no, err);
2116	/* Update the initialized size. */
2117	if (al_a->initialized_size != al_a->data_size) {
2118		dirty_mft = TRUE;
2119		al_a->initialized_size = al_a->data_size;
2120	}
2121unl_done:
2122	lck_rw_unlock_exclusive(&base_ni->attr_list_rl.lock);
2123done:
2124	/* Make sure the modified base mft record is written out. */
2125	if (dirty_mft)
2126		NInoSetMrecNeedsDirtying(base_ni);
2127	if (remap_needed && ctx->ni != base_ni) {
2128		MFT_RECORD *em;
2129
2130retry_map:
2131		err2 = ntfs_mft_record_map(ctx->ni, &em);
2132		if (err2) {
2133			/*
2134			 * Something bad has happened.  If out of memory retry
2135			 * till it succeeds.  Any other errors are fatal and we
2136			 * return the error code in @ctx->m.
2137			 *
2138			 * We do not need to undo anything as the extension of
2139			 * the attribute list attribute has already been done
2140			 * and if it failed the failure has already been dealt
2141			 * with.
2142			 *
2143			 * We just need to fudge things so the caller can
2144			 * reinit and/or put the search context safely.
2145			 */
2146			if (err2 == ENOMEM) {
2147				(void)thread_block(THREAD_CONTINUE_NULL);
2148				goto retry_map;
2149			}
2150			ctx->is_error = 1;
2151			ctx->error = err2;
2152			ctx->ni = base_ni;
2153		}
2154		if (!ctx->is_error && em != ctx->m) {
2155			ctx->a = (ATTR_RECORD*)((u8*)em +
2156					((u8*)ctx->a - (u8*)ctx->m));
2157			ctx->m = em;
2158		}
2159	}
2160	return err;
2161}
2162
2163/**
2164 * ntfs_attr_list_entries_delete - delete one or more attribute list entries
2165 * @ni:			base ntfs inode whose attribute list to delete from
2166 * @start_entry:	first attribute list entry to be deleted
2167 * @end_entry:		attribute list entry at which to stop deleting
2168 *
2169 * Delete the attribute list attribute entries starting at @start_entry and
2170 * finishing at @end_entry (@end_entry itself is not deleted) from the
2171 * attribute list attribute belonging to the base ntfs inode @ni.
2172 *
2173 * This function cannot fail.
2174 */
2175void ntfs_attr_list_entries_delete(ntfs_inode *ni,
2176		ATTR_LIST_ENTRY *start_entry, ATTR_LIST_ENTRY *end_entry)
2177{
2178	unsigned to_delete, to_copy, new_alloc;
2179
2180	/*
2181	 * Determine the number of bytes to be deleted from the attribute list
2182	 * attribute.
2183	 */
2184	to_delete = (u8*)end_entry - (u8*)start_entry;
2185	ntfs_debug("Entering for base mft_no 0x%llx, attr type 0x%x, "
2186			"start_entry length 0x%x, start_entry offset 0x%lx, "
2187			"end_entry offset 0x%lx, bytes to_delete 0x%x.",
2188			(unsigned long long)ni->mft_no,
2189			le32_to_cpu(start_entry->type),
2190			(unsigned)le16_to_cpu(start_entry->length),
2191			(unsigned long)((u8*)start_entry - ni->attr_list),
2192			(unsigned long)((u8*)end_entry - ni->attr_list),
2193			to_delete);
2194	/*
2195	 * Determine the number of bytes in the attribute list attribute
2196	 * following the entries to be deleted.
2197	 */
2198	to_copy = ni->attr_list_size - ((u8*)end_entry - ni->attr_list);
2199	/*
2200	 * Determine the new size and allocated size for the attribute list
2201	 * attribute.
2202	 */
2203	ni->attr_list_size -= to_delete;
2204	new_alloc = (ni->attr_list_size + NTFS_ALLOC_BLOCK - 1) &
2205			~(NTFS_ALLOC_BLOCK - 1);
2206	/*
2207	 * @new_alloc cannot reach zero because the attribute list has to at
2208	 * least contain the standard information attribute.
2209	 */
2210	if (!new_alloc)
2211		panic("%s(): !new_alloc\n", __FUNCTION__);
2212	/*
2213	 * Remove the attribute list entries to be deleted from the in memory
2214	 * copy of the attribute list attribute and reallocate the attribute
2215	 * list buffer if it shrinks past an NTFS_ALLOC_BLOCK byte boundary.
2216	 */
2217	if (new_alloc >= ni->attr_list_alloc) {
2218		if (new_alloc > ni->attr_list_alloc)
2219			panic("%s(): (new_alloc > ni->attr_list_alloc\n",
2220					__FUNCTION__);
2221cut:
2222		/*
2223		 * If the end entry is not the last entry, move all following
2224		 * entries forward on top of the entries to be deleted.
2225		 */
2226		if (to_copy > 0)
2227			memmove(start_entry, end_entry, to_copy);
2228	} else {
2229		u8 *tmp;
2230		unsigned entry_ofs;
2231
2232		tmp = OSMalloc(new_alloc, ntfs_malloc_tag);
2233		/*
2234		 * If the allocation fails then do not shrink the buffer and
2235		 * just cut out the entries to be deleted which will waste some
2236		 * memory but is otherwise ok.
2237		 */
2238		if (!tmp)
2239			goto cut;
2240		entry_ofs = (u8*)start_entry - ni->attr_list;
2241		memcpy(tmp, ni->attr_list, entry_ofs);
2242		if (to_copy > 0)
2243			memcpy(tmp + entry_ofs, end_entry, to_copy);
2244		OSFree(ni->attr_list, ni->attr_list_alloc, ntfs_malloc_tag);
2245		ni->attr_list_alloc = new_alloc;
2246		ni->attr_list = tmp;
2247	}
2248	ntfs_debug("Done.");
2249}
2250