xref: /openbmc/linux/fs/ntfs3/frecord.c (revision 9144f784f852f9a125cabe9927b986d909bfa439)
14342306fSKonstantin Komarov // SPDX-License-Identifier: GPL-2.0
24342306fSKonstantin Komarov /*
34342306fSKonstantin Komarov  *
44342306fSKonstantin Komarov  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
54342306fSKonstantin Komarov  *
64342306fSKonstantin Komarov  */
74342306fSKonstantin Komarov 
84342306fSKonstantin Komarov #include <linux/fiemap.h>
94342306fSKonstantin Komarov #include <linux/fs.h>
1019d1b787SKonstantin Komarov #include <linux/minmax.h>
114342306fSKonstantin Komarov #include <linux/vmalloc.h>
124342306fSKonstantin Komarov 
134342306fSKonstantin Komarov #include "debug.h"
144342306fSKonstantin Komarov #include "ntfs.h"
154342306fSKonstantin Komarov #include "ntfs_fs.h"
164342306fSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
174342306fSKonstantin Komarov #include "lib/lib.h"
184342306fSKonstantin Komarov #endif
194342306fSKonstantin Komarov 
ni_ins_mi(struct ntfs_inode * ni,struct rb_root * tree,CLST ino,struct rb_node * ins)204342306fSKonstantin Komarov static struct mft_inode *ni_ins_mi(struct ntfs_inode *ni, struct rb_root *tree,
214342306fSKonstantin Komarov 				   CLST ino, struct rb_node *ins)
224342306fSKonstantin Komarov {
234342306fSKonstantin Komarov 	struct rb_node **p = &tree->rb_node;
244342306fSKonstantin Komarov 	struct rb_node *pr = NULL;
254342306fSKonstantin Komarov 
264342306fSKonstantin Komarov 	while (*p) {
274342306fSKonstantin Komarov 		struct mft_inode *mi;
284342306fSKonstantin Komarov 
294342306fSKonstantin Komarov 		pr = *p;
304342306fSKonstantin Komarov 		mi = rb_entry(pr, struct mft_inode, node);
314342306fSKonstantin Komarov 		if (mi->rno > ino)
324342306fSKonstantin Komarov 			p = &pr->rb_left;
334342306fSKonstantin Komarov 		else if (mi->rno < ino)
344342306fSKonstantin Komarov 			p = &pr->rb_right;
354342306fSKonstantin Komarov 		else
364342306fSKonstantin Komarov 			return mi;
374342306fSKonstantin Komarov 	}
384342306fSKonstantin Komarov 
394342306fSKonstantin Komarov 	if (!ins)
404342306fSKonstantin Komarov 		return NULL;
414342306fSKonstantin Komarov 
424342306fSKonstantin Komarov 	rb_link_node(ins, pr, p);
434342306fSKonstantin Komarov 	rb_insert_color(ins, tree);
444342306fSKonstantin Komarov 	return rb_entry(ins, struct mft_inode, node);
454342306fSKonstantin Komarov }
464342306fSKonstantin Komarov 
474342306fSKonstantin Komarov /*
48e8b8e97fSKari Argillander  * ni_find_mi - Find mft_inode by record number.
494342306fSKonstantin Komarov  */
ni_find_mi(struct ntfs_inode * ni,CLST rno)504342306fSKonstantin Komarov static struct mft_inode *ni_find_mi(struct ntfs_inode *ni, CLST rno)
514342306fSKonstantin Komarov {
524342306fSKonstantin Komarov 	return ni_ins_mi(ni, &ni->mi_tree, rno, NULL);
534342306fSKonstantin Komarov }
544342306fSKonstantin Komarov 
554342306fSKonstantin Komarov /*
56e8b8e97fSKari Argillander  * ni_add_mi - Add new mft_inode into ntfs_inode.
574342306fSKonstantin Komarov  */
ni_add_mi(struct ntfs_inode * ni,struct mft_inode * mi)584342306fSKonstantin Komarov static void ni_add_mi(struct ntfs_inode *ni, struct mft_inode *mi)
594342306fSKonstantin Komarov {
604342306fSKonstantin Komarov 	ni_ins_mi(ni, &ni->mi_tree, mi->rno, &mi->node);
614342306fSKonstantin Komarov }
624342306fSKonstantin Komarov 
634342306fSKonstantin Komarov /*
64e8b8e97fSKari Argillander  * ni_remove_mi - Remove mft_inode from ntfs_inode.
654342306fSKonstantin Komarov  */
ni_remove_mi(struct ntfs_inode * ni,struct mft_inode * mi)664342306fSKonstantin Komarov void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi)
674342306fSKonstantin Komarov {
684342306fSKonstantin Komarov 	rb_erase(&mi->node, &ni->mi_tree);
694342306fSKonstantin Komarov }
704342306fSKonstantin Komarov 
71d3624466SKonstantin Komarov /*
72d3624466SKonstantin Komarov  * ni_std - Return: Pointer into std_info from primary record.
734342306fSKonstantin Komarov  */
ni_std(struct ntfs_inode * ni)744342306fSKonstantin Komarov struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni)
754342306fSKonstantin Komarov {
764342306fSKonstantin Komarov 	const struct ATTRIB *attr;
774342306fSKonstantin Komarov 
784342306fSKonstantin Komarov 	attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
7996de65a9SKonstantin Komarov 	return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO)) :
8096de65a9SKonstantin Komarov 		      NULL;
814342306fSKonstantin Komarov }
824342306fSKonstantin Komarov 
834342306fSKonstantin Komarov /*
844342306fSKonstantin Komarov  * ni_std5
854342306fSKonstantin Komarov  *
86e8b8e97fSKari Argillander  * Return: Pointer into std_info from primary record.
874342306fSKonstantin Komarov  */
ni_std5(struct ntfs_inode * ni)884342306fSKonstantin Komarov struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni)
894342306fSKonstantin Komarov {
904342306fSKonstantin Komarov 	const struct ATTRIB *attr;
914342306fSKonstantin Komarov 
924342306fSKonstantin Komarov 	attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
934342306fSKonstantin Komarov 
9496de65a9SKonstantin Komarov 	return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO5)) :
9596de65a9SKonstantin Komarov 		      NULL;
964342306fSKonstantin Komarov }
974342306fSKonstantin Komarov 
984342306fSKonstantin Komarov /*
99e8b8e97fSKari Argillander  * ni_clear - Clear resources allocated by ntfs_inode.
1004342306fSKonstantin Komarov  */
ni_clear(struct ntfs_inode * ni)1014342306fSKonstantin Komarov void ni_clear(struct ntfs_inode *ni)
1024342306fSKonstantin Komarov {
1034342306fSKonstantin Komarov 	struct rb_node *node;
1044342306fSKonstantin Komarov 
1057a4ace68SKonstantin Komarov 	if (!ni->vfs_inode.i_nlink && ni->mi.mrec &&
1067a4ace68SKonstantin Komarov 	    is_rec_inuse(ni->mi.mrec) &&
1077a4ace68SKonstantin Komarov 	    !(ni->mi.sbi->flags & NTFS_FLAGS_LOG_REPLAYING))
1084342306fSKonstantin Komarov 		ni_delete_all(ni);
1094342306fSKonstantin Komarov 
1104342306fSKonstantin Komarov 	al_destroy(ni);
1114342306fSKonstantin Komarov 
1124342306fSKonstantin Komarov 	for (node = rb_first(&ni->mi_tree); node;) {
1134342306fSKonstantin Komarov 		struct rb_node *next = rb_next(node);
1144342306fSKonstantin Komarov 		struct mft_inode *mi = rb_entry(node, struct mft_inode, node);
1154342306fSKonstantin Komarov 
1164342306fSKonstantin Komarov 		rb_erase(node, &ni->mi_tree);
1174342306fSKonstantin Komarov 		mi_put(mi);
1184342306fSKonstantin Komarov 		node = next;
1194342306fSKonstantin Komarov 	}
1204342306fSKonstantin Komarov 
121e8b8e97fSKari Argillander 	/* Bad inode always has mode == S_IFREG. */
1224342306fSKonstantin Komarov 	if (ni->ni_flags & NI_FLAG_DIR)
1234342306fSKonstantin Komarov 		indx_clear(&ni->dir);
1244342306fSKonstantin Komarov 	else {
1254342306fSKonstantin Komarov 		run_close(&ni->file.run);
1264342306fSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
1274342306fSKonstantin Komarov 		if (ni->file.offs_page) {
128e8b8e97fSKari Argillander 			/* On-demand allocated page for offsets. */
1294342306fSKonstantin Komarov 			put_page(ni->file.offs_page);
1304342306fSKonstantin Komarov 			ni->file.offs_page = NULL;
1314342306fSKonstantin Komarov 		}
1324342306fSKonstantin Komarov #endif
1334342306fSKonstantin Komarov 	}
1344342306fSKonstantin Komarov 
1354342306fSKonstantin Komarov 	mi_clear(&ni->mi);
1364342306fSKonstantin Komarov }
1374342306fSKonstantin Komarov 
1384342306fSKonstantin Komarov /*
139e8b8e97fSKari Argillander  * ni_load_mi_ex - Find mft_inode by record number.
1404342306fSKonstantin Komarov  */
ni_load_mi_ex(struct ntfs_inode * ni,CLST rno,struct mft_inode ** mi)1414342306fSKonstantin Komarov int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi)
1424342306fSKonstantin Komarov {
1434342306fSKonstantin Komarov 	int err;
1444342306fSKonstantin Komarov 	struct mft_inode *r;
1454342306fSKonstantin Komarov 
1464342306fSKonstantin Komarov 	r = ni_find_mi(ni, rno);
1474342306fSKonstantin Komarov 	if (r)
1484342306fSKonstantin Komarov 		goto out;
1494342306fSKonstantin Komarov 
1504342306fSKonstantin Komarov 	err = mi_get(ni->mi.sbi, rno, &r);
1514342306fSKonstantin Komarov 	if (err)
1524342306fSKonstantin Komarov 		return err;
1534342306fSKonstantin Komarov 
1544342306fSKonstantin Komarov 	ni_add_mi(ni, r);
1554342306fSKonstantin Komarov 
1564342306fSKonstantin Komarov out:
1574342306fSKonstantin Komarov 	if (mi)
1584342306fSKonstantin Komarov 		*mi = r;
1594342306fSKonstantin Komarov 	return 0;
1604342306fSKonstantin Komarov }
1614342306fSKonstantin Komarov 
1624342306fSKonstantin Komarov /*
163e8b8e97fSKari Argillander  * ni_load_mi - Load mft_inode corresponded list_entry.
1644342306fSKonstantin Komarov  */
ni_load_mi(struct ntfs_inode * ni,const struct ATTR_LIST_ENTRY * le,struct mft_inode ** mi)16578ab59feSKonstantin Komarov int ni_load_mi(struct ntfs_inode *ni, const struct ATTR_LIST_ENTRY *le,
1664342306fSKonstantin Komarov 	       struct mft_inode **mi)
1674342306fSKonstantin Komarov {
1684342306fSKonstantin Komarov 	CLST rno;
1694342306fSKonstantin Komarov 
1704342306fSKonstantin Komarov 	if (!le) {
1714342306fSKonstantin Komarov 		*mi = &ni->mi;
1724342306fSKonstantin Komarov 		return 0;
1734342306fSKonstantin Komarov 	}
1744342306fSKonstantin Komarov 
1754342306fSKonstantin Komarov 	rno = ino_get(&le->ref);
1764342306fSKonstantin Komarov 	if (rno == ni->mi.rno) {
1774342306fSKonstantin Komarov 		*mi = &ni->mi;
1784342306fSKonstantin Komarov 		return 0;
1794342306fSKonstantin Komarov 	}
1804342306fSKonstantin Komarov 	return ni_load_mi_ex(ni, rno, mi);
1814342306fSKonstantin Komarov }
1824342306fSKonstantin Komarov 
1834342306fSKonstantin Komarov /*
1844342306fSKonstantin Komarov  * ni_find_attr
1854342306fSKonstantin Komarov  *
186e8b8e97fSKari Argillander  * Return: Attribute and record this attribute belongs to.
1874342306fSKonstantin Komarov  */
ni_find_attr(struct ntfs_inode * ni,struct ATTRIB * attr,struct ATTR_LIST_ENTRY ** le_o,enum ATTR_TYPE type,const __le16 * name,u8 name_len,const CLST * vcn,struct mft_inode ** mi)1884342306fSKonstantin Komarov struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
1894342306fSKonstantin Komarov 			    struct ATTR_LIST_ENTRY **le_o, enum ATTR_TYPE type,
1904342306fSKonstantin Komarov 			    const __le16 *name, u8 name_len, const CLST *vcn,
1914342306fSKonstantin Komarov 			    struct mft_inode **mi)
1924342306fSKonstantin Komarov {
1934342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
1944342306fSKonstantin Komarov 	struct mft_inode *m;
1954342306fSKonstantin Komarov 
1964342306fSKonstantin Komarov 	if (!ni->attr_list.size ||
1974342306fSKonstantin Komarov 	    (!name_len && (type == ATTR_LIST || type == ATTR_STD))) {
1984342306fSKonstantin Komarov 		if (le_o)
1994342306fSKonstantin Komarov 			*le_o = NULL;
2004342306fSKonstantin Komarov 		if (mi)
2014342306fSKonstantin Komarov 			*mi = &ni->mi;
2024342306fSKonstantin Komarov 
203e8b8e97fSKari Argillander 		/* Look for required attribute in primary record. */
2044342306fSKonstantin Komarov 		return mi_find_attr(&ni->mi, attr, type, name, name_len, NULL);
2054342306fSKonstantin Komarov 	}
2064342306fSKonstantin Komarov 
207e8b8e97fSKari Argillander 	/* First look for list entry of required type. */
2084342306fSKonstantin Komarov 	le = al_find_ex(ni, le_o ? *le_o : NULL, type, name, name_len, vcn);
2094342306fSKonstantin Komarov 	if (!le)
2104342306fSKonstantin Komarov 		return NULL;
2114342306fSKonstantin Komarov 
2124342306fSKonstantin Komarov 	if (le_o)
2134342306fSKonstantin Komarov 		*le_o = le;
2144342306fSKonstantin Komarov 
215e8b8e97fSKari Argillander 	/* Load record that contains this attribute. */
2164342306fSKonstantin Komarov 	if (ni_load_mi(ni, le, &m))
2174342306fSKonstantin Komarov 		return NULL;
2184342306fSKonstantin Komarov 
219e8b8e97fSKari Argillander 	/* Look for required attribute. */
2204342306fSKonstantin Komarov 	attr = mi_find_attr(m, NULL, type, name, name_len, &le->id);
2214342306fSKonstantin Komarov 
2224342306fSKonstantin Komarov 	if (!attr)
2234342306fSKonstantin Komarov 		goto out;
2244342306fSKonstantin Komarov 
2254342306fSKonstantin Komarov 	if (!attr->non_res) {
2264342306fSKonstantin Komarov 		if (vcn && *vcn)
2274342306fSKonstantin Komarov 			goto out;
2284342306fSKonstantin Komarov 	} else if (!vcn) {
2294342306fSKonstantin Komarov 		if (attr->nres.svcn)
2304342306fSKonstantin Komarov 			goto out;
2314342306fSKonstantin Komarov 	} else if (le64_to_cpu(attr->nres.svcn) > *vcn ||
2324342306fSKonstantin Komarov 		   *vcn > le64_to_cpu(attr->nres.evcn)) {
2334342306fSKonstantin Komarov 		goto out;
2344342306fSKonstantin Komarov 	}
2354342306fSKonstantin Komarov 
2364342306fSKonstantin Komarov 	if (mi)
2374342306fSKonstantin Komarov 		*mi = m;
2384342306fSKonstantin Komarov 	return attr;
2394342306fSKonstantin Komarov 
2404342306fSKonstantin Komarov out:
241d5ca7733SKonstantin Komarov 	ntfs_inode_err(&ni->vfs_inode, "failed to parse mft record");
2424342306fSKonstantin Komarov 	ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
2434342306fSKonstantin Komarov 	return NULL;
2444342306fSKonstantin Komarov }
2454342306fSKonstantin Komarov 
2464342306fSKonstantin Komarov /*
247e8b8e97fSKari Argillander  * ni_enum_attr_ex - Enumerates attributes in ntfs_inode.
2484342306fSKonstantin Komarov  */
ni_enum_attr_ex(struct ntfs_inode * ni,struct ATTRIB * attr,struct ATTR_LIST_ENTRY ** le,struct mft_inode ** mi)2494342306fSKonstantin Komarov struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
2504342306fSKonstantin Komarov 			       struct ATTR_LIST_ENTRY **le,
2514342306fSKonstantin Komarov 			       struct mft_inode **mi)
2524342306fSKonstantin Komarov {
2534342306fSKonstantin Komarov 	struct mft_inode *mi2;
2544342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le2;
2554342306fSKonstantin Komarov 
2564342306fSKonstantin Komarov 	/* Do we have an attribute list? */
2574342306fSKonstantin Komarov 	if (!ni->attr_list.size) {
2584342306fSKonstantin Komarov 		*le = NULL;
2594342306fSKonstantin Komarov 		if (mi)
2604342306fSKonstantin Komarov 			*mi = &ni->mi;
261e8b8e97fSKari Argillander 		/* Enum attributes in primary record. */
2624342306fSKonstantin Komarov 		return mi_enum_attr(&ni->mi, attr);
2634342306fSKonstantin Komarov 	}
2644342306fSKonstantin Komarov 
265e8b8e97fSKari Argillander 	/* Get next list entry. */
2664342306fSKonstantin Komarov 	le2 = *le = al_enumerate(ni, attr ? *le : NULL);
2674342306fSKonstantin Komarov 	if (!le2)
2684342306fSKonstantin Komarov 		return NULL;
2694342306fSKonstantin Komarov 
270e8b8e97fSKari Argillander 	/* Load record that contains the required attribute. */
2714342306fSKonstantin Komarov 	if (ni_load_mi(ni, le2, &mi2))
2724342306fSKonstantin Komarov 		return NULL;
2734342306fSKonstantin Komarov 
2744342306fSKonstantin Komarov 	if (mi)
2754342306fSKonstantin Komarov 		*mi = mi2;
2764342306fSKonstantin Komarov 
277e8b8e97fSKari Argillander 	/* Find attribute in loaded record. */
2784342306fSKonstantin Komarov 	return rec_find_attr_le(mi2, le2);
2794342306fSKonstantin Komarov }
2804342306fSKonstantin Komarov 
2814342306fSKonstantin Komarov /*
282e8b8e97fSKari Argillander  * ni_load_attr - Load attribute that contains given VCN.
2834342306fSKonstantin Komarov  */
ni_load_attr(struct ntfs_inode * ni,enum ATTR_TYPE type,const __le16 * name,u8 name_len,CLST vcn,struct mft_inode ** pmi)2844342306fSKonstantin Komarov struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
2854342306fSKonstantin Komarov 			    const __le16 *name, u8 name_len, CLST vcn,
2864342306fSKonstantin Komarov 			    struct mft_inode **pmi)
2874342306fSKonstantin Komarov {
2884342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
2894342306fSKonstantin Komarov 	struct ATTRIB *attr;
2904342306fSKonstantin Komarov 	struct mft_inode *mi;
2914342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *next;
2924342306fSKonstantin Komarov 
2934342306fSKonstantin Komarov 	if (!ni->attr_list.size) {
2944342306fSKonstantin Komarov 		if (pmi)
2954342306fSKonstantin Komarov 			*pmi = &ni->mi;
2964342306fSKonstantin Komarov 		return mi_find_attr(&ni->mi, NULL, type, name, name_len, NULL);
2974342306fSKonstantin Komarov 	}
2984342306fSKonstantin Komarov 
2994342306fSKonstantin Komarov 	le = al_find_ex(ni, NULL, type, name, name_len, NULL);
3004342306fSKonstantin Komarov 	if (!le)
3014342306fSKonstantin Komarov 		return NULL;
3024342306fSKonstantin Komarov 
3034342306fSKonstantin Komarov 	/*
304e8b8e97fSKari Argillander 	 * Unfortunately ATTR_LIST_ENTRY contains only start VCN.
3054342306fSKonstantin Komarov 	 * So to find the ATTRIB segment that contains 'vcn' we should
306e8b8e97fSKari Argillander 	 * enumerate some entries.
3074342306fSKonstantin Komarov 	 */
3084342306fSKonstantin Komarov 	if (vcn) {
3094342306fSKonstantin Komarov 		for (;; le = next) {
3104342306fSKonstantin Komarov 			next = al_find_ex(ni, le, type, name, name_len, NULL);
3114342306fSKonstantin Komarov 			if (!next || le64_to_cpu(next->vcn) > vcn)
3124342306fSKonstantin Komarov 				break;
3134342306fSKonstantin Komarov 		}
3144342306fSKonstantin Komarov 	}
3154342306fSKonstantin Komarov 
3164342306fSKonstantin Komarov 	if (ni_load_mi(ni, le, &mi))
3174342306fSKonstantin Komarov 		return NULL;
3184342306fSKonstantin Komarov 
3194342306fSKonstantin Komarov 	if (pmi)
3204342306fSKonstantin Komarov 		*pmi = mi;
3214342306fSKonstantin Komarov 
3224342306fSKonstantin Komarov 	attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id);
3234342306fSKonstantin Komarov 	if (!attr)
3244342306fSKonstantin Komarov 		return NULL;
3254342306fSKonstantin Komarov 
3264342306fSKonstantin Komarov 	if (!attr->non_res)
3274342306fSKonstantin Komarov 		return attr;
3284342306fSKonstantin Komarov 
3294342306fSKonstantin Komarov 	if (le64_to_cpu(attr->nres.svcn) <= vcn &&
3304342306fSKonstantin Komarov 	    vcn <= le64_to_cpu(attr->nres.evcn))
3314342306fSKonstantin Komarov 		return attr;
3324342306fSKonstantin Komarov 
3334342306fSKonstantin Komarov 	return NULL;
3344342306fSKonstantin Komarov }
3354342306fSKonstantin Komarov 
3364342306fSKonstantin Komarov /*
337e8b8e97fSKari Argillander  * ni_load_all_mi - Load all subrecords.
3384342306fSKonstantin Komarov  */
ni_load_all_mi(struct ntfs_inode * ni)3394342306fSKonstantin Komarov int ni_load_all_mi(struct ntfs_inode *ni)
3404342306fSKonstantin Komarov {
3414342306fSKonstantin Komarov 	int err;
3424342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
3434342306fSKonstantin Komarov 
3444342306fSKonstantin Komarov 	if (!ni->attr_list.size)
3454342306fSKonstantin Komarov 		return 0;
3464342306fSKonstantin Komarov 
3474342306fSKonstantin Komarov 	le = NULL;
3484342306fSKonstantin Komarov 
3494342306fSKonstantin Komarov 	while ((le = al_enumerate(ni, le))) {
3504342306fSKonstantin Komarov 		CLST rno = ino_get(&le->ref);
3514342306fSKonstantin Komarov 
3524342306fSKonstantin Komarov 		if (rno == ni->mi.rno)
3534342306fSKonstantin Komarov 			continue;
3544342306fSKonstantin Komarov 
3554342306fSKonstantin Komarov 		err = ni_load_mi_ex(ni, rno, NULL);
3564342306fSKonstantin Komarov 		if (err)
3574342306fSKonstantin Komarov 			return err;
3584342306fSKonstantin Komarov 	}
3594342306fSKonstantin Komarov 
3604342306fSKonstantin Komarov 	return 0;
3614342306fSKonstantin Komarov }
3624342306fSKonstantin Komarov 
3634342306fSKonstantin Komarov /*
364e8b8e97fSKari Argillander  * ni_add_subrecord - Allocate + format + attach a new subrecord.
3654342306fSKonstantin Komarov  */
ni_add_subrecord(struct ntfs_inode * ni,CLST rno,struct mft_inode ** mi)3664342306fSKonstantin Komarov bool ni_add_subrecord(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi)
3674342306fSKonstantin Komarov {
3684342306fSKonstantin Komarov 	struct mft_inode *m;
3694342306fSKonstantin Komarov 
370195c52bdSKari Argillander 	m = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
3714342306fSKonstantin Komarov 	if (!m)
3724342306fSKonstantin Komarov 		return false;
3734342306fSKonstantin Komarov 
3744342306fSKonstantin Komarov 	if (mi_format_new(m, ni->mi.sbi, rno, 0, ni->mi.rno == MFT_REC_MFT)) {
3754342306fSKonstantin Komarov 		mi_put(m);
3764342306fSKonstantin Komarov 		return false;
3774342306fSKonstantin Komarov 	}
3784342306fSKonstantin Komarov 
3794342306fSKonstantin Komarov 	mi_get_ref(&ni->mi, &m->mrec->parent_ref);
3804342306fSKonstantin Komarov 
3814342306fSKonstantin Komarov 	ni_add_mi(ni, m);
3824342306fSKonstantin Komarov 	*mi = m;
3834342306fSKonstantin Komarov 	return true;
3844342306fSKonstantin Komarov }
3854342306fSKonstantin Komarov 
3864342306fSKonstantin Komarov /*
387e8b8e97fSKari Argillander  * ni_remove_attr - Remove all attributes for the given type/name/id.
3884342306fSKonstantin Komarov  */
ni_remove_attr(struct ntfs_inode * ni,enum ATTR_TYPE type,const __le16 * name,u8 name_len,bool base_only,const __le16 * id)3894342306fSKonstantin Komarov int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
390a81f47c4SKonstantin Komarov 		   const __le16 *name, u8 name_len, bool base_only,
3914342306fSKonstantin Komarov 		   const __le16 *id)
3924342306fSKonstantin Komarov {
3934342306fSKonstantin Komarov 	int err;
3944342306fSKonstantin Komarov 	struct ATTRIB *attr;
3954342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
3964342306fSKonstantin Komarov 	struct mft_inode *mi;
3974342306fSKonstantin Komarov 	u32 type_in;
3984342306fSKonstantin Komarov 	int diff;
3994342306fSKonstantin Komarov 
4004342306fSKonstantin Komarov 	if (base_only || type == ATTR_LIST || !ni->attr_list.size) {
4014342306fSKonstantin Komarov 		attr = mi_find_attr(&ni->mi, NULL, type, name, name_len, id);
4024342306fSKonstantin Komarov 		if (!attr)
4034342306fSKonstantin Komarov 			return -ENOENT;
4044342306fSKonstantin Komarov 
40578ab59feSKonstantin Komarov 		mi_remove_attr(ni, &ni->mi, attr);
4064342306fSKonstantin Komarov 		return 0;
4074342306fSKonstantin Komarov 	}
4084342306fSKonstantin Komarov 
4094342306fSKonstantin Komarov 	type_in = le32_to_cpu(type);
4104342306fSKonstantin Komarov 	le = NULL;
4114342306fSKonstantin Komarov 
4124342306fSKonstantin Komarov 	for (;;) {
4134342306fSKonstantin Komarov 		le = al_enumerate(ni, le);
4144342306fSKonstantin Komarov 		if (!le)
4154342306fSKonstantin Komarov 			return 0;
4164342306fSKonstantin Komarov 
4174342306fSKonstantin Komarov next_le2:
4184342306fSKonstantin Komarov 		diff = le32_to_cpu(le->type) - type_in;
4194342306fSKonstantin Komarov 		if (diff < 0)
4204342306fSKonstantin Komarov 			continue;
4214342306fSKonstantin Komarov 
4224342306fSKonstantin Komarov 		if (diff > 0)
4234342306fSKonstantin Komarov 			return 0;
4244342306fSKonstantin Komarov 
4254342306fSKonstantin Komarov 		if (le->name_len != name_len)
4264342306fSKonstantin Komarov 			continue;
4274342306fSKonstantin Komarov 
4284342306fSKonstantin Komarov 		if (name_len &&
4294342306fSKonstantin Komarov 		    memcmp(le_name(le), name, name_len * sizeof(short)))
4304342306fSKonstantin Komarov 			continue;
4314342306fSKonstantin Komarov 
4324342306fSKonstantin Komarov 		if (id && le->id != *id)
4334342306fSKonstantin Komarov 			continue;
4344342306fSKonstantin Komarov 		err = ni_load_mi(ni, le, &mi);
4354342306fSKonstantin Komarov 		if (err)
4364342306fSKonstantin Komarov 			return err;
4374342306fSKonstantin Komarov 
4384342306fSKonstantin Komarov 		al_remove_le(ni, le);
4394342306fSKonstantin Komarov 
4404342306fSKonstantin Komarov 		attr = mi_find_attr(mi, NULL, type, name, name_len, id);
4414342306fSKonstantin Komarov 		if (!attr)
4424342306fSKonstantin Komarov 			return -ENOENT;
4434342306fSKonstantin Komarov 
44478ab59feSKonstantin Komarov 		mi_remove_attr(ni, mi, attr);
4454342306fSKonstantin Komarov 
4464342306fSKonstantin Komarov 		if (PtrOffset(ni->attr_list.le, le) >= ni->attr_list.size)
4474342306fSKonstantin Komarov 			return 0;
4484342306fSKonstantin Komarov 		goto next_le2;
4494342306fSKonstantin Komarov 	}
4504342306fSKonstantin Komarov }
4514342306fSKonstantin Komarov 
4524342306fSKonstantin Komarov /*
453e8b8e97fSKari Argillander  * ni_ins_new_attr - Insert the attribute into record.
4544342306fSKonstantin Komarov  *
455e8b8e97fSKari Argillander  * Return: Not full constructed attribute or NULL if not possible to create.
4564342306fSKonstantin Komarov  */
45778ab59feSKonstantin Komarov static struct ATTRIB *
ni_ins_new_attr(struct ntfs_inode * ni,struct mft_inode * mi,struct ATTR_LIST_ENTRY * le,enum ATTR_TYPE type,const __le16 * name,u8 name_len,u32 asize,u16 name_off,CLST svcn,struct ATTR_LIST_ENTRY ** ins_le)45878ab59feSKonstantin Komarov ni_ins_new_attr(struct ntfs_inode *ni, struct mft_inode *mi,
45978ab59feSKonstantin Komarov 		struct ATTR_LIST_ENTRY *le, enum ATTR_TYPE type,
46078ab59feSKonstantin Komarov 		const __le16 *name, u8 name_len, u32 asize, u16 name_off,
46178ab59feSKonstantin Komarov 		CLST svcn, struct ATTR_LIST_ENTRY **ins_le)
4624342306fSKonstantin Komarov {
4634342306fSKonstantin Komarov 	int err;
4644342306fSKonstantin Komarov 	struct ATTRIB *attr;
4654342306fSKonstantin Komarov 	bool le_added = false;
4664342306fSKonstantin Komarov 	struct MFT_REF ref;
4674342306fSKonstantin Komarov 
4684342306fSKonstantin Komarov 	mi_get_ref(mi, &ref);
4694342306fSKonstantin Komarov 
4704342306fSKonstantin Komarov 	if (type != ATTR_LIST && !le && ni->attr_list.size) {
4714342306fSKonstantin Komarov 		err = al_add_le(ni, type, name, name_len, svcn, cpu_to_le16(-1),
4724342306fSKonstantin Komarov 				&ref, &le);
4734342306fSKonstantin Komarov 		if (err) {
474e8b8e97fSKari Argillander 			/* No memory or no space. */
475451e45a0SKonstantin Komarov 			return ERR_PTR(err);
4764342306fSKonstantin Komarov 		}
4774342306fSKonstantin Komarov 		le_added = true;
4784342306fSKonstantin Komarov 
4794342306fSKonstantin Komarov 		/*
4804342306fSKonstantin Komarov 		 * al_add_le -> attr_set_size (list) -> ni_expand_list
4814342306fSKonstantin Komarov 		 * which moves some attributes out of primary record
4824342306fSKonstantin Komarov 		 * this means that name may point into moved memory
483e8b8e97fSKari Argillander 		 * reinit 'name' from le.
4844342306fSKonstantin Komarov 		 */
4854342306fSKonstantin Komarov 		name = le->name;
4864342306fSKonstantin Komarov 	}
4874342306fSKonstantin Komarov 
4884342306fSKonstantin Komarov 	attr = mi_insert_attr(mi, type, name, name_len, asize, name_off);
4894342306fSKonstantin Komarov 	if (!attr) {
4904342306fSKonstantin Komarov 		if (le_added)
4914342306fSKonstantin Komarov 			al_remove_le(ni, le);
4924342306fSKonstantin Komarov 		return NULL;
4934342306fSKonstantin Komarov 	}
4944342306fSKonstantin Komarov 
4954342306fSKonstantin Komarov 	if (type == ATTR_LIST) {
496e8b8e97fSKari Argillander 		/* Attr list is not in list entry array. */
4974342306fSKonstantin Komarov 		goto out;
4984342306fSKonstantin Komarov 	}
4994342306fSKonstantin Komarov 
5004342306fSKonstantin Komarov 	if (!le)
5014342306fSKonstantin Komarov 		goto out;
5024342306fSKonstantin Komarov 
503e8b8e97fSKari Argillander 	/* Update ATTRIB Id and record reference. */
5044342306fSKonstantin Komarov 	le->id = attr->id;
5054342306fSKonstantin Komarov 	ni->attr_list.dirty = true;
5064342306fSKonstantin Komarov 	le->ref = ref;
5074342306fSKonstantin Komarov 
5084342306fSKonstantin Komarov out:
50978ab59feSKonstantin Komarov 	if (ins_le)
51078ab59feSKonstantin Komarov 		*ins_le = le;
5114342306fSKonstantin Komarov 	return attr;
5124342306fSKonstantin Komarov }
5134342306fSKonstantin Komarov 
5144342306fSKonstantin Komarov /*
515e8b8e97fSKari Argillander  * ni_repack
516e8b8e97fSKari Argillander  *
517e8b8e97fSKari Argillander  * Random write access to sparsed or compressed file may result to
5184342306fSKonstantin Komarov  * not optimized packed runs.
519e8b8e97fSKari Argillander  * Here is the place to optimize it.
5204342306fSKonstantin Komarov  */
ni_repack(struct ntfs_inode * ni)5214342306fSKonstantin Komarov static int ni_repack(struct ntfs_inode *ni)
5224342306fSKonstantin Komarov {
523f0377761SKonstantin Komarov #if 1
524f0377761SKonstantin Komarov 	return 0;
525f0377761SKonstantin Komarov #else
5264342306fSKonstantin Komarov 	int err = 0;
5274342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
5284342306fSKonstantin Komarov 	struct mft_inode *mi, *mi_p = NULL;
5294342306fSKonstantin Komarov 	struct ATTRIB *attr = NULL, *attr_p;
5304342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le = NULL, *le_p;
5314342306fSKonstantin Komarov 	CLST alloc = 0;
5324342306fSKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
5334342306fSKonstantin Komarov 	CLST svcn, evcn = 0, svcn_p, evcn_p, next_svcn;
5344342306fSKonstantin Komarov 	u32 roff, rs = sbi->record_size;
5354342306fSKonstantin Komarov 	struct runs_tree run;
5364342306fSKonstantin Komarov 
5374342306fSKonstantin Komarov 	run_init(&run);
5384342306fSKonstantin Komarov 
5394342306fSKonstantin Komarov 	while ((attr = ni_enum_attr_ex(ni, attr, &le, &mi))) {
5404342306fSKonstantin Komarov 		if (!attr->non_res)
5414342306fSKonstantin Komarov 			continue;
5424342306fSKonstantin Komarov 
5434342306fSKonstantin Komarov 		svcn = le64_to_cpu(attr->nres.svcn);
5444342306fSKonstantin Komarov 		if (svcn != le64_to_cpu(le->vcn)) {
5454342306fSKonstantin Komarov 			err = -EINVAL;
5464342306fSKonstantin Komarov 			break;
5474342306fSKonstantin Komarov 		}
5484342306fSKonstantin Komarov 
5494342306fSKonstantin Komarov 		if (!svcn) {
5504342306fSKonstantin Komarov 			alloc = le64_to_cpu(attr->nres.alloc_size) >>
5514342306fSKonstantin Komarov 				cluster_bits;
5524342306fSKonstantin Komarov 			mi_p = NULL;
5534342306fSKonstantin Komarov 		} else if (svcn != evcn + 1) {
5544342306fSKonstantin Komarov 			err = -EINVAL;
5554342306fSKonstantin Komarov 			break;
5564342306fSKonstantin Komarov 		}
5574342306fSKonstantin Komarov 
5584342306fSKonstantin Komarov 		evcn = le64_to_cpu(attr->nres.evcn);
5594342306fSKonstantin Komarov 
5604342306fSKonstantin Komarov 		if (svcn > evcn + 1) {
5614342306fSKonstantin Komarov 			err = -EINVAL;
5624342306fSKonstantin Komarov 			break;
5634342306fSKonstantin Komarov 		}
5644342306fSKonstantin Komarov 
5654342306fSKonstantin Komarov 		if (!mi_p) {
566bd6ae049SKonstantin Komarov 			/* Do not try if not enough free space. */
5674342306fSKonstantin Komarov 			if (le32_to_cpu(mi->mrec->used) + 8 >= rs)
5684342306fSKonstantin Komarov 				continue;
5694342306fSKonstantin Komarov 
570e8b8e97fSKari Argillander 			/* Do not try if last attribute segment. */
5714342306fSKonstantin Komarov 			if (evcn + 1 == alloc)
5724342306fSKonstantin Komarov 				continue;
5734342306fSKonstantin Komarov 			run_close(&run);
5744342306fSKonstantin Komarov 		}
5754342306fSKonstantin Komarov 
5764342306fSKonstantin Komarov 		roff = le16_to_cpu(attr->nres.run_off);
5776db62086SEdward Lo 
5786db62086SEdward Lo 		if (roff > le32_to_cpu(attr->size)) {
5796db62086SEdward Lo 			err = -EINVAL;
5806db62086SEdward Lo 			break;
5816db62086SEdward Lo 		}
5826db62086SEdward Lo 
5834342306fSKonstantin Komarov 		err = run_unpack(&run, sbi, ni->mi.rno, svcn, evcn, svcn,
5844342306fSKonstantin Komarov 				 Add2Ptr(attr, roff),
5854342306fSKonstantin Komarov 				 le32_to_cpu(attr->size) - roff);
5864342306fSKonstantin Komarov 		if (err < 0)
5874342306fSKonstantin Komarov 			break;
5884342306fSKonstantin Komarov 
5894342306fSKonstantin Komarov 		if (!mi_p) {
5904342306fSKonstantin Komarov 			mi_p = mi;
5914342306fSKonstantin Komarov 			attr_p = attr;
5924342306fSKonstantin Komarov 			svcn_p = svcn;
5934342306fSKonstantin Komarov 			evcn_p = evcn;
5944342306fSKonstantin Komarov 			le_p = le;
5954342306fSKonstantin Komarov 			err = 0;
5964342306fSKonstantin Komarov 			continue;
5974342306fSKonstantin Komarov 		}
5984342306fSKonstantin Komarov 
5994342306fSKonstantin Komarov 		/*
600e8b8e97fSKari Argillander 		 * Run contains data from two records: mi_p and mi
601e8b8e97fSKari Argillander 		 * Try to pack in one.
6024342306fSKonstantin Komarov 		 */
6034342306fSKonstantin Komarov 		err = mi_pack_runs(mi_p, attr_p, &run, evcn + 1 - svcn_p);
6044342306fSKonstantin Komarov 		if (err)
6054342306fSKonstantin Komarov 			break;
6064342306fSKonstantin Komarov 
6074342306fSKonstantin Komarov 		next_svcn = le64_to_cpu(attr_p->nres.evcn) + 1;
6084342306fSKonstantin Komarov 
6094342306fSKonstantin Komarov 		if (next_svcn >= evcn + 1) {
610e8b8e97fSKari Argillander 			/* We can remove this attribute segment. */
6114342306fSKonstantin Komarov 			al_remove_le(ni, le);
61278ab59feSKonstantin Komarov 			mi_remove_attr(NULL, mi, attr);
6134342306fSKonstantin Komarov 			le = le_p;
6144342306fSKonstantin Komarov 			continue;
6154342306fSKonstantin Komarov 		}
6164342306fSKonstantin Komarov 
6174342306fSKonstantin Komarov 		attr->nres.svcn = le->vcn = cpu_to_le64(next_svcn);
6184342306fSKonstantin Komarov 		mi->dirty = true;
6194342306fSKonstantin Komarov 		ni->attr_list.dirty = true;
6204342306fSKonstantin Komarov 
6214342306fSKonstantin Komarov 		if (evcn + 1 == alloc) {
6224342306fSKonstantin Komarov 			err = mi_pack_runs(mi, attr, &run,
6234342306fSKonstantin Komarov 					   evcn + 1 - next_svcn);
6244342306fSKonstantin Komarov 			if (err)
6254342306fSKonstantin Komarov 				break;
6264342306fSKonstantin Komarov 			mi_p = NULL;
6274342306fSKonstantin Komarov 		} else {
6284342306fSKonstantin Komarov 			mi_p = mi;
6294342306fSKonstantin Komarov 			attr_p = attr;
6304342306fSKonstantin Komarov 			svcn_p = next_svcn;
6314342306fSKonstantin Komarov 			evcn_p = evcn;
6324342306fSKonstantin Komarov 			le_p = le;
6334342306fSKonstantin Komarov 			run_truncate_head(&run, next_svcn);
6344342306fSKonstantin Komarov 		}
6354342306fSKonstantin Komarov 	}
6364342306fSKonstantin Komarov 
6374342306fSKonstantin Komarov 	if (err) {
6384342306fSKonstantin Komarov 		ntfs_inode_warn(&ni->vfs_inode, "repack problem");
6394342306fSKonstantin Komarov 		ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
6404342306fSKonstantin Komarov 
641e8b8e97fSKari Argillander 		/* Pack loaded but not packed runs. */
6424342306fSKonstantin Komarov 		if (mi_p)
6434342306fSKonstantin Komarov 			mi_pack_runs(mi_p, attr_p, &run, evcn_p + 1 - svcn_p);
6444342306fSKonstantin Komarov 	}
6454342306fSKonstantin Komarov 
6464342306fSKonstantin Komarov 	run_close(&run);
6474342306fSKonstantin Komarov 	return err;
648f0377761SKonstantin Komarov #endif
6494342306fSKonstantin Komarov }
6504342306fSKonstantin Komarov 
6514342306fSKonstantin Komarov /*
6524342306fSKonstantin Komarov  * ni_try_remove_attr_list
6534342306fSKonstantin Komarov  *
6544342306fSKonstantin Komarov  * Can we remove attribute list?
655e8b8e97fSKari Argillander  * Check the case when primary record contains enough space for all attributes.
6564342306fSKonstantin Komarov  */
ni_try_remove_attr_list(struct ntfs_inode * ni)6574342306fSKonstantin Komarov static int ni_try_remove_attr_list(struct ntfs_inode *ni)
6584342306fSKonstantin Komarov {
6594342306fSKonstantin Komarov 	int err = 0;
6604342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
6614342306fSKonstantin Komarov 	struct ATTRIB *attr, *attr_list, *attr_ins;
6624342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
6634342306fSKonstantin Komarov 	struct mft_inode *mi;
6644342306fSKonstantin Komarov 	u32 asize, free;
6654342306fSKonstantin Komarov 	struct MFT_REF ref;
66619d1b787SKonstantin Komarov 	struct MFT_REC *mrec;
6674342306fSKonstantin Komarov 	__le16 id;
6684342306fSKonstantin Komarov 
6694342306fSKonstantin Komarov 	if (!ni->attr_list.dirty)
6704342306fSKonstantin Komarov 		return 0;
6714342306fSKonstantin Komarov 
6724342306fSKonstantin Komarov 	err = ni_repack(ni);
6734342306fSKonstantin Komarov 	if (err)
6744342306fSKonstantin Komarov 		return err;
6754342306fSKonstantin Komarov 
6764342306fSKonstantin Komarov 	attr_list = mi_find_attr(&ni->mi, NULL, ATTR_LIST, NULL, 0, NULL);
6774342306fSKonstantin Komarov 	if (!attr_list)
6784342306fSKonstantin Komarov 		return 0;
6794342306fSKonstantin Komarov 
6804342306fSKonstantin Komarov 	asize = le32_to_cpu(attr_list->size);
6814342306fSKonstantin Komarov 
682e8b8e97fSKari Argillander 	/* Free space in primary record without attribute list. */
6834342306fSKonstantin Komarov 	free = sbi->record_size - le32_to_cpu(ni->mi.mrec->used) + asize;
6844342306fSKonstantin Komarov 	mi_get_ref(&ni->mi, &ref);
6854342306fSKonstantin Komarov 
6864342306fSKonstantin Komarov 	le = NULL;
6874342306fSKonstantin Komarov 	while ((le = al_enumerate(ni, le))) {
6884342306fSKonstantin Komarov 		if (!memcmp(&le->ref, &ref, sizeof(ref)))
6894342306fSKonstantin Komarov 			continue;
6904342306fSKonstantin Komarov 
6914342306fSKonstantin Komarov 		if (le->vcn)
6924342306fSKonstantin Komarov 			return 0;
6934342306fSKonstantin Komarov 
6944342306fSKonstantin Komarov 		mi = ni_find_mi(ni, ino_get(&le->ref));
6954342306fSKonstantin Komarov 		if (!mi)
6964342306fSKonstantin Komarov 			return 0;
6974342306fSKonstantin Komarov 
6984342306fSKonstantin Komarov 		attr = mi_find_attr(mi, NULL, le->type, le_name(le),
6994342306fSKonstantin Komarov 				    le->name_len, &le->id);
7004342306fSKonstantin Komarov 		if (!attr)
7014342306fSKonstantin Komarov 			return 0;
7024342306fSKonstantin Komarov 
7034342306fSKonstantin Komarov 		asize = le32_to_cpu(attr->size);
7044342306fSKonstantin Komarov 		if (asize > free)
7054342306fSKonstantin Komarov 			return 0;
7064342306fSKonstantin Komarov 
7074342306fSKonstantin Komarov 		free -= asize;
7084342306fSKonstantin Komarov 	}
7094342306fSKonstantin Komarov 
71019d1b787SKonstantin Komarov 	/* Make a copy of primary record to restore if error. */
71119d1b787SKonstantin Komarov 	mrec = kmemdup(ni->mi.mrec, sbi->record_size, GFP_NOFS);
71219d1b787SKonstantin Komarov 	if (!mrec)
71319d1b787SKonstantin Komarov 		return 0; /* Not critical. */
71419d1b787SKonstantin Komarov 
71578ab59feSKonstantin Komarov 	/* It seems that attribute list can be removed from primary record. */
71678ab59feSKonstantin Komarov 	mi_remove_attr(NULL, &ni->mi, attr_list);
7174342306fSKonstantin Komarov 
7184342306fSKonstantin Komarov 	/*
71919d1b787SKonstantin Komarov 	 * Repeat the cycle above and copy all attributes to primary record.
72019d1b787SKonstantin Komarov 	 * Do not remove original attributes from subrecords!
7214342306fSKonstantin Komarov 	 * It should be success!
7224342306fSKonstantin Komarov 	 */
7234342306fSKonstantin Komarov 	le = NULL;
7244342306fSKonstantin Komarov 	while ((le = al_enumerate(ni, le))) {
7254342306fSKonstantin Komarov 		if (!memcmp(&le->ref, &ref, sizeof(ref)))
7264342306fSKonstantin Komarov 			continue;
7274342306fSKonstantin Komarov 
7284342306fSKonstantin Komarov 		mi = ni_find_mi(ni, ino_get(&le->ref));
7298607954cSKonstantin Komarov 		if (!mi) {
7308607954cSKonstantin Komarov 			/* Should never happened, 'cause already checked. */
73119d1b787SKonstantin Komarov 			goto out;
7328607954cSKonstantin Komarov 		}
7334342306fSKonstantin Komarov 
7344342306fSKonstantin Komarov 		attr = mi_find_attr(mi, NULL, le->type, le_name(le),
7354342306fSKonstantin Komarov 				    le->name_len, &le->id);
7368607954cSKonstantin Komarov 		if (!attr) {
7378607954cSKonstantin Komarov 			/* Should never happened, 'cause already checked. */
73819d1b787SKonstantin Komarov 			goto out;
7398607954cSKonstantin Komarov 		}
7404342306fSKonstantin Komarov 		asize = le32_to_cpu(attr->size);
7414342306fSKonstantin Komarov 
742e8b8e97fSKari Argillander 		/* Insert into primary record. */
7434342306fSKonstantin Komarov 		attr_ins = mi_insert_attr(&ni->mi, le->type, le_name(le),
7444342306fSKonstantin Komarov 					  le->name_len, asize,
7454342306fSKonstantin Komarov 					  le16_to_cpu(attr->name_off));
7468607954cSKonstantin Komarov 		if (!attr_ins) {
7478607954cSKonstantin Komarov 			/*
74819d1b787SKonstantin Komarov 			 * No space in primary record (already checked).
7498607954cSKonstantin Komarov 			 */
75019d1b787SKonstantin Komarov 			goto out;
7518607954cSKonstantin Komarov 		}
7524342306fSKonstantin Komarov 
753e8b8e97fSKari Argillander 		/* Copy all except id. */
7548607954cSKonstantin Komarov 		id = attr_ins->id;
7554342306fSKonstantin Komarov 		memcpy(attr_ins, attr, asize);
7564342306fSKonstantin Komarov 		attr_ins->id = id;
75719d1b787SKonstantin Komarov 	}
75819d1b787SKonstantin Komarov 
75919d1b787SKonstantin Komarov 	/*
76019d1b787SKonstantin Komarov 	 * Repeat the cycle above and remove all attributes from subrecords.
76119d1b787SKonstantin Komarov 	 */
76219d1b787SKonstantin Komarov 	le = NULL;
76319d1b787SKonstantin Komarov 	while ((le = al_enumerate(ni, le))) {
76419d1b787SKonstantin Komarov 		if (!memcmp(&le->ref, &ref, sizeof(ref)))
76519d1b787SKonstantin Komarov 			continue;
76619d1b787SKonstantin Komarov 
76719d1b787SKonstantin Komarov 		mi = ni_find_mi(ni, ino_get(&le->ref));
76819d1b787SKonstantin Komarov 		if (!mi)
76919d1b787SKonstantin Komarov 			continue;
77019d1b787SKonstantin Komarov 
77119d1b787SKonstantin Komarov 		attr = mi_find_attr(mi, NULL, le->type, le_name(le),
77219d1b787SKonstantin Komarov 				    le->name_len, &le->id);
77319d1b787SKonstantin Komarov 		if (!attr)
77419d1b787SKonstantin Komarov 			continue;
7754342306fSKonstantin Komarov 
776e8b8e97fSKari Argillander 		/* Remove from original record. */
77778ab59feSKonstantin Komarov 		mi_remove_attr(NULL, mi, attr);
7784342306fSKonstantin Komarov 	}
7794342306fSKonstantin Komarov 
7804342306fSKonstantin Komarov 	run_deallocate(sbi, &ni->attr_list.run, true);
7814342306fSKonstantin Komarov 	run_close(&ni->attr_list.run);
7824342306fSKonstantin Komarov 	ni->attr_list.size = 0;
78386cd4631SKonstantin Komarov 	kvfree(ni->attr_list.le);
7844342306fSKonstantin Komarov 	ni->attr_list.le = NULL;
7854342306fSKonstantin Komarov 	ni->attr_list.dirty = false;
7864342306fSKonstantin Komarov 
78719d1b787SKonstantin Komarov 	kfree(mrec);
7884342306fSKonstantin Komarov 	return 0;
78919d1b787SKonstantin Komarov out:
79019d1b787SKonstantin Komarov 	/* Restore primary record. */
79119d1b787SKonstantin Komarov 	swap(mrec, ni->mi.mrec);
79219d1b787SKonstantin Komarov 	kfree(mrec);
79319d1b787SKonstantin Komarov 	return 0;
7944342306fSKonstantin Komarov }
7954342306fSKonstantin Komarov 
7964342306fSKonstantin Komarov /*
797e8b8e97fSKari Argillander  * ni_create_attr_list - Generates an attribute list for this primary record.
7984342306fSKonstantin Komarov  */
ni_create_attr_list(struct ntfs_inode * ni)7994342306fSKonstantin Komarov int ni_create_attr_list(struct ntfs_inode *ni)
8004342306fSKonstantin Komarov {
8014342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
8024342306fSKonstantin Komarov 	int err;
8034342306fSKonstantin Komarov 	u32 lsize;
8044342306fSKonstantin Komarov 	struct ATTRIB *attr;
8054342306fSKonstantin Komarov 	struct ATTRIB *arr_move[7];
8064342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le, *le_b[7];
8074342306fSKonstantin Komarov 	struct MFT_REC *rec;
8084342306fSKonstantin Komarov 	bool is_mft;
8094342306fSKonstantin Komarov 	CLST rno = 0;
8104342306fSKonstantin Komarov 	struct mft_inode *mi;
8114342306fSKonstantin Komarov 	u32 free_b, nb, to_free, rs;
8124342306fSKonstantin Komarov 	u16 sz;
8134342306fSKonstantin Komarov 
8144342306fSKonstantin Komarov 	is_mft = ni->mi.rno == MFT_REC_MFT;
8154342306fSKonstantin Komarov 	rec = ni->mi.mrec;
8164342306fSKonstantin Komarov 	rs = sbi->record_size;
8174342306fSKonstantin Komarov 
8184342306fSKonstantin Komarov 	/*
819e8b8e97fSKari Argillander 	 * Skip estimating exact memory requirement.
820e8b8e97fSKari Argillander 	 * Looks like one record_size is always enough.
8214342306fSKonstantin Komarov 	 */
822195c52bdSKari Argillander 	le = kmalloc(al_aligned(rs), GFP_NOFS);
82314f527d4SKonstantin Komarov 	if (!le)
82414f527d4SKonstantin Komarov 		return -ENOMEM;
8254342306fSKonstantin Komarov 
8264342306fSKonstantin Komarov 	mi_get_ref(&ni->mi, &le->ref);
8274342306fSKonstantin Komarov 	ni->attr_list.le = le;
8284342306fSKonstantin Komarov 
8294342306fSKonstantin Komarov 	attr = NULL;
8304342306fSKonstantin Komarov 	nb = 0;
8314342306fSKonstantin Komarov 	free_b = 0;
8324342306fSKonstantin Komarov 	attr = NULL;
8334342306fSKonstantin Komarov 
8344342306fSKonstantin Komarov 	for (; (attr = mi_enum_attr(&ni->mi, attr)); le = Add2Ptr(le, sz)) {
8354342306fSKonstantin Komarov 		sz = le_size(attr->name_len);
8364342306fSKonstantin Komarov 		le->type = attr->type;
8374342306fSKonstantin Komarov 		le->size = cpu_to_le16(sz);
8384342306fSKonstantin Komarov 		le->name_len = attr->name_len;
8394342306fSKonstantin Komarov 		le->name_off = offsetof(struct ATTR_LIST_ENTRY, name);
8404342306fSKonstantin Komarov 		le->vcn = 0;
8414342306fSKonstantin Komarov 		if (le != ni->attr_list.le)
8424342306fSKonstantin Komarov 			le->ref = ni->attr_list.le->ref;
8434342306fSKonstantin Komarov 		le->id = attr->id;
8444342306fSKonstantin Komarov 
8454342306fSKonstantin Komarov 		if (attr->name_len)
8464342306fSKonstantin Komarov 			memcpy(le->name, attr_name(attr),
8474342306fSKonstantin Komarov 			       sizeof(short) * attr->name_len);
8484342306fSKonstantin Komarov 		else if (attr->type == ATTR_STD)
8494342306fSKonstantin Komarov 			continue;
8504342306fSKonstantin Komarov 		else if (attr->type == ATTR_LIST)
8514342306fSKonstantin Komarov 			continue;
8524342306fSKonstantin Komarov 		else if (is_mft && attr->type == ATTR_DATA)
8534342306fSKonstantin Komarov 			continue;
8544342306fSKonstantin Komarov 
8554342306fSKonstantin Komarov 		if (!nb || nb < ARRAY_SIZE(arr_move)) {
8564342306fSKonstantin Komarov 			le_b[nb] = le;
8574342306fSKonstantin Komarov 			arr_move[nb++] = attr;
8584342306fSKonstantin Komarov 			free_b += le32_to_cpu(attr->size);
8594342306fSKonstantin Komarov 		}
8604342306fSKonstantin Komarov 	}
8614342306fSKonstantin Komarov 
8624342306fSKonstantin Komarov 	lsize = PtrOffset(ni->attr_list.le, le);
8634342306fSKonstantin Komarov 	ni->attr_list.size = lsize;
8644342306fSKonstantin Komarov 
8654342306fSKonstantin Komarov 	to_free = le32_to_cpu(rec->used) + lsize + SIZEOF_RESIDENT;
8664342306fSKonstantin Komarov 	if (to_free <= rs) {
8674342306fSKonstantin Komarov 		to_free = 0;
8684342306fSKonstantin Komarov 	} else {
8694342306fSKonstantin Komarov 		to_free -= rs;
8704342306fSKonstantin Komarov 
8714342306fSKonstantin Komarov 		if (to_free > free_b) {
8724342306fSKonstantin Komarov 			err = -EINVAL;
87314f527d4SKonstantin Komarov 			goto out;
8744342306fSKonstantin Komarov 		}
8754342306fSKonstantin Komarov 	}
8764342306fSKonstantin Komarov 
877e8b8e97fSKari Argillander 	/* Allocate child MFT. */
8784342306fSKonstantin Komarov 	err = ntfs_look_free_mft(sbi, &rno, is_mft, ni, &mi);
8794342306fSKonstantin Komarov 	if (err)
88014f527d4SKonstantin Komarov 		goto out;
8814342306fSKonstantin Komarov 
882fdec309cSEdward Lo 	err = -EINVAL;
883e8b8e97fSKari Argillander 	/* Call mi_remove_attr() in reverse order to keep pointers 'arr_move' valid. */
8844342306fSKonstantin Komarov 	while (to_free > 0) {
8854342306fSKonstantin Komarov 		struct ATTRIB *b = arr_move[--nb];
8864342306fSKonstantin Komarov 		u32 asize = le32_to_cpu(b->size);
8874342306fSKonstantin Komarov 		u16 name_off = le16_to_cpu(b->name_off);
8884342306fSKonstantin Komarov 
8894342306fSKonstantin Komarov 		attr = mi_insert_attr(mi, b->type, Add2Ptr(b, name_off),
8904342306fSKonstantin Komarov 				      b->name_len, asize, name_off);
891fdec309cSEdward Lo 		if (!attr)
89214f527d4SKonstantin Komarov 			goto out;
8934342306fSKonstantin Komarov 
8944342306fSKonstantin Komarov 		mi_get_ref(mi, &le_b[nb]->ref);
8954342306fSKonstantin Komarov 		le_b[nb]->id = attr->id;
8964342306fSKonstantin Komarov 
897e8b8e97fSKari Argillander 		/* Copy all except id. */
8984342306fSKonstantin Komarov 		memcpy(attr, b, asize);
8994342306fSKonstantin Komarov 		attr->id = le_b[nb]->id;
9004342306fSKonstantin Komarov 
90178ab59feSKonstantin Komarov 		/* Remove from primary record. */
902fdec309cSEdward Lo 		if (!mi_remove_attr(NULL, &ni->mi, b))
90314f527d4SKonstantin Komarov 			goto out;
9044342306fSKonstantin Komarov 
9054342306fSKonstantin Komarov 		if (to_free <= asize)
9064342306fSKonstantin Komarov 			break;
9074342306fSKonstantin Komarov 		to_free -= asize;
908fdec309cSEdward Lo 		if (!nb)
90914f527d4SKonstantin Komarov 			goto out;
9104342306fSKonstantin Komarov 	}
9114342306fSKonstantin Komarov 
9124342306fSKonstantin Komarov 	attr = mi_insert_attr(&ni->mi, ATTR_LIST, NULL, 0,
9134342306fSKonstantin Komarov 			      lsize + SIZEOF_RESIDENT, SIZEOF_RESIDENT);
914fdec309cSEdward Lo 	if (!attr)
91514f527d4SKonstantin Komarov 		goto out;
9164342306fSKonstantin Komarov 
9174342306fSKonstantin Komarov 	attr->non_res = 0;
9184342306fSKonstantin Komarov 	attr->flags = 0;
9194342306fSKonstantin Komarov 	attr->res.data_size = cpu_to_le32(lsize);
9204342306fSKonstantin Komarov 	attr->res.data_off = SIZEOF_RESIDENT_LE;
9214342306fSKonstantin Komarov 	attr->res.flags = 0;
9224342306fSKonstantin Komarov 	attr->res.res = 0;
9234342306fSKonstantin Komarov 
9244342306fSKonstantin Komarov 	memcpy(resident_data_ex(attr, lsize), ni->attr_list.le, lsize);
9254342306fSKonstantin Komarov 
9264342306fSKonstantin Komarov 	ni->attr_list.dirty = false;
9274342306fSKonstantin Komarov 
9284342306fSKonstantin Komarov 	mark_inode_dirty(&ni->vfs_inode);
92914f527d4SKonstantin Komarov 	return 0;
9304342306fSKonstantin Komarov 
93114f527d4SKonstantin Komarov out:
93286cd4631SKonstantin Komarov 	kvfree(ni->attr_list.le);
9334342306fSKonstantin Komarov 	ni->attr_list.le = NULL;
9344342306fSKonstantin Komarov 	ni->attr_list.size = 0;
935fdec309cSEdward Lo 	return err;
9364342306fSKonstantin Komarov }
9374342306fSKonstantin Komarov 
9384342306fSKonstantin Komarov /*
939e8b8e97fSKari Argillander  * ni_ins_attr_ext - Add an external attribute to the ntfs_inode.
9404342306fSKonstantin Komarov  */
ni_ins_attr_ext(struct ntfs_inode * ni,struct ATTR_LIST_ENTRY * le,enum ATTR_TYPE type,const __le16 * name,u8 name_len,u32 asize,CLST svcn,u16 name_off,bool force_ext,struct ATTRIB ** ins_attr,struct mft_inode ** ins_mi,struct ATTR_LIST_ENTRY ** ins_le)9414342306fSKonstantin Komarov static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
9424342306fSKonstantin Komarov 			   enum ATTR_TYPE type, const __le16 *name, u8 name_len,
9434342306fSKonstantin Komarov 			   u32 asize, CLST svcn, u16 name_off, bool force_ext,
94478ab59feSKonstantin Komarov 			   struct ATTRIB **ins_attr, struct mft_inode **ins_mi,
94578ab59feSKonstantin Komarov 			   struct ATTR_LIST_ENTRY **ins_le)
9464342306fSKonstantin Komarov {
9474342306fSKonstantin Komarov 	struct ATTRIB *attr;
9484342306fSKonstantin Komarov 	struct mft_inode *mi;
9494342306fSKonstantin Komarov 	CLST rno;
9504342306fSKonstantin Komarov 	u64 vbo;
9514342306fSKonstantin Komarov 	struct rb_node *node;
9524342306fSKonstantin Komarov 	int err;
9534342306fSKonstantin Komarov 	bool is_mft, is_mft_data;
9544342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
9554342306fSKonstantin Komarov 
9564342306fSKonstantin Komarov 	is_mft = ni->mi.rno == MFT_REC_MFT;
9574342306fSKonstantin Komarov 	is_mft_data = is_mft && type == ATTR_DATA && !name_len;
9584342306fSKonstantin Komarov 
9594342306fSKonstantin Komarov 	if (asize > sbi->max_bytes_per_attr) {
9604342306fSKonstantin Komarov 		err = -EINVAL;
9614342306fSKonstantin Komarov 		goto out;
9624342306fSKonstantin Komarov 	}
9634342306fSKonstantin Komarov 
9644342306fSKonstantin Komarov 	/*
965e8b8e97fSKari Argillander 	 * Standard information and attr_list cannot be made external.
966e8b8e97fSKari Argillander 	 * The Log File cannot have any external attributes.
9674342306fSKonstantin Komarov 	 */
9684342306fSKonstantin Komarov 	if (type == ATTR_STD || type == ATTR_LIST ||
9694342306fSKonstantin Komarov 	    ni->mi.rno == MFT_REC_LOG) {
9704342306fSKonstantin Komarov 		err = -EINVAL;
9714342306fSKonstantin Komarov 		goto out;
9724342306fSKonstantin Komarov 	}
9734342306fSKonstantin Komarov 
974e8b8e97fSKari Argillander 	/* Create attribute list if it is not already existed. */
9754342306fSKonstantin Komarov 	if (!ni->attr_list.size) {
9764342306fSKonstantin Komarov 		err = ni_create_attr_list(ni);
9774342306fSKonstantin Komarov 		if (err)
9784342306fSKonstantin Komarov 			goto out;
9794342306fSKonstantin Komarov 	}
9804342306fSKonstantin Komarov 
9814342306fSKonstantin Komarov 	vbo = is_mft_data ? ((u64)svcn << sbi->cluster_bits) : 0;
9824342306fSKonstantin Komarov 
9834342306fSKonstantin Komarov 	if (force_ext)
9844342306fSKonstantin Komarov 		goto insert_ext;
9854342306fSKonstantin Komarov 
9864342306fSKonstantin Komarov 	/* Load all subrecords into memory. */
9874342306fSKonstantin Komarov 	err = ni_load_all_mi(ni);
9884342306fSKonstantin Komarov 	if (err)
9894342306fSKonstantin Komarov 		goto out;
9904342306fSKonstantin Komarov 
991e8b8e97fSKari Argillander 	/* Check each of loaded subrecord. */
9924342306fSKonstantin Komarov 	for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
9934342306fSKonstantin Komarov 		mi = rb_entry(node, struct mft_inode, node);
9944342306fSKonstantin Komarov 
9954342306fSKonstantin Komarov 		if (is_mft_data &&
9964342306fSKonstantin Komarov 		    (mi_enum_attr(mi, NULL) ||
9974342306fSKonstantin Komarov 		     vbo <= ((u64)mi->rno << sbi->record_bits))) {
998d3624466SKonstantin Komarov 			/* We can't accept this record 'cause MFT's bootstrapping. */
9994342306fSKonstantin Komarov 			continue;
10004342306fSKonstantin Komarov 		}
10014342306fSKonstantin Komarov 		if (is_mft &&
10024342306fSKonstantin Komarov 		    mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0, NULL)) {
10034342306fSKonstantin Komarov 			/*
10044342306fSKonstantin Komarov 			 * This child record already has a ATTR_DATA.
10054342306fSKonstantin Komarov 			 * So it can't accept any other records.
10064342306fSKonstantin Komarov 			 */
10074342306fSKonstantin Komarov 			continue;
10084342306fSKonstantin Komarov 		}
10094342306fSKonstantin Komarov 
10104342306fSKonstantin Komarov 		if ((type != ATTR_NAME || name_len) &&
10114342306fSKonstantin Komarov 		    mi_find_attr(mi, NULL, type, name, name_len, NULL)) {
1012e8b8e97fSKari Argillander 			/* Only indexed attributes can share same record. */
10134342306fSKonstantin Komarov 			continue;
10144342306fSKonstantin Komarov 		}
10154342306fSKonstantin Komarov 
1016ee9d4810SKonstantin Komarov 		/*
1017ee9d4810SKonstantin Komarov 		 * Do not try to insert this attribute
1018ee9d4810SKonstantin Komarov 		 * if there is no room in record.
1019ee9d4810SKonstantin Komarov 		 */
1020ee9d4810SKonstantin Komarov 		if (le32_to_cpu(mi->mrec->used) + asize > sbi->record_size)
1021ee9d4810SKonstantin Komarov 			continue;
1022ee9d4810SKonstantin Komarov 
1023e8b8e97fSKari Argillander 		/* Try to insert attribute into this subrecord. */
10244342306fSKonstantin Komarov 		attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize,
102578ab59feSKonstantin Komarov 				       name_off, svcn, ins_le);
10264342306fSKonstantin Komarov 		if (!attr)
10274342306fSKonstantin Komarov 			continue;
1028451e45a0SKonstantin Komarov 		if (IS_ERR(attr))
1029451e45a0SKonstantin Komarov 			return PTR_ERR(attr);
10304342306fSKonstantin Komarov 
10314342306fSKonstantin Komarov 		if (ins_attr)
10324342306fSKonstantin Komarov 			*ins_attr = attr;
103378ab59feSKonstantin Komarov 		if (ins_mi)
103478ab59feSKonstantin Komarov 			*ins_mi = mi;
10354342306fSKonstantin Komarov 		return 0;
10364342306fSKonstantin Komarov 	}
10374342306fSKonstantin Komarov 
10384342306fSKonstantin Komarov insert_ext:
1039e8b8e97fSKari Argillander 	/* We have to allocate a new child subrecord. */
10404342306fSKonstantin Komarov 	err = ntfs_look_free_mft(sbi, &rno, is_mft_data, ni, &mi);
10414342306fSKonstantin Komarov 	if (err)
10424342306fSKonstantin Komarov 		goto out;
10434342306fSKonstantin Komarov 
10444342306fSKonstantin Komarov 	if (is_mft_data && vbo <= ((u64)rno << sbi->record_bits)) {
10454342306fSKonstantin Komarov 		err = -EINVAL;
10464342306fSKonstantin Komarov 		goto out1;
10474342306fSKonstantin Komarov 	}
10484342306fSKonstantin Komarov 
10494342306fSKonstantin Komarov 	attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize,
105078ab59feSKonstantin Komarov 			       name_off, svcn, ins_le);
1051451e45a0SKonstantin Komarov 	if (!attr) {
1052451e45a0SKonstantin Komarov 		err = -EINVAL;
10534342306fSKonstantin Komarov 		goto out2;
1054451e45a0SKonstantin Komarov 	}
1055451e45a0SKonstantin Komarov 
1056451e45a0SKonstantin Komarov 	if (IS_ERR(attr)) {
1057451e45a0SKonstantin Komarov 		err = PTR_ERR(attr);
1058451e45a0SKonstantin Komarov 		goto out2;
1059451e45a0SKonstantin Komarov 	}
10604342306fSKonstantin Komarov 
10614342306fSKonstantin Komarov 	if (ins_attr)
10624342306fSKonstantin Komarov 		*ins_attr = attr;
10634342306fSKonstantin Komarov 	if (ins_mi)
10644342306fSKonstantin Komarov 		*ins_mi = mi;
10654342306fSKonstantin Komarov 
10664342306fSKonstantin Komarov 	return 0;
10674342306fSKonstantin Komarov 
10684342306fSKonstantin Komarov out2:
10694342306fSKonstantin Komarov 	ni_remove_mi(ni, mi);
10704342306fSKonstantin Komarov 	mi_put(mi);
10714342306fSKonstantin Komarov 
10724342306fSKonstantin Komarov out1:
1073071100eaSKonstantin Komarov 	ntfs_mark_rec_free(sbi, rno, is_mft);
10744342306fSKonstantin Komarov 
10754342306fSKonstantin Komarov out:
10764342306fSKonstantin Komarov 	return err;
10774342306fSKonstantin Komarov }
10784342306fSKonstantin Komarov 
10794342306fSKonstantin Komarov /*
1080e8b8e97fSKari Argillander  * ni_insert_attr - Insert an attribute into the file.
10814342306fSKonstantin Komarov  *
10824342306fSKonstantin Komarov  * If the primary record has room, it will just insert the attribute.
10834342306fSKonstantin Komarov  * If not, it may make the attribute external.
10844342306fSKonstantin Komarov  * For $MFT::Data it may make room for the attribute by
10854342306fSKonstantin Komarov  * making other attributes external.
10864342306fSKonstantin Komarov  *
10874342306fSKonstantin Komarov  * NOTE:
10884342306fSKonstantin Komarov  * The ATTR_LIST and ATTR_STD cannot be made external.
1089e8b8e97fSKari Argillander  * This function does not fill new attribute full.
1090e8b8e97fSKari Argillander  * It only fills 'size'/'type'/'id'/'name_len' fields.
10914342306fSKonstantin Komarov  */
ni_insert_attr(struct ntfs_inode * ni,enum ATTR_TYPE type,const __le16 * name,u8 name_len,u32 asize,u16 name_off,CLST svcn,struct ATTRIB ** ins_attr,struct mft_inode ** ins_mi,struct ATTR_LIST_ENTRY ** ins_le)10924342306fSKonstantin Komarov static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
10934342306fSKonstantin Komarov 			  const __le16 *name, u8 name_len, u32 asize,
10944342306fSKonstantin Komarov 			  u16 name_off, CLST svcn, struct ATTRIB **ins_attr,
109578ab59feSKonstantin Komarov 			  struct mft_inode **ins_mi,
109678ab59feSKonstantin Komarov 			  struct ATTR_LIST_ENTRY **ins_le)
10974342306fSKonstantin Komarov {
10984342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
10994342306fSKonstantin Komarov 	int err;
11004342306fSKonstantin Komarov 	struct ATTRIB *attr, *eattr;
11014342306fSKonstantin Komarov 	struct MFT_REC *rec;
11024342306fSKonstantin Komarov 	bool is_mft;
11034342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
11044342306fSKonstantin Komarov 	u32 list_reserve, max_free, free, used, t32;
11054342306fSKonstantin Komarov 	__le16 id;
11064342306fSKonstantin Komarov 	u16 t16;
11074342306fSKonstantin Komarov 
11084342306fSKonstantin Komarov 	is_mft = ni->mi.rno == MFT_REC_MFT;
11094342306fSKonstantin Komarov 	rec = ni->mi.mrec;
11104342306fSKonstantin Komarov 
11114342306fSKonstantin Komarov 	list_reserve = SIZEOF_NONRESIDENT + 3 * (1 + 2 * sizeof(u32));
11124342306fSKonstantin Komarov 	used = le32_to_cpu(rec->used);
11134342306fSKonstantin Komarov 	free = sbi->record_size - used;
11144342306fSKonstantin Komarov 
11154342306fSKonstantin Komarov 	if (is_mft && type != ATTR_LIST) {
1116e8b8e97fSKari Argillander 		/* Reserve space for the ATTRIB list. */
11174342306fSKonstantin Komarov 		if (free < list_reserve)
11184342306fSKonstantin Komarov 			free = 0;
11194342306fSKonstantin Komarov 		else
11204342306fSKonstantin Komarov 			free -= list_reserve;
11214342306fSKonstantin Komarov 	}
11224342306fSKonstantin Komarov 
11234342306fSKonstantin Komarov 	if (asize <= free) {
11244342306fSKonstantin Komarov 		attr = ni_ins_new_attr(ni, &ni->mi, NULL, type, name, name_len,
112578ab59feSKonstantin Komarov 				       asize, name_off, svcn, ins_le);
1126451e45a0SKonstantin Komarov 		if (IS_ERR(attr)) {
1127451e45a0SKonstantin Komarov 			err = PTR_ERR(attr);
1128451e45a0SKonstantin Komarov 			goto out;
1129451e45a0SKonstantin Komarov 		}
1130451e45a0SKonstantin Komarov 
11314342306fSKonstantin Komarov 		if (attr) {
11324342306fSKonstantin Komarov 			if (ins_attr)
11334342306fSKonstantin Komarov 				*ins_attr = attr;
11344342306fSKonstantin Komarov 			if (ins_mi)
11354342306fSKonstantin Komarov 				*ins_mi = &ni->mi;
11364342306fSKonstantin Komarov 			err = 0;
11374342306fSKonstantin Komarov 			goto out;
11384342306fSKonstantin Komarov 		}
11394342306fSKonstantin Komarov 	}
11404342306fSKonstantin Komarov 
11414342306fSKonstantin Komarov 	if (!is_mft || type != ATTR_DATA || svcn) {
11424342306fSKonstantin Komarov 		/* This ATTRIB will be external. */
11434342306fSKonstantin Komarov 		err = ni_ins_attr_ext(ni, NULL, type, name, name_len, asize,
114478ab59feSKonstantin Komarov 				      svcn, name_off, false, ins_attr, ins_mi,
114578ab59feSKonstantin Komarov 				      ins_le);
11464342306fSKonstantin Komarov 		goto out;
11474342306fSKonstantin Komarov 	}
11484342306fSKonstantin Komarov 
11494342306fSKonstantin Komarov 	/*
1150e8b8e97fSKari Argillander 	 * Here we have: "is_mft && type == ATTR_DATA && !svcn"
11514342306fSKonstantin Komarov 	 *
11524342306fSKonstantin Komarov 	 * The first chunk of the $MFT::Data ATTRIB must be the base record.
11534342306fSKonstantin Komarov 	 * Evict as many other attributes as possible.
11544342306fSKonstantin Komarov 	 */
11554342306fSKonstantin Komarov 	max_free = free;
11564342306fSKonstantin Komarov 
11574342306fSKonstantin Komarov 	/* Estimate the result of moving all possible attributes away. */
11584342306fSKonstantin Komarov 	attr = NULL;
11594342306fSKonstantin Komarov 
11604342306fSKonstantin Komarov 	while ((attr = mi_enum_attr(&ni->mi, attr))) {
11614342306fSKonstantin Komarov 		if (attr->type == ATTR_STD)
11624342306fSKonstantin Komarov 			continue;
11634342306fSKonstantin Komarov 		if (attr->type == ATTR_LIST)
11644342306fSKonstantin Komarov 			continue;
11654342306fSKonstantin Komarov 		max_free += le32_to_cpu(attr->size);
11664342306fSKonstantin Komarov 	}
11674342306fSKonstantin Komarov 
11684342306fSKonstantin Komarov 	if (max_free < asize + list_reserve) {
1169e8b8e97fSKari Argillander 		/* Impossible to insert this attribute into primary record. */
11704342306fSKonstantin Komarov 		err = -EINVAL;
11714342306fSKonstantin Komarov 		goto out;
11724342306fSKonstantin Komarov 	}
11734342306fSKonstantin Komarov 
1174d3624466SKonstantin Komarov 	/* Start real attribute moving. */
11754342306fSKonstantin Komarov 	attr = NULL;
11764342306fSKonstantin Komarov 
11774342306fSKonstantin Komarov 	for (;;) {
11784342306fSKonstantin Komarov 		attr = mi_enum_attr(&ni->mi, attr);
11794342306fSKonstantin Komarov 		if (!attr) {
1180e8b8e97fSKari Argillander 			/* We should never be here 'cause we have already check this case. */
11814342306fSKonstantin Komarov 			err = -EINVAL;
11824342306fSKonstantin Komarov 			goto out;
11834342306fSKonstantin Komarov 		}
11844342306fSKonstantin Komarov 
1185e8b8e97fSKari Argillander 		/* Skip attributes that MUST be primary record. */
11864342306fSKonstantin Komarov 		if (attr->type == ATTR_STD || attr->type == ATTR_LIST)
11874342306fSKonstantin Komarov 			continue;
11884342306fSKonstantin Komarov 
11894342306fSKonstantin Komarov 		le = NULL;
11904342306fSKonstantin Komarov 		if (ni->attr_list.size) {
11914342306fSKonstantin Komarov 			le = al_find_le(ni, NULL, attr);
11924342306fSKonstantin Komarov 			if (!le) {
1193e8b8e97fSKari Argillander 				/* Really this is a serious bug. */
11944342306fSKonstantin Komarov 				err = -EINVAL;
11954342306fSKonstantin Komarov 				goto out;
11964342306fSKonstantin Komarov 			}
11974342306fSKonstantin Komarov 		}
11984342306fSKonstantin Komarov 
11994342306fSKonstantin Komarov 		t32 = le32_to_cpu(attr->size);
12004342306fSKonstantin Komarov 		t16 = le16_to_cpu(attr->name_off);
12014342306fSKonstantin Komarov 		err = ni_ins_attr_ext(ni, le, attr->type, Add2Ptr(attr, t16),
12024342306fSKonstantin Komarov 				      attr->name_len, t32, attr_svcn(attr), t16,
120378ab59feSKonstantin Komarov 				      false, &eattr, NULL, NULL);
12044342306fSKonstantin Komarov 		if (err)
12054342306fSKonstantin Komarov 			return err;
12064342306fSKonstantin Komarov 
12074342306fSKonstantin Komarov 		id = eattr->id;
12084342306fSKonstantin Komarov 		memcpy(eattr, attr, t32);
12094342306fSKonstantin Komarov 		eattr->id = id;
12104342306fSKonstantin Komarov 
121178ab59feSKonstantin Komarov 		/* Remove from primary record. */
121278ab59feSKonstantin Komarov 		mi_remove_attr(NULL, &ni->mi, attr);
12134342306fSKonstantin Komarov 
1214e8b8e97fSKari Argillander 		/* attr now points to next attribute. */
12154342306fSKonstantin Komarov 		if (attr->type == ATTR_END)
12164342306fSKonstantin Komarov 			goto out;
12174342306fSKonstantin Komarov 	}
12184342306fSKonstantin Komarov 	while (asize + list_reserve > sbi->record_size - le32_to_cpu(rec->used))
12194342306fSKonstantin Komarov 		;
12204342306fSKonstantin Komarov 
12214342306fSKonstantin Komarov 	attr = ni_ins_new_attr(ni, &ni->mi, NULL, type, name, name_len, asize,
122278ab59feSKonstantin Komarov 			       name_off, svcn, ins_le);
12234342306fSKonstantin Komarov 	if (!attr) {
12244342306fSKonstantin Komarov 		err = -EINVAL;
12254342306fSKonstantin Komarov 		goto out;
12264342306fSKonstantin Komarov 	}
12274342306fSKonstantin Komarov 
1228451e45a0SKonstantin Komarov 	if (IS_ERR(attr)) {
1229451e45a0SKonstantin Komarov 		err = PTR_ERR(attr);
1230451e45a0SKonstantin Komarov 		goto out;
1231451e45a0SKonstantin Komarov 	}
1232451e45a0SKonstantin Komarov 
12334342306fSKonstantin Komarov 	if (ins_attr)
12344342306fSKonstantin Komarov 		*ins_attr = attr;
12354342306fSKonstantin Komarov 	if (ins_mi)
12364342306fSKonstantin Komarov 		*ins_mi = &ni->mi;
12374342306fSKonstantin Komarov 
12384342306fSKonstantin Komarov out:
12394342306fSKonstantin Komarov 	return err;
12404342306fSKonstantin Komarov }
12414342306fSKonstantin Komarov 
1242e8b8e97fSKari Argillander /* ni_expand_mft_list - Split ATTR_DATA of $MFT. */
ni_expand_mft_list(struct ntfs_inode * ni)12434342306fSKonstantin Komarov static int ni_expand_mft_list(struct ntfs_inode *ni)
12444342306fSKonstantin Komarov {
12454342306fSKonstantin Komarov 	int err = 0;
12464342306fSKonstantin Komarov 	struct runs_tree *run = &ni->file.run;
12474342306fSKonstantin Komarov 	u32 asize, run_size, done = 0;
12484342306fSKonstantin Komarov 	struct ATTRIB *attr;
12494342306fSKonstantin Komarov 	struct rb_node *node;
12504342306fSKonstantin Komarov 	CLST mft_min, mft_new, svcn, evcn, plen;
12514342306fSKonstantin Komarov 	struct mft_inode *mi, *mi_min, *mi_new;
12524342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
12534342306fSKonstantin Komarov 
1254e8b8e97fSKari Argillander 	/* Find the nearest MFT. */
12554342306fSKonstantin Komarov 	mft_min = 0;
12564342306fSKonstantin Komarov 	mft_new = 0;
12574342306fSKonstantin Komarov 	mi_min = NULL;
12584342306fSKonstantin Komarov 
12594342306fSKonstantin Komarov 	for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
12604342306fSKonstantin Komarov 		mi = rb_entry(node, struct mft_inode, node);
12614342306fSKonstantin Komarov 
12624342306fSKonstantin Komarov 		attr = mi_enum_attr(mi, NULL);
12634342306fSKonstantin Komarov 
12644342306fSKonstantin Komarov 		if (!attr) {
12654342306fSKonstantin Komarov 			mft_min = mi->rno;
12664342306fSKonstantin Komarov 			mi_min = mi;
12674342306fSKonstantin Komarov 			break;
12684342306fSKonstantin Komarov 		}
12694342306fSKonstantin Komarov 	}
12704342306fSKonstantin Komarov 
12714342306fSKonstantin Komarov 	if (ntfs_look_free_mft(sbi, &mft_new, true, ni, &mi_new)) {
12724342306fSKonstantin Komarov 		mft_new = 0;
1273e8b8e97fSKari Argillander 		/* Really this is not critical. */
12744342306fSKonstantin Komarov 	} else if (mft_min > mft_new) {
12754342306fSKonstantin Komarov 		mft_min = mft_new;
12764342306fSKonstantin Komarov 		mi_min = mi_new;
12774342306fSKonstantin Komarov 	} else {
1278071100eaSKonstantin Komarov 		ntfs_mark_rec_free(sbi, mft_new, true);
12794342306fSKonstantin Komarov 		mft_new = 0;
12804342306fSKonstantin Komarov 		ni_remove_mi(ni, mi_new);
12814342306fSKonstantin Komarov 	}
12824342306fSKonstantin Komarov 
12834342306fSKonstantin Komarov 	attr = mi_find_attr(&ni->mi, NULL, ATTR_DATA, NULL, 0, NULL);
12844342306fSKonstantin Komarov 	if (!attr) {
12854342306fSKonstantin Komarov 		err = -EINVAL;
12864342306fSKonstantin Komarov 		goto out;
12874342306fSKonstantin Komarov 	}
12884342306fSKonstantin Komarov 
12894342306fSKonstantin Komarov 	asize = le32_to_cpu(attr->size);
12904342306fSKonstantin Komarov 
12914342306fSKonstantin Komarov 	evcn = le64_to_cpu(attr->nres.evcn);
12924342306fSKonstantin Komarov 	svcn = bytes_to_cluster(sbi, (u64)(mft_min + 1) << sbi->record_bits);
12934342306fSKonstantin Komarov 	if (evcn + 1 >= svcn) {
12944342306fSKonstantin Komarov 		err = -EINVAL;
12954342306fSKonstantin Komarov 		goto out;
12964342306fSKonstantin Komarov 	}
12974342306fSKonstantin Komarov 
12984342306fSKonstantin Komarov 	/*
1299e8b8e97fSKari Argillander 	 * Split primary attribute [0 evcn] in two parts [0 svcn) + [svcn evcn].
13004342306fSKonstantin Komarov 	 *
1301e8b8e97fSKari Argillander 	 * Update first part of ATTR_DATA in 'primary MFT.
13024342306fSKonstantin Komarov 	 */
13034342306fSKonstantin Komarov 	err = run_pack(run, 0, svcn, Add2Ptr(attr, SIZEOF_NONRESIDENT),
13044342306fSKonstantin Komarov 		       asize - SIZEOF_NONRESIDENT, &plen);
13054342306fSKonstantin Komarov 	if (err < 0)
13064342306fSKonstantin Komarov 		goto out;
13074342306fSKonstantin Komarov 
1308fa3cacf5SKari Argillander 	run_size = ALIGN(err, 8);
13094342306fSKonstantin Komarov 	err = 0;
13104342306fSKonstantin Komarov 
13114342306fSKonstantin Komarov 	if (plen < svcn) {
13124342306fSKonstantin Komarov 		err = -EINVAL;
13134342306fSKonstantin Komarov 		goto out;
13144342306fSKonstantin Komarov 	}
13154342306fSKonstantin Komarov 
13164342306fSKonstantin Komarov 	attr->nres.evcn = cpu_to_le64(svcn - 1);
13174342306fSKonstantin Komarov 	attr->size = cpu_to_le32(run_size + SIZEOF_NONRESIDENT);
1318e8b8e97fSKari Argillander 	/* 'done' - How many bytes of primary MFT becomes free. */
13194342306fSKonstantin Komarov 	done = asize - run_size - SIZEOF_NONRESIDENT;
13204342306fSKonstantin Komarov 	le32_sub_cpu(&ni->mi.mrec->used, done);
13214342306fSKonstantin Komarov 
132254033c13SKonstantin Komarov 	/* Estimate packed size (run_buf=NULL). */
13234342306fSKonstantin Komarov 	err = run_pack(run, svcn, evcn + 1 - svcn, NULL, sbi->record_size,
13244342306fSKonstantin Komarov 		       &plen);
13254342306fSKonstantin Komarov 	if (err < 0)
13264342306fSKonstantin Komarov 		goto out;
13274342306fSKonstantin Komarov 
1328fa3cacf5SKari Argillander 	run_size = ALIGN(err, 8);
13294342306fSKonstantin Komarov 	err = 0;
13304342306fSKonstantin Komarov 
13314342306fSKonstantin Komarov 	if (plen < evcn + 1 - svcn) {
13324342306fSKonstantin Komarov 		err = -EINVAL;
13334342306fSKonstantin Komarov 		goto out;
13344342306fSKonstantin Komarov 	}
13354342306fSKonstantin Komarov 
13364342306fSKonstantin Komarov 	/*
1337e8b8e97fSKari Argillander 	 * This function may implicitly call expand attr_list.
1338e8b8e97fSKari Argillander 	 * Insert second part of ATTR_DATA in 'mi_min'.
13394342306fSKonstantin Komarov 	 */
13404342306fSKonstantin Komarov 	attr = ni_ins_new_attr(ni, mi_min, NULL, ATTR_DATA, NULL, 0,
13414342306fSKonstantin Komarov 			       SIZEOF_NONRESIDENT + run_size,
134278ab59feSKonstantin Komarov 			       SIZEOF_NONRESIDENT, svcn, NULL);
13434342306fSKonstantin Komarov 	if (!attr) {
13444342306fSKonstantin Komarov 		err = -EINVAL;
13454342306fSKonstantin Komarov 		goto out;
13464342306fSKonstantin Komarov 	}
13474342306fSKonstantin Komarov 
1348451e45a0SKonstantin Komarov 	if (IS_ERR(attr)) {
1349451e45a0SKonstantin Komarov 		err = PTR_ERR(attr);
1350451e45a0SKonstantin Komarov 		goto out;
1351451e45a0SKonstantin Komarov 	}
1352451e45a0SKonstantin Komarov 
13534342306fSKonstantin Komarov 	attr->non_res = 1;
13544342306fSKonstantin Komarov 	attr->name_off = SIZEOF_NONRESIDENT_LE;
13554342306fSKonstantin Komarov 	attr->flags = 0;
13564342306fSKonstantin Komarov 
135754033c13SKonstantin Komarov 	/* This function can't fail - cause already checked above. */
13584342306fSKonstantin Komarov 	run_pack(run, svcn, evcn + 1 - svcn, Add2Ptr(attr, SIZEOF_NONRESIDENT),
13594342306fSKonstantin Komarov 		 run_size, &plen);
13604342306fSKonstantin Komarov 
13614342306fSKonstantin Komarov 	attr->nres.svcn = cpu_to_le64(svcn);
13624342306fSKonstantin Komarov 	attr->nres.evcn = cpu_to_le64(evcn);
13634342306fSKonstantin Komarov 	attr->nres.run_off = cpu_to_le16(SIZEOF_NONRESIDENT);
13644342306fSKonstantin Komarov 
13654342306fSKonstantin Komarov out:
13664342306fSKonstantin Komarov 	if (mft_new) {
1367071100eaSKonstantin Komarov 		ntfs_mark_rec_free(sbi, mft_new, true);
13684342306fSKonstantin Komarov 		ni_remove_mi(ni, mi_new);
13694342306fSKonstantin Komarov 	}
13704342306fSKonstantin Komarov 
13714342306fSKonstantin Komarov 	return !err && !done ? -EOPNOTSUPP : err;
13724342306fSKonstantin Komarov }
13734342306fSKonstantin Komarov 
13744342306fSKonstantin Komarov /*
1375e8b8e97fSKari Argillander  * ni_expand_list - Move all possible attributes out of primary record.
13764342306fSKonstantin Komarov  */
ni_expand_list(struct ntfs_inode * ni)13774342306fSKonstantin Komarov int ni_expand_list(struct ntfs_inode *ni)
13784342306fSKonstantin Komarov {
13794342306fSKonstantin Komarov 	int err = 0;
13804342306fSKonstantin Komarov 	u32 asize, done = 0;
13814342306fSKonstantin Komarov 	struct ATTRIB *attr, *ins_attr;
13824342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
13834342306fSKonstantin Komarov 	bool is_mft = ni->mi.rno == MFT_REC_MFT;
13844342306fSKonstantin Komarov 	struct MFT_REF ref;
13854342306fSKonstantin Komarov 
13864342306fSKonstantin Komarov 	mi_get_ref(&ni->mi, &ref);
13874342306fSKonstantin Komarov 	le = NULL;
13884342306fSKonstantin Komarov 
13894342306fSKonstantin Komarov 	while ((le = al_enumerate(ni, le))) {
13904342306fSKonstantin Komarov 		if (le->type == ATTR_STD)
13914342306fSKonstantin Komarov 			continue;
13924342306fSKonstantin Komarov 
13934342306fSKonstantin Komarov 		if (memcmp(&ref, &le->ref, sizeof(struct MFT_REF)))
13944342306fSKonstantin Komarov 			continue;
13954342306fSKonstantin Komarov 
13964342306fSKonstantin Komarov 		if (is_mft && le->type == ATTR_DATA)
13974342306fSKonstantin Komarov 			continue;
13984342306fSKonstantin Komarov 
1399e8b8e97fSKari Argillander 		/* Find attribute in primary record. */
14004342306fSKonstantin Komarov 		attr = rec_find_attr_le(&ni->mi, le);
14014342306fSKonstantin Komarov 		if (!attr) {
14024342306fSKonstantin Komarov 			err = -EINVAL;
14034342306fSKonstantin Komarov 			goto out;
14044342306fSKonstantin Komarov 		}
14054342306fSKonstantin Komarov 
14064342306fSKonstantin Komarov 		asize = le32_to_cpu(attr->size);
14074342306fSKonstantin Komarov 
1408e8b8e97fSKari Argillander 		/* Always insert into new record to avoid collisions (deep recursive). */
14094342306fSKonstantin Komarov 		err = ni_ins_attr_ext(ni, le, attr->type, attr_name(attr),
14104342306fSKonstantin Komarov 				      attr->name_len, asize, attr_svcn(attr),
14114342306fSKonstantin Komarov 				      le16_to_cpu(attr->name_off), true,
141278ab59feSKonstantin Komarov 				      &ins_attr, NULL, NULL);
14134342306fSKonstantin Komarov 
14144342306fSKonstantin Komarov 		if (err)
14154342306fSKonstantin Komarov 			goto out;
14164342306fSKonstantin Komarov 
14174342306fSKonstantin Komarov 		memcpy(ins_attr, attr, asize);
14184342306fSKonstantin Komarov 		ins_attr->id = le->id;
141978ab59feSKonstantin Komarov 		/* Remove from primary record. */
142078ab59feSKonstantin Komarov 		mi_remove_attr(NULL, &ni->mi, attr);
14214342306fSKonstantin Komarov 
14224342306fSKonstantin Komarov 		done += asize;
14234342306fSKonstantin Komarov 		goto out;
14244342306fSKonstantin Komarov 	}
14254342306fSKonstantin Komarov 
14264342306fSKonstantin Komarov 	if (!is_mft) {
1427e8b8e97fSKari Argillander 		err = -EFBIG; /* Attr list is too big(?) */
14284342306fSKonstantin Komarov 		goto out;
14294342306fSKonstantin Komarov 	}
14304342306fSKonstantin Komarov 
1431e8b8e97fSKari Argillander 	/* Split MFT data as much as possible. */
14324342306fSKonstantin Komarov 	err = ni_expand_mft_list(ni);
14334342306fSKonstantin Komarov 
14344342306fSKonstantin Komarov out:
14354342306fSKonstantin Komarov 	return !err && !done ? -EOPNOTSUPP : err;
14364342306fSKonstantin Komarov }
14374342306fSKonstantin Komarov 
14384342306fSKonstantin Komarov /*
1439e8b8e97fSKari Argillander  * ni_insert_nonresident - Insert new nonresident attribute.
14404342306fSKonstantin Komarov  */
ni_insert_nonresident(struct ntfs_inode * ni,enum ATTR_TYPE type,const __le16 * name,u8 name_len,const struct runs_tree * run,CLST svcn,CLST len,__le16 flags,struct ATTRIB ** new_attr,struct mft_inode ** mi,struct ATTR_LIST_ENTRY ** le)14414342306fSKonstantin Komarov int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type,
14424342306fSKonstantin Komarov 			  const __le16 *name, u8 name_len,
14434342306fSKonstantin Komarov 			  const struct runs_tree *run, CLST svcn, CLST len,
14444342306fSKonstantin Komarov 			  __le16 flags, struct ATTRIB **new_attr,
1445c1e0ab37SKonstantin Komarov 			  struct mft_inode **mi, struct ATTR_LIST_ENTRY **le)
14464342306fSKonstantin Komarov {
14474342306fSKonstantin Komarov 	int err;
14484342306fSKonstantin Komarov 	CLST plen;
14494342306fSKonstantin Komarov 	struct ATTRIB *attr;
145096de65a9SKonstantin Komarov 	bool is_ext = (flags & (ATTR_FLAG_SPARSED | ATTR_FLAG_COMPRESSED)) &&
145196de65a9SKonstantin Komarov 		      !svcn;
1452fa3cacf5SKari Argillander 	u32 name_size = ALIGN(name_len * sizeof(short), 8);
14534342306fSKonstantin Komarov 	u32 name_off = is_ext ? SIZEOF_NONRESIDENT_EX : SIZEOF_NONRESIDENT;
14544342306fSKonstantin Komarov 	u32 run_off = name_off + name_size;
14554342306fSKonstantin Komarov 	u32 run_size, asize;
14564342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
14574342306fSKonstantin Komarov 
145854033c13SKonstantin Komarov 	/* Estimate packed size (run_buf=NULL). */
14594342306fSKonstantin Komarov 	err = run_pack(run, svcn, len, NULL, sbi->max_bytes_per_attr - run_off,
14604342306fSKonstantin Komarov 		       &plen);
14614342306fSKonstantin Komarov 	if (err < 0)
14624342306fSKonstantin Komarov 		goto out;
14634342306fSKonstantin Komarov 
1464fa3cacf5SKari Argillander 	run_size = ALIGN(err, 8);
14654342306fSKonstantin Komarov 
14664342306fSKonstantin Komarov 	if (plen < len) {
14674342306fSKonstantin Komarov 		err = -EINVAL;
14684342306fSKonstantin Komarov 		goto out;
14694342306fSKonstantin Komarov 	}
14704342306fSKonstantin Komarov 
14714342306fSKonstantin Komarov 	asize = run_off + run_size;
14724342306fSKonstantin Komarov 
14734342306fSKonstantin Komarov 	if (asize > sbi->max_bytes_per_attr) {
14744342306fSKonstantin Komarov 		err = -EINVAL;
14754342306fSKonstantin Komarov 		goto out;
14764342306fSKonstantin Komarov 	}
14774342306fSKonstantin Komarov 
14784342306fSKonstantin Komarov 	err = ni_insert_attr(ni, type, name, name_len, asize, name_off, svcn,
1479c1e0ab37SKonstantin Komarov 			     &attr, mi, le);
14804342306fSKonstantin Komarov 
14814342306fSKonstantin Komarov 	if (err)
14824342306fSKonstantin Komarov 		goto out;
14834342306fSKonstantin Komarov 
14844342306fSKonstantin Komarov 	attr->non_res = 1;
14854342306fSKonstantin Komarov 	attr->name_off = cpu_to_le16(name_off);
14864342306fSKonstantin Komarov 	attr->flags = flags;
14874342306fSKonstantin Komarov 
148854033c13SKonstantin Komarov 	/* This function can't fail - cause already checked above. */
14894342306fSKonstantin Komarov 	run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size, &plen);
14904342306fSKonstantin Komarov 
14914342306fSKonstantin Komarov 	attr->nres.svcn = cpu_to_le64(svcn);
14924342306fSKonstantin Komarov 	attr->nres.evcn = cpu_to_le64((u64)svcn + len - 1);
14934342306fSKonstantin Komarov 
14944342306fSKonstantin Komarov 	if (new_attr)
14954342306fSKonstantin Komarov 		*new_attr = attr;
14964342306fSKonstantin Komarov 
14974342306fSKonstantin Komarov 	*(__le64 *)&attr->nres.run_off = cpu_to_le64(run_off);
14984342306fSKonstantin Komarov 
14994342306fSKonstantin Komarov 	attr->nres.alloc_size =
15004342306fSKonstantin Komarov 		svcn ? 0 : cpu_to_le64((u64)len << ni->mi.sbi->cluster_bits);
15014342306fSKonstantin Komarov 	attr->nres.data_size = attr->nres.alloc_size;
15024342306fSKonstantin Komarov 	attr->nres.valid_size = attr->nres.alloc_size;
15034342306fSKonstantin Komarov 
15044342306fSKonstantin Komarov 	if (is_ext) {
15054342306fSKonstantin Komarov 		if (flags & ATTR_FLAG_COMPRESSED)
1506f37b756aSKonstantin Komarov 			attr->nres.c_unit = NTFS_LZNT_CUNIT;
15074342306fSKonstantin Komarov 		attr->nres.total_size = attr->nres.alloc_size;
15084342306fSKonstantin Komarov 	}
15094342306fSKonstantin Komarov 
15104342306fSKonstantin Komarov out:
15114342306fSKonstantin Komarov 	return err;
15124342306fSKonstantin Komarov }
15134342306fSKonstantin Komarov 
15144342306fSKonstantin Komarov /*
1515e8b8e97fSKari Argillander  * ni_insert_resident - Inserts new resident attribute.
15164342306fSKonstantin Komarov  */
ni_insert_resident(struct ntfs_inode * ni,u32 data_size,enum ATTR_TYPE type,const __le16 * name,u8 name_len,struct ATTRIB ** new_attr,struct mft_inode ** mi,struct ATTR_LIST_ENTRY ** le)15174342306fSKonstantin Komarov int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
15184342306fSKonstantin Komarov 		       enum ATTR_TYPE type, const __le16 *name, u8 name_len,
151978ab59feSKonstantin Komarov 		       struct ATTRIB **new_attr, struct mft_inode **mi,
152078ab59feSKonstantin Komarov 		       struct ATTR_LIST_ENTRY **le)
15214342306fSKonstantin Komarov {
15224342306fSKonstantin Komarov 	int err;
1523fa3cacf5SKari Argillander 	u32 name_size = ALIGN(name_len * sizeof(short), 8);
1524fa3cacf5SKari Argillander 	u32 asize = SIZEOF_RESIDENT + name_size + ALIGN(data_size, 8);
15254342306fSKonstantin Komarov 	struct ATTRIB *attr;
15264342306fSKonstantin Komarov 
15274342306fSKonstantin Komarov 	err = ni_insert_attr(ni, type, name, name_len, asize, SIZEOF_RESIDENT,
152878ab59feSKonstantin Komarov 			     0, &attr, mi, le);
15294342306fSKonstantin Komarov 	if (err)
15304342306fSKonstantin Komarov 		return err;
15314342306fSKonstantin Komarov 
15324342306fSKonstantin Komarov 	attr->non_res = 0;
15334342306fSKonstantin Komarov 	attr->flags = 0;
15344342306fSKonstantin Komarov 
15354342306fSKonstantin Komarov 	attr->res.data_size = cpu_to_le32(data_size);
15364342306fSKonstantin Komarov 	attr->res.data_off = cpu_to_le16(SIZEOF_RESIDENT + name_size);
153778ab59feSKonstantin Komarov 	if (type == ATTR_NAME) {
15384342306fSKonstantin Komarov 		attr->res.flags = RESIDENT_FLAG_INDEXED;
153978ab59feSKonstantin Komarov 
154078ab59feSKonstantin Komarov 		/* is_attr_indexed(attr)) == true */
15417d95995aSKari Argillander 		le16_add_cpu(&ni->mi.mrec->hard_links, 1);
154278ab59feSKonstantin Komarov 		ni->mi.dirty = true;
154378ab59feSKonstantin Komarov 	}
15444342306fSKonstantin Komarov 	attr->res.res = 0;
15454342306fSKonstantin Komarov 
15464342306fSKonstantin Komarov 	if (new_attr)
15474342306fSKonstantin Komarov 		*new_attr = attr;
15484342306fSKonstantin Komarov 
15494342306fSKonstantin Komarov 	return 0;
15504342306fSKonstantin Komarov }
15514342306fSKonstantin Komarov 
15524342306fSKonstantin Komarov /*
1553e8b8e97fSKari Argillander  * ni_remove_attr_le - Remove attribute from record.
15544342306fSKonstantin Komarov  */
ni_remove_attr_le(struct ntfs_inode * ni,struct ATTRIB * attr,struct mft_inode * mi,struct ATTR_LIST_ENTRY * le)155578ab59feSKonstantin Komarov void ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
155678ab59feSKonstantin Komarov 		       struct mft_inode *mi, struct ATTR_LIST_ENTRY *le)
15574342306fSKonstantin Komarov {
155878ab59feSKonstantin Komarov 	mi_remove_attr(ni, mi, attr);
15594342306fSKonstantin Komarov 
15604342306fSKonstantin Komarov 	if (le)
15614342306fSKonstantin Komarov 		al_remove_le(ni, le);
15624342306fSKonstantin Komarov }
15634342306fSKonstantin Komarov 
15644342306fSKonstantin Komarov /*
1565e8b8e97fSKari Argillander  * ni_delete_all - Remove all attributes and frees allocates space.
15664342306fSKonstantin Komarov  *
1567e8b8e97fSKari Argillander  * ntfs_evict_inode->ntfs_clear_inode->ni_delete_all (if no links).
15684342306fSKonstantin Komarov  */
ni_delete_all(struct ntfs_inode * ni)15694342306fSKonstantin Komarov int ni_delete_all(struct ntfs_inode *ni)
15704342306fSKonstantin Komarov {
15714342306fSKonstantin Komarov 	int err;
15724342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le = NULL;
15734342306fSKonstantin Komarov 	struct ATTRIB *attr = NULL;
15744342306fSKonstantin Komarov 	struct rb_node *node;
15754342306fSKonstantin Komarov 	u16 roff;
15764342306fSKonstantin Komarov 	u32 asize;
15774342306fSKonstantin Komarov 	CLST svcn, evcn;
15784342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
15794342306fSKonstantin Komarov 	bool nt3 = is_ntfs3(sbi);
15804342306fSKonstantin Komarov 	struct MFT_REF ref;
15814342306fSKonstantin Komarov 
15824342306fSKonstantin Komarov 	while ((attr = ni_enum_attr_ex(ni, attr, &le, NULL))) {
15834342306fSKonstantin Komarov 		if (!nt3 || attr->name_len) {
15844342306fSKonstantin Komarov 			;
15854342306fSKonstantin Komarov 		} else if (attr->type == ATTR_REPARSE) {
15864342306fSKonstantin Komarov 			mi_get_ref(&ni->mi, &ref);
15874342306fSKonstantin Komarov 			ntfs_remove_reparse(sbi, 0, &ref);
15884342306fSKonstantin Komarov 		} else if (attr->type == ATTR_ID && !attr->non_res &&
15894342306fSKonstantin Komarov 			   le32_to_cpu(attr->res.data_size) >=
15904342306fSKonstantin Komarov 				   sizeof(struct GUID)) {
15914342306fSKonstantin Komarov 			ntfs_objid_remove(sbi, resident_data(attr));
15924342306fSKonstantin Komarov 		}
15934342306fSKonstantin Komarov 
15944342306fSKonstantin Komarov 		if (!attr->non_res)
15954342306fSKonstantin Komarov 			continue;
15964342306fSKonstantin Komarov 
15974342306fSKonstantin Komarov 		svcn = le64_to_cpu(attr->nres.svcn);
15984342306fSKonstantin Komarov 		evcn = le64_to_cpu(attr->nres.evcn);
15994342306fSKonstantin Komarov 
16004342306fSKonstantin Komarov 		if (evcn + 1 <= svcn)
16014342306fSKonstantin Komarov 			continue;
16024342306fSKonstantin Komarov 
16034342306fSKonstantin Komarov 		asize = le32_to_cpu(attr->size);
16044342306fSKonstantin Komarov 		roff = le16_to_cpu(attr->nres.run_off);
16054342306fSKonstantin Komarov 
1606d670934dSKonstantin Komarov 		if (roff > asize) {
1607d670934dSKonstantin Komarov 			_ntfs_bad_inode(&ni->vfs_inode);
16086db62086SEdward Lo 			return -EINVAL;
1609d670934dSKonstantin Komarov 		}
16106db62086SEdward Lo 
1611e8b8e97fSKari Argillander 		/* run==1 means unpack and deallocate. */
16124342306fSKonstantin Komarov 		run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn,
16134342306fSKonstantin Komarov 			      Add2Ptr(attr, roff), asize - roff);
16144342306fSKonstantin Komarov 	}
16154342306fSKonstantin Komarov 
16164342306fSKonstantin Komarov 	if (ni->attr_list.size) {
16174342306fSKonstantin Komarov 		run_deallocate(ni->mi.sbi, &ni->attr_list.run, true);
16184342306fSKonstantin Komarov 		al_destroy(ni);
16194342306fSKonstantin Komarov 	}
16204342306fSKonstantin Komarov 
1621e8b8e97fSKari Argillander 	/* Free all subrecords. */
16224342306fSKonstantin Komarov 	for (node = rb_first(&ni->mi_tree); node;) {
16234342306fSKonstantin Komarov 		struct rb_node *next = rb_next(node);
16244342306fSKonstantin Komarov 		struct mft_inode *mi = rb_entry(node, struct mft_inode, node);
16254342306fSKonstantin Komarov 
16264342306fSKonstantin Komarov 		clear_rec_inuse(mi->mrec);
16274342306fSKonstantin Komarov 		mi->dirty = true;
16284342306fSKonstantin Komarov 		mi_write(mi, 0);
16294342306fSKonstantin Komarov 
1630071100eaSKonstantin Komarov 		ntfs_mark_rec_free(sbi, mi->rno, false);
16314342306fSKonstantin Komarov 		ni_remove_mi(ni, mi);
16324342306fSKonstantin Komarov 		mi_put(mi);
16334342306fSKonstantin Komarov 		node = next;
16344342306fSKonstantin Komarov 	}
16354342306fSKonstantin Komarov 
1636d3624466SKonstantin Komarov 	/* Free base record. */
16374342306fSKonstantin Komarov 	clear_rec_inuse(ni->mi.mrec);
16384342306fSKonstantin Komarov 	ni->mi.dirty = true;
16394342306fSKonstantin Komarov 	err = mi_write(&ni->mi, 0);
16404342306fSKonstantin Komarov 
1641071100eaSKonstantin Komarov 	ntfs_mark_rec_free(sbi, ni->mi.rno, false);
16424342306fSKonstantin Komarov 
16434342306fSKonstantin Komarov 	return err;
16444342306fSKonstantin Komarov }
16454342306fSKonstantin Komarov 
1646e8b8e97fSKari Argillander /* ni_fname_name
16474342306fSKonstantin Komarov  *
164878ab59feSKonstantin Komarov  * Return: File name attribute by its value.
164978ab59feSKonstantin Komarov  */
ni_fname_name(struct ntfs_inode * ni,const struct le_str * uni,const struct MFT_REF * home_dir,struct mft_inode ** mi,struct ATTR_LIST_ENTRY ** le)16504342306fSKonstantin Komarov struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
1651d5ca7733SKonstantin Komarov 				     const struct le_str *uni,
16524342306fSKonstantin Komarov 				     const struct MFT_REF *home_dir,
165378ab59feSKonstantin Komarov 				     struct mft_inode **mi,
16544342306fSKonstantin Komarov 				     struct ATTR_LIST_ENTRY **le)
16554342306fSKonstantin Komarov {
16564342306fSKonstantin Komarov 	struct ATTRIB *attr = NULL;
16574342306fSKonstantin Komarov 	struct ATTR_FILE_NAME *fname;
16584342306fSKonstantin Komarov 
165942f66a7fSKonstantin Komarov 	if (le)
16604342306fSKonstantin Komarov 		*le = NULL;
16614342306fSKonstantin Komarov 
1662e8b8e97fSKari Argillander 	/* Enumerate all names. */
16634342306fSKonstantin Komarov next:
166478ab59feSKonstantin Komarov 	attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL, mi);
16654342306fSKonstantin Komarov 	if (!attr)
16664342306fSKonstantin Komarov 		return NULL;
16674342306fSKonstantin Komarov 
16684342306fSKonstantin Komarov 	fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
16694342306fSKonstantin Komarov 	if (!fname)
16704342306fSKonstantin Komarov 		goto next;
16714342306fSKonstantin Komarov 
16724342306fSKonstantin Komarov 	if (home_dir && memcmp(home_dir, &fname->home, sizeof(*home_dir)))
16734342306fSKonstantin Komarov 		goto next;
16744342306fSKonstantin Komarov 
16754342306fSKonstantin Komarov 	if (!uni)
167642f66a7fSKonstantin Komarov 		return fname;
16774342306fSKonstantin Komarov 
16784342306fSKonstantin Komarov 	if (uni->len != fname->name_len)
16794342306fSKonstantin Komarov 		goto next;
16804342306fSKonstantin Komarov 
1681d5ca7733SKonstantin Komarov 	if (ntfs_cmp_names(uni->name, uni->len, fname->name, uni->len, NULL,
1682d5ca7733SKonstantin Komarov 			   false))
16834342306fSKonstantin Komarov 		goto next;
16844342306fSKonstantin Komarov 	return fname;
16854342306fSKonstantin Komarov }
16864342306fSKonstantin Komarov 
16874342306fSKonstantin Komarov /*
16884342306fSKonstantin Komarov  * ni_fname_type
16894342306fSKonstantin Komarov  *
1690e8b8e97fSKari Argillander  * Return: File name attribute with given type.
16914342306fSKonstantin Komarov  */
ni_fname_type(struct ntfs_inode * ni,u8 name_type,struct mft_inode ** mi,struct ATTR_LIST_ENTRY ** le)16924342306fSKonstantin Komarov struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type,
169378ab59feSKonstantin Komarov 				     struct mft_inode **mi,
16944342306fSKonstantin Komarov 				     struct ATTR_LIST_ENTRY **le)
16954342306fSKonstantin Komarov {
16964342306fSKonstantin Komarov 	struct ATTRIB *attr = NULL;
16974342306fSKonstantin Komarov 	struct ATTR_FILE_NAME *fname;
16984342306fSKonstantin Komarov 
16994342306fSKonstantin Komarov 	*le = NULL;
17004342306fSKonstantin Komarov 
17014ca7fe57SKari Argillander 	if (name_type == FILE_NAME_POSIX)
170278ab59feSKonstantin Komarov 		return NULL;
170378ab59feSKonstantin Komarov 
1704e8b8e97fSKari Argillander 	/* Enumerate all names. */
17054342306fSKonstantin Komarov 	for (;;) {
170678ab59feSKonstantin Komarov 		attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL, mi);
17074342306fSKonstantin Komarov 		if (!attr)
17084342306fSKonstantin Komarov 			return NULL;
17094342306fSKonstantin Komarov 
17104342306fSKonstantin Komarov 		fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
17114342306fSKonstantin Komarov 		if (fname && name_type == fname->type)
17124342306fSKonstantin Komarov 			return fname;
17134342306fSKonstantin Komarov 	}
17144342306fSKonstantin Komarov }
17154342306fSKonstantin Komarov 
17164342306fSKonstantin Komarov /*
1717e8b8e97fSKari Argillander  * ni_new_attr_flags
1718e8b8e97fSKari Argillander  *
1719e8b8e97fSKari Argillander  * Process compressed/sparsed in special way.
1720e8b8e97fSKari Argillander  * NOTE: You need to set ni->std_fa = new_fa
1721e8b8e97fSKari Argillander  * after this function to keep internal structures in consistency.
17224342306fSKonstantin Komarov  */
ni_new_attr_flags(struct ntfs_inode * ni,enum FILE_ATTRIBUTE new_fa)17234342306fSKonstantin Komarov int ni_new_attr_flags(struct ntfs_inode *ni, enum FILE_ATTRIBUTE new_fa)
17244342306fSKonstantin Komarov {
17254342306fSKonstantin Komarov 	struct ATTRIB *attr;
17264342306fSKonstantin Komarov 	struct mft_inode *mi;
17274342306fSKonstantin Komarov 	__le16 new_aflags;
17284342306fSKonstantin Komarov 	u32 new_asize;
17294342306fSKonstantin Komarov 
17304342306fSKonstantin Komarov 	attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, &mi);
17314342306fSKonstantin Komarov 	if (!attr)
17324342306fSKonstantin Komarov 		return -EINVAL;
17334342306fSKonstantin Komarov 
17344342306fSKonstantin Komarov 	new_aflags = attr->flags;
17354342306fSKonstantin Komarov 
17364342306fSKonstantin Komarov 	if (new_fa & FILE_ATTRIBUTE_SPARSE_FILE)
17374342306fSKonstantin Komarov 		new_aflags |= ATTR_FLAG_SPARSED;
17384342306fSKonstantin Komarov 	else
17394342306fSKonstantin Komarov 		new_aflags &= ~ATTR_FLAG_SPARSED;
17404342306fSKonstantin Komarov 
17414342306fSKonstantin Komarov 	if (new_fa & FILE_ATTRIBUTE_COMPRESSED)
17424342306fSKonstantin Komarov 		new_aflags |= ATTR_FLAG_COMPRESSED;
17434342306fSKonstantin Komarov 	else
17444342306fSKonstantin Komarov 		new_aflags &= ~ATTR_FLAG_COMPRESSED;
17454342306fSKonstantin Komarov 
17464342306fSKonstantin Komarov 	if (new_aflags == attr->flags)
17474342306fSKonstantin Komarov 		return 0;
17484342306fSKonstantin Komarov 
17494342306fSKonstantin Komarov 	if ((new_aflags & (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) ==
17504342306fSKonstantin Komarov 	    (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) {
17514342306fSKonstantin Komarov 		ntfs_inode_warn(&ni->vfs_inode,
17524342306fSKonstantin Komarov 				"file can't be sparsed and compressed");
17534342306fSKonstantin Komarov 		return -EOPNOTSUPP;
17544342306fSKonstantin Komarov 	}
17554342306fSKonstantin Komarov 
17564342306fSKonstantin Komarov 	if (!attr->non_res)
17574342306fSKonstantin Komarov 		goto out;
17584342306fSKonstantin Komarov 
17594342306fSKonstantin Komarov 	if (attr->nres.data_size) {
17604342306fSKonstantin Komarov 		ntfs_inode_warn(
17614342306fSKonstantin Komarov 			&ni->vfs_inode,
17624342306fSKonstantin Komarov 			"one can change sparsed/compressed only for empty files");
17634342306fSKonstantin Komarov 		return -EOPNOTSUPP;
17644342306fSKonstantin Komarov 	}
17654342306fSKonstantin Komarov 
1766e8b8e97fSKari Argillander 	/* Resize nonresident empty attribute in-place only. */
176796de65a9SKonstantin Komarov 	new_asize = (new_aflags & (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) ?
176896de65a9SKonstantin Komarov 			    (SIZEOF_NONRESIDENT_EX + 8) :
176996de65a9SKonstantin Komarov 			    (SIZEOF_NONRESIDENT + 8);
17704342306fSKonstantin Komarov 
17714342306fSKonstantin Komarov 	if (!mi_resize_attr(mi, attr, new_asize - le32_to_cpu(attr->size)))
17724342306fSKonstantin Komarov 		return -EOPNOTSUPP;
17734342306fSKonstantin Komarov 
17744342306fSKonstantin Komarov 	if (new_aflags & ATTR_FLAG_SPARSED) {
17754342306fSKonstantin Komarov 		attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
1776e8b8e97fSKari Argillander 		/* Windows uses 16 clusters per frame but supports one cluster per frame too. */
17774342306fSKonstantin Komarov 		attr->nres.c_unit = 0;
17784342306fSKonstantin Komarov 		ni->vfs_inode.i_mapping->a_ops = &ntfs_aops;
17794342306fSKonstantin Komarov 	} else if (new_aflags & ATTR_FLAG_COMPRESSED) {
17804342306fSKonstantin Komarov 		attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
1781e8b8e97fSKari Argillander 		/* The only allowed: 16 clusters per frame. */
17824342306fSKonstantin Komarov 		attr->nres.c_unit = NTFS_LZNT_CUNIT;
17834342306fSKonstantin Komarov 		ni->vfs_inode.i_mapping->a_ops = &ntfs_aops_cmpr;
17844342306fSKonstantin Komarov 	} else {
17854342306fSKonstantin Komarov 		attr->name_off = SIZEOF_NONRESIDENT_LE;
1786e8b8e97fSKari Argillander 		/* Normal files. */
17874342306fSKonstantin Komarov 		attr->nres.c_unit = 0;
17884342306fSKonstantin Komarov 		ni->vfs_inode.i_mapping->a_ops = &ntfs_aops;
17894342306fSKonstantin Komarov 	}
17904342306fSKonstantin Komarov 	attr->nres.run_off = attr->name_off;
17914342306fSKonstantin Komarov out:
17924342306fSKonstantin Komarov 	attr->flags = new_aflags;
17934342306fSKonstantin Komarov 	mi->dirty = true;
17944342306fSKonstantin Komarov 
17954342306fSKonstantin Komarov 	return 0;
17964342306fSKonstantin Komarov }
17974342306fSKonstantin Komarov 
17984342306fSKonstantin Komarov /*
17994342306fSKonstantin Komarov  * ni_parse_reparse
18004342306fSKonstantin Komarov  *
1801cd4c76ffSKonstantin Komarov  * buffer - memory for reparse buffer header
18024342306fSKonstantin Komarov  */
ni_parse_reparse(struct ntfs_inode * ni,struct ATTRIB * attr,struct REPARSE_DATA_BUFFER * buffer)18034342306fSKonstantin Komarov enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,
1804cd4c76ffSKonstantin Komarov 				   struct REPARSE_DATA_BUFFER *buffer)
18054342306fSKonstantin Komarov {
18064342306fSKonstantin Komarov 	const struct REPARSE_DATA_BUFFER *rp = NULL;
18074342306fSKonstantin Komarov 	u8 bits;
18084342306fSKonstantin Komarov 	u16 len;
18094342306fSKonstantin Komarov 	typeof(rp->CompressReparseBuffer) *cmpr;
18104342306fSKonstantin Komarov 
1811e8b8e97fSKari Argillander 	/* Try to estimate reparse point. */
18124342306fSKonstantin Komarov 	if (!attr->non_res) {
18134342306fSKonstantin Komarov 		rp = resident_data_ex(attr, sizeof(struct REPARSE_DATA_BUFFER));
18144342306fSKonstantin Komarov 	} else if (le64_to_cpu(attr->nres.data_size) >=
18154342306fSKonstantin Komarov 		   sizeof(struct REPARSE_DATA_BUFFER)) {
18164342306fSKonstantin Komarov 		struct runs_tree run;
18174342306fSKonstantin Komarov 
18184342306fSKonstantin Komarov 		run_init(&run);
18194342306fSKonstantin Komarov 
18204342306fSKonstantin Komarov 		if (!attr_load_runs_vcn(ni, ATTR_REPARSE, NULL, 0, &run, 0) &&
18214342306fSKonstantin Komarov 		    !ntfs_read_run_nb(ni->mi.sbi, &run, 0, buffer,
18224342306fSKonstantin Komarov 				      sizeof(struct REPARSE_DATA_BUFFER),
18234342306fSKonstantin Komarov 				      NULL)) {
18244342306fSKonstantin Komarov 			rp = buffer;
18254342306fSKonstantin Komarov 		}
18264342306fSKonstantin Komarov 
18274342306fSKonstantin Komarov 		run_close(&run);
18284342306fSKonstantin Komarov 	}
18294342306fSKonstantin Komarov 
18304342306fSKonstantin Komarov 	if (!rp)
18314342306fSKonstantin Komarov 		return REPARSE_NONE;
18324342306fSKonstantin Komarov 
18334342306fSKonstantin Komarov 	len = le16_to_cpu(rp->ReparseDataLength);
18344342306fSKonstantin Komarov 	switch (rp->ReparseTag) {
18354342306fSKonstantin Komarov 	case (IO_REPARSE_TAG_MICROSOFT | IO_REPARSE_TAG_SYMBOLIC_LINK):
1836e8b8e97fSKari Argillander 		break; /* Symbolic link. */
18374342306fSKonstantin Komarov 	case IO_REPARSE_TAG_MOUNT_POINT:
1838e8b8e97fSKari Argillander 		break; /* Mount points and junctions. */
18394342306fSKonstantin Komarov 	case IO_REPARSE_TAG_SYMLINK:
18404342306fSKonstantin Komarov 		break;
18414342306fSKonstantin Komarov 	case IO_REPARSE_TAG_COMPRESS:
18424342306fSKonstantin Komarov 		/*
184324516d48SKari Argillander 		 * WOF - Windows Overlay Filter - Used to compress files with
184424516d48SKari Argillander 		 * LZX/Xpress.
184524516d48SKari Argillander 		 *
184624516d48SKari Argillander 		 * Unlike native NTFS file compression, the Windows
184724516d48SKari Argillander 		 * Overlay Filter supports only read operations. This means
184824516d48SKari Argillander 		 * that it doesn't need to sector-align each compressed chunk,
184924516d48SKari Argillander 		 * so the compressed data can be packed more tightly together.
185024516d48SKari Argillander 		 * If you open the file for writing, the WOF just decompresses
18514342306fSKonstantin Komarov 		 * the entire file, turning it back into a plain file.
18524342306fSKonstantin Komarov 		 *
185324516d48SKari Argillander 		 * Ntfs3 driver decompresses the entire file only on write or
185424516d48SKari Argillander 		 * change size requests.
18554342306fSKonstantin Komarov 		 */
18564342306fSKonstantin Komarov 
18574342306fSKonstantin Komarov 		cmpr = &rp->CompressReparseBuffer;
18584342306fSKonstantin Komarov 		if (len < sizeof(*cmpr) ||
18594342306fSKonstantin Komarov 		    cmpr->WofVersion != WOF_CURRENT_VERSION ||
18604342306fSKonstantin Komarov 		    cmpr->WofProvider != WOF_PROVIDER_SYSTEM ||
18614342306fSKonstantin Komarov 		    cmpr->ProviderVer != WOF_PROVIDER_CURRENT_VERSION) {
18624342306fSKonstantin Komarov 			return REPARSE_NONE;
18634342306fSKonstantin Komarov 		}
18644342306fSKonstantin Komarov 
18654342306fSKonstantin Komarov 		switch (cmpr->CompressionFormat) {
18664342306fSKonstantin Komarov 		case WOF_COMPRESSION_XPRESS4K:
18674342306fSKonstantin Komarov 			bits = 0xc; // 4k
18684342306fSKonstantin Komarov 			break;
18694342306fSKonstantin Komarov 		case WOF_COMPRESSION_XPRESS8K:
18704342306fSKonstantin Komarov 			bits = 0xd; // 8k
18714342306fSKonstantin Komarov 			break;
18724342306fSKonstantin Komarov 		case WOF_COMPRESSION_XPRESS16K:
18734342306fSKonstantin Komarov 			bits = 0xe; // 16k
18744342306fSKonstantin Komarov 			break;
18754342306fSKonstantin Komarov 		case WOF_COMPRESSION_LZX32K:
18764342306fSKonstantin Komarov 			bits = 0xf; // 32k
18774342306fSKonstantin Komarov 			break;
18784342306fSKonstantin Komarov 		default:
18794342306fSKonstantin Komarov 			bits = 0x10; // 64k
18804342306fSKonstantin Komarov 			break;
18814342306fSKonstantin Komarov 		}
18824342306fSKonstantin Komarov 		ni_set_ext_compress_bits(ni, bits);
18834342306fSKonstantin Komarov 		return REPARSE_COMPRESSED;
18844342306fSKonstantin Komarov 
18854342306fSKonstantin Komarov 	case IO_REPARSE_TAG_DEDUP:
18864342306fSKonstantin Komarov 		ni->ni_flags |= NI_FLAG_DEDUPLICATED;
18874342306fSKonstantin Komarov 		return REPARSE_DEDUPLICATED;
18884342306fSKonstantin Komarov 
18894342306fSKonstantin Komarov 	default:
18904342306fSKonstantin Komarov 		if (rp->ReparseTag & IO_REPARSE_TAG_NAME_SURROGATE)
18914342306fSKonstantin Komarov 			break;
18924342306fSKonstantin Komarov 
18934342306fSKonstantin Komarov 		return REPARSE_NONE;
18944342306fSKonstantin Komarov 	}
18954342306fSKonstantin Komarov 
1896cd4c76ffSKonstantin Komarov 	if (buffer != rp)
1897cd4c76ffSKonstantin Komarov 		memcpy(buffer, rp, sizeof(struct REPARSE_DATA_BUFFER));
1898cd4c76ffSKonstantin Komarov 
1899e8b8e97fSKari Argillander 	/* Looks like normal symlink. */
19004342306fSKonstantin Komarov 	return REPARSE_LINK;
19014342306fSKonstantin Komarov }
19024342306fSKonstantin Komarov 
19034342306fSKonstantin Komarov /*
1904e8b8e97fSKari Argillander  * ni_fiemap - Helper for file_fiemap().
1905e8b8e97fSKari Argillander  *
1906e8b8e97fSKari Argillander  * Assumed ni_lock.
1907e8b8e97fSKari Argillander  * TODO: Less aggressive locks.
19084342306fSKonstantin Komarov  */
ni_fiemap(struct ntfs_inode * ni,struct fiemap_extent_info * fieinfo,__u64 vbo,__u64 len)19094342306fSKonstantin Komarov int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
19104342306fSKonstantin Komarov 	      __u64 vbo, __u64 len)
19114342306fSKonstantin Komarov {
19124342306fSKonstantin Komarov 	int err = 0;
19134342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
19144342306fSKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
1915*c2556801SKonstantin Komarov 	struct runs_tree run;
19164342306fSKonstantin Komarov 	struct ATTRIB *attr;
19174342306fSKonstantin Komarov 	CLST vcn = vbo >> cluster_bits;
19184342306fSKonstantin Komarov 	CLST lcn, clen;
19194342306fSKonstantin Komarov 	u64 valid = ni->i_valid;
19204342306fSKonstantin Komarov 	u64 lbo, bytes;
19214342306fSKonstantin Komarov 	u64 end, alloc_size;
19224342306fSKonstantin Komarov 	size_t idx = -1;
19234342306fSKonstantin Komarov 	u32 flags;
19244342306fSKonstantin Komarov 	bool ok;
19254342306fSKonstantin Komarov 
1926*c2556801SKonstantin Komarov 	run_init(&run);
19274342306fSKonstantin Komarov 	if (S_ISDIR(ni->vfs_inode.i_mode)) {
19284342306fSKonstantin Komarov 		attr = ni_find_attr(ni, NULL, NULL, ATTR_ALLOC, I30_NAME,
19294342306fSKonstantin Komarov 				    ARRAY_SIZE(I30_NAME), NULL, NULL);
19304342306fSKonstantin Komarov 	} else {
19314342306fSKonstantin Komarov 		attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL,
19324342306fSKonstantin Komarov 				    NULL);
19334342306fSKonstantin Komarov 		if (!attr) {
19344342306fSKonstantin Komarov 			err = -EINVAL;
19354342306fSKonstantin Komarov 			goto out;
19364342306fSKonstantin Komarov 		}
19374342306fSKonstantin Komarov 		if (is_attr_compressed(attr)) {
1938e8b8e97fSKari Argillander 			/* Unfortunately cp -r incorrectly treats compressed clusters. */
19394342306fSKonstantin Komarov 			err = -EOPNOTSUPP;
19404342306fSKonstantin Komarov 			ntfs_inode_warn(
19414342306fSKonstantin Komarov 				&ni->vfs_inode,
19424342306fSKonstantin Komarov 				"fiemap is not supported for compressed file (cp -r)");
19434342306fSKonstantin Komarov 			goto out;
19444342306fSKonstantin Komarov 		}
19454342306fSKonstantin Komarov 	}
19464342306fSKonstantin Komarov 
19474342306fSKonstantin Komarov 	if (!attr || !attr->non_res) {
19484342306fSKonstantin Komarov 		err = fiemap_fill_next_extent(
19494342306fSKonstantin Komarov 			fieinfo, 0, 0,
19504342306fSKonstantin Komarov 			attr ? le32_to_cpu(attr->res.data_size) : 0,
19514342306fSKonstantin Komarov 			FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_LAST |
19524342306fSKonstantin Komarov 				FIEMAP_EXTENT_MERGED);
19534342306fSKonstantin Komarov 		goto out;
19544342306fSKonstantin Komarov 	}
19554342306fSKonstantin Komarov 
19564342306fSKonstantin Komarov 	end = vbo + len;
19574342306fSKonstantin Komarov 	alloc_size = le64_to_cpu(attr->nres.alloc_size);
19584342306fSKonstantin Komarov 	if (end > alloc_size)
19594342306fSKonstantin Komarov 		end = alloc_size;
19604342306fSKonstantin Komarov 
19614342306fSKonstantin Komarov 
19624342306fSKonstantin Komarov 	while (vbo < end) {
19634342306fSKonstantin Komarov 		if (idx == -1) {
1964*c2556801SKonstantin Komarov 			ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx);
19654342306fSKonstantin Komarov 		} else {
19664342306fSKonstantin Komarov 			CLST vcn_next = vcn;
19674342306fSKonstantin Komarov 
1968*c2556801SKonstantin Komarov 			ok = run_get_entry(&run, ++idx, &vcn, &lcn, &clen) &&
19694342306fSKonstantin Komarov 			     vcn == vcn_next;
19704342306fSKonstantin Komarov 			if (!ok)
19714342306fSKonstantin Komarov 				vcn = vcn_next;
19724342306fSKonstantin Komarov 		}
19734342306fSKonstantin Komarov 
19744342306fSKonstantin Komarov 		if (!ok) {
19754342306fSKonstantin Komarov 			err = attr_load_runs_vcn(ni, attr->type,
19764342306fSKonstantin Komarov 						 attr_name(attr),
1977*c2556801SKonstantin Komarov 						 attr->name_len, &run, vcn);
19784342306fSKonstantin Komarov 
19794342306fSKonstantin Komarov 			if (err)
19804342306fSKonstantin Komarov 				break;
19814342306fSKonstantin Komarov 
1982*c2556801SKonstantin Komarov 			ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx);
19834342306fSKonstantin Komarov 
19844342306fSKonstantin Komarov 			if (!ok) {
19854342306fSKonstantin Komarov 				err = -EINVAL;
19864342306fSKonstantin Komarov 				break;
19874342306fSKonstantin Komarov 			}
19884342306fSKonstantin Komarov 		}
19894342306fSKonstantin Komarov 
19904342306fSKonstantin Komarov 		if (!clen) {
19914342306fSKonstantin Komarov 			err = -EINVAL; // ?
19924342306fSKonstantin Komarov 			break;
19934342306fSKonstantin Komarov 		}
19944342306fSKonstantin Komarov 
19954342306fSKonstantin Komarov 		if (lcn == SPARSE_LCN) {
19964342306fSKonstantin Komarov 			vcn += clen;
19974342306fSKonstantin Komarov 			vbo = (u64)vcn << cluster_bits;
19984342306fSKonstantin Komarov 			continue;
19994342306fSKonstantin Komarov 		}
20004342306fSKonstantin Komarov 
20014342306fSKonstantin Komarov 		flags = FIEMAP_EXTENT_MERGED;
20024342306fSKonstantin Komarov 		if (S_ISDIR(ni->vfs_inode.i_mode)) {
20034342306fSKonstantin Komarov 			;
20044342306fSKonstantin Komarov 		} else if (is_attr_compressed(attr)) {
20054342306fSKonstantin Komarov 			CLST clst_data;
20064342306fSKonstantin Komarov 
2007*c2556801SKonstantin Komarov 			err = attr_is_frame_compressed(ni, attr,
2008*c2556801SKonstantin Komarov 						       vcn >> attr->nres.c_unit,
2009*c2556801SKonstantin Komarov 						       &clst_data, &run);
20104342306fSKonstantin Komarov 			if (err)
20114342306fSKonstantin Komarov 				break;
20124342306fSKonstantin Komarov 			if (clst_data < NTFS_LZNT_CLUSTERS)
20134342306fSKonstantin Komarov 				flags |= FIEMAP_EXTENT_ENCODED;
20144342306fSKonstantin Komarov 		} else if (is_attr_encrypted(attr)) {
20154342306fSKonstantin Komarov 			flags |= FIEMAP_EXTENT_DATA_ENCRYPTED;
20164342306fSKonstantin Komarov 		}
20174342306fSKonstantin Komarov 
20184342306fSKonstantin Komarov 		vbo = (u64)vcn << cluster_bits;
20194342306fSKonstantin Komarov 		bytes = (u64)clen << cluster_bits;
20204342306fSKonstantin Komarov 		lbo = (u64)lcn << cluster_bits;
20214342306fSKonstantin Komarov 
20224342306fSKonstantin Komarov 		vcn += clen;
20234342306fSKonstantin Komarov 
20243880f2b8SKonstantin Komarov 		if (vbo + bytes >= end)
20254342306fSKonstantin Komarov 			bytes = end - vbo;
20264342306fSKonstantin Komarov 
20274342306fSKonstantin Komarov 		if (vbo + bytes <= valid) {
20284342306fSKonstantin Komarov 			;
20294342306fSKonstantin Komarov 		} else if (vbo >= valid) {
20304342306fSKonstantin Komarov 			flags |= FIEMAP_EXTENT_UNWRITTEN;
20314342306fSKonstantin Komarov 		} else {
20324342306fSKonstantin Komarov 			/* vbo < valid && valid < vbo + bytes */
20334342306fSKonstantin Komarov 			u64 dlen = valid - vbo;
20344342306fSKonstantin Komarov 
20353880f2b8SKonstantin Komarov 			if (vbo + dlen >= end)
20363880f2b8SKonstantin Komarov 				flags |= FIEMAP_EXTENT_LAST;
20373880f2b8SKonstantin Komarov 
2038*c2556801SKonstantin Komarov 			err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen,
2039*c2556801SKonstantin Komarov 						      flags);
20405472b587SKonstantin Komarov 
20414342306fSKonstantin Komarov 			if (err < 0)
20424342306fSKonstantin Komarov 				break;
20434342306fSKonstantin Komarov 			if (err == 1) {
20444342306fSKonstantin Komarov 				err = 0;
20454342306fSKonstantin Komarov 				break;
20464342306fSKonstantin Komarov 			}
20474342306fSKonstantin Komarov 
20484342306fSKonstantin Komarov 			vbo = valid;
20494342306fSKonstantin Komarov 			bytes -= dlen;
20504342306fSKonstantin Komarov 			if (!bytes)
20514342306fSKonstantin Komarov 				continue;
20524342306fSKonstantin Komarov 
20534342306fSKonstantin Komarov 			lbo += dlen;
20544342306fSKonstantin Komarov 			flags |= FIEMAP_EXTENT_UNWRITTEN;
20554342306fSKonstantin Komarov 		}
20564342306fSKonstantin Komarov 
20573880f2b8SKonstantin Komarov 		if (vbo + bytes >= end)
20583880f2b8SKonstantin Komarov 			flags |= FIEMAP_EXTENT_LAST;
20593880f2b8SKonstantin Komarov 
2060*c2556801SKonstantin Komarov 		err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags);
20614342306fSKonstantin Komarov 		if (err < 0)
20624342306fSKonstantin Komarov 			break;
20634342306fSKonstantin Komarov 		if (err == 1) {
20644342306fSKonstantin Komarov 			err = 0;
20654342306fSKonstantin Komarov 			break;
20664342306fSKonstantin Komarov 		}
20674342306fSKonstantin Komarov 
20684342306fSKonstantin Komarov 		vbo += bytes;
20694342306fSKonstantin Komarov 	}
20704342306fSKonstantin Komarov 
20714342306fSKonstantin Komarov out:
2072*c2556801SKonstantin Komarov 	run_close(&run);
20734342306fSKonstantin Komarov 	return err;
20744342306fSKonstantin Komarov }
20754342306fSKonstantin Komarov 
20764342306fSKonstantin Komarov /*
2077e8b8e97fSKari Argillander  * ni_readpage_cmpr
2078e8b8e97fSKari Argillander  *
20794342306fSKonstantin Komarov  * When decompressing, we typically obtain more than one page per reference.
20804342306fSKonstantin Komarov  * We inject the additional pages into the page cache.
20814342306fSKonstantin Komarov  */
ni_readpage_cmpr(struct ntfs_inode * ni,struct page * page)20824342306fSKonstantin Komarov int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page)
20834342306fSKonstantin Komarov {
20844342306fSKonstantin Komarov 	int err;
20854342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
20864342306fSKonstantin Komarov 	struct address_space *mapping = page->mapping;
20874342306fSKonstantin Komarov 	pgoff_t index = page->index;
20884342306fSKonstantin Komarov 	u64 frame_vbo, vbo = (u64)index << PAGE_SHIFT;
2089e8b8e97fSKari Argillander 	struct page **pages = NULL; /* Array of at most 16 pages. stack? */
20904342306fSKonstantin Komarov 	u8 frame_bits;
20914342306fSKonstantin Komarov 	CLST frame;
20924342306fSKonstantin Komarov 	u32 i, idx, frame_size, pages_per_frame;
20934342306fSKonstantin Komarov 	gfp_t gfp_mask;
20944342306fSKonstantin Komarov 	struct page *pg;
20954342306fSKonstantin Komarov 
2096f4cf29c6SKonstantin Komarov 	if (vbo >= i_size_read(&ni->vfs_inode)) {
20974342306fSKonstantin Komarov 		SetPageUptodate(page);
20984342306fSKonstantin Komarov 		err = 0;
20994342306fSKonstantin Komarov 		goto out;
21004342306fSKonstantin Komarov 	}
21014342306fSKonstantin Komarov 
21024342306fSKonstantin Komarov 	if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) {
2103e8b8e97fSKari Argillander 		/* Xpress or LZX. */
21044342306fSKonstantin Komarov 		frame_bits = ni_ext_compress_bits(ni);
21054342306fSKonstantin Komarov 	} else {
2106e8b8e97fSKari Argillander 		/* LZNT compression. */
21074342306fSKonstantin Komarov 		frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits;
21084342306fSKonstantin Komarov 	}
21094342306fSKonstantin Komarov 	frame_size = 1u << frame_bits;
21104342306fSKonstantin Komarov 	frame = vbo >> frame_bits;
21114342306fSKonstantin Komarov 	frame_vbo = (u64)frame << frame_bits;
21124342306fSKonstantin Komarov 	idx = (vbo - frame_vbo) >> PAGE_SHIFT;
21134342306fSKonstantin Komarov 
21144342306fSKonstantin Komarov 	pages_per_frame = frame_size >> PAGE_SHIFT;
2115345482bcSKari Argillander 	pages = kcalloc(pages_per_frame, sizeof(struct page *), GFP_NOFS);
21164342306fSKonstantin Komarov 	if (!pages) {
21174342306fSKonstantin Komarov 		err = -ENOMEM;
21184342306fSKonstantin Komarov 		goto out;
21194342306fSKonstantin Komarov 	}
21204342306fSKonstantin Komarov 
21214342306fSKonstantin Komarov 	pages[idx] = page;
21224342306fSKonstantin Komarov 	index = frame_vbo >> PAGE_SHIFT;
21234342306fSKonstantin Komarov 	gfp_mask = mapping_gfp_mask(mapping);
21244342306fSKonstantin Komarov 
21254342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++, index++) {
21264342306fSKonstantin Komarov 		if (i == idx)
21274342306fSKonstantin Komarov 			continue;
21284342306fSKonstantin Komarov 
21294342306fSKonstantin Komarov 		pg = find_or_create_page(mapping, index, gfp_mask);
21304342306fSKonstantin Komarov 		if (!pg) {
21314342306fSKonstantin Komarov 			err = -ENOMEM;
21324342306fSKonstantin Komarov 			goto out1;
21334342306fSKonstantin Komarov 		}
21344342306fSKonstantin Komarov 		pages[i] = pg;
21354342306fSKonstantin Komarov 	}
21364342306fSKonstantin Komarov 
21374342306fSKonstantin Komarov 	err = ni_read_frame(ni, frame_vbo, pages, pages_per_frame);
21384342306fSKonstantin Komarov 
21394342306fSKonstantin Komarov out1:
21404342306fSKonstantin Komarov 	if (err)
21414342306fSKonstantin Komarov 		SetPageError(page);
21424342306fSKonstantin Komarov 
21434342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++) {
21444342306fSKonstantin Komarov 		pg = pages[i];
214532e92122SKonstantin Komarov 		if (i == idx || !pg)
21464342306fSKonstantin Komarov 			continue;
21474342306fSKonstantin Komarov 		unlock_page(pg);
21484342306fSKonstantin Komarov 		put_page(pg);
21494342306fSKonstantin Komarov 	}
21504342306fSKonstantin Komarov 
21514342306fSKonstantin Komarov out:
2152e8b8e97fSKari Argillander 	/* At this point, err contains 0 or -EIO depending on the "critical" page. */
2153195c52bdSKari Argillander 	kfree(pages);
21544342306fSKonstantin Komarov 	unlock_page(page);
21554342306fSKonstantin Komarov 
21564342306fSKonstantin Komarov 	return err;
21574342306fSKonstantin Komarov }
21584342306fSKonstantin Komarov 
21594342306fSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
21604342306fSKonstantin Komarov /*
2161e8b8e97fSKari Argillander  * ni_decompress_file - Decompress LZX/Xpress compressed file.
2162e8b8e97fSKari Argillander  *
2163e8b8e97fSKari Argillander  * Remove ATTR_DATA::WofCompressedData.
2164e8b8e97fSKari Argillander  * Remove ATTR_REPARSE.
21654342306fSKonstantin Komarov  */
ni_decompress_file(struct ntfs_inode * ni)21664342306fSKonstantin Komarov int ni_decompress_file(struct ntfs_inode *ni)
21674342306fSKonstantin Komarov {
21684342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
21694342306fSKonstantin Komarov 	struct inode *inode = &ni->vfs_inode;
2170f4cf29c6SKonstantin Komarov 	loff_t i_size = i_size_read(inode);
21714342306fSKonstantin Komarov 	struct address_space *mapping = inode->i_mapping;
21724342306fSKonstantin Komarov 	gfp_t gfp_mask = mapping_gfp_mask(mapping);
21734342306fSKonstantin Komarov 	struct page **pages = NULL;
21744342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
21754342306fSKonstantin Komarov 	struct ATTRIB *attr;
21764342306fSKonstantin Komarov 	CLST vcn, cend, lcn, clen, end;
21774342306fSKonstantin Komarov 	pgoff_t index;
21784342306fSKonstantin Komarov 	u64 vbo;
21794342306fSKonstantin Komarov 	u8 frame_bits;
21804342306fSKonstantin Komarov 	u32 i, frame_size, pages_per_frame, bytes;
21814342306fSKonstantin Komarov 	struct mft_inode *mi;
21824342306fSKonstantin Komarov 	int err;
21834342306fSKonstantin Komarov 
2184e8b8e97fSKari Argillander 	/* Clusters for decompressed data. */
21854342306fSKonstantin Komarov 	cend = bytes_to_cluster(sbi, i_size);
21864342306fSKonstantin Komarov 
21874342306fSKonstantin Komarov 	if (!i_size)
21884342306fSKonstantin Komarov 		goto remove_wof;
21894342306fSKonstantin Komarov 
2190e8b8e97fSKari Argillander 	/* Check in advance. */
21914342306fSKonstantin Komarov 	if (cend > wnd_zeroes(&sbi->used.bitmap)) {
21924342306fSKonstantin Komarov 		err = -ENOSPC;
21934342306fSKonstantin Komarov 		goto out;
21944342306fSKonstantin Komarov 	}
21954342306fSKonstantin Komarov 
21964342306fSKonstantin Komarov 	frame_bits = ni_ext_compress_bits(ni);
21974342306fSKonstantin Komarov 	frame_size = 1u << frame_bits;
21984342306fSKonstantin Komarov 	pages_per_frame = frame_size >> PAGE_SHIFT;
2199345482bcSKari Argillander 	pages = kcalloc(pages_per_frame, sizeof(struct page *), GFP_NOFS);
22004342306fSKonstantin Komarov 	if (!pages) {
22014342306fSKonstantin Komarov 		err = -ENOMEM;
22024342306fSKonstantin Komarov 		goto out;
22034342306fSKonstantin Komarov 	}
22044342306fSKonstantin Komarov 
22054342306fSKonstantin Komarov 	/*
2206e8b8e97fSKari Argillander 	 * Step 1: Decompress data and copy to new allocated clusters.
22074342306fSKonstantin Komarov 	 */
22084342306fSKonstantin Komarov 	index = 0;
22094342306fSKonstantin Komarov 	for (vbo = 0; vbo < i_size; vbo += bytes) {
22104342306fSKonstantin Komarov 		u32 nr_pages;
22114342306fSKonstantin Komarov 		bool new;
22124342306fSKonstantin Komarov 
22134342306fSKonstantin Komarov 		if (vbo + frame_size > i_size) {
22144342306fSKonstantin Komarov 			bytes = i_size - vbo;
22154342306fSKonstantin Komarov 			nr_pages = (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
22164342306fSKonstantin Komarov 		} else {
22174342306fSKonstantin Komarov 			nr_pages = pages_per_frame;
22184342306fSKonstantin Komarov 			bytes = frame_size;
22194342306fSKonstantin Komarov 		}
22204342306fSKonstantin Komarov 
22214342306fSKonstantin Komarov 		end = bytes_to_cluster(sbi, vbo + bytes);
22224342306fSKonstantin Komarov 
22234342306fSKonstantin Komarov 		for (vcn = vbo >> sbi->cluster_bits; vcn < end; vcn += clen) {
22244342306fSKonstantin Komarov 			err = attr_data_get_block(ni, vcn, cend - vcn, &lcn,
2225c380b52fSKonstantin Komarov 						  &clen, &new, false);
22264342306fSKonstantin Komarov 			if (err)
22274342306fSKonstantin Komarov 				goto out;
22284342306fSKonstantin Komarov 		}
22294342306fSKonstantin Komarov 
22304342306fSKonstantin Komarov 		for (i = 0; i < pages_per_frame; i++, index++) {
22314342306fSKonstantin Komarov 			struct page *pg;
22324342306fSKonstantin Komarov 
22334342306fSKonstantin Komarov 			pg = find_or_create_page(mapping, index, gfp_mask);
22344342306fSKonstantin Komarov 			if (!pg) {
22354342306fSKonstantin Komarov 				while (i--) {
22364342306fSKonstantin Komarov 					unlock_page(pages[i]);
22374342306fSKonstantin Komarov 					put_page(pages[i]);
22384342306fSKonstantin Komarov 				}
22394342306fSKonstantin Komarov 				err = -ENOMEM;
22404342306fSKonstantin Komarov 				goto out;
22414342306fSKonstantin Komarov 			}
22424342306fSKonstantin Komarov 			pages[i] = pg;
22434342306fSKonstantin Komarov 		}
22444342306fSKonstantin Komarov 
22454342306fSKonstantin Komarov 		err = ni_read_frame(ni, vbo, pages, pages_per_frame);
22464342306fSKonstantin Komarov 
22474342306fSKonstantin Komarov 		if (!err) {
22484342306fSKonstantin Komarov 			down_read(&ni->file.run_lock);
22494342306fSKonstantin Komarov 			err = ntfs_bio_pages(sbi, &ni->file.run, pages,
22504342306fSKonstantin Komarov 					     nr_pages, vbo, bytes,
22514342306fSKonstantin Komarov 					     REQ_OP_WRITE);
22524342306fSKonstantin Komarov 			up_read(&ni->file.run_lock);
22534342306fSKonstantin Komarov 		}
22544342306fSKonstantin Komarov 
22554342306fSKonstantin Komarov 		for (i = 0; i < pages_per_frame; i++) {
22564342306fSKonstantin Komarov 			unlock_page(pages[i]);
22574342306fSKonstantin Komarov 			put_page(pages[i]);
22584342306fSKonstantin Komarov 		}
22594342306fSKonstantin Komarov 
22604342306fSKonstantin Komarov 		if (err)
22614342306fSKonstantin Komarov 			goto out;
22624342306fSKonstantin Komarov 
22634342306fSKonstantin Komarov 		cond_resched();
22644342306fSKonstantin Komarov 	}
22654342306fSKonstantin Komarov 
22664342306fSKonstantin Komarov remove_wof:
22674342306fSKonstantin Komarov 	/*
2268e8b8e97fSKari Argillander 	 * Step 2: Deallocate attributes ATTR_DATA::WofCompressedData
2269e8b8e97fSKari Argillander 	 * and ATTR_REPARSE.
22704342306fSKonstantin Komarov 	 */
22714342306fSKonstantin Komarov 	attr = NULL;
22724342306fSKonstantin Komarov 	le = NULL;
22734342306fSKonstantin Komarov 	while ((attr = ni_enum_attr_ex(ni, attr, &le, NULL))) {
22744342306fSKonstantin Komarov 		CLST svcn, evcn;
22754342306fSKonstantin Komarov 		u32 asize, roff;
22764342306fSKonstantin Komarov 
22774342306fSKonstantin Komarov 		if (attr->type == ATTR_REPARSE) {
22784342306fSKonstantin Komarov 			struct MFT_REF ref;
22794342306fSKonstantin Komarov 
22804342306fSKonstantin Komarov 			mi_get_ref(&ni->mi, &ref);
22814342306fSKonstantin Komarov 			ntfs_remove_reparse(sbi, 0, &ref);
22824342306fSKonstantin Komarov 		}
22834342306fSKonstantin Komarov 
22844342306fSKonstantin Komarov 		if (!attr->non_res)
22854342306fSKonstantin Komarov 			continue;
22864342306fSKonstantin Komarov 
22874342306fSKonstantin Komarov 		if (attr->type != ATTR_REPARSE &&
22884342306fSKonstantin Komarov 		    (attr->type != ATTR_DATA ||
22894342306fSKonstantin Komarov 		     attr->name_len != ARRAY_SIZE(WOF_NAME) ||
22904342306fSKonstantin Komarov 		     memcmp(attr_name(attr), WOF_NAME, sizeof(WOF_NAME))))
22914342306fSKonstantin Komarov 			continue;
22924342306fSKonstantin Komarov 
22934342306fSKonstantin Komarov 		svcn = le64_to_cpu(attr->nres.svcn);
22944342306fSKonstantin Komarov 		evcn = le64_to_cpu(attr->nres.evcn);
22954342306fSKonstantin Komarov 
22964342306fSKonstantin Komarov 		if (evcn + 1 <= svcn)
22974342306fSKonstantin Komarov 			continue;
22984342306fSKonstantin Komarov 
22994342306fSKonstantin Komarov 		asize = le32_to_cpu(attr->size);
23004342306fSKonstantin Komarov 		roff = le16_to_cpu(attr->nres.run_off);
23014342306fSKonstantin Komarov 
23026db62086SEdward Lo 		if (roff > asize) {
23036db62086SEdward Lo 			err = -EINVAL;
23046db62086SEdward Lo 			goto out;
23056db62086SEdward Lo 		}
23066db62086SEdward Lo 
2307e8b8e97fSKari Argillander 		/*run==1  Means unpack and deallocate. */
23084342306fSKonstantin Komarov 		run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn,
23094342306fSKonstantin Komarov 			      Add2Ptr(attr, roff), asize - roff);
23104342306fSKonstantin Komarov 	}
23114342306fSKonstantin Komarov 
23124342306fSKonstantin Komarov 	/*
2313e8b8e97fSKari Argillander 	 * Step 3: Remove attribute ATTR_DATA::WofCompressedData.
23144342306fSKonstantin Komarov 	 */
23154342306fSKonstantin Komarov 	err = ni_remove_attr(ni, ATTR_DATA, WOF_NAME, ARRAY_SIZE(WOF_NAME),
23164342306fSKonstantin Komarov 			     false, NULL);
23174342306fSKonstantin Komarov 	if (err)
23184342306fSKonstantin Komarov 		goto out;
23194342306fSKonstantin Komarov 
23204342306fSKonstantin Komarov 	/*
2321e8b8e97fSKari Argillander 	 * Step 4: Remove ATTR_REPARSE.
23224342306fSKonstantin Komarov 	 */
23234342306fSKonstantin Komarov 	err = ni_remove_attr(ni, ATTR_REPARSE, NULL, 0, false, NULL);
23244342306fSKonstantin Komarov 	if (err)
23254342306fSKonstantin Komarov 		goto out;
23264342306fSKonstantin Komarov 
23274342306fSKonstantin Komarov 	/*
2328e8b8e97fSKari Argillander 	 * Step 5: Remove sparse flag from data attribute.
23294342306fSKonstantin Komarov 	 */
23304342306fSKonstantin Komarov 	attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, &mi);
23314342306fSKonstantin Komarov 	if (!attr) {
23324342306fSKonstantin Komarov 		err = -EINVAL;
23334342306fSKonstantin Komarov 		goto out;
23344342306fSKonstantin Komarov 	}
23354342306fSKonstantin Komarov 
23364342306fSKonstantin Komarov 	if (attr->non_res && is_attr_sparsed(attr)) {
2337d3624466SKonstantin Komarov 		/* Sparsed attribute header is 8 bytes bigger than normal. */
23384342306fSKonstantin Komarov 		struct MFT_REC *rec = mi->mrec;
23394342306fSKonstantin Komarov 		u32 used = le32_to_cpu(rec->used);
23404342306fSKonstantin Komarov 		u32 asize = le32_to_cpu(attr->size);
23414342306fSKonstantin Komarov 		u16 roff = le16_to_cpu(attr->nres.run_off);
23424342306fSKonstantin Komarov 		char *rbuf = Add2Ptr(attr, roff);
23434342306fSKonstantin Komarov 
23444342306fSKonstantin Komarov 		memmove(rbuf - 8, rbuf, used - PtrOffset(rec, rbuf));
23454342306fSKonstantin Komarov 		attr->size = cpu_to_le32(asize - 8);
23464342306fSKonstantin Komarov 		attr->flags &= ~ATTR_FLAG_SPARSED;
23474342306fSKonstantin Komarov 		attr->nres.run_off = cpu_to_le16(roff - 8);
23484342306fSKonstantin Komarov 		attr->nres.c_unit = 0;
23494342306fSKonstantin Komarov 		rec->used = cpu_to_le32(used - 8);
23504342306fSKonstantin Komarov 		mi->dirty = true;
23514342306fSKonstantin Komarov 		ni->std_fa &= ~(FILE_ATTRIBUTE_SPARSE_FILE |
23524342306fSKonstantin Komarov 				FILE_ATTRIBUTE_REPARSE_POINT);
23534342306fSKonstantin Komarov 
23544342306fSKonstantin Komarov 		mark_inode_dirty(inode);
23554342306fSKonstantin Komarov 	}
23564342306fSKonstantin Komarov 
2357e8b8e97fSKari Argillander 	/* Clear cached flag. */
23584342306fSKonstantin Komarov 	ni->ni_flags &= ~NI_FLAG_COMPRESSED_MASK;
23594342306fSKonstantin Komarov 	if (ni->file.offs_page) {
23604342306fSKonstantin Komarov 		put_page(ni->file.offs_page);
23614342306fSKonstantin Komarov 		ni->file.offs_page = NULL;
23624342306fSKonstantin Komarov 	}
23634342306fSKonstantin Komarov 	mapping->a_ops = &ntfs_aops;
23644342306fSKonstantin Komarov 
23654342306fSKonstantin Komarov out:
2366195c52bdSKari Argillander 	kfree(pages);
2367c12df45eSKonstantin Komarov 	if (err)
2368c12df45eSKonstantin Komarov 		_ntfs_bad_inode(inode);
23694342306fSKonstantin Komarov 
23704342306fSKonstantin Komarov 	return err;
23714342306fSKonstantin Komarov }
23724342306fSKonstantin Komarov 
2373e8b8e97fSKari Argillander /*
2374e8b8e97fSKari Argillander  * decompress_lzx_xpress - External compression LZX/Xpress.
2375e8b8e97fSKari Argillander  */
decompress_lzx_xpress(struct ntfs_sb_info * sbi,const char * cmpr,size_t cmpr_size,void * unc,size_t unc_size,u32 frame_size)23764342306fSKonstantin Komarov static int decompress_lzx_xpress(struct ntfs_sb_info *sbi, const char *cmpr,
23774342306fSKonstantin Komarov 				 size_t cmpr_size, void *unc, size_t unc_size,
23784342306fSKonstantin Komarov 				 u32 frame_size)
23794342306fSKonstantin Komarov {
23804342306fSKonstantin Komarov 	int err;
23814342306fSKonstantin Komarov 	void *ctx;
23824342306fSKonstantin Komarov 
23834342306fSKonstantin Komarov 	if (cmpr_size == unc_size) {
2384e8b8e97fSKari Argillander 		/* Frame not compressed. */
23854342306fSKonstantin Komarov 		memcpy(unc, cmpr, unc_size);
23864342306fSKonstantin Komarov 		return 0;
23874342306fSKonstantin Komarov 	}
23884342306fSKonstantin Komarov 
23894342306fSKonstantin Komarov 	err = 0;
23904342306fSKonstantin Komarov 	if (frame_size == 0x8000) {
23914342306fSKonstantin Komarov 		mutex_lock(&sbi->compress.mtx_lzx);
2392e8b8e97fSKari Argillander 		/* LZX: Frame compressed. */
23934342306fSKonstantin Komarov 		ctx = sbi->compress.lzx;
23944342306fSKonstantin Komarov 		if (!ctx) {
2395e8b8e97fSKari Argillander 			/* Lazy initialize LZX decompress context. */
23964342306fSKonstantin Komarov 			ctx = lzx_allocate_decompressor();
23974342306fSKonstantin Komarov 			if (!ctx) {
23984342306fSKonstantin Komarov 				err = -ENOMEM;
23994342306fSKonstantin Komarov 				goto out1;
24004342306fSKonstantin Komarov 			}
24014342306fSKonstantin Komarov 
24024342306fSKonstantin Komarov 			sbi->compress.lzx = ctx;
24034342306fSKonstantin Komarov 		}
24044342306fSKonstantin Komarov 
24054342306fSKonstantin Komarov 		if (lzx_decompress(ctx, cmpr, cmpr_size, unc, unc_size)) {
2406e8b8e97fSKari Argillander 			/* Treat all errors as "invalid argument". */
24074342306fSKonstantin Komarov 			err = -EINVAL;
24084342306fSKonstantin Komarov 		}
24094342306fSKonstantin Komarov out1:
24104342306fSKonstantin Komarov 		mutex_unlock(&sbi->compress.mtx_lzx);
24114342306fSKonstantin Komarov 	} else {
2412e8b8e97fSKari Argillander 		/* XPRESS: Frame compressed. */
24134342306fSKonstantin Komarov 		mutex_lock(&sbi->compress.mtx_xpress);
24144342306fSKonstantin Komarov 		ctx = sbi->compress.xpress;
24154342306fSKonstantin Komarov 		if (!ctx) {
2416d3624466SKonstantin Komarov 			/* Lazy initialize Xpress decompress context. */
24174342306fSKonstantin Komarov 			ctx = xpress_allocate_decompressor();
24184342306fSKonstantin Komarov 			if (!ctx) {
24194342306fSKonstantin Komarov 				err = -ENOMEM;
24204342306fSKonstantin Komarov 				goto out2;
24214342306fSKonstantin Komarov 			}
24224342306fSKonstantin Komarov 
24234342306fSKonstantin Komarov 			sbi->compress.xpress = ctx;
24244342306fSKonstantin Komarov 		}
24254342306fSKonstantin Komarov 
24264342306fSKonstantin Komarov 		if (xpress_decompress(ctx, cmpr, cmpr_size, unc, unc_size)) {
2427e8b8e97fSKari Argillander 			/* Treat all errors as "invalid argument". */
24284342306fSKonstantin Komarov 			err = -EINVAL;
24294342306fSKonstantin Komarov 		}
24304342306fSKonstantin Komarov out2:
24314342306fSKonstantin Komarov 		mutex_unlock(&sbi->compress.mtx_xpress);
24324342306fSKonstantin Komarov 	}
24334342306fSKonstantin Komarov 	return err;
24344342306fSKonstantin Komarov }
24354342306fSKonstantin Komarov #endif
24364342306fSKonstantin Komarov 
24374342306fSKonstantin Komarov /*
24384342306fSKonstantin Komarov  * ni_read_frame
24394342306fSKonstantin Komarov  *
2440d3624466SKonstantin Komarov  * Pages - Array of locked pages.
24414342306fSKonstantin Komarov  */
ni_read_frame(struct ntfs_inode * ni,u64 frame_vbo,struct page ** pages,u32 pages_per_frame)24424342306fSKonstantin Komarov int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
24434342306fSKonstantin Komarov 		  u32 pages_per_frame)
24444342306fSKonstantin Komarov {
24454342306fSKonstantin Komarov 	int err;
24464342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
24474342306fSKonstantin Komarov 	u8 cluster_bits = sbi->cluster_bits;
24484342306fSKonstantin Komarov 	char *frame_ondisk = NULL;
24494342306fSKonstantin Komarov 	char *frame_mem = NULL;
24504342306fSKonstantin Komarov 	struct page **pages_disk = NULL;
24514342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le = NULL;
24524342306fSKonstantin Komarov 	struct runs_tree *run = &ni->file.run;
24534342306fSKonstantin Komarov 	u64 valid_size = ni->i_valid;
24544342306fSKonstantin Komarov 	u64 vbo_disk;
24554342306fSKonstantin Komarov 	size_t unc_size;
24564342306fSKonstantin Komarov 	u32 frame_size, i, npages_disk, ondisk_size;
24574342306fSKonstantin Komarov 	struct page *pg;
24584342306fSKonstantin Komarov 	struct ATTRIB *attr;
24594342306fSKonstantin Komarov 	CLST frame, clst_data;
24604342306fSKonstantin Komarov 
24614342306fSKonstantin Komarov 	/*
2462e8b8e97fSKari Argillander 	 * To simplify decompress algorithm do vmap for source
2463e8b8e97fSKari Argillander 	 * and target pages.
24644342306fSKonstantin Komarov 	 */
24654342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++)
24664342306fSKonstantin Komarov 		kmap(pages[i]);
24674342306fSKonstantin Komarov 
24684342306fSKonstantin Komarov 	frame_size = pages_per_frame << PAGE_SHIFT;
24694342306fSKonstantin Komarov 	frame_mem = vmap(pages, pages_per_frame, VM_MAP, PAGE_KERNEL);
24704342306fSKonstantin Komarov 	if (!frame_mem) {
24714342306fSKonstantin Komarov 		err = -ENOMEM;
24724342306fSKonstantin Komarov 		goto out;
24734342306fSKonstantin Komarov 	}
24744342306fSKonstantin Komarov 
24754342306fSKonstantin Komarov 	attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, NULL);
24764342306fSKonstantin Komarov 	if (!attr) {
24774342306fSKonstantin Komarov 		err = -ENOENT;
24784342306fSKonstantin Komarov 		goto out1;
24794342306fSKonstantin Komarov 	}
24804342306fSKonstantin Komarov 
24814342306fSKonstantin Komarov 	if (!attr->non_res) {
24824342306fSKonstantin Komarov 		u32 data_size = le32_to_cpu(attr->res.data_size);
24834342306fSKonstantin Komarov 
24844342306fSKonstantin Komarov 		memset(frame_mem, 0, frame_size);
24854342306fSKonstantin Komarov 		if (frame_vbo < data_size) {
24864342306fSKonstantin Komarov 			ondisk_size = data_size - frame_vbo;
24874342306fSKonstantin Komarov 			memcpy(frame_mem, resident_data(attr) + frame_vbo,
24884342306fSKonstantin Komarov 			       min(ondisk_size, frame_size));
24894342306fSKonstantin Komarov 		}
24904342306fSKonstantin Komarov 		err = 0;
24914342306fSKonstantin Komarov 		goto out1;
24924342306fSKonstantin Komarov 	}
24934342306fSKonstantin Komarov 
24944342306fSKonstantin Komarov 	if (frame_vbo >= valid_size) {
24954342306fSKonstantin Komarov 		memset(frame_mem, 0, frame_size);
24964342306fSKonstantin Komarov 		err = 0;
24974342306fSKonstantin Komarov 		goto out1;
24984342306fSKonstantin Komarov 	}
24994342306fSKonstantin Komarov 
25004342306fSKonstantin Komarov 	if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) {
25014342306fSKonstantin Komarov #ifndef CONFIG_NTFS3_LZX_XPRESS
25024342306fSKonstantin Komarov 		err = -EOPNOTSUPP;
25034342306fSKonstantin Komarov 		goto out1;
25044342306fSKonstantin Komarov #else
2505af0d04f0SMark O'Donovan 		loff_t i_size = i_size_read(&ni->vfs_inode);
25064342306fSKonstantin Komarov 		u32 frame_bits = ni_ext_compress_bits(ni);
25074342306fSKonstantin Komarov 		u64 frame64 = frame_vbo >> frame_bits;
25084342306fSKonstantin Komarov 		u64 frames, vbo_data;
25094342306fSKonstantin Komarov 
25104342306fSKonstantin Komarov 		if (frame_size != (1u << frame_bits)) {
25114342306fSKonstantin Komarov 			err = -EINVAL;
25124342306fSKonstantin Komarov 			goto out1;
25134342306fSKonstantin Komarov 		}
25144342306fSKonstantin Komarov 		switch (frame_size) {
25154342306fSKonstantin Komarov 		case 0x1000:
25164342306fSKonstantin Komarov 		case 0x2000:
25174342306fSKonstantin Komarov 		case 0x4000:
25184342306fSKonstantin Komarov 		case 0x8000:
25194342306fSKonstantin Komarov 			break;
25204342306fSKonstantin Komarov 		default:
2521e8b8e97fSKari Argillander 			/* Unknown compression. */
25224342306fSKonstantin Komarov 			err = -EOPNOTSUPP;
25234342306fSKonstantin Komarov 			goto out1;
25244342306fSKonstantin Komarov 		}
25254342306fSKonstantin Komarov 
25264342306fSKonstantin Komarov 		attr = ni_find_attr(ni, attr, &le, ATTR_DATA, WOF_NAME,
25274342306fSKonstantin Komarov 				    ARRAY_SIZE(WOF_NAME), NULL, NULL);
25284342306fSKonstantin Komarov 		if (!attr) {
25294342306fSKonstantin Komarov 			ntfs_inode_err(
25304342306fSKonstantin Komarov 				&ni->vfs_inode,
25314342306fSKonstantin Komarov 				"external compressed file should contains data attribute \"WofCompressedData\"");
25324342306fSKonstantin Komarov 			err = -EINVAL;
25334342306fSKonstantin Komarov 			goto out1;
25344342306fSKonstantin Komarov 		}
25354342306fSKonstantin Komarov 
25364342306fSKonstantin Komarov 		if (!attr->non_res) {
25374342306fSKonstantin Komarov 			run = NULL;
25384342306fSKonstantin Komarov 		} else {
25394342306fSKonstantin Komarov 			run = run_alloc();
25404342306fSKonstantin Komarov 			if (!run) {
25414342306fSKonstantin Komarov 				err = -ENOMEM;
25424342306fSKonstantin Komarov 				goto out1;
25434342306fSKonstantin Komarov 			}
25444342306fSKonstantin Komarov 		}
25454342306fSKonstantin Komarov 
2546f4cf29c6SKonstantin Komarov 		frames = (i_size - 1) >> frame_bits;
25474342306fSKonstantin Komarov 
25484342306fSKonstantin Komarov 		err = attr_wof_frame_info(ni, attr, run, frame64, frames,
25494342306fSKonstantin Komarov 					  frame_bits, &ondisk_size, &vbo_data);
25504342306fSKonstantin Komarov 		if (err)
25514342306fSKonstantin Komarov 			goto out2;
25524342306fSKonstantin Komarov 
25534342306fSKonstantin Komarov 		if (frame64 == frames) {
2554f4cf29c6SKonstantin Komarov 			unc_size = 1 + ((i_size - 1) & (frame_size - 1));
25554342306fSKonstantin Komarov 			ondisk_size = attr_size(attr) - vbo_data;
25564342306fSKonstantin Komarov 		} else {
25574342306fSKonstantin Komarov 			unc_size = frame_size;
25584342306fSKonstantin Komarov 		}
25594342306fSKonstantin Komarov 
25604342306fSKonstantin Komarov 		if (ondisk_size > frame_size) {
25614342306fSKonstantin Komarov 			err = -EINVAL;
25624342306fSKonstantin Komarov 			goto out2;
25634342306fSKonstantin Komarov 		}
25644342306fSKonstantin Komarov 
25654342306fSKonstantin Komarov 		if (!attr->non_res) {
25664342306fSKonstantin Komarov 			if (vbo_data + ondisk_size >
25674342306fSKonstantin Komarov 			    le32_to_cpu(attr->res.data_size)) {
25684342306fSKonstantin Komarov 				err = -EINVAL;
25694342306fSKonstantin Komarov 				goto out1;
25704342306fSKonstantin Komarov 			}
25714342306fSKonstantin Komarov 
25724342306fSKonstantin Komarov 			err = decompress_lzx_xpress(
25734342306fSKonstantin Komarov 				sbi, Add2Ptr(resident_data(attr), vbo_data),
25744342306fSKonstantin Komarov 				ondisk_size, frame_mem, unc_size, frame_size);
25754342306fSKonstantin Komarov 			goto out1;
25764342306fSKonstantin Komarov 		}
25774342306fSKonstantin Komarov 		vbo_disk = vbo_data;
2578e8b8e97fSKari Argillander 		/* Load all runs to read [vbo_disk-vbo_to). */
25794342306fSKonstantin Komarov 		err = attr_load_runs_range(ni, ATTR_DATA, WOF_NAME,
25804342306fSKonstantin Komarov 					   ARRAY_SIZE(WOF_NAME), run, vbo_disk,
25814342306fSKonstantin Komarov 					   vbo_data + ondisk_size);
25824342306fSKonstantin Komarov 		if (err)
25834342306fSKonstantin Komarov 			goto out2;
25844342306fSKonstantin Komarov 		npages_disk = (ondisk_size + (vbo_disk & (PAGE_SIZE - 1)) +
25854342306fSKonstantin Komarov 			       PAGE_SIZE - 1) >>
25864342306fSKonstantin Komarov 			      PAGE_SHIFT;
25874342306fSKonstantin Komarov #endif
25884342306fSKonstantin Komarov 	} else if (is_attr_compressed(attr)) {
2589e8b8e97fSKari Argillander 		/* LZNT compression. */
25904342306fSKonstantin Komarov 		if (sbi->cluster_size > NTFS_LZNT_MAX_CLUSTER) {
25914342306fSKonstantin Komarov 			err = -EOPNOTSUPP;
25924342306fSKonstantin Komarov 			goto out1;
25934342306fSKonstantin Komarov 		}
25944342306fSKonstantin Komarov 
25954342306fSKonstantin Komarov 		if (attr->nres.c_unit != NTFS_LZNT_CUNIT) {
25964342306fSKonstantin Komarov 			err = -EOPNOTSUPP;
25974342306fSKonstantin Komarov 			goto out1;
25984342306fSKonstantin Komarov 		}
25994342306fSKonstantin Komarov 
26004342306fSKonstantin Komarov 		down_write(&ni->file.run_lock);
26014342306fSKonstantin Komarov 		run_truncate_around(run, le64_to_cpu(attr->nres.svcn));
26024342306fSKonstantin Komarov 		frame = frame_vbo >> (cluster_bits + NTFS_LZNT_CUNIT);
2603*c2556801SKonstantin Komarov 		err = attr_is_frame_compressed(ni, attr, frame, &clst_data,
2604*c2556801SKonstantin Komarov 					       run);
26054342306fSKonstantin Komarov 		up_write(&ni->file.run_lock);
26064342306fSKonstantin Komarov 		if (err)
26074342306fSKonstantin Komarov 			goto out1;
26084342306fSKonstantin Komarov 
26094342306fSKonstantin Komarov 		if (!clst_data) {
26104342306fSKonstantin Komarov 			memset(frame_mem, 0, frame_size);
26114342306fSKonstantin Komarov 			goto out1;
26124342306fSKonstantin Komarov 		}
26134342306fSKonstantin Komarov 
26144342306fSKonstantin Komarov 		frame_size = sbi->cluster_size << NTFS_LZNT_CUNIT;
26154342306fSKonstantin Komarov 		ondisk_size = clst_data << cluster_bits;
26164342306fSKonstantin Komarov 
26174342306fSKonstantin Komarov 		if (clst_data >= NTFS_LZNT_CLUSTERS) {
2618e8b8e97fSKari Argillander 			/* Frame is not compressed. */
26194342306fSKonstantin Komarov 			down_read(&ni->file.run_lock);
26204342306fSKonstantin Komarov 			err = ntfs_bio_pages(sbi, run, pages, pages_per_frame,
26214342306fSKonstantin Komarov 					     frame_vbo, ondisk_size,
26224342306fSKonstantin Komarov 					     REQ_OP_READ);
26234342306fSKonstantin Komarov 			up_read(&ni->file.run_lock);
26244342306fSKonstantin Komarov 			goto out1;
26254342306fSKonstantin Komarov 		}
26264342306fSKonstantin Komarov 		vbo_disk = frame_vbo;
26274342306fSKonstantin Komarov 		npages_disk = (ondisk_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
26284342306fSKonstantin Komarov 	} else {
26294342306fSKonstantin Komarov 		__builtin_unreachable();
26304342306fSKonstantin Komarov 		err = -EINVAL;
26314342306fSKonstantin Komarov 		goto out1;
26324342306fSKonstantin Komarov 	}
26334342306fSKonstantin Komarov 
2634195c52bdSKari Argillander 	pages_disk = kzalloc(npages_disk * sizeof(struct page *), GFP_NOFS);
26354342306fSKonstantin Komarov 	if (!pages_disk) {
26364342306fSKonstantin Komarov 		err = -ENOMEM;
26374342306fSKonstantin Komarov 		goto out2;
26384342306fSKonstantin Komarov 	}
26394342306fSKonstantin Komarov 
26404342306fSKonstantin Komarov 	for (i = 0; i < npages_disk; i++) {
26414342306fSKonstantin Komarov 		pg = alloc_page(GFP_KERNEL);
26424342306fSKonstantin Komarov 		if (!pg) {
26434342306fSKonstantin Komarov 			err = -ENOMEM;
26444342306fSKonstantin Komarov 			goto out3;
26454342306fSKonstantin Komarov 		}
26464342306fSKonstantin Komarov 		pages_disk[i] = pg;
26474342306fSKonstantin Komarov 		lock_page(pg);
26484342306fSKonstantin Komarov 		kmap(pg);
26494342306fSKonstantin Komarov 	}
26504342306fSKonstantin Komarov 
2651e8b8e97fSKari Argillander 	/* Read 'ondisk_size' bytes from disk. */
26524342306fSKonstantin Komarov 	down_read(&ni->file.run_lock);
26534342306fSKonstantin Komarov 	err = ntfs_bio_pages(sbi, run, pages_disk, npages_disk, vbo_disk,
26544342306fSKonstantin Komarov 			     ondisk_size, REQ_OP_READ);
26554342306fSKonstantin Komarov 	up_read(&ni->file.run_lock);
26564342306fSKonstantin Komarov 	if (err)
26574342306fSKonstantin Komarov 		goto out3;
26584342306fSKonstantin Komarov 
26594342306fSKonstantin Komarov 	/*
2660e8b8e97fSKari Argillander 	 * To simplify decompress algorithm do vmap for source and target pages.
26614342306fSKonstantin Komarov 	 */
26624342306fSKonstantin Komarov 	frame_ondisk = vmap(pages_disk, npages_disk, VM_MAP, PAGE_KERNEL_RO);
26634342306fSKonstantin Komarov 	if (!frame_ondisk) {
26644342306fSKonstantin Komarov 		err = -ENOMEM;
26654342306fSKonstantin Komarov 		goto out3;
26664342306fSKonstantin Komarov 	}
26674342306fSKonstantin Komarov 
2668e8b8e97fSKari Argillander 	/* Decompress: Frame_ondisk -> frame_mem. */
26694342306fSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
26704342306fSKonstantin Komarov 	if (run != &ni->file.run) {
26714342306fSKonstantin Komarov 		/* LZX or XPRESS */
26724342306fSKonstantin Komarov 		err = decompress_lzx_xpress(
26734342306fSKonstantin Komarov 			sbi, frame_ondisk + (vbo_disk & (PAGE_SIZE - 1)),
26744342306fSKonstantin Komarov 			ondisk_size, frame_mem, unc_size, frame_size);
26754342306fSKonstantin Komarov 	} else
26764342306fSKonstantin Komarov #endif
26774342306fSKonstantin Komarov 	{
2678e8b8e97fSKari Argillander 		/* LZNT - Native NTFS compression. */
26794342306fSKonstantin Komarov 		unc_size = decompress_lznt(frame_ondisk, ondisk_size, frame_mem,
26804342306fSKonstantin Komarov 					   frame_size);
26814342306fSKonstantin Komarov 		if ((ssize_t)unc_size < 0)
26824342306fSKonstantin Komarov 			err = unc_size;
26834342306fSKonstantin Komarov 		else if (!unc_size || unc_size > frame_size)
26844342306fSKonstantin Komarov 			err = -EINVAL;
26854342306fSKonstantin Komarov 	}
26864342306fSKonstantin Komarov 	if (!err && valid_size < frame_vbo + frame_size) {
26874342306fSKonstantin Komarov 		size_t ok = valid_size - frame_vbo;
26884342306fSKonstantin Komarov 
26894342306fSKonstantin Komarov 		memset(frame_mem + ok, 0, frame_size - ok);
26904342306fSKonstantin Komarov 	}
26914342306fSKonstantin Komarov 
26924342306fSKonstantin Komarov 	vunmap(frame_ondisk);
26934342306fSKonstantin Komarov 
26944342306fSKonstantin Komarov out3:
26954342306fSKonstantin Komarov 	for (i = 0; i < npages_disk; i++) {
26964342306fSKonstantin Komarov 		pg = pages_disk[i];
26974342306fSKonstantin Komarov 		if (pg) {
26984342306fSKonstantin Komarov 			kunmap(pg);
26994342306fSKonstantin Komarov 			unlock_page(pg);
27004342306fSKonstantin Komarov 			put_page(pg);
27014342306fSKonstantin Komarov 		}
27024342306fSKonstantin Komarov 	}
2703195c52bdSKari Argillander 	kfree(pages_disk);
27044342306fSKonstantin Komarov 
27054342306fSKonstantin Komarov out2:
27064342306fSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS
27074342306fSKonstantin Komarov 	if (run != &ni->file.run)
27084342306fSKonstantin Komarov 		run_free(run);
27094342306fSKonstantin Komarov #endif
27104342306fSKonstantin Komarov out1:
27114342306fSKonstantin Komarov 	vunmap(frame_mem);
27124342306fSKonstantin Komarov out:
27134342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++) {
27144342306fSKonstantin Komarov 		pg = pages[i];
27154342306fSKonstantin Komarov 		kunmap(pg);
27164342306fSKonstantin Komarov 		ClearPageError(pg);
27174342306fSKonstantin Komarov 		SetPageUptodate(pg);
27184342306fSKonstantin Komarov 	}
27194342306fSKonstantin Komarov 
27204342306fSKonstantin Komarov 	return err;
27214342306fSKonstantin Komarov }
27224342306fSKonstantin Komarov 
27234342306fSKonstantin Komarov /*
27244342306fSKonstantin Komarov  * ni_write_frame
27254342306fSKonstantin Komarov  *
2726e8b8e97fSKari Argillander  * Pages - Array of locked pages.
27274342306fSKonstantin Komarov  */
ni_write_frame(struct ntfs_inode * ni,struct page ** pages,u32 pages_per_frame)27284342306fSKonstantin Komarov int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
27294342306fSKonstantin Komarov 		   u32 pages_per_frame)
27304342306fSKonstantin Komarov {
27314342306fSKonstantin Komarov 	int err;
27324342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
27334342306fSKonstantin Komarov 	u8 frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits;
27344342306fSKonstantin Komarov 	u32 frame_size = sbi->cluster_size << NTFS_LZNT_CUNIT;
27354342306fSKonstantin Komarov 	u64 frame_vbo = (u64)pages[0]->index << PAGE_SHIFT;
27364342306fSKonstantin Komarov 	CLST frame = frame_vbo >> frame_bits;
27374342306fSKonstantin Komarov 	char *frame_ondisk = NULL;
27384342306fSKonstantin Komarov 	struct page **pages_disk = NULL;
27394342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le = NULL;
27404342306fSKonstantin Komarov 	char *frame_mem;
27414342306fSKonstantin Komarov 	struct ATTRIB *attr;
27424342306fSKonstantin Komarov 	struct mft_inode *mi;
27434342306fSKonstantin Komarov 	u32 i;
27444342306fSKonstantin Komarov 	struct page *pg;
27454342306fSKonstantin Komarov 	size_t compr_size, ondisk_size;
27464342306fSKonstantin Komarov 	struct lznt *lznt;
27474342306fSKonstantin Komarov 
27484342306fSKonstantin Komarov 	attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, &mi);
27494342306fSKonstantin Komarov 	if (!attr) {
27504342306fSKonstantin Komarov 		err = -ENOENT;
27514342306fSKonstantin Komarov 		goto out;
27524342306fSKonstantin Komarov 	}
27534342306fSKonstantin Komarov 
27544342306fSKonstantin Komarov 	if (WARN_ON(!is_attr_compressed(attr))) {
27554342306fSKonstantin Komarov 		err = -EINVAL;
27564342306fSKonstantin Komarov 		goto out;
27574342306fSKonstantin Komarov 	}
27584342306fSKonstantin Komarov 
27594342306fSKonstantin Komarov 	if (sbi->cluster_size > NTFS_LZNT_MAX_CLUSTER) {
27604342306fSKonstantin Komarov 		err = -EOPNOTSUPP;
27614342306fSKonstantin Komarov 		goto out;
27624342306fSKonstantin Komarov 	}
27634342306fSKonstantin Komarov 
27644342306fSKonstantin Komarov 	if (!attr->non_res) {
27654342306fSKonstantin Komarov 		down_write(&ni->file.run_lock);
27664342306fSKonstantin Komarov 		err = attr_make_nonresident(ni, attr, le, mi,
27674342306fSKonstantin Komarov 					    le32_to_cpu(attr->res.data_size),
27684342306fSKonstantin Komarov 					    &ni->file.run, &attr, pages[0]);
27694342306fSKonstantin Komarov 		up_write(&ni->file.run_lock);
27704342306fSKonstantin Komarov 		if (err)
27714342306fSKonstantin Komarov 			goto out;
27724342306fSKonstantin Komarov 	}
27734342306fSKonstantin Komarov 
27744342306fSKonstantin Komarov 	if (attr->nres.c_unit != NTFS_LZNT_CUNIT) {
27754342306fSKonstantin Komarov 		err = -EOPNOTSUPP;
27764342306fSKonstantin Komarov 		goto out;
27774342306fSKonstantin Komarov 	}
27784342306fSKonstantin Komarov 
2779345482bcSKari Argillander 	pages_disk = kcalloc(pages_per_frame, sizeof(struct page *), GFP_NOFS);
27804342306fSKonstantin Komarov 	if (!pages_disk) {
27814342306fSKonstantin Komarov 		err = -ENOMEM;
27824342306fSKonstantin Komarov 		goto out;
27834342306fSKonstantin Komarov 	}
27844342306fSKonstantin Komarov 
27854342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++) {
27864342306fSKonstantin Komarov 		pg = alloc_page(GFP_KERNEL);
27874342306fSKonstantin Komarov 		if (!pg) {
27884342306fSKonstantin Komarov 			err = -ENOMEM;
27894342306fSKonstantin Komarov 			goto out1;
27904342306fSKonstantin Komarov 		}
27914342306fSKonstantin Komarov 		pages_disk[i] = pg;
27924342306fSKonstantin Komarov 		lock_page(pg);
27934342306fSKonstantin Komarov 		kmap(pg);
27944342306fSKonstantin Komarov 	}
27954342306fSKonstantin Komarov 
2796e8b8e97fSKari Argillander 	/* To simplify compress algorithm do vmap for source and target pages. */
27974342306fSKonstantin Komarov 	frame_ondisk = vmap(pages_disk, pages_per_frame, VM_MAP, PAGE_KERNEL);
27984342306fSKonstantin Komarov 	if (!frame_ondisk) {
27994342306fSKonstantin Komarov 		err = -ENOMEM;
28004342306fSKonstantin Komarov 		goto out1;
28014342306fSKonstantin Komarov 	}
28024342306fSKonstantin Komarov 
28034342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++)
28044342306fSKonstantin Komarov 		kmap(pages[i]);
28054342306fSKonstantin Komarov 
2806e8b8e97fSKari Argillander 	/* Map in-memory frame for read-only. */
28074342306fSKonstantin Komarov 	frame_mem = vmap(pages, pages_per_frame, VM_MAP, PAGE_KERNEL_RO);
28084342306fSKonstantin Komarov 	if (!frame_mem) {
28094342306fSKonstantin Komarov 		err = -ENOMEM;
28104342306fSKonstantin Komarov 		goto out2;
28114342306fSKonstantin Komarov 	}
28124342306fSKonstantin Komarov 
28134342306fSKonstantin Komarov 	mutex_lock(&sbi->compress.mtx_lznt);
28144342306fSKonstantin Komarov 	lznt = NULL;
28154342306fSKonstantin Komarov 	if (!sbi->compress.lznt) {
28164342306fSKonstantin Komarov 		/*
2817e8b8e97fSKari Argillander 		 * LZNT implements two levels of compression:
2818e8b8e97fSKari Argillander 		 * 0 - Standard compression
2819e8b8e97fSKari Argillander 		 * 1 - Best compression, requires a lot of cpu
28204342306fSKonstantin Komarov 		 * use mount option?
28214342306fSKonstantin Komarov 		 */
28224342306fSKonstantin Komarov 		lznt = get_lznt_ctx(0);
28234342306fSKonstantin Komarov 		if (!lznt) {
28244342306fSKonstantin Komarov 			mutex_unlock(&sbi->compress.mtx_lznt);
28254342306fSKonstantin Komarov 			err = -ENOMEM;
28264342306fSKonstantin Komarov 			goto out3;
28274342306fSKonstantin Komarov 		}
28284342306fSKonstantin Komarov 
28294342306fSKonstantin Komarov 		sbi->compress.lznt = lznt;
28304342306fSKonstantin Komarov 		lznt = NULL;
28314342306fSKonstantin Komarov 	}
28324342306fSKonstantin Komarov 
2833d3624466SKonstantin Komarov 	/* Compress: frame_mem -> frame_ondisk */
28344342306fSKonstantin Komarov 	compr_size = compress_lznt(frame_mem, frame_size, frame_ondisk,
28354342306fSKonstantin Komarov 				   frame_size, sbi->compress.lznt);
28364342306fSKonstantin Komarov 	mutex_unlock(&sbi->compress.mtx_lznt);
2837195c52bdSKari Argillander 	kfree(lznt);
28384342306fSKonstantin Komarov 
28394342306fSKonstantin Komarov 	if (compr_size + sbi->cluster_size > frame_size) {
2840e8b8e97fSKari Argillander 		/* Frame is not compressed. */
28414342306fSKonstantin Komarov 		compr_size = frame_size;
28424342306fSKonstantin Komarov 		ondisk_size = frame_size;
28434342306fSKonstantin Komarov 	} else if (compr_size) {
2844e8b8e97fSKari Argillander 		/* Frame is compressed. */
28454342306fSKonstantin Komarov 		ondisk_size = ntfs_up_cluster(sbi, compr_size);
28464342306fSKonstantin Komarov 		memset(frame_ondisk + compr_size, 0, ondisk_size - compr_size);
28474342306fSKonstantin Komarov 	} else {
2848e8b8e97fSKari Argillander 		/* Frame is sparsed. */
28494342306fSKonstantin Komarov 		ondisk_size = 0;
28504342306fSKonstantin Komarov 	}
28514342306fSKonstantin Komarov 
28524342306fSKonstantin Komarov 	down_write(&ni->file.run_lock);
28534342306fSKonstantin Komarov 	run_truncate_around(&ni->file.run, le64_to_cpu(attr->nres.svcn));
28544342306fSKonstantin Komarov 	err = attr_allocate_frame(ni, frame, compr_size, ni->i_valid);
28554342306fSKonstantin Komarov 	up_write(&ni->file.run_lock);
28564342306fSKonstantin Komarov 	if (err)
28574342306fSKonstantin Komarov 		goto out2;
28584342306fSKonstantin Komarov 
28594342306fSKonstantin Komarov 	if (!ondisk_size)
28604342306fSKonstantin Komarov 		goto out2;
28614342306fSKonstantin Komarov 
28624342306fSKonstantin Komarov 	down_read(&ni->file.run_lock);
28634342306fSKonstantin Komarov 	err = ntfs_bio_pages(sbi, &ni->file.run,
28644342306fSKonstantin Komarov 			     ondisk_size < frame_size ? pages_disk : pages,
28654342306fSKonstantin Komarov 			     pages_per_frame, frame_vbo, ondisk_size,
28664342306fSKonstantin Komarov 			     REQ_OP_WRITE);
28674342306fSKonstantin Komarov 	up_read(&ni->file.run_lock);
28684342306fSKonstantin Komarov 
28694342306fSKonstantin Komarov out3:
28704342306fSKonstantin Komarov 	vunmap(frame_mem);
28714342306fSKonstantin Komarov 
28724342306fSKonstantin Komarov out2:
28734342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++)
28744342306fSKonstantin Komarov 		kunmap(pages[i]);
28754342306fSKonstantin Komarov 
28764342306fSKonstantin Komarov 	vunmap(frame_ondisk);
28774342306fSKonstantin Komarov out1:
28784342306fSKonstantin Komarov 	for (i = 0; i < pages_per_frame; i++) {
28794342306fSKonstantin Komarov 		pg = pages_disk[i];
28804342306fSKonstantin Komarov 		if (pg) {
28814342306fSKonstantin Komarov 			kunmap(pg);
28824342306fSKonstantin Komarov 			unlock_page(pg);
28834342306fSKonstantin Komarov 			put_page(pg);
28844342306fSKonstantin Komarov 		}
28854342306fSKonstantin Komarov 	}
2886195c52bdSKari Argillander 	kfree(pages_disk);
28874342306fSKonstantin Komarov out:
28884342306fSKonstantin Komarov 	return err;
28894342306fSKonstantin Komarov }
28904342306fSKonstantin Komarov 
28914342306fSKonstantin Komarov /*
289278ab59feSKonstantin Komarov  * ni_remove_name - Removes name 'de' from MFT and from directory.
289378ab59feSKonstantin Komarov  * 'de2' and 'undo_step' are used to restore MFT/dir, if error occurs.
289478ab59feSKonstantin Komarov  */
ni_remove_name(struct ntfs_inode * dir_ni,struct ntfs_inode * ni,struct NTFS_DE * de,struct NTFS_DE ** de2,int * undo_step)289578ab59feSKonstantin Komarov int ni_remove_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
289678ab59feSKonstantin Komarov 		   struct NTFS_DE *de, struct NTFS_DE **de2, int *undo_step)
289778ab59feSKonstantin Komarov {
289878ab59feSKonstantin Komarov 	int err;
289978ab59feSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
290078ab59feSKonstantin Komarov 	struct ATTR_FILE_NAME *de_name = (struct ATTR_FILE_NAME *)(de + 1);
290178ab59feSKonstantin Komarov 	struct ATTR_FILE_NAME *fname;
290278ab59feSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
290378ab59feSKonstantin Komarov 	struct mft_inode *mi;
290478ab59feSKonstantin Komarov 	u16 de_key_size = le16_to_cpu(de->key_size);
290578ab59feSKonstantin Komarov 	u8 name_type;
290678ab59feSKonstantin Komarov 
290778ab59feSKonstantin Komarov 	*undo_step = 0;
290878ab59feSKonstantin Komarov 
290978ab59feSKonstantin Komarov 	/* Find name in record. */
291078ab59feSKonstantin Komarov 	mi_get_ref(&dir_ni->mi, &de_name->home);
291178ab59feSKonstantin Komarov 
2912d5ca7733SKonstantin Komarov 	fname = ni_fname_name(ni, (struct le_str *)&de_name->name_len,
291378ab59feSKonstantin Komarov 			      &de_name->home, &mi, &le);
291478ab59feSKonstantin Komarov 	if (!fname)
291578ab59feSKonstantin Komarov 		return -ENOENT;
291678ab59feSKonstantin Komarov 
291778ab59feSKonstantin Komarov 	memcpy(&de_name->dup, &fname->dup, sizeof(struct NTFS_DUP_INFO));
291878ab59feSKonstantin Komarov 	name_type = paired_name(fname->type);
291978ab59feSKonstantin Komarov 
292078ab59feSKonstantin Komarov 	/* Mark ntfs as dirty. It will be cleared at umount. */
292178ab59feSKonstantin Komarov 	ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
292278ab59feSKonstantin Komarov 
292378ab59feSKonstantin Komarov 	/* Step 1: Remove name from directory. */
292478ab59feSKonstantin Komarov 	err = indx_delete_entry(&dir_ni->dir, dir_ni, fname, de_key_size, sbi);
292578ab59feSKonstantin Komarov 	if (err)
292678ab59feSKonstantin Komarov 		return err;
292778ab59feSKonstantin Komarov 
292878ab59feSKonstantin Komarov 	/* Step 2: Remove name from MFT. */
292978ab59feSKonstantin Komarov 	ni_remove_attr_le(ni, attr_from_name(fname), mi, le);
293078ab59feSKonstantin Komarov 
293178ab59feSKonstantin Komarov 	*undo_step = 2;
293278ab59feSKonstantin Komarov 
293378ab59feSKonstantin Komarov 	/* Get paired name. */
293478ab59feSKonstantin Komarov 	fname = ni_fname_type(ni, name_type, &mi, &le);
293578ab59feSKonstantin Komarov 	if (fname) {
293678ab59feSKonstantin Komarov 		u16 de2_key_size = fname_full_size(fname);
293778ab59feSKonstantin Komarov 
293878ab59feSKonstantin Komarov 		*de2 = Add2Ptr(de, 1024);
293978ab59feSKonstantin Komarov 		(*de2)->key_size = cpu_to_le16(de2_key_size);
294078ab59feSKonstantin Komarov 
294178ab59feSKonstantin Komarov 		memcpy(*de2 + 1, fname, de2_key_size);
294278ab59feSKonstantin Komarov 
294378ab59feSKonstantin Komarov 		/* Step 3: Remove paired name from directory. */
294478ab59feSKonstantin Komarov 		err = indx_delete_entry(&dir_ni->dir, dir_ni, fname,
294578ab59feSKonstantin Komarov 					de2_key_size, sbi);
294678ab59feSKonstantin Komarov 		if (err)
294778ab59feSKonstantin Komarov 			return err;
294878ab59feSKonstantin Komarov 
294978ab59feSKonstantin Komarov 		/* Step 4: Remove paired name from MFT. */
295078ab59feSKonstantin Komarov 		ni_remove_attr_le(ni, attr_from_name(fname), mi, le);
295178ab59feSKonstantin Komarov 
295278ab59feSKonstantin Komarov 		*undo_step = 4;
295378ab59feSKonstantin Komarov 	}
295478ab59feSKonstantin Komarov 	return 0;
295578ab59feSKonstantin Komarov }
295678ab59feSKonstantin Komarov 
295778ab59feSKonstantin Komarov /*
295878ab59feSKonstantin Komarov  * ni_remove_name_undo - Paired function for ni_remove_name.
295978ab59feSKonstantin Komarov  *
296078ab59feSKonstantin Komarov  * Return: True if ok
296178ab59feSKonstantin Komarov  */
ni_remove_name_undo(struct ntfs_inode * dir_ni,struct ntfs_inode * ni,struct NTFS_DE * de,struct NTFS_DE * de2,int undo_step)296278ab59feSKonstantin Komarov bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
296378ab59feSKonstantin Komarov 			 struct NTFS_DE *de, struct NTFS_DE *de2, int undo_step)
296478ab59feSKonstantin Komarov {
296578ab59feSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
296678ab59feSKonstantin Komarov 	struct ATTRIB *attr;
296796de65a9SKonstantin Komarov 	u16 de_key_size;
296878ab59feSKonstantin Komarov 
296978ab59feSKonstantin Komarov 	switch (undo_step) {
297078ab59feSKonstantin Komarov 	case 4:
297196de65a9SKonstantin Komarov 		de_key_size = le16_to_cpu(de2->key_size);
297278ab59feSKonstantin Komarov 		if (ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0,
297396de65a9SKonstantin Komarov 				       &attr, NULL, NULL))
297478ab59feSKonstantin Komarov 			return false;
297578ab59feSKonstantin Komarov 		memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de2 + 1, de_key_size);
297678ab59feSKonstantin Komarov 
297778ab59feSKonstantin Komarov 		mi_get_ref(&ni->mi, &de2->ref);
297878ab59feSKonstantin Komarov 		de2->size = cpu_to_le16(ALIGN(de_key_size, 8) +
297978ab59feSKonstantin Komarov 					sizeof(struct NTFS_DE));
298078ab59feSKonstantin Komarov 		de2->flags = 0;
298178ab59feSKonstantin Komarov 		de2->res = 0;
298278ab59feSKonstantin Komarov 
298396de65a9SKonstantin Komarov 		if (indx_insert_entry(&dir_ni->dir, dir_ni, de2, sbi, NULL, 1))
298478ab59feSKonstantin Komarov 			return false;
298578ab59feSKonstantin Komarov 		fallthrough;
298678ab59feSKonstantin Komarov 
298778ab59feSKonstantin Komarov 	case 2:
298878ab59feSKonstantin Komarov 		de_key_size = le16_to_cpu(de->key_size);
298978ab59feSKonstantin Komarov 
299078ab59feSKonstantin Komarov 		if (ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0,
299196de65a9SKonstantin Komarov 				       &attr, NULL, NULL))
299278ab59feSKonstantin Komarov 			return false;
299378ab59feSKonstantin Komarov 
299478ab59feSKonstantin Komarov 		memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de + 1, de_key_size);
299578ab59feSKonstantin Komarov 		mi_get_ref(&ni->mi, &de->ref);
299678ab59feSKonstantin Komarov 
29972829e39eSKari Argillander 		if (indx_insert_entry(&dir_ni->dir, dir_ni, de, sbi, NULL, 1))
299878ab59feSKonstantin Komarov 			return false;
299978ab59feSKonstantin Komarov 	}
300078ab59feSKonstantin Komarov 
300178ab59feSKonstantin Komarov 	return true;
300278ab59feSKonstantin Komarov }
300378ab59feSKonstantin Komarov 
300478ab59feSKonstantin Komarov /*
300542f66a7fSKonstantin Komarov  * ni_add_name - Add new name into MFT and into directory.
300678ab59feSKonstantin Komarov  */
ni_add_name(struct ntfs_inode * dir_ni,struct ntfs_inode * ni,struct NTFS_DE * de)300778ab59feSKonstantin Komarov int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
300878ab59feSKonstantin Komarov 		struct NTFS_DE *de)
300978ab59feSKonstantin Komarov {
301078ab59feSKonstantin Komarov 	int err;
30111d07a9dfSDaniel Pinto 	struct ntfs_sb_info *sbi = ni->mi.sbi;
301278ab59feSKonstantin Komarov 	struct ATTRIB *attr;
301378ab59feSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le;
301478ab59feSKonstantin Komarov 	struct mft_inode *mi;
301542f66a7fSKonstantin Komarov 	struct ATTR_FILE_NAME *fname;
301678ab59feSKonstantin Komarov 	struct ATTR_FILE_NAME *de_name = (struct ATTR_FILE_NAME *)(de + 1);
301778ab59feSKonstantin Komarov 	u16 de_key_size = le16_to_cpu(de->key_size);
301878ab59feSKonstantin Komarov 
30191d07a9dfSDaniel Pinto 	if (sbi->options->windows_names &&
30201d07a9dfSDaniel Pinto 	    !valid_windows_name(sbi, (struct le_str *)&de_name->name_len))
30211d07a9dfSDaniel Pinto 		return -EINVAL;
30221d07a9dfSDaniel Pinto 
3023dc0fcc99SDaniel Pinto 	/* If option "hide_dot_files" then set hidden attribute for dot files. */
302466223324SDaniel Pinto 	if (ni->mi.sbi->options->hide_dot_files) {
302566223324SDaniel Pinto 		if (de_name->name_len > 0 &&
302666223324SDaniel Pinto 		    le16_to_cpu(de_name->name[0]) == '.')
302766223324SDaniel Pinto 			ni->std_fa |= FILE_ATTRIBUTE_HIDDEN;
302866223324SDaniel Pinto 		else
302966223324SDaniel Pinto 			ni->std_fa &= ~FILE_ATTRIBUTE_HIDDEN;
303066223324SDaniel Pinto 	}
303166223324SDaniel Pinto 
303278ab59feSKonstantin Komarov 	mi_get_ref(&ni->mi, &de->ref);
303378ab59feSKonstantin Komarov 	mi_get_ref(&dir_ni->mi, &de_name->home);
303478ab59feSKonstantin Komarov 
303542f66a7fSKonstantin Komarov 	/* Fill duplicate from any ATTR_NAME. */
303642f66a7fSKonstantin Komarov 	fname = ni_fname_name(ni, NULL, NULL, NULL, NULL);
303742f66a7fSKonstantin Komarov 	if (fname)
303842f66a7fSKonstantin Komarov 		memcpy(&de_name->dup, &fname->dup, sizeof(fname->dup));
303942f66a7fSKonstantin Komarov 	de_name->dup.fa = ni->std_fa;
304042f66a7fSKonstantin Komarov 
304142f66a7fSKonstantin Komarov 	/* Insert new name into MFT. */
304278ab59feSKonstantin Komarov 	err = ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0, &attr,
304378ab59feSKonstantin Komarov 				 &mi, &le);
304478ab59feSKonstantin Komarov 	if (err)
304578ab59feSKonstantin Komarov 		return err;
304678ab59feSKonstantin Komarov 
304778ab59feSKonstantin Komarov 	memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de_name, de_key_size);
304878ab59feSKonstantin Komarov 
304942f66a7fSKonstantin Komarov 	/* Insert new name into directory. */
30501d07a9dfSDaniel Pinto 	err = indx_insert_entry(&dir_ni->dir, dir_ni, de, sbi, NULL, 0);
305178ab59feSKonstantin Komarov 	if (err)
305278ab59feSKonstantin Komarov 		ni_remove_attr_le(ni, attr, mi, le);
305378ab59feSKonstantin Komarov 
305478ab59feSKonstantin Komarov 	return err;
305578ab59feSKonstantin Komarov }
305678ab59feSKonstantin Komarov 
305778ab59feSKonstantin Komarov /*
305878ab59feSKonstantin Komarov  * ni_rename - Remove one name and insert new name.
305978ab59feSKonstantin Komarov  */
ni_rename(struct ntfs_inode * dir_ni,struct ntfs_inode * new_dir_ni,struct ntfs_inode * ni,struct NTFS_DE * de,struct NTFS_DE * new_de,bool * is_bad)306078ab59feSKonstantin Komarov int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
306178ab59feSKonstantin Komarov 	      struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
306278ab59feSKonstantin Komarov 	      bool *is_bad)
306378ab59feSKonstantin Komarov {
306478ab59feSKonstantin Komarov 	int err;
306578ab59feSKonstantin Komarov 	struct NTFS_DE *de2 = NULL;
306678ab59feSKonstantin Komarov 	int undo = 0;
306778ab59feSKonstantin Komarov 
306878ab59feSKonstantin Komarov 	/*
306978ab59feSKonstantin Komarov 	 * There are two possible ways to rename:
307078ab59feSKonstantin Komarov 	 * 1) Add new name and remove old name.
307178ab59feSKonstantin Komarov 	 * 2) Remove old name and add new name.
307278ab59feSKonstantin Komarov 	 *
307342f66a7fSKonstantin Komarov 	 * In most cases (not all!) adding new name into MFT and into directory can
307478ab59feSKonstantin Komarov 	 * allocate additional cluster(s).
307578ab59feSKonstantin Komarov 	 * Second way may result to bad inode if we can't add new name
307678ab59feSKonstantin Komarov 	 * and then can't restore (add) old name.
307778ab59feSKonstantin Komarov 	 */
307878ab59feSKonstantin Komarov 
307978ab59feSKonstantin Komarov 	/*
308078ab59feSKonstantin Komarov 	 * Way 1 - Add new + remove old.
308178ab59feSKonstantin Komarov 	 */
308278ab59feSKonstantin Komarov 	err = ni_add_name(new_dir_ni, ni, new_de);
308378ab59feSKonstantin Komarov 	if (!err) {
308478ab59feSKonstantin Komarov 		err = ni_remove_name(dir_ni, ni, de, &de2, &undo);
308578ab59feSKonstantin Komarov 		if (err && ni_remove_name(new_dir_ni, ni, new_de, &de2, &undo))
308678ab59feSKonstantin Komarov 			*is_bad = true;
308778ab59feSKonstantin Komarov 	}
308878ab59feSKonstantin Komarov 
308978ab59feSKonstantin Komarov 	/*
309078ab59feSKonstantin Komarov 	 * Way 2 - Remove old + add new.
309178ab59feSKonstantin Komarov 	 */
309278ab59feSKonstantin Komarov 	/*
309378ab59feSKonstantin Komarov 	 *	err = ni_remove_name(dir_ni, ni, de, &de2, &undo);
309478ab59feSKonstantin Komarov 	 *	if (!err) {
309578ab59feSKonstantin Komarov 	 *		err = ni_add_name(new_dir_ni, ni, new_de);
309678ab59feSKonstantin Komarov 	 *		if (err && !ni_remove_name_undo(dir_ni, ni, de, de2, undo))
309778ab59feSKonstantin Komarov 	 *			*is_bad = true;
309878ab59feSKonstantin Komarov 	 *	}
309978ab59feSKonstantin Komarov 	 */
310078ab59feSKonstantin Komarov 
310178ab59feSKonstantin Komarov 	return err;
310278ab59feSKonstantin Komarov }
310378ab59feSKonstantin Komarov 
310478ab59feSKonstantin Komarov /*
310578ab59feSKonstantin Komarov  * ni_is_dirty - Return: True if 'ni' requires ni_write_inode.
310678ab59feSKonstantin Komarov  */
ni_is_dirty(struct inode * inode)310778ab59feSKonstantin Komarov bool ni_is_dirty(struct inode *inode)
310878ab59feSKonstantin Komarov {
310978ab59feSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(inode);
311078ab59feSKonstantin Komarov 	struct rb_node *node;
311178ab59feSKonstantin Komarov 
311278ab59feSKonstantin Komarov 	if (ni->mi.dirty || ni->attr_list.dirty ||
311378ab59feSKonstantin Komarov 	    (ni->ni_flags & NI_FLAG_UPDATE_PARENT))
311478ab59feSKonstantin Komarov 		return true;
311578ab59feSKonstantin Komarov 
311678ab59feSKonstantin Komarov 	for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
311778ab59feSKonstantin Komarov 		if (rb_entry(node, struct mft_inode, node)->dirty)
311878ab59feSKonstantin Komarov 			return true;
311978ab59feSKonstantin Komarov 	}
312078ab59feSKonstantin Komarov 
312178ab59feSKonstantin Komarov 	return false;
312278ab59feSKonstantin Komarov }
312378ab59feSKonstantin Komarov 
312478ab59feSKonstantin Komarov /*
3125e8b8e97fSKari Argillander  * ni_update_parent
3126e8b8e97fSKari Argillander  *
3127e8b8e97fSKari Argillander  * Update duplicate info of ATTR_FILE_NAME in MFT and in parent directories.
31284342306fSKonstantin Komarov  */
ni_update_parent(struct ntfs_inode * ni,struct NTFS_DUP_INFO * dup,int sync)31294342306fSKonstantin Komarov static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup,
31304342306fSKonstantin Komarov 			     int sync)
31314342306fSKonstantin Komarov {
31324342306fSKonstantin Komarov 	struct ATTRIB *attr;
31334342306fSKonstantin Komarov 	struct mft_inode *mi;
31344342306fSKonstantin Komarov 	struct ATTR_LIST_ENTRY *le = NULL;
31354342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = ni->mi.sbi;
31364342306fSKonstantin Komarov 	struct super_block *sb = sbi->sb;
31374342306fSKonstantin Komarov 	bool re_dirty = false;
31384342306fSKonstantin Komarov 
31394342306fSKonstantin Komarov 	if (ni->mi.mrec->flags & RECORD_FLAG_DIR) {
31404342306fSKonstantin Komarov 		dup->fa |= FILE_ATTRIBUTE_DIRECTORY;
31414342306fSKonstantin Komarov 		attr = NULL;
31424342306fSKonstantin Komarov 		dup->alloc_size = 0;
31434342306fSKonstantin Komarov 		dup->data_size = 0;
31444342306fSKonstantin Komarov 	} else {
31454342306fSKonstantin Komarov 		dup->fa &= ~FILE_ATTRIBUTE_DIRECTORY;
31464342306fSKonstantin Komarov 
31474342306fSKonstantin Komarov 		attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL,
31484342306fSKonstantin Komarov 				    &mi);
31494342306fSKonstantin Komarov 		if (!attr) {
31504342306fSKonstantin Komarov 			dup->alloc_size = dup->data_size = 0;
31514342306fSKonstantin Komarov 		} else if (!attr->non_res) {
31524342306fSKonstantin Komarov 			u32 data_size = le32_to_cpu(attr->res.data_size);
31534342306fSKonstantin Komarov 
3154fa3cacf5SKari Argillander 			dup->alloc_size = cpu_to_le64(ALIGN(data_size, 8));
31554342306fSKonstantin Komarov 			dup->data_size = cpu_to_le64(data_size);
31564342306fSKonstantin Komarov 		} else {
31574342306fSKonstantin Komarov 			u64 new_valid = ni->i_valid;
31584342306fSKonstantin Komarov 			u64 data_size = le64_to_cpu(attr->nres.data_size);
31594342306fSKonstantin Komarov 			__le64 valid_le;
31604342306fSKonstantin Komarov 
316196de65a9SKonstantin Komarov 			dup->alloc_size = is_attr_ext(attr) ?
316296de65a9SKonstantin Komarov 						  attr->nres.total_size :
316396de65a9SKonstantin Komarov 						  attr->nres.alloc_size;
31644342306fSKonstantin Komarov 			dup->data_size = attr->nres.data_size;
31654342306fSKonstantin Komarov 
31664342306fSKonstantin Komarov 			if (new_valid > data_size)
31674342306fSKonstantin Komarov 				new_valid = data_size;
31684342306fSKonstantin Komarov 
31694342306fSKonstantin Komarov 			valid_le = cpu_to_le64(new_valid);
31704342306fSKonstantin Komarov 			if (valid_le != attr->nres.valid_size) {
31714342306fSKonstantin Komarov 				attr->nres.valid_size = valid_le;
31724342306fSKonstantin Komarov 				mi->dirty = true;
31734342306fSKonstantin Komarov 			}
31744342306fSKonstantin Komarov 		}
31754342306fSKonstantin Komarov 	}
31764342306fSKonstantin Komarov 
3177e8b8e97fSKari Argillander 	/* TODO: Fill reparse info. */
31784342306fSKonstantin Komarov 	dup->reparse = 0;
31794342306fSKonstantin Komarov 	dup->ea_size = 0;
31804342306fSKonstantin Komarov 
31814342306fSKonstantin Komarov 	if (ni->ni_flags & NI_FLAG_EA) {
31824342306fSKonstantin Komarov 		attr = ni_find_attr(ni, attr, &le, ATTR_EA_INFO, NULL, 0, NULL,
31834342306fSKonstantin Komarov 				    NULL);
31844342306fSKonstantin Komarov 		if (attr) {
31854342306fSKonstantin Komarov 			const struct EA_INFO *info;
31864342306fSKonstantin Komarov 
31874342306fSKonstantin Komarov 			info = resident_data_ex(attr, sizeof(struct EA_INFO));
318835afb70dSKonstantin Komarov 			/* If ATTR_EA_INFO exists 'info' can't be NULL. */
318935afb70dSKonstantin Komarov 			if (info)
31904342306fSKonstantin Komarov 				dup->ea_size = info->size_pack;
31914342306fSKonstantin Komarov 		}
31924342306fSKonstantin Komarov 	}
31934342306fSKonstantin Komarov 
31944342306fSKonstantin Komarov 	attr = NULL;
31954342306fSKonstantin Komarov 	le = NULL;
31964342306fSKonstantin Komarov 
31974342306fSKonstantin Komarov 	while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
31984342306fSKonstantin Komarov 				    &mi))) {
31994342306fSKonstantin Komarov 		struct inode *dir;
32004342306fSKonstantin Komarov 		struct ATTR_FILE_NAME *fname;
32014342306fSKonstantin Komarov 
32024342306fSKonstantin Komarov 		fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
320378ab59feSKonstantin Komarov 		if (!fname || !memcmp(&fname->dup, dup, sizeof(fname->dup)))
32044342306fSKonstantin Komarov 			continue;
32054342306fSKonstantin Komarov 
320687d1888aSKonstantin Komarov 		/* Check simple case when parent inode equals current inode. */
320787d1888aSKonstantin Komarov 		if (ino_get(&fname->home) == ni->vfs_inode.i_ino) {
320887d1888aSKonstantin Komarov 			ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
320987d1888aSKonstantin Komarov 			continue;
321087d1888aSKonstantin Komarov 		}
321187d1888aSKonstantin Komarov 
3212e8b8e97fSKari Argillander 		/* ntfs_iget5 may sleep. */
32134342306fSKonstantin Komarov 		dir = ntfs_iget5(sb, &fname->home, NULL);
32144342306fSKonstantin Komarov 		if (IS_ERR(dir)) {
32154342306fSKonstantin Komarov 			ntfs_inode_warn(
32164342306fSKonstantin Komarov 				&ni->vfs_inode,
32174342306fSKonstantin Komarov 				"failed to open parent directory r=%lx to update",
32184342306fSKonstantin Komarov 				(long)ino_get(&fname->home));
32194342306fSKonstantin Komarov 			continue;
32204342306fSKonstantin Komarov 		}
32214342306fSKonstantin Komarov 
32224342306fSKonstantin Komarov 		if (!is_bad_inode(dir)) {
32234342306fSKonstantin Komarov 			struct ntfs_inode *dir_ni = ntfs_i(dir);
32244342306fSKonstantin Komarov 
32254342306fSKonstantin Komarov 			if (!ni_trylock(dir_ni)) {
32264342306fSKonstantin Komarov 				re_dirty = true;
32274342306fSKonstantin Komarov 			} else {
32284342306fSKonstantin Komarov 				indx_update_dup(dir_ni, sbi, fname, dup, sync);
32294342306fSKonstantin Komarov 				ni_unlock(dir_ni);
323078ab59feSKonstantin Komarov 				memcpy(&fname->dup, dup, sizeof(fname->dup));
323178ab59feSKonstantin Komarov 				mi->dirty = true;
32324342306fSKonstantin Komarov 			}
32334342306fSKonstantin Komarov 		}
32344342306fSKonstantin Komarov 		iput(dir);
32354342306fSKonstantin Komarov 	}
32364342306fSKonstantin Komarov 
32374342306fSKonstantin Komarov 	return re_dirty;
32384342306fSKonstantin Komarov }
32394342306fSKonstantin Komarov 
32404342306fSKonstantin Komarov /*
3241e8b8e97fSKari Argillander  * ni_write_inode - Write MFT base record and all subrecords to disk.
32424342306fSKonstantin Komarov  */
ni_write_inode(struct inode * inode,int sync,const char * hint)32434342306fSKonstantin Komarov int ni_write_inode(struct inode *inode, int sync, const char *hint)
32444342306fSKonstantin Komarov {
32454342306fSKonstantin Komarov 	int err = 0, err2;
32464342306fSKonstantin Komarov 	struct ntfs_inode *ni = ntfs_i(inode);
32474342306fSKonstantin Komarov 	struct super_block *sb = inode->i_sb;
32484342306fSKonstantin Komarov 	struct ntfs_sb_info *sbi = sb->s_fs_info;
32494342306fSKonstantin Komarov 	bool re_dirty = false;
32504342306fSKonstantin Komarov 	struct ATTR_STD_INFO *std;
32514342306fSKonstantin Komarov 	struct rb_node *node, *next;
32524342306fSKonstantin Komarov 	struct NTFS_DUP_INFO dup;
32534342306fSKonstantin Komarov 
32544342306fSKonstantin Komarov 	if (is_bad_inode(inode) || sb_rdonly(sb))
32554342306fSKonstantin Komarov 		return 0;
32564342306fSKonstantin Komarov 
3257f73f9397SKonstantin Komarov 	if (unlikely(ntfs3_forced_shutdown(sb)))
3258f73f9397SKonstantin Komarov 		return -EIO;
3259f73f9397SKonstantin Komarov 
32604342306fSKonstantin Komarov 	if (!ni_trylock(ni)) {
3261e8b8e97fSKari Argillander 		/* 'ni' is under modification, skip for now. */
32624342306fSKonstantin Komarov 		mark_inode_dirty_sync(inode);
32634342306fSKonstantin Komarov 		return 0;
32644342306fSKonstantin Komarov 	}
32654342306fSKonstantin Komarov 
32668dae4f63SAbdun Nihaal 	if (!ni->mi.mrec)
32678dae4f63SAbdun Nihaal 		goto out;
32688dae4f63SAbdun Nihaal 
32694342306fSKonstantin Komarov 	if (is_rec_inuse(ni->mi.mrec) &&
32704342306fSKonstantin Komarov 	    !(sbi->flags & NTFS_FLAGS_LOG_REPLAYING) && inode->i_nlink) {
32714342306fSKonstantin Komarov 		bool modified = false;
32723d65c46fSJeff Layton 		struct timespec64 ctime = inode_get_ctime(inode);
32734342306fSKonstantin Komarov 
3274e8b8e97fSKari Argillander 		/* Update times in standard attribute. */
32754342306fSKonstantin Komarov 		std = ni_std(ni);
32764342306fSKonstantin Komarov 		if (!std) {
32774342306fSKonstantin Komarov 			err = -EINVAL;
32784342306fSKonstantin Komarov 			goto out;
32794342306fSKonstantin Komarov 		}
32804342306fSKonstantin Komarov 
32814342306fSKonstantin Komarov 		/* Update the access times if they have changed. */
32824342306fSKonstantin Komarov 		dup.m_time = kernel2nt(&inode->i_mtime);
32834342306fSKonstantin Komarov 		if (std->m_time != dup.m_time) {
32844342306fSKonstantin Komarov 			std->m_time = dup.m_time;
32854342306fSKonstantin Komarov 			modified = true;
32864342306fSKonstantin Komarov 		}
32874342306fSKonstantin Komarov 
32883d65c46fSJeff Layton 		dup.c_time = kernel2nt(&ctime);
32894342306fSKonstantin Komarov 		if (std->c_time != dup.c_time) {
32904342306fSKonstantin Komarov 			std->c_time = dup.c_time;
32914342306fSKonstantin Komarov 			modified = true;
32924342306fSKonstantin Komarov 		}
32934342306fSKonstantin Komarov 
32944342306fSKonstantin Komarov 		dup.a_time = kernel2nt(&inode->i_atime);
32954342306fSKonstantin Komarov 		if (std->a_time != dup.a_time) {
32964342306fSKonstantin Komarov 			std->a_time = dup.a_time;
32974342306fSKonstantin Komarov 			modified = true;
32984342306fSKonstantin Komarov 		}
32994342306fSKonstantin Komarov 
33004342306fSKonstantin Komarov 		dup.fa = ni->std_fa;
33014342306fSKonstantin Komarov 		if (std->fa != dup.fa) {
33024342306fSKonstantin Komarov 			std->fa = dup.fa;
33034342306fSKonstantin Komarov 			modified = true;
33044342306fSKonstantin Komarov 		}
33054342306fSKonstantin Komarov 
330643f03acbSKonstantin Komarov 		/* std attribute is always in primary MFT record. */
33074342306fSKonstantin Komarov 		if (modified)
33084342306fSKonstantin Komarov 			ni->mi.dirty = true;
33094342306fSKonstantin Komarov 
33104342306fSKonstantin Komarov 		if (!ntfs_is_meta_file(sbi, inode->i_ino) &&
331178ab59feSKonstantin Komarov 		    (modified || (ni->ni_flags & NI_FLAG_UPDATE_PARENT))
331278ab59feSKonstantin Komarov 		    /* Avoid __wait_on_freeing_inode(inode). */
331378ab59feSKonstantin Komarov 		    && (sb->s_flags & SB_ACTIVE)) {
33144342306fSKonstantin Komarov 			dup.cr_time = std->cr_time;
3315e8b8e97fSKari Argillander 			/* Not critical if this function fail. */
33164342306fSKonstantin Komarov 			re_dirty = ni_update_parent(ni, &dup, sync);
33174342306fSKonstantin Komarov 
33184342306fSKonstantin Komarov 			if (re_dirty)
33194342306fSKonstantin Komarov 				ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
33204342306fSKonstantin Komarov 			else
33214342306fSKonstantin Komarov 				ni->ni_flags &= ~NI_FLAG_UPDATE_PARENT;
33224342306fSKonstantin Komarov 		}
33234342306fSKonstantin Komarov 
3324e8b8e97fSKari Argillander 		/* Update attribute list. */
33254342306fSKonstantin Komarov 		if (ni->attr_list.size && ni->attr_list.dirty) {
33264342306fSKonstantin Komarov 			if (inode->i_ino != MFT_REC_MFT || sync) {
33274342306fSKonstantin Komarov 				err = ni_try_remove_attr_list(ni);
33284342306fSKonstantin Komarov 				if (err)
33294342306fSKonstantin Komarov 					goto out;
33304342306fSKonstantin Komarov 			}
33314342306fSKonstantin Komarov 
333263544672SKonstantin Komarov 			err = al_update(ni, sync);
33334342306fSKonstantin Komarov 			if (err)
33344342306fSKonstantin Komarov 				goto out;
33354342306fSKonstantin Komarov 		}
33364342306fSKonstantin Komarov 	}
33374342306fSKonstantin Komarov 
33384342306fSKonstantin Komarov 	for (node = rb_first(&ni->mi_tree); node; node = next) {
33394342306fSKonstantin Komarov 		struct mft_inode *mi = rb_entry(node, struct mft_inode, node);
33404342306fSKonstantin Komarov 		bool is_empty;
33414342306fSKonstantin Komarov 
33424342306fSKonstantin Komarov 		next = rb_next(node);
33434342306fSKonstantin Komarov 
33444342306fSKonstantin Komarov 		if (!mi->dirty)
33454342306fSKonstantin Komarov 			continue;
33464342306fSKonstantin Komarov 
33474342306fSKonstantin Komarov 		is_empty = !mi_enum_attr(mi, NULL);
33484342306fSKonstantin Komarov 
33494342306fSKonstantin Komarov 		if (is_empty)
33504342306fSKonstantin Komarov 			clear_rec_inuse(mi->mrec);
33514342306fSKonstantin Komarov 
33524342306fSKonstantin Komarov 		err2 = mi_write(mi, sync);
33534342306fSKonstantin Komarov 		if (!err && err2)
33544342306fSKonstantin Komarov 			err = err2;
33554342306fSKonstantin Komarov 
33564342306fSKonstantin Komarov 		if (is_empty) {
3357071100eaSKonstantin Komarov 			ntfs_mark_rec_free(sbi, mi->rno, false);
33584342306fSKonstantin Komarov 			rb_erase(node, &ni->mi_tree);
33594342306fSKonstantin Komarov 			mi_put(mi);
33604342306fSKonstantin Komarov 		}
33614342306fSKonstantin Komarov 	}
33624342306fSKonstantin Komarov 
33634342306fSKonstantin Komarov 	if (ni->mi.dirty) {
33644342306fSKonstantin Komarov 		err2 = mi_write(&ni->mi, sync);
33654342306fSKonstantin Komarov 		if (!err && err2)
33664342306fSKonstantin Komarov 			err = err2;
33674342306fSKonstantin Komarov 	}
33684342306fSKonstantin Komarov out:
33694342306fSKonstantin Komarov 	ni_unlock(ni);
33704342306fSKonstantin Komarov 
33714342306fSKonstantin Komarov 	if (err) {
3372e43f6ec2SKonstantin Komarov 		ntfs_inode_err(inode, "%s failed, %d.", hint, err);
33734342306fSKonstantin Komarov 		ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
33744342306fSKonstantin Komarov 		return err;
33754342306fSKonstantin Komarov 	}
33764342306fSKonstantin Komarov 
337778ab59feSKonstantin Komarov 	if (re_dirty)
33784342306fSKonstantin Komarov 		mark_inode_dirty_sync(inode);
33794342306fSKonstantin Komarov 
33804342306fSKonstantin Komarov 	return 0;
33814342306fSKonstantin Komarov }
3382