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