11e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 21e9ea7e0SNamjae Jeon /* 3af0db57dSNamjae Jeon * NTFS kernel inode handling. 41e9ea7e0SNamjae Jeon * 51e9ea7e0SNamjae Jeon * Copyright (c) 2001-2014 Anton Altaparmakov and Tuxera Inc. 6af0db57dSNamjae Jeon * Copyright (c) 2025 LG Electronics Co., Ltd. 71e9ea7e0SNamjae Jeon */ 81e9ea7e0SNamjae Jeon 9af0db57dSNamjae Jeon #include <linux/writeback.h> 10af0db57dSNamjae Jeon #include <linux/seq_file.h> 111e9ea7e0SNamjae Jeon 121e9ea7e0SNamjae Jeon #include "lcnalloc.h" 131e9ea7e0SNamjae Jeon #include "time.h" 141e9ea7e0SNamjae Jeon #include "ntfs.h" 15af0db57dSNamjae Jeon #include "index.h" 16af0db57dSNamjae Jeon #include "attrlist.h" 17af0db57dSNamjae Jeon #include "reparse.h" 18af0db57dSNamjae Jeon #include "ea.h" 19af0db57dSNamjae Jeon #include "attrib.h" 20af0db57dSNamjae Jeon #include "iomap.h" 21af0db57dSNamjae Jeon #include "object_id.h" 221e9ea7e0SNamjae Jeon 23af0db57dSNamjae Jeon /* 241e9ea7e0SNamjae Jeon * ntfs_test_inode - compare two (possibly fake) inodes for equality 251e9ea7e0SNamjae Jeon * @vi: vfs inode which to test 261e9ea7e0SNamjae Jeon * @data: data which is being tested with 271e9ea7e0SNamjae Jeon * 281e9ea7e0SNamjae Jeon * Compare the ntfs attribute embedded in the ntfs specific part of the vfs 291e9ea7e0SNamjae Jeon * inode @vi for equality with the ntfs attribute @data. 301e9ea7e0SNamjae Jeon * 311e9ea7e0SNamjae Jeon * If searching for the normal file/directory inode, set @na->type to AT_UNUSED. 321e9ea7e0SNamjae Jeon * @na->name and @na->name_len are then ignored. 331e9ea7e0SNamjae Jeon * 341e9ea7e0SNamjae Jeon * Return 1 if the attributes match and 0 if not. 351e9ea7e0SNamjae Jeon * 361e9ea7e0SNamjae Jeon * NOTE: This function runs with the inode_hash_lock spin lock held so it is not 371e9ea7e0SNamjae Jeon * allowed to sleep. 381e9ea7e0SNamjae Jeon */ 391e9ea7e0SNamjae Jeon int ntfs_test_inode(struct inode *vi, void *data) 401e9ea7e0SNamjae Jeon { 41af0db57dSNamjae Jeon struct ntfs_attr *na = data; 42af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 431e9ea7e0SNamjae Jeon 441e9ea7e0SNamjae Jeon if (vi->i_ino != na->mft_no) 451e9ea7e0SNamjae Jeon return 0; 46af0db57dSNamjae Jeon 471e9ea7e0SNamjae Jeon /* If !NInoAttr(ni), @vi is a normal file or directory inode. */ 481e9ea7e0SNamjae Jeon if (likely(!NInoAttr(ni))) { 491e9ea7e0SNamjae Jeon /* If not looking for a normal inode this is a mismatch. */ 501e9ea7e0SNamjae Jeon if (unlikely(na->type != AT_UNUSED)) 511e9ea7e0SNamjae Jeon return 0; 521e9ea7e0SNamjae Jeon } else { 531e9ea7e0SNamjae Jeon /* A fake inode describing an attribute. */ 541e9ea7e0SNamjae Jeon if (ni->type != na->type) 551e9ea7e0SNamjae Jeon return 0; 561e9ea7e0SNamjae Jeon if (ni->name_len != na->name_len) 571e9ea7e0SNamjae Jeon return 0; 581e9ea7e0SNamjae Jeon if (na->name_len && memcmp(ni->name, na->name, 59af0db57dSNamjae Jeon na->name_len * sizeof(__le16))) 60af0db57dSNamjae Jeon return 0; 61af0db57dSNamjae Jeon if (!ni->ext.base_ntfs_ino) 621e9ea7e0SNamjae Jeon return 0; 631e9ea7e0SNamjae Jeon } 64af0db57dSNamjae Jeon 651e9ea7e0SNamjae Jeon /* Match! */ 661e9ea7e0SNamjae Jeon return 1; 671e9ea7e0SNamjae Jeon } 681e9ea7e0SNamjae Jeon 69af0db57dSNamjae Jeon /* 701e9ea7e0SNamjae Jeon * ntfs_init_locked_inode - initialize an inode 711e9ea7e0SNamjae Jeon * @vi: vfs inode to initialize 721e9ea7e0SNamjae Jeon * @data: data which to initialize @vi to 731e9ea7e0SNamjae Jeon * 741e9ea7e0SNamjae Jeon * Initialize the vfs inode @vi with the values from the ntfs attribute @data in 751e9ea7e0SNamjae Jeon * order to enable ntfs_test_inode() to do its work. 761e9ea7e0SNamjae Jeon * 771e9ea7e0SNamjae Jeon * If initializing the normal file/directory inode, set @na->type to AT_UNUSED. 781e9ea7e0SNamjae Jeon * In that case, @na->name and @na->name_len should be set to NULL and 0, 791e9ea7e0SNamjae Jeon * respectively. Although that is not strictly necessary as 801e9ea7e0SNamjae Jeon * ntfs_read_locked_inode() will fill them in later. 811e9ea7e0SNamjae Jeon * 82af0db57dSNamjae Jeon * Return 0 on success and error. 831e9ea7e0SNamjae Jeon * 841e9ea7e0SNamjae Jeon * NOTE: This function runs with the inode->i_lock spin lock held so it is not 851e9ea7e0SNamjae Jeon * allowed to sleep. (Hence the GFP_ATOMIC allocation.) 861e9ea7e0SNamjae Jeon */ 871e9ea7e0SNamjae Jeon static int ntfs_init_locked_inode(struct inode *vi, void *data) 881e9ea7e0SNamjae Jeon { 89af0db57dSNamjae Jeon struct ntfs_attr *na = data; 90af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 911e9ea7e0SNamjae Jeon 92d9038d99SNamjae Jeon vi->i_ino = (unsigned long)na->mft_no; 931e9ea7e0SNamjae Jeon 941e9ea7e0SNamjae Jeon if (na->type == AT_INDEX_ALLOCATION) 951e9ea7e0SNamjae Jeon NInoSetMstProtected(ni); 96af0db57dSNamjae Jeon else 97af0db57dSNamjae Jeon ni->type = na->type; 981e9ea7e0SNamjae Jeon 991e9ea7e0SNamjae Jeon ni->name = na->name; 1001e9ea7e0SNamjae Jeon ni->name_len = na->name_len; 101af0db57dSNamjae Jeon ni->folio = NULL; 102af0db57dSNamjae Jeon atomic_set(&ni->count, 1); 1031e9ea7e0SNamjae Jeon 1041e9ea7e0SNamjae Jeon /* If initializing a normal inode, we are done. */ 105af0db57dSNamjae Jeon if (likely(na->type == AT_UNUSED)) 1061e9ea7e0SNamjae Jeon return 0; 1071e9ea7e0SNamjae Jeon 1081e9ea7e0SNamjae Jeon /* It is a fake inode. */ 1091e9ea7e0SNamjae Jeon NInoSetAttr(ni); 1101e9ea7e0SNamjae Jeon 1111e9ea7e0SNamjae Jeon /* 1121e9ea7e0SNamjae Jeon * We have I30 global constant as an optimization as it is the name 1131e9ea7e0SNamjae Jeon * in >99.9% of named attributes! The other <0.1% incur a GFP_ATOMIC 1141e9ea7e0SNamjae Jeon * allocation but that is ok. And most attributes are unnamed anyway, 1151e9ea7e0SNamjae Jeon * thus the fraction of named attributes with name != I30 is actually 1161e9ea7e0SNamjae Jeon * absolutely tiny. 1171e9ea7e0SNamjae Jeon */ 1181e9ea7e0SNamjae Jeon if (na->name_len && na->name != I30) { 1191e9ea7e0SNamjae Jeon unsigned int i; 1201e9ea7e0SNamjae Jeon 121af0db57dSNamjae Jeon i = na->name_len * sizeof(__le16); 122af0db57dSNamjae Jeon ni->name = kmalloc(i + sizeof(__le16), GFP_ATOMIC); 1231e9ea7e0SNamjae Jeon if (!ni->name) 1241e9ea7e0SNamjae Jeon return -ENOMEM; 1251e9ea7e0SNamjae Jeon memcpy(ni->name, na->name, i); 1261e9ea7e0SNamjae Jeon ni->name[na->name_len] = 0; 1271e9ea7e0SNamjae Jeon } 1281e9ea7e0SNamjae Jeon return 0; 1291e9ea7e0SNamjae Jeon } 1301e9ea7e0SNamjae Jeon 1311e9ea7e0SNamjae Jeon static int ntfs_read_locked_inode(struct inode *vi); 1321e9ea7e0SNamjae Jeon static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi); 1331e9ea7e0SNamjae Jeon static int ntfs_read_locked_index_inode(struct inode *base_vi, 1341e9ea7e0SNamjae Jeon struct inode *vi); 1351e9ea7e0SNamjae Jeon 136af0db57dSNamjae Jeon /* 1371e9ea7e0SNamjae Jeon * ntfs_iget - obtain a struct inode corresponding to a specific normal inode 1381e9ea7e0SNamjae Jeon * @sb: super block of mounted volume 1391e9ea7e0SNamjae Jeon * @mft_no: mft record number / inode number to obtain 1401e9ea7e0SNamjae Jeon * 1411e9ea7e0SNamjae Jeon * Obtain the struct inode corresponding to a specific normal inode (i.e. a 1421e9ea7e0SNamjae Jeon * file or directory). 1431e9ea7e0SNamjae Jeon * 1441e9ea7e0SNamjae Jeon * If the inode is in the cache, it is just returned with an increased 1451e9ea7e0SNamjae Jeon * reference count. Otherwise, a new struct inode is allocated and initialized, 1461e9ea7e0SNamjae Jeon * and finally ntfs_read_locked_inode() is called to read in the inode and 1471e9ea7e0SNamjae Jeon * fill in the remainder of the inode structure. 1481e9ea7e0SNamjae Jeon * 1491e9ea7e0SNamjae Jeon * Return the struct inode on success. Check the return value with IS_ERR() and 1501e9ea7e0SNamjae Jeon * if true, the function failed and the error code is obtained from PTR_ERR(). 1511e9ea7e0SNamjae Jeon */ 152d9038d99SNamjae Jeon struct inode *ntfs_iget(struct super_block *sb, u64 mft_no) 1531e9ea7e0SNamjae Jeon { 1541e9ea7e0SNamjae Jeon struct inode *vi; 1551e9ea7e0SNamjae Jeon int err; 156af0db57dSNamjae Jeon struct ntfs_attr na; 1571e9ea7e0SNamjae Jeon 1581e9ea7e0SNamjae Jeon na.mft_no = mft_no; 1591e9ea7e0SNamjae Jeon na.type = AT_UNUSED; 1601e9ea7e0SNamjae Jeon na.name = NULL; 1611e9ea7e0SNamjae Jeon na.name_len = 0; 1621e9ea7e0SNamjae Jeon 1631e9ea7e0SNamjae Jeon vi = iget5_locked(sb, mft_no, ntfs_test_inode, 1641e9ea7e0SNamjae Jeon ntfs_init_locked_inode, &na); 1651e9ea7e0SNamjae Jeon if (unlikely(!vi)) 1661e9ea7e0SNamjae Jeon return ERR_PTR(-ENOMEM); 1671e9ea7e0SNamjae Jeon 1681e9ea7e0SNamjae Jeon err = 0; 1691e9ea7e0SNamjae Jeon 1701e9ea7e0SNamjae Jeon /* If this is a freshly allocated inode, need to read it now. */ 171af0db57dSNamjae Jeon if (inode_state_read_once(vi) & I_NEW) { 1721e9ea7e0SNamjae Jeon err = ntfs_read_locked_inode(vi); 1731e9ea7e0SNamjae Jeon unlock_new_inode(vi); 1741e9ea7e0SNamjae Jeon } 1751e9ea7e0SNamjae Jeon /* 1761e9ea7e0SNamjae Jeon * There is no point in keeping bad inodes around if the failure was 1771e9ea7e0SNamjae Jeon * due to ENOMEM. We want to be able to retry again later. 1781e9ea7e0SNamjae Jeon */ 1791e9ea7e0SNamjae Jeon if (unlikely(err == -ENOMEM)) { 1801e9ea7e0SNamjae Jeon iput(vi); 1811e9ea7e0SNamjae Jeon vi = ERR_PTR(err); 1821e9ea7e0SNamjae Jeon } 1831e9ea7e0SNamjae Jeon return vi; 1841e9ea7e0SNamjae Jeon } 1851e9ea7e0SNamjae Jeon 186af0db57dSNamjae Jeon /* 1871e9ea7e0SNamjae Jeon * ntfs_attr_iget - obtain a struct inode corresponding to an attribute 1881e9ea7e0SNamjae Jeon * @base_vi: vfs base inode containing the attribute 1891e9ea7e0SNamjae Jeon * @type: attribute type 1901e9ea7e0SNamjae Jeon * @name: Unicode name of the attribute (NULL if unnamed) 1911e9ea7e0SNamjae Jeon * @name_len: length of @name in Unicode characters (0 if unnamed) 1921e9ea7e0SNamjae Jeon * 1931e9ea7e0SNamjae Jeon * Obtain the (fake) struct inode corresponding to the attribute specified by 1941e9ea7e0SNamjae Jeon * @type, @name, and @name_len, which is present in the base mft record 1951e9ea7e0SNamjae Jeon * specified by the vfs inode @base_vi. 1961e9ea7e0SNamjae Jeon * 1971e9ea7e0SNamjae Jeon * If the attribute inode is in the cache, it is just returned with an 1981e9ea7e0SNamjae Jeon * increased reference count. Otherwise, a new struct inode is allocated and 1991e9ea7e0SNamjae Jeon * initialized, and finally ntfs_read_locked_attr_inode() is called to read the 2001e9ea7e0SNamjae Jeon * attribute and fill in the inode structure. 2011e9ea7e0SNamjae Jeon * 2021e9ea7e0SNamjae Jeon * Note, for index allocation attributes, you need to use ntfs_index_iget() 2031e9ea7e0SNamjae Jeon * instead of ntfs_attr_iget() as working with indices is a lot more complex. 2041e9ea7e0SNamjae Jeon * 2051e9ea7e0SNamjae Jeon * Return the struct inode of the attribute inode on success. Check the return 2061e9ea7e0SNamjae Jeon * value with IS_ERR() and if true, the function failed and the error code is 2071e9ea7e0SNamjae Jeon * obtained from PTR_ERR(). 2081e9ea7e0SNamjae Jeon */ 209af0db57dSNamjae Jeon struct inode *ntfs_attr_iget(struct inode *base_vi, __le32 type, 210af0db57dSNamjae Jeon __le16 *name, u32 name_len) 2111e9ea7e0SNamjae Jeon { 2121e9ea7e0SNamjae Jeon struct inode *vi; 2131e9ea7e0SNamjae Jeon int err; 214af0db57dSNamjae Jeon struct ntfs_attr na; 2151e9ea7e0SNamjae Jeon 2161e9ea7e0SNamjae Jeon /* Make sure no one calls ntfs_attr_iget() for indices. */ 217af0db57dSNamjae Jeon WARN_ON(type == AT_INDEX_ALLOCATION); 2181e9ea7e0SNamjae Jeon 2191e9ea7e0SNamjae Jeon na.mft_no = base_vi->i_ino; 2201e9ea7e0SNamjae Jeon na.type = type; 2211e9ea7e0SNamjae Jeon na.name = name; 2221e9ea7e0SNamjae Jeon na.name_len = name_len; 2231e9ea7e0SNamjae Jeon 2241e9ea7e0SNamjae Jeon vi = iget5_locked(base_vi->i_sb, na.mft_no, ntfs_test_inode, 2251e9ea7e0SNamjae Jeon ntfs_init_locked_inode, &na); 2261e9ea7e0SNamjae Jeon if (unlikely(!vi)) 2271e9ea7e0SNamjae Jeon return ERR_PTR(-ENOMEM); 2281e9ea7e0SNamjae Jeon err = 0; 2291e9ea7e0SNamjae Jeon 2301e9ea7e0SNamjae Jeon /* If this is a freshly allocated inode, need to read it now. */ 231af0db57dSNamjae Jeon if (inode_state_read_once(vi) & I_NEW) { 2321e9ea7e0SNamjae Jeon err = ntfs_read_locked_attr_inode(base_vi, vi); 2331e9ea7e0SNamjae Jeon unlock_new_inode(vi); 2341e9ea7e0SNamjae Jeon } 2351e9ea7e0SNamjae Jeon /* 2361e9ea7e0SNamjae Jeon * There is no point in keeping bad attribute inodes around. This also 2371e9ea7e0SNamjae Jeon * simplifies things in that we never need to check for bad attribute 2381e9ea7e0SNamjae Jeon * inodes elsewhere. 2391e9ea7e0SNamjae Jeon */ 2401e9ea7e0SNamjae Jeon if (unlikely(err)) { 2411e9ea7e0SNamjae Jeon iput(vi); 2421e9ea7e0SNamjae Jeon vi = ERR_PTR(err); 2431e9ea7e0SNamjae Jeon } 2441e9ea7e0SNamjae Jeon return vi; 2451e9ea7e0SNamjae Jeon } 2461e9ea7e0SNamjae Jeon 247af0db57dSNamjae Jeon /* 2481e9ea7e0SNamjae Jeon * ntfs_index_iget - obtain a struct inode corresponding to an index 2491e9ea7e0SNamjae Jeon * @base_vi: vfs base inode containing the index related attributes 2501e9ea7e0SNamjae Jeon * @name: Unicode name of the index 2511e9ea7e0SNamjae Jeon * @name_len: length of @name in Unicode characters 2521e9ea7e0SNamjae Jeon * 2531e9ea7e0SNamjae Jeon * Obtain the (fake) struct inode corresponding to the index specified by @name 2541e9ea7e0SNamjae Jeon * and @name_len, which is present in the base mft record specified by the vfs 2551e9ea7e0SNamjae Jeon * inode @base_vi. 2561e9ea7e0SNamjae Jeon * 2571e9ea7e0SNamjae Jeon * If the index inode is in the cache, it is just returned with an increased 2581e9ea7e0SNamjae Jeon * reference count. Otherwise, a new struct inode is allocated and 2591e9ea7e0SNamjae Jeon * initialized, and finally ntfs_read_locked_index_inode() is called to read 2601e9ea7e0SNamjae Jeon * the index related attributes and fill in the inode structure. 2611e9ea7e0SNamjae Jeon * 2621e9ea7e0SNamjae Jeon * Return the struct inode of the index inode on success. Check the return 2631e9ea7e0SNamjae Jeon * value with IS_ERR() and if true, the function failed and the error code is 2641e9ea7e0SNamjae Jeon * obtained from PTR_ERR(). 2651e9ea7e0SNamjae Jeon */ 266af0db57dSNamjae Jeon struct inode *ntfs_index_iget(struct inode *base_vi, __le16 *name, 2671e9ea7e0SNamjae Jeon u32 name_len) 2681e9ea7e0SNamjae Jeon { 2691e9ea7e0SNamjae Jeon struct inode *vi; 2701e9ea7e0SNamjae Jeon int err; 271af0db57dSNamjae Jeon struct ntfs_attr na; 2721e9ea7e0SNamjae Jeon 2731e9ea7e0SNamjae Jeon na.mft_no = base_vi->i_ino; 2741e9ea7e0SNamjae Jeon na.type = AT_INDEX_ALLOCATION; 2751e9ea7e0SNamjae Jeon na.name = name; 2761e9ea7e0SNamjae Jeon na.name_len = name_len; 2771e9ea7e0SNamjae Jeon 2781e9ea7e0SNamjae Jeon vi = iget5_locked(base_vi->i_sb, na.mft_no, ntfs_test_inode, 2791e9ea7e0SNamjae Jeon ntfs_init_locked_inode, &na); 2801e9ea7e0SNamjae Jeon if (unlikely(!vi)) 2811e9ea7e0SNamjae Jeon return ERR_PTR(-ENOMEM); 2821e9ea7e0SNamjae Jeon 2831e9ea7e0SNamjae Jeon err = 0; 2841e9ea7e0SNamjae Jeon 2851e9ea7e0SNamjae Jeon /* If this is a freshly allocated inode, need to read it now. */ 286af0db57dSNamjae Jeon if (inode_state_read_once(vi) & I_NEW) { 2871e9ea7e0SNamjae Jeon err = ntfs_read_locked_index_inode(base_vi, vi); 2881e9ea7e0SNamjae Jeon unlock_new_inode(vi); 2891e9ea7e0SNamjae Jeon } 2901e9ea7e0SNamjae Jeon /* 2911e9ea7e0SNamjae Jeon * There is no point in keeping bad index inodes around. This also 2921e9ea7e0SNamjae Jeon * simplifies things in that we never need to check for bad index 2931e9ea7e0SNamjae Jeon * inodes elsewhere. 2941e9ea7e0SNamjae Jeon */ 2951e9ea7e0SNamjae Jeon if (unlikely(err)) { 2961e9ea7e0SNamjae Jeon iput(vi); 2971e9ea7e0SNamjae Jeon vi = ERR_PTR(err); 2981e9ea7e0SNamjae Jeon } 2991e9ea7e0SNamjae Jeon return vi; 3001e9ea7e0SNamjae Jeon } 3011e9ea7e0SNamjae Jeon 3021e9ea7e0SNamjae Jeon struct inode *ntfs_alloc_big_inode(struct super_block *sb) 3031e9ea7e0SNamjae Jeon { 304af0db57dSNamjae Jeon struct ntfs_inode *ni; 3051e9ea7e0SNamjae Jeon 3061e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 3071e9ea7e0SNamjae Jeon ni = alloc_inode_sb(sb, ntfs_big_inode_cache, GFP_NOFS); 3081e9ea7e0SNamjae Jeon if (likely(ni != NULL)) { 3091e9ea7e0SNamjae Jeon ni->state = 0; 310af0db57dSNamjae Jeon ni->type = 0; 311af0db57dSNamjae Jeon ni->mft_no = 0; 3121e9ea7e0SNamjae Jeon return VFS_I(ni); 3131e9ea7e0SNamjae Jeon } 3141e9ea7e0SNamjae Jeon ntfs_error(sb, "Allocation of NTFS big inode structure failed."); 3151e9ea7e0SNamjae Jeon return NULL; 3161e9ea7e0SNamjae Jeon } 3171e9ea7e0SNamjae Jeon 3181e9ea7e0SNamjae Jeon void ntfs_free_big_inode(struct inode *inode) 3191e9ea7e0SNamjae Jeon { 3201e9ea7e0SNamjae Jeon kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode)); 3211e9ea7e0SNamjae Jeon } 3221e9ea7e0SNamjae Jeon 323af0db57dSNamjae Jeon static int ntfs_non_resident_dealloc_clusters(struct ntfs_inode *ni) 3241e9ea7e0SNamjae Jeon { 325af0db57dSNamjae Jeon struct super_block *sb = ni->vol->sb; 326af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *actx; 327af0db57dSNamjae Jeon int err = 0; 328af0db57dSNamjae Jeon 329af0db57dSNamjae Jeon actx = ntfs_attr_get_search_ctx(ni, NULL); 330af0db57dSNamjae Jeon if (!actx) 331af0db57dSNamjae Jeon return -ENOMEM; 332af0db57dSNamjae Jeon WARN_ON(actx->mrec->link_count != 0); 333af0db57dSNamjae Jeon 334af0db57dSNamjae Jeon /** 335af0db57dSNamjae Jeon * ntfs_truncate_vfs cannot be called in evict() context due 336af0db57dSNamjae Jeon * to some limitations, which are the @ni vfs inode is marked 337af0db57dSNamjae Jeon * with I_FREEING, and etc. 338af0db57dSNamjae Jeon */ 339af0db57dSNamjae Jeon if (NInoRunlistDirty(ni)) { 340af0db57dSNamjae Jeon err = ntfs_cluster_free_from_rl(ni->vol, ni->runlist.rl); 341af0db57dSNamjae Jeon if (err) 342af0db57dSNamjae Jeon ntfs_error(sb, 343af0db57dSNamjae Jeon "Failed to free clusters. Leaving inconsistent metadata.\n"); 344af0db57dSNamjae Jeon } 345af0db57dSNamjae Jeon 346af0db57dSNamjae Jeon while ((err = ntfs_attrs_walk(actx)) == 0) { 347af0db57dSNamjae Jeon if (actx->attr->non_resident && 348af0db57dSNamjae Jeon (!NInoRunlistDirty(ni) || actx->attr->type != AT_DATA)) { 349af0db57dSNamjae Jeon struct runlist_element *rl; 350af0db57dSNamjae Jeon size_t new_rl_count; 351af0db57dSNamjae Jeon 352af0db57dSNamjae Jeon rl = ntfs_mapping_pairs_decompress(ni->vol, actx->attr, NULL, 353af0db57dSNamjae Jeon &new_rl_count); 354af0db57dSNamjae Jeon if (IS_ERR(rl)) { 355af0db57dSNamjae Jeon err = PTR_ERR(rl); 356af0db57dSNamjae Jeon ntfs_error(sb, 357af0db57dSNamjae Jeon "Failed to decompress runlist. Leaving inconsistent metadata.\n"); 358af0db57dSNamjae Jeon continue; 359af0db57dSNamjae Jeon } 360af0db57dSNamjae Jeon 361af0db57dSNamjae Jeon err = ntfs_cluster_free_from_rl(ni->vol, rl); 362af0db57dSNamjae Jeon if (err) 363af0db57dSNamjae Jeon ntfs_error(sb, 364af0db57dSNamjae Jeon "Failed to free attribute clusters. Leaving inconsistent metadata.\n"); 365af0db57dSNamjae Jeon kvfree(rl); 366af0db57dSNamjae Jeon } 367af0db57dSNamjae Jeon } 368af0db57dSNamjae Jeon 369af0db57dSNamjae Jeon ntfs_release_dirty_clusters(ni->vol, ni->i_dealloc_clusters); 370af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(actx); 371af0db57dSNamjae Jeon return err; 372af0db57dSNamjae Jeon } 373af0db57dSNamjae Jeon 374af0db57dSNamjae Jeon int ntfs_drop_big_inode(struct inode *inode) 375af0db57dSNamjae Jeon { 376af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(inode); 377af0db57dSNamjae Jeon 378af0db57dSNamjae Jeon if (!inode_unhashed(inode) && inode_state_read_once(inode) & I_SYNC) { 379af0db57dSNamjae Jeon if (ni->type == AT_DATA || ni->type == AT_INDEX_ALLOCATION) { 380af0db57dSNamjae Jeon if (!inode->i_nlink) { 381af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(inode); 382af0db57dSNamjae Jeon 383af0db57dSNamjae Jeon if (ni->data_size == 0) 384af0db57dSNamjae Jeon return 0; 385af0db57dSNamjae Jeon 386af0db57dSNamjae Jeon /* To avoid evict_inode call simultaneously */ 387af0db57dSNamjae Jeon atomic_inc(&inode->i_count); 388af0db57dSNamjae Jeon spin_unlock(&inode->i_lock); 389af0db57dSNamjae Jeon 390af0db57dSNamjae Jeon truncate_setsize(VFS_I(ni), 0); 391af0db57dSNamjae Jeon ntfs_truncate_vfs(VFS_I(ni), 0, 1); 392af0db57dSNamjae Jeon 393af0db57dSNamjae Jeon sb_start_intwrite(inode->i_sb); 394af0db57dSNamjae Jeon i_size_write(inode, 0); 395af0db57dSNamjae Jeon ni->allocated_size = ni->initialized_size = ni->data_size = 0; 396af0db57dSNamjae Jeon 397af0db57dSNamjae Jeon truncate_inode_pages_final(inode->i_mapping); 398af0db57dSNamjae Jeon sb_end_intwrite(inode->i_sb); 399af0db57dSNamjae Jeon 400af0db57dSNamjae Jeon spin_lock(&inode->i_lock); 401af0db57dSNamjae Jeon atomic_dec(&inode->i_count); 402af0db57dSNamjae Jeon } 403af0db57dSNamjae Jeon } 404af0db57dSNamjae Jeon return 0; 405af0db57dSNamjae Jeon } 406af0db57dSNamjae Jeon 407af0db57dSNamjae Jeon return inode_generic_drop(inode); 408af0db57dSNamjae Jeon } 409af0db57dSNamjae Jeon 410af0db57dSNamjae Jeon static inline struct ntfs_inode *ntfs_alloc_extent_inode(void) 411af0db57dSNamjae Jeon { 412af0db57dSNamjae Jeon struct ntfs_inode *ni; 4131e9ea7e0SNamjae Jeon 4141e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 4151e9ea7e0SNamjae Jeon ni = kmem_cache_alloc(ntfs_inode_cache, GFP_NOFS); 4161e9ea7e0SNamjae Jeon if (likely(ni != NULL)) { 4171e9ea7e0SNamjae Jeon ni->state = 0; 4181e9ea7e0SNamjae Jeon return ni; 4191e9ea7e0SNamjae Jeon } 4201e9ea7e0SNamjae Jeon ntfs_error(NULL, "Allocation of NTFS inode structure failed."); 4211e9ea7e0SNamjae Jeon return NULL; 4221e9ea7e0SNamjae Jeon } 4231e9ea7e0SNamjae Jeon 424af0db57dSNamjae Jeon static void ntfs_destroy_extent_inode(struct ntfs_inode *ni) 4251e9ea7e0SNamjae Jeon { 4261e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 427af0db57dSNamjae Jeon 4281e9ea7e0SNamjae Jeon if (!atomic_dec_and_test(&ni->count)) 429af0db57dSNamjae Jeon WARN_ON(1); 430af0db57dSNamjae Jeon if (ni->folio) 431af0db57dSNamjae Jeon folio_put(ni->folio); 432af0db57dSNamjae Jeon kfree(ni->mrec); 4331e9ea7e0SNamjae Jeon kmem_cache_free(ntfs_inode_cache, ni); 4341e9ea7e0SNamjae Jeon } 4351e9ea7e0SNamjae Jeon 436af0db57dSNamjae Jeon static struct lock_class_key attr_inode_mrec_lock_class; 437af0db57dSNamjae Jeon static struct lock_class_key attr_list_inode_mrec_lock_class; 438af0db57dSNamjae Jeon 4391e9ea7e0SNamjae Jeon /* 4401e9ea7e0SNamjae Jeon * The attribute runlist lock has separate locking rules from the 4411e9ea7e0SNamjae Jeon * normal runlist lock, so split the two lock-classes: 4421e9ea7e0SNamjae Jeon */ 4431e9ea7e0SNamjae Jeon static struct lock_class_key attr_list_rl_lock_class; 4441e9ea7e0SNamjae Jeon 445af0db57dSNamjae Jeon /* 4461e9ea7e0SNamjae Jeon * __ntfs_init_inode - initialize ntfs specific part of an inode 4471e9ea7e0SNamjae Jeon * @sb: super block of mounted volume 4481e9ea7e0SNamjae Jeon * @ni: freshly allocated ntfs inode which to initialize 4491e9ea7e0SNamjae Jeon * 4501e9ea7e0SNamjae Jeon * Initialize an ntfs inode to defaults. 4511e9ea7e0SNamjae Jeon * 4521e9ea7e0SNamjae Jeon * NOTE: ni->mft_no, ni->state, ni->type, ni->name, and ni->name_len are left 4531e9ea7e0SNamjae Jeon * untouched. Make sure to initialize them elsewhere. 4541e9ea7e0SNamjae Jeon */ 455af0db57dSNamjae Jeon void __ntfs_init_inode(struct super_block *sb, struct ntfs_inode *ni) 4561e9ea7e0SNamjae Jeon { 4571e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 4581e9ea7e0SNamjae Jeon rwlock_init(&ni->size_lock); 4591e9ea7e0SNamjae Jeon ni->initialized_size = ni->allocated_size = 0; 4601e9ea7e0SNamjae Jeon ni->seq_no = 0; 4611e9ea7e0SNamjae Jeon atomic_set(&ni->count, 1); 4621e9ea7e0SNamjae Jeon ni->vol = NTFS_SB(sb); 4631e9ea7e0SNamjae Jeon ntfs_init_runlist(&ni->runlist); 4641e9ea7e0SNamjae Jeon mutex_init(&ni->mrec_lock); 465af0db57dSNamjae Jeon if (ni->type == AT_ATTRIBUTE_LIST) { 466af0db57dSNamjae Jeon lockdep_set_class(&ni->mrec_lock, 467af0db57dSNamjae Jeon &attr_list_inode_mrec_lock_class); 468af0db57dSNamjae Jeon lockdep_set_class(&ni->runlist.lock, 469af0db57dSNamjae Jeon &attr_list_rl_lock_class); 470af0db57dSNamjae Jeon } else if (NInoAttr(ni)) { 471af0db57dSNamjae Jeon lockdep_set_class(&ni->mrec_lock, 472af0db57dSNamjae Jeon &attr_inode_mrec_lock_class); 473af0db57dSNamjae Jeon } 474af0db57dSNamjae Jeon 475af0db57dSNamjae Jeon ni->folio = NULL; 476af0db57dSNamjae Jeon ni->folio_ofs = 0; 477af0db57dSNamjae Jeon ni->mrec = NULL; 4781e9ea7e0SNamjae Jeon ni->attr_list_size = 0; 4791e9ea7e0SNamjae Jeon ni->attr_list = NULL; 4801e9ea7e0SNamjae Jeon ni->itype.index.block_size = 0; 4811e9ea7e0SNamjae Jeon ni->itype.index.vcn_size = 0; 4821e9ea7e0SNamjae Jeon ni->itype.index.collation_rule = 0; 4831e9ea7e0SNamjae Jeon ni->itype.index.block_size_bits = 0; 4841e9ea7e0SNamjae Jeon ni->itype.index.vcn_size_bits = 0; 4851e9ea7e0SNamjae Jeon mutex_init(&ni->extent_lock); 4861e9ea7e0SNamjae Jeon ni->nr_extents = 0; 4871e9ea7e0SNamjae Jeon ni->ext.base_ntfs_ino = NULL; 488af0db57dSNamjae Jeon ni->flags = 0; 489af0db57dSNamjae Jeon ni->mft_lcn[0] = LCN_RL_NOT_MAPPED; 490af0db57dSNamjae Jeon ni->mft_lcn_count = 0; 491af0db57dSNamjae Jeon ni->target = NULL; 492af0db57dSNamjae Jeon ni->i_dealloc_clusters = 0; 4931e9ea7e0SNamjae Jeon } 4941e9ea7e0SNamjae Jeon 4951e9ea7e0SNamjae Jeon /* 4961e9ea7e0SNamjae Jeon * Extent inodes get MFT-mapped in a nested way, while the base inode 4971e9ea7e0SNamjae Jeon * is still mapped. Teach this nesting to the lock validator by creating 4981e9ea7e0SNamjae Jeon * a separate class for nested inode's mrec_lock's: 4991e9ea7e0SNamjae Jeon */ 5001e9ea7e0SNamjae Jeon static struct lock_class_key extent_inode_mrec_lock_key; 5011e9ea7e0SNamjae Jeon 502af0db57dSNamjae Jeon inline struct ntfs_inode *ntfs_new_extent_inode(struct super_block *sb, 503d9038d99SNamjae Jeon u64 mft_no) 5041e9ea7e0SNamjae Jeon { 505af0db57dSNamjae Jeon struct ntfs_inode *ni = ntfs_alloc_extent_inode(); 5061e9ea7e0SNamjae Jeon 5071e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 5081e9ea7e0SNamjae Jeon if (likely(ni != NULL)) { 5091e9ea7e0SNamjae Jeon __ntfs_init_inode(sb, ni); 5101e9ea7e0SNamjae Jeon lockdep_set_class(&ni->mrec_lock, &extent_inode_mrec_lock_key); 5111e9ea7e0SNamjae Jeon ni->mft_no = mft_no; 5121e9ea7e0SNamjae Jeon ni->type = AT_UNUSED; 5131e9ea7e0SNamjae Jeon ni->name = NULL; 5141e9ea7e0SNamjae Jeon ni->name_len = 0; 5151e9ea7e0SNamjae Jeon } 5161e9ea7e0SNamjae Jeon return ni; 5171e9ea7e0SNamjae Jeon } 5181e9ea7e0SNamjae Jeon 519af0db57dSNamjae Jeon /* 5201e9ea7e0SNamjae Jeon * ntfs_is_extended_system_file - check if a file is in the $Extend directory 5211e9ea7e0SNamjae Jeon * @ctx: initialized attribute search context 5221e9ea7e0SNamjae Jeon * 5231e9ea7e0SNamjae Jeon * Search all file name attributes in the inode described by the attribute 5241e9ea7e0SNamjae Jeon * search context @ctx and check if any of the names are in the $Extend system 5251e9ea7e0SNamjae Jeon * directory. 5261e9ea7e0SNamjae Jeon * 5271e9ea7e0SNamjae Jeon * Return values: 528af0db57dSNamjae Jeon * 3: file is $ObjId in $Extend directory 529af0db57dSNamjae Jeon * 2: file is $Reparse in $Extend directory 5301e9ea7e0SNamjae Jeon * 1: file is in $Extend directory 5311e9ea7e0SNamjae Jeon * 0: file is not in $Extend directory 5321e9ea7e0SNamjae Jeon * -errno: failed to determine if the file is in the $Extend directory 5331e9ea7e0SNamjae Jeon */ 534af0db57dSNamjae Jeon static int ntfs_is_extended_system_file(struct ntfs_attr_search_ctx *ctx) 5351e9ea7e0SNamjae Jeon { 5361e9ea7e0SNamjae Jeon int nr_links, err; 5371e9ea7e0SNamjae Jeon 5381e9ea7e0SNamjae Jeon /* Restart search. */ 5391e9ea7e0SNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 5401e9ea7e0SNamjae Jeon 5411e9ea7e0SNamjae Jeon /* Get number of hard links. */ 5421e9ea7e0SNamjae Jeon nr_links = le16_to_cpu(ctx->mrec->link_count); 5431e9ea7e0SNamjae Jeon 5441e9ea7e0SNamjae Jeon /* Loop through all hard links. */ 5451e9ea7e0SNamjae Jeon while (!(err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, 5461e9ea7e0SNamjae Jeon ctx))) { 547af0db57dSNamjae Jeon struct file_name_attr *file_name_attr; 548af0db57dSNamjae Jeon struct attr_record *attr = ctx->attr; 5491e9ea7e0SNamjae Jeon u8 *p, *p2; 5501e9ea7e0SNamjae Jeon 5511e9ea7e0SNamjae Jeon nr_links--; 5521e9ea7e0SNamjae Jeon /* 5531e9ea7e0SNamjae Jeon * Maximum sanity checking as we are called on an inode that 5541e9ea7e0SNamjae Jeon * we suspect might be corrupt. 5551e9ea7e0SNamjae Jeon */ 5561e9ea7e0SNamjae Jeon p = (u8 *)attr + le32_to_cpu(attr->length); 5571e9ea7e0SNamjae Jeon if (p < (u8 *)ctx->mrec || (u8 *)p > (u8 *)ctx->mrec + 5581e9ea7e0SNamjae Jeon le32_to_cpu(ctx->mrec->bytes_in_use)) { 5591e9ea7e0SNamjae Jeon err_corrupt_attr: 560af0db57dSNamjae Jeon ntfs_error(ctx->ntfs_ino->vol->sb, 561af0db57dSNamjae Jeon "Corrupt file name attribute. You should run chkdsk."); 5621e9ea7e0SNamjae Jeon return -EIO; 5631e9ea7e0SNamjae Jeon } 5641e9ea7e0SNamjae Jeon if (attr->non_resident) { 565af0db57dSNamjae Jeon ntfs_error(ctx->ntfs_ino->vol->sb, 566af0db57dSNamjae Jeon "Non-resident file name. You should run chkdsk."); 5671e9ea7e0SNamjae Jeon return -EIO; 5681e9ea7e0SNamjae Jeon } 5691e9ea7e0SNamjae Jeon if (attr->flags) { 570af0db57dSNamjae Jeon ntfs_error(ctx->ntfs_ino->vol->sb, 571af0db57dSNamjae Jeon "File name with invalid flags. You should run chkdsk."); 5721e9ea7e0SNamjae Jeon return -EIO; 5731e9ea7e0SNamjae Jeon } 5741e9ea7e0SNamjae Jeon if (!(attr->data.resident.flags & RESIDENT_ATTR_IS_INDEXED)) { 575af0db57dSNamjae Jeon ntfs_error(ctx->ntfs_ino->vol->sb, 576af0db57dSNamjae Jeon "Unindexed file name. You should run chkdsk."); 5771e9ea7e0SNamjae Jeon return -EIO; 5781e9ea7e0SNamjae Jeon } 579af0db57dSNamjae Jeon file_name_attr = (struct file_name_attr *)((u8 *)attr + 5801e9ea7e0SNamjae Jeon le16_to_cpu(attr->data.resident.value_offset)); 5811e9ea7e0SNamjae Jeon p2 = (u8 *)file_name_attr + le32_to_cpu(attr->data.resident.value_length); 5821e9ea7e0SNamjae Jeon if (p2 < (u8 *)attr || p2 > p) 5831e9ea7e0SNamjae Jeon goto err_corrupt_attr; 5841e9ea7e0SNamjae Jeon /* This attribute is ok, but is it in the $Extend directory? */ 585af0db57dSNamjae Jeon if (MREF_LE(file_name_attr->parent_directory) == FILE_Extend) { 586af0db57dSNamjae Jeon unsigned char *s; 587af0db57dSNamjae Jeon 588af0db57dSNamjae Jeon s = ntfs_attr_name_get(ctx->ntfs_ino->vol, 589af0db57dSNamjae Jeon file_name_attr->file_name, 590af0db57dSNamjae Jeon file_name_attr->file_name_length); 591af0db57dSNamjae Jeon if (!s) 592af0db57dSNamjae Jeon return 1; 593af0db57dSNamjae Jeon if (!strcmp("$Reparse", s)) { 594af0db57dSNamjae Jeon ntfs_attr_name_free(&s); 595af0db57dSNamjae Jeon return 2; /* it's reparse point file */ 596af0db57dSNamjae Jeon } 597af0db57dSNamjae Jeon if (!strcmp("$ObjId", s)) { 598af0db57dSNamjae Jeon ntfs_attr_name_free(&s); 599af0db57dSNamjae Jeon return 3; /* it's object id file */ 600af0db57dSNamjae Jeon } 601af0db57dSNamjae Jeon ntfs_attr_name_free(&s); 6021e9ea7e0SNamjae Jeon return 1; /* YES, it's an extended system file. */ 6031e9ea7e0SNamjae Jeon } 604af0db57dSNamjae Jeon } 6051e9ea7e0SNamjae Jeon if (unlikely(err != -ENOENT)) 6061e9ea7e0SNamjae Jeon return err; 6071e9ea7e0SNamjae Jeon if (unlikely(nr_links)) { 608af0db57dSNamjae Jeon ntfs_error(ctx->ntfs_ino->vol->sb, 609af0db57dSNamjae Jeon "Inode hard link count doesn't match number of name attributes. You should run chkdsk."); 6101e9ea7e0SNamjae Jeon return -EIO; 6111e9ea7e0SNamjae Jeon } 6121e9ea7e0SNamjae Jeon return 0; /* NO, it is not an extended system file. */ 6131e9ea7e0SNamjae Jeon } 6141e9ea7e0SNamjae Jeon 615af0db57dSNamjae Jeon static struct lock_class_key ntfs_dir_inval_lock_key; 616af0db57dSNamjae Jeon 617af0db57dSNamjae Jeon void ntfs_set_vfs_operations(struct inode *inode, mode_t mode, dev_t dev) 618af0db57dSNamjae Jeon { 619af0db57dSNamjae Jeon if (S_ISDIR(mode)) { 620af0db57dSNamjae Jeon if (!NInoAttr(NTFS_I(inode))) { 621af0db57dSNamjae Jeon inode->i_op = &ntfs_dir_inode_ops; 622af0db57dSNamjae Jeon inode->i_fop = &ntfs_dir_ops; 623af0db57dSNamjae Jeon } 624af0db57dSNamjae Jeon inode->i_mapping->a_ops = &ntfs_aops; 625af0db57dSNamjae Jeon lockdep_set_class(&inode->i_mapping->invalidate_lock, 626af0db57dSNamjae Jeon &ntfs_dir_inval_lock_key); 627af0db57dSNamjae Jeon } else if (S_ISLNK(mode)) { 628af0db57dSNamjae Jeon inode->i_op = &ntfs_symlink_inode_operations; 629af0db57dSNamjae Jeon inode->i_mapping->a_ops = &ntfs_aops; 630af0db57dSNamjae Jeon } else if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { 631af0db57dSNamjae Jeon inode->i_op = &ntfs_special_inode_operations; 632af0db57dSNamjae Jeon init_special_inode(inode, inode->i_mode, dev); 633af0db57dSNamjae Jeon } else { 634af0db57dSNamjae Jeon if (!NInoAttr(NTFS_I(inode))) { 635af0db57dSNamjae Jeon inode->i_op = &ntfs_file_inode_ops; 636af0db57dSNamjae Jeon inode->i_fop = &ntfs_file_ops; 637af0db57dSNamjae Jeon } 638af0db57dSNamjae Jeon if (inode->i_ino == FILE_MFT) 639af0db57dSNamjae Jeon inode->i_mapping->a_ops = &ntfs_mft_aops; 640af0db57dSNamjae Jeon else 641af0db57dSNamjae Jeon inode->i_mapping->a_ops = &ntfs_aops; 642af0db57dSNamjae Jeon } 643af0db57dSNamjae Jeon } 644af0db57dSNamjae Jeon 645af0db57dSNamjae Jeon /* 6461e9ea7e0SNamjae Jeon * ntfs_read_locked_inode - read an inode from its device 6471e9ea7e0SNamjae Jeon * @vi: inode to read 6481e9ea7e0SNamjae Jeon * 6491e9ea7e0SNamjae Jeon * ntfs_read_locked_inode() is called from ntfs_iget() to read the inode 6501e9ea7e0SNamjae Jeon * described by @vi into memory from the device. 6511e9ea7e0SNamjae Jeon * 6521e9ea7e0SNamjae Jeon * The only fields in @vi that we need to/can look at when the function is 6531e9ea7e0SNamjae Jeon * called are i_sb, pointing to the mounted device's super block, and i_ino, 6541e9ea7e0SNamjae Jeon * the number of the inode to load. 6551e9ea7e0SNamjae Jeon * 6561e9ea7e0SNamjae Jeon * ntfs_read_locked_inode() maps, pins and locks the mft record number i_ino 6571e9ea7e0SNamjae Jeon * for reading and sets up the necessary @vi fields as well as initializing 6581e9ea7e0SNamjae Jeon * the ntfs inode. 6591e9ea7e0SNamjae Jeon * 6601e9ea7e0SNamjae Jeon * Q: What locks are held when the function is called? 6611e9ea7e0SNamjae Jeon * A: i_state has I_NEW set, hence the inode is locked, also 6621e9ea7e0SNamjae Jeon * i_count is set to 1, so it is not going to go away 6631e9ea7e0SNamjae Jeon * i_flags is set to 0 and we have no business touching it. Only an ioctl() 6641e9ea7e0SNamjae Jeon * is allowed to write to them. We should of course be honouring them but 6651e9ea7e0SNamjae Jeon * we need to do that using the IS_* macros defined in include/linux/fs.h. 6661e9ea7e0SNamjae Jeon * In any case ntfs_read_locked_inode() has nothing to do with i_flags. 6671e9ea7e0SNamjae Jeon * 668af0db57dSNamjae Jeon * Return 0 on success and -errno on error. 6691e9ea7e0SNamjae Jeon */ 6701e9ea7e0SNamjae Jeon static int ntfs_read_locked_inode(struct inode *vi) 6711e9ea7e0SNamjae Jeon { 672af0db57dSNamjae Jeon struct ntfs_volume *vol = NTFS_SB(vi->i_sb); 673e7d82353SNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 674af0db57dSNamjae Jeon struct mft_record *m; 675af0db57dSNamjae Jeon struct attr_record *a; 676af0db57dSNamjae Jeon struct standard_information *si; 677af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 6781e9ea7e0SNamjae Jeon int err = 0; 679af0db57dSNamjae Jeon __le16 *name = I30; 680af0db57dSNamjae Jeon unsigned int name_len = 4, flags = 0; 681af0db57dSNamjae Jeon int extend_sys = 0; 682af0db57dSNamjae Jeon dev_t dev = 0; 683af0db57dSNamjae Jeon bool vol_err = true; 6841e9ea7e0SNamjae Jeon 685e7d82353SNamjae Jeon ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no); 6861e9ea7e0SNamjae Jeon 687af0db57dSNamjae Jeon if (uid_valid(vol->uid)) { 6881e9ea7e0SNamjae Jeon vi->i_uid = vol->uid; 689af0db57dSNamjae Jeon flags |= NTFS_VOL_UID; 690af0db57dSNamjae Jeon } else 691af0db57dSNamjae Jeon vi->i_uid = GLOBAL_ROOT_UID; 692af0db57dSNamjae Jeon 693af0db57dSNamjae Jeon if (gid_valid(vol->gid)) { 6941e9ea7e0SNamjae Jeon vi->i_gid = vol->gid; 695af0db57dSNamjae Jeon flags |= NTFS_VOL_GID; 696af0db57dSNamjae Jeon } else 697af0db57dSNamjae Jeon vi->i_gid = GLOBAL_ROOT_GID; 698af0db57dSNamjae Jeon 699af0db57dSNamjae Jeon vi->i_mode = 0777; 7001e9ea7e0SNamjae Jeon 7011e9ea7e0SNamjae Jeon /* 7021e9ea7e0SNamjae Jeon * Initialize the ntfs specific part of @vi special casing 7031e9ea7e0SNamjae Jeon * FILE_MFT which we need to do at mount time. 7041e9ea7e0SNamjae Jeon */ 7051e9ea7e0SNamjae Jeon if (vi->i_ino != FILE_MFT) 7061e9ea7e0SNamjae Jeon ntfs_init_big_inode(vi); 7071e9ea7e0SNamjae Jeon 7081e9ea7e0SNamjae Jeon m = map_mft_record(ni); 7091e9ea7e0SNamjae Jeon if (IS_ERR(m)) { 7101e9ea7e0SNamjae Jeon err = PTR_ERR(m); 7111e9ea7e0SNamjae Jeon goto err_out; 7121e9ea7e0SNamjae Jeon } 713af0db57dSNamjae Jeon 7141e9ea7e0SNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, m); 7151e9ea7e0SNamjae Jeon if (!ctx) { 7161e9ea7e0SNamjae Jeon err = -ENOMEM; 7171e9ea7e0SNamjae Jeon goto unm_err_out; 7181e9ea7e0SNamjae Jeon } 7191e9ea7e0SNamjae Jeon 7201e9ea7e0SNamjae Jeon if (!(m->flags & MFT_RECORD_IN_USE)) { 721af0db57dSNamjae Jeon err = -ENOENT; 722af0db57dSNamjae Jeon vol_err = false; 7231e9ea7e0SNamjae Jeon goto unm_err_out; 7241e9ea7e0SNamjae Jeon } 725af0db57dSNamjae Jeon 7261e9ea7e0SNamjae Jeon if (m->base_mft_record) { 7271e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Inode is an extent inode!"); 7281e9ea7e0SNamjae Jeon goto unm_err_out; 7291e9ea7e0SNamjae Jeon } 7301e9ea7e0SNamjae Jeon 7311e9ea7e0SNamjae Jeon /* Transfer information from mft record into vfs and ntfs inodes. */ 7321e9ea7e0SNamjae Jeon vi->i_generation = ni->seq_no = le16_to_cpu(m->sequence_number); 7331e9ea7e0SNamjae Jeon 734af0db57dSNamjae Jeon if (le16_to_cpu(m->link_count) < 1) { 735af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Inode link count is 0!"); 736af0db57dSNamjae Jeon goto unm_err_out; 737af0db57dSNamjae Jeon } 7381e9ea7e0SNamjae Jeon set_nlink(vi, le16_to_cpu(m->link_count)); 739af0db57dSNamjae Jeon 7401e9ea7e0SNamjae Jeon /* If read-only, no one gets write permissions. */ 7411e9ea7e0SNamjae Jeon if (IS_RDONLY(vi)) 742af0db57dSNamjae Jeon vi->i_mode &= ~0222; 743af0db57dSNamjae Jeon 7441e9ea7e0SNamjae Jeon /* 7451e9ea7e0SNamjae Jeon * Find the standard information attribute in the mft record. At this 7461e9ea7e0SNamjae Jeon * stage we haven't setup the attribute list stuff yet, so this could 7471e9ea7e0SNamjae Jeon * in fact fail if the standard information is in an extent record, but 7481e9ea7e0SNamjae Jeon * I don't think this actually ever happens. 7491e9ea7e0SNamjae Jeon */ 750af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 7511e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0, 0, 0, NULL, 0, 7521e9ea7e0SNamjae Jeon ctx); 7531e9ea7e0SNamjae Jeon if (unlikely(err)) { 754af0db57dSNamjae Jeon if (err == -ENOENT) 755af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "$STANDARD_INFORMATION attribute is missing."); 7561e9ea7e0SNamjae Jeon goto unm_err_out; 7571e9ea7e0SNamjae Jeon } 7581e9ea7e0SNamjae Jeon a = ctx->attr; 7591e9ea7e0SNamjae Jeon /* Get the standard information attribute value. */ 760af0db57dSNamjae Jeon si = (struct standard_information *)((u8 *)a + 7611e9ea7e0SNamjae Jeon le16_to_cpu(a->data.resident.value_offset)); 7621e9ea7e0SNamjae Jeon 7631e9ea7e0SNamjae Jeon /* Transfer information from the standard information into vi. */ 7641e9ea7e0SNamjae Jeon /* 7651e9ea7e0SNamjae Jeon * Note: The i_?times do not quite map perfectly onto the NTFS times, 7661e9ea7e0SNamjae Jeon * but they are close enough, and in the end it doesn't really matter 7671e9ea7e0SNamjae Jeon * that much... 7681e9ea7e0SNamjae Jeon */ 7691e9ea7e0SNamjae Jeon /* 7701e9ea7e0SNamjae Jeon * mtime is the last change of the data within the file. Not changed 7711e9ea7e0SNamjae Jeon * when only metadata is changed, e.g. a rename doesn't affect mtime. 7721e9ea7e0SNamjae Jeon */ 773af0db57dSNamjae Jeon ni->i_crtime = ntfs2utc(si->creation_time); 774af0db57dSNamjae Jeon 7751e9ea7e0SNamjae Jeon inode_set_mtime_to_ts(vi, ntfs2utc(si->last_data_change_time)); 7761e9ea7e0SNamjae Jeon /* 7771e9ea7e0SNamjae Jeon * ctime is the last change of the metadata of the file. This obviously 7781e9ea7e0SNamjae Jeon * always changes, when mtime is changed. ctime can be changed on its 7791e9ea7e0SNamjae Jeon * own, mtime is then not changed, e.g. when a file is renamed. 7801e9ea7e0SNamjae Jeon */ 7811e9ea7e0SNamjae Jeon inode_set_ctime_to_ts(vi, ntfs2utc(si->last_mft_change_time)); 7821e9ea7e0SNamjae Jeon /* 7831e9ea7e0SNamjae Jeon * Last access to the data within the file. Not changed during a rename 7841e9ea7e0SNamjae Jeon * for example but changed whenever the file is written to. 7851e9ea7e0SNamjae Jeon */ 7861e9ea7e0SNamjae Jeon inode_set_atime_to_ts(vi, ntfs2utc(si->last_access_time)); 787af0db57dSNamjae Jeon ni->flags = si->file_attributes; 7881e9ea7e0SNamjae Jeon 7891e9ea7e0SNamjae Jeon /* Find the attribute list attribute if present. */ 7901e9ea7e0SNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 7911e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx); 7921e9ea7e0SNamjae Jeon if (err) { 7931e9ea7e0SNamjae Jeon if (unlikely(err != -ENOENT)) { 794af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to lookup attribute list attribute."); 7951e9ea7e0SNamjae Jeon goto unm_err_out; 7961e9ea7e0SNamjae Jeon } 797af0db57dSNamjae Jeon } else { 7981e9ea7e0SNamjae Jeon if (vi->i_ino == FILE_MFT) 7991e9ea7e0SNamjae Jeon goto skip_attr_list_load; 800e7d82353SNamjae Jeon ntfs_debug("Attribute list found in inode 0x%llx.", ni->mft_no); 8011e9ea7e0SNamjae Jeon NInoSetAttrList(ni); 8021e9ea7e0SNamjae Jeon a = ctx->attr; 8031e9ea7e0SNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK) { 804af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 805af0db57dSNamjae Jeon "Attribute list attribute is compressed."); 8061e9ea7e0SNamjae Jeon goto unm_err_out; 8071e9ea7e0SNamjae Jeon } 8081e9ea7e0SNamjae Jeon if (a->flags & ATTR_IS_ENCRYPTED || 8091e9ea7e0SNamjae Jeon a->flags & ATTR_IS_SPARSE) { 8101e9ea7e0SNamjae Jeon if (a->non_resident) { 811af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 812af0db57dSNamjae Jeon "Non-resident attribute list attribute is encrypted/sparse."); 8131e9ea7e0SNamjae Jeon goto unm_err_out; 8141e9ea7e0SNamjae Jeon } 815af0db57dSNamjae Jeon ntfs_warning(vi->i_sb, 816e7d82353SNamjae Jeon "Resident attribute list attribute in inode 0x%llx is marked encrypted/sparse which is not true. However, Windows allows this and chkdsk does not detect or correct it so we will just ignore the invalid flags and pretend they are not set.", 817e7d82353SNamjae Jeon ni->mft_no); 8181e9ea7e0SNamjae Jeon } 8191e9ea7e0SNamjae Jeon /* Now allocate memory for the attribute list. */ 8201e9ea7e0SNamjae Jeon ni->attr_list_size = (u32)ntfs_attr_size(a); 821af0db57dSNamjae Jeon if (!ni->attr_list_size) { 822af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Attr_list_size is zero"); 823af0db57dSNamjae Jeon goto unm_err_out; 824af0db57dSNamjae Jeon } 825af0db57dSNamjae Jeon ni->attr_list = kvzalloc(ni->attr_list_size, GFP_NOFS); 8261e9ea7e0SNamjae Jeon if (!ni->attr_list) { 827af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 828af0db57dSNamjae Jeon "Not enough memory to allocate buffer for attribute list."); 8291e9ea7e0SNamjae Jeon err = -ENOMEM; 8301e9ea7e0SNamjae Jeon goto unm_err_out; 8311e9ea7e0SNamjae Jeon } 8321e9ea7e0SNamjae Jeon if (a->non_resident) { 8331e9ea7e0SNamjae Jeon NInoSetAttrListNonResident(ni); 8341e9ea7e0SNamjae Jeon if (a->data.non_resident.lowest_vcn) { 835af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Attribute list has non zero lowest_vcn."); 8361e9ea7e0SNamjae Jeon goto unm_err_out; 8371e9ea7e0SNamjae Jeon } 838af0db57dSNamjae Jeon 8391e9ea7e0SNamjae Jeon /* Now load the attribute list. */ 840af0db57dSNamjae Jeon err = load_attribute_list(ni, ni->attr_list, ni->attr_list_size); 841af0db57dSNamjae Jeon if (err) { 842af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to load attribute list attribute."); 8431e9ea7e0SNamjae Jeon goto unm_err_out; 8441e9ea7e0SNamjae Jeon } 8451e9ea7e0SNamjae Jeon } else /* if (!a->non_resident) */ { 8461e9ea7e0SNamjae Jeon /* Now copy the attribute list. */ 8471e9ea7e0SNamjae Jeon memcpy(ni->attr_list, (u8 *)a + le16_to_cpu( 8481e9ea7e0SNamjae Jeon a->data.resident.value_offset), 8491e9ea7e0SNamjae Jeon le32_to_cpu( 8501e9ea7e0SNamjae Jeon a->data.resident.value_length)); 8511e9ea7e0SNamjae Jeon } 8521e9ea7e0SNamjae Jeon } 8531e9ea7e0SNamjae Jeon skip_attr_list_load: 854af0db57dSNamjae Jeon err = ntfs_attr_lookup(AT_EA_INFORMATION, NULL, 0, 0, 0, NULL, 0, ctx); 855a7325868SHyunchul Lee if (!err) { 856af0db57dSNamjae Jeon NInoSetHasEA(ni); 857af0db57dSNamjae Jeon ntfs_ea_get_wsl_inode(vi, &dev, flags); 858a7325868SHyunchul Lee } 859af0db57dSNamjae Jeon 860af0db57dSNamjae Jeon if (m->flags & MFT_RECORD_IS_DIRECTORY) { 861af0db57dSNamjae Jeon vi->i_mode |= S_IFDIR; 862af0db57dSNamjae Jeon /* 863af0db57dSNamjae Jeon * Apply the directory permissions mask set in the mount 864af0db57dSNamjae Jeon * options. 865af0db57dSNamjae Jeon */ 866af0db57dSNamjae Jeon vi->i_mode &= ~vol->dmask; 867af0db57dSNamjae Jeon /* Things break without this kludge! */ 868af0db57dSNamjae Jeon if (vi->i_nlink > 1) 869af0db57dSNamjae Jeon set_nlink(vi, 1); 870af0db57dSNamjae Jeon } else { 871af0db57dSNamjae Jeon if (ni->flags & FILE_ATTR_REPARSE_POINT) { 872af0db57dSNamjae Jeon unsigned int mode; 873af0db57dSNamjae Jeon 874af0db57dSNamjae Jeon mode = ntfs_make_symlink(ni); 875af0db57dSNamjae Jeon if (mode) 876af0db57dSNamjae Jeon vi->i_mode |= mode; 877af0db57dSNamjae Jeon else { 878af0db57dSNamjae Jeon vi->i_mode &= ~S_IFLNK; 879af0db57dSNamjae Jeon vi->i_mode |= S_IFREG; 880af0db57dSNamjae Jeon } 881af0db57dSNamjae Jeon } else 882af0db57dSNamjae Jeon vi->i_mode |= S_IFREG; 883af0db57dSNamjae Jeon /* Apply the file permissions mask set in the mount options. */ 884af0db57dSNamjae Jeon vi->i_mode &= ~vol->fmask; 885af0db57dSNamjae Jeon } 886af0db57dSNamjae Jeon 8871e9ea7e0SNamjae Jeon /* 8881e9ea7e0SNamjae Jeon * If an attribute list is present we now have the attribute list value 8891e9ea7e0SNamjae Jeon * in ntfs_ino->attr_list and it is ntfs_ino->attr_list_size bytes. 8901e9ea7e0SNamjae Jeon */ 8911e9ea7e0SNamjae Jeon if (S_ISDIR(vi->i_mode)) { 892af0db57dSNamjae Jeon struct index_root *ir; 8931e9ea7e0SNamjae Jeon u8 *ir_end, *index_end; 8941e9ea7e0SNamjae Jeon 895af0db57dSNamjae Jeon view_index_meta: 8961e9ea7e0SNamjae Jeon /* It is a directory, find index root attribute. */ 8971e9ea7e0SNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 898af0db57dSNamjae Jeon err = ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, 8991e9ea7e0SNamjae Jeon 0, NULL, 0, ctx); 9001e9ea7e0SNamjae Jeon if (unlikely(err)) { 901af0db57dSNamjae Jeon if (err == -ENOENT) 902af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is missing."); 9031e9ea7e0SNamjae Jeon goto unm_err_out; 9041e9ea7e0SNamjae Jeon } 9051e9ea7e0SNamjae Jeon a = ctx->attr; 9061e9ea7e0SNamjae Jeon /* Set up the state. */ 9071e9ea7e0SNamjae Jeon if (unlikely(a->non_resident)) { 908af0db57dSNamjae Jeon ntfs_error(vol->sb, 909af0db57dSNamjae Jeon "$INDEX_ROOT attribute is not resident."); 9101e9ea7e0SNamjae Jeon goto unm_err_out; 9111e9ea7e0SNamjae Jeon } 9121e9ea7e0SNamjae Jeon /* Ensure the attribute name is placed before the value. */ 9131e9ea7e0SNamjae Jeon if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= 9141e9ea7e0SNamjae Jeon le16_to_cpu(a->data.resident.value_offset)))) { 915af0db57dSNamjae Jeon ntfs_error(vol->sb, 916af0db57dSNamjae Jeon "$INDEX_ROOT attribute name is placed after the attribute value."); 9171e9ea7e0SNamjae Jeon goto unm_err_out; 9181e9ea7e0SNamjae Jeon } 9191e9ea7e0SNamjae Jeon /* 9201e9ea7e0SNamjae Jeon * Compressed/encrypted index root just means that the newly 9211e9ea7e0SNamjae Jeon * created files in that directory should be created compressed/ 9221e9ea7e0SNamjae Jeon * encrypted. However index root cannot be both compressed and 9231e9ea7e0SNamjae Jeon * encrypted. 9241e9ea7e0SNamjae Jeon */ 925af0db57dSNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK) { 9261e9ea7e0SNamjae Jeon NInoSetCompressed(ni); 927af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_COMPRESSED; 928af0db57dSNamjae Jeon } 9291e9ea7e0SNamjae Jeon if (a->flags & ATTR_IS_ENCRYPTED) { 9301e9ea7e0SNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK) { 931af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Found encrypted and compressed attribute."); 9321e9ea7e0SNamjae Jeon goto unm_err_out; 9331e9ea7e0SNamjae Jeon } 9341e9ea7e0SNamjae Jeon NInoSetEncrypted(ni); 935af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_ENCRYPTED; 9361e9ea7e0SNamjae Jeon } 937af0db57dSNamjae Jeon if (a->flags & ATTR_IS_SPARSE) { 9381e9ea7e0SNamjae Jeon NInoSetSparse(ni); 939af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_SPARSE_FILE; 940af0db57dSNamjae Jeon } 941af0db57dSNamjae Jeon ir = (struct index_root *)((u8 *)a + 9421e9ea7e0SNamjae Jeon le16_to_cpu(a->data.resident.value_offset)); 9431e9ea7e0SNamjae Jeon ir_end = (u8 *)ir + le32_to_cpu(a->data.resident.value_length); 9441e9ea7e0SNamjae Jeon index_end = (u8 *)&ir->index + 9451e9ea7e0SNamjae Jeon le32_to_cpu(ir->index.index_length); 9461e9ea7e0SNamjae Jeon if (index_end > ir_end) { 9471e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Directory index is corrupt."); 9481e9ea7e0SNamjae Jeon goto unm_err_out; 9491e9ea7e0SNamjae Jeon } 950af0db57dSNamjae Jeon 951af0db57dSNamjae Jeon if (extend_sys) { 952af0db57dSNamjae Jeon if (ir->type) { 953af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Indexed attribute is not zero."); 954af0db57dSNamjae Jeon goto unm_err_out; 955af0db57dSNamjae Jeon } 956af0db57dSNamjae Jeon } else { 9571e9ea7e0SNamjae Jeon if (ir->type != AT_FILE_NAME) { 958af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Indexed attribute is not $FILE_NAME."); 9591e9ea7e0SNamjae Jeon goto unm_err_out; 9601e9ea7e0SNamjae Jeon } 961af0db57dSNamjae Jeon 9621e9ea7e0SNamjae Jeon if (ir->collation_rule != COLLATION_FILE_NAME) { 963af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 964af0db57dSNamjae Jeon "Index collation rule is not COLLATION_FILE_NAME."); 9651e9ea7e0SNamjae Jeon goto unm_err_out; 9661e9ea7e0SNamjae Jeon } 967af0db57dSNamjae Jeon } 968af0db57dSNamjae Jeon 9691e9ea7e0SNamjae Jeon ni->itype.index.collation_rule = ir->collation_rule; 9701e9ea7e0SNamjae Jeon ni->itype.index.block_size = le32_to_cpu(ir->index_block_size); 9711e9ea7e0SNamjae Jeon if (ni->itype.index.block_size & 9721e9ea7e0SNamjae Jeon (ni->itype.index.block_size - 1)) { 973af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Index block size (%u) is not a power of two.", 9741e9ea7e0SNamjae Jeon ni->itype.index.block_size); 9751e9ea7e0SNamjae Jeon goto unm_err_out; 9761e9ea7e0SNamjae Jeon } 9771e9ea7e0SNamjae Jeon if (ni->itype.index.block_size > PAGE_SIZE) { 978af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 979af0db57dSNamjae Jeon "Index block size (%u) > PAGE_SIZE (%ld) is not supported.", 9801e9ea7e0SNamjae Jeon ni->itype.index.block_size, 9811e9ea7e0SNamjae Jeon PAGE_SIZE); 9821e9ea7e0SNamjae Jeon err = -EOPNOTSUPP; 9831e9ea7e0SNamjae Jeon goto unm_err_out; 9841e9ea7e0SNamjae Jeon } 9851e9ea7e0SNamjae Jeon if (ni->itype.index.block_size < NTFS_BLOCK_SIZE) { 986af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 987af0db57dSNamjae Jeon "Index block size (%u) < NTFS_BLOCK_SIZE (%i) is not supported.", 9881e9ea7e0SNamjae Jeon ni->itype.index.block_size, 9891e9ea7e0SNamjae Jeon NTFS_BLOCK_SIZE); 9901e9ea7e0SNamjae Jeon err = -EOPNOTSUPP; 9911e9ea7e0SNamjae Jeon goto unm_err_out; 9921e9ea7e0SNamjae Jeon } 9931e9ea7e0SNamjae Jeon ni->itype.index.block_size_bits = 9941e9ea7e0SNamjae Jeon ffs(ni->itype.index.block_size) - 1; 9951e9ea7e0SNamjae Jeon /* Determine the size of a vcn in the directory index. */ 9961e9ea7e0SNamjae Jeon if (vol->cluster_size <= ni->itype.index.block_size) { 9971e9ea7e0SNamjae Jeon ni->itype.index.vcn_size = vol->cluster_size; 9981e9ea7e0SNamjae Jeon ni->itype.index.vcn_size_bits = vol->cluster_size_bits; 9991e9ea7e0SNamjae Jeon } else { 10001e9ea7e0SNamjae Jeon ni->itype.index.vcn_size = vol->sector_size; 10011e9ea7e0SNamjae Jeon ni->itype.index.vcn_size_bits = vol->sector_size_bits; 10021e9ea7e0SNamjae Jeon } 10031e9ea7e0SNamjae Jeon 10041e9ea7e0SNamjae Jeon /* Setup the index allocation attribute, even if not present. */ 1005af0db57dSNamjae Jeon ni->type = AT_INDEX_ROOT; 1006af0db57dSNamjae Jeon ni->name = name; 1007af0db57dSNamjae Jeon ni->name_len = name_len; 1008af0db57dSNamjae Jeon vi->i_size = ni->initialized_size = ni->data_size = 1009af0db57dSNamjae Jeon le32_to_cpu(a->data.resident.value_length); 1010af0db57dSNamjae Jeon ni->allocated_size = (ni->data_size + 7) & ~7; 10111e9ea7e0SNamjae Jeon /* We are done with the mft record, so we release it. */ 10121e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 10131e9ea7e0SNamjae Jeon unmap_mft_record(ni); 10141e9ea7e0SNamjae Jeon m = NULL; 10151e9ea7e0SNamjae Jeon ctx = NULL; 10161e9ea7e0SNamjae Jeon /* Setup the operations for this inode. */ 1017af0db57dSNamjae Jeon ntfs_set_vfs_operations(vi, S_IFDIR, 0); 1018af0db57dSNamjae Jeon if (ir->index.flags & LARGE_INDEX) 1019af0db57dSNamjae Jeon NInoSetIndexAllocPresent(ni); 10201e9ea7e0SNamjae Jeon } else { 10211e9ea7e0SNamjae Jeon /* It is a file. */ 10221e9ea7e0SNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 10231e9ea7e0SNamjae Jeon 10241e9ea7e0SNamjae Jeon /* Setup the data attribute, even if not present. */ 10251e9ea7e0SNamjae Jeon ni->type = AT_DATA; 1026af0db57dSNamjae Jeon ni->name = AT_UNNAMED; 10271e9ea7e0SNamjae Jeon ni->name_len = 0; 10281e9ea7e0SNamjae Jeon 10291e9ea7e0SNamjae Jeon /* Find first extent of the unnamed data attribute. */ 10301e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx); 10311e9ea7e0SNamjae Jeon if (unlikely(err)) { 10321e9ea7e0SNamjae Jeon vi->i_size = ni->initialized_size = 10331e9ea7e0SNamjae Jeon ni->allocated_size = 0; 10341e9ea7e0SNamjae Jeon if (err != -ENOENT) { 1035af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to lookup $DATA attribute."); 10361e9ea7e0SNamjae Jeon goto unm_err_out; 10371e9ea7e0SNamjae Jeon } 10381e9ea7e0SNamjae Jeon /* 10391e9ea7e0SNamjae Jeon * FILE_Secure does not have an unnamed $DATA 10401e9ea7e0SNamjae Jeon * attribute, so we special case it here. 10411e9ea7e0SNamjae Jeon */ 10421e9ea7e0SNamjae Jeon if (vi->i_ino == FILE_Secure) 10431e9ea7e0SNamjae Jeon goto no_data_attr_special_case; 10441e9ea7e0SNamjae Jeon /* 10451e9ea7e0SNamjae Jeon * Most if not all the system files in the $Extend 10461e9ea7e0SNamjae Jeon * system directory do not have unnamed data 10471e9ea7e0SNamjae Jeon * attributes so we need to check if the parent 10481e9ea7e0SNamjae Jeon * directory of the file is FILE_Extend and if it is 10491e9ea7e0SNamjae Jeon * ignore this error. To do this we need to get the 10501e9ea7e0SNamjae Jeon * name of this inode from the mft record as the name 10511e9ea7e0SNamjae Jeon * contains the back reference to the parent directory. 10521e9ea7e0SNamjae Jeon */ 1053af0db57dSNamjae Jeon extend_sys = ntfs_is_extended_system_file(ctx); 1054af0db57dSNamjae Jeon if (extend_sys > 0) { 1055af0db57dSNamjae Jeon if (m->flags & MFT_RECORD_IS_VIEW_INDEX) { 1056af0db57dSNamjae Jeon if (extend_sys == 2) { 1057af0db57dSNamjae Jeon name = reparse_index_name; 1058af0db57dSNamjae Jeon name_len = 2; 1059af0db57dSNamjae Jeon goto view_index_meta; 1060af0db57dSNamjae Jeon } else if (extend_sys == 3) { 1061af0db57dSNamjae Jeon name = objid_index_name; 1062af0db57dSNamjae Jeon name_len = 2; 1063af0db57dSNamjae Jeon goto view_index_meta; 1064af0db57dSNamjae Jeon } 1065af0db57dSNamjae Jeon } 10661e9ea7e0SNamjae Jeon goto no_data_attr_special_case; 1067af0db57dSNamjae Jeon } 1068af0db57dSNamjae Jeon 1069af0db57dSNamjae Jeon err = extend_sys; 1070af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "$DATA attribute is missing, err : %d", err); 10711e9ea7e0SNamjae Jeon goto unm_err_out; 10721e9ea7e0SNamjae Jeon } 10731e9ea7e0SNamjae Jeon a = ctx->attr; 10741e9ea7e0SNamjae Jeon /* Setup the state. */ 10751e9ea7e0SNamjae Jeon if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) { 10761e9ea7e0SNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK) { 10771e9ea7e0SNamjae Jeon NInoSetCompressed(ni); 1078af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_COMPRESSED; 10791e9ea7e0SNamjae Jeon if (vol->cluster_size > 4096) { 1080af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1081af0db57dSNamjae Jeon "Found compressed data but compression is disabled due to cluster size (%i) > 4kiB.", 10821e9ea7e0SNamjae Jeon vol->cluster_size); 10831e9ea7e0SNamjae Jeon goto unm_err_out; 10841e9ea7e0SNamjae Jeon } 10851e9ea7e0SNamjae Jeon if ((a->flags & ATTR_COMPRESSION_MASK) 10861e9ea7e0SNamjae Jeon != ATTR_IS_COMPRESSED) { 1087af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1088af0db57dSNamjae Jeon "Found unknown compression method or corrupt file."); 10891e9ea7e0SNamjae Jeon goto unm_err_out; 10901e9ea7e0SNamjae Jeon } 10911e9ea7e0SNamjae Jeon } 1092af0db57dSNamjae Jeon if (a->flags & ATTR_IS_SPARSE) { 10931e9ea7e0SNamjae Jeon NInoSetSparse(ni); 1094af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_SPARSE_FILE; 1095af0db57dSNamjae Jeon } 10961e9ea7e0SNamjae Jeon } 10971e9ea7e0SNamjae Jeon if (a->flags & ATTR_IS_ENCRYPTED) { 10981e9ea7e0SNamjae Jeon if (NInoCompressed(ni)) { 1099af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Found encrypted and compressed data."); 11001e9ea7e0SNamjae Jeon goto unm_err_out; 11011e9ea7e0SNamjae Jeon } 11021e9ea7e0SNamjae Jeon NInoSetEncrypted(ni); 1103af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_ENCRYPTED; 11041e9ea7e0SNamjae Jeon } 11051e9ea7e0SNamjae Jeon if (a->non_resident) { 11061e9ea7e0SNamjae Jeon NInoSetNonResident(ni); 11071e9ea7e0SNamjae Jeon if (NInoCompressed(ni) || NInoSparse(ni)) { 1108af0db57dSNamjae Jeon if (NInoCompressed(ni) && 1109af0db57dSNamjae Jeon a->data.non_resident.compression_unit != 4) { 1110af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1111af0db57dSNamjae Jeon "Found non-standard compression unit (%u instead of 4). Cannot handle this.", 1112af0db57dSNamjae Jeon a->data.non_resident.compression_unit); 11131e9ea7e0SNamjae Jeon err = -EOPNOTSUPP; 11141e9ea7e0SNamjae Jeon goto unm_err_out; 11151e9ea7e0SNamjae Jeon } 1116af0db57dSNamjae Jeon 1117af0db57dSNamjae Jeon if (NInoSparse(ni) && 1118af0db57dSNamjae Jeon a->data.non_resident.compression_unit && 1119af0db57dSNamjae Jeon a->data.non_resident.compression_unit != 1120af0db57dSNamjae Jeon vol->sparse_compression_unit) { 1121af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1122af0db57dSNamjae Jeon "Found non-standard compression unit (%u instead of 0 or %d). Cannot handle this.", 1123af0db57dSNamjae Jeon a->data.non_resident.compression_unit, 1124af0db57dSNamjae Jeon vol->sparse_compression_unit); 1125af0db57dSNamjae Jeon err = -EOPNOTSUPP; 1126af0db57dSNamjae Jeon goto unm_err_out; 1127af0db57dSNamjae Jeon } 1128af0db57dSNamjae Jeon 1129af0db57dSNamjae Jeon 11301e9ea7e0SNamjae Jeon if (a->data.non_resident.compression_unit) { 11311e9ea7e0SNamjae Jeon ni->itype.compressed.block_size = 1U << 1132af0db57dSNamjae Jeon (a->data.non_resident.compression_unit + 11331e9ea7e0SNamjae Jeon vol->cluster_size_bits); 11341e9ea7e0SNamjae Jeon ni->itype.compressed.block_size_bits = 1135af0db57dSNamjae Jeon ffs(ni->itype.compressed.block_size) - 1; 11361e9ea7e0SNamjae Jeon ni->itype.compressed.block_clusters = 1137af0db57dSNamjae Jeon 1U << a->data.non_resident.compression_unit; 11381e9ea7e0SNamjae Jeon } else { 11391e9ea7e0SNamjae Jeon ni->itype.compressed.block_size = 0; 11401e9ea7e0SNamjae Jeon ni->itype.compressed.block_size_bits = 11411e9ea7e0SNamjae Jeon 0; 11421e9ea7e0SNamjae Jeon ni->itype.compressed.block_clusters = 11431e9ea7e0SNamjae Jeon 0; 11441e9ea7e0SNamjae Jeon } 1145af0db57dSNamjae Jeon ni->itype.compressed.size = le64_to_cpu( 1146af0db57dSNamjae Jeon a->data.non_resident.compressed_size); 11471e9ea7e0SNamjae Jeon } 11481e9ea7e0SNamjae Jeon if (a->data.non_resident.lowest_vcn) { 1149af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1150af0db57dSNamjae Jeon "First extent of $DATA attribute has non zero lowest_vcn."); 11511e9ea7e0SNamjae Jeon goto unm_err_out; 11521e9ea7e0SNamjae Jeon } 1153af0db57dSNamjae Jeon vi->i_size = ni->data_size = le64_to_cpu(a->data.non_resident.data_size); 1154af0db57dSNamjae Jeon ni->initialized_size = le64_to_cpu(a->data.non_resident.initialized_size); 1155af0db57dSNamjae Jeon ni->allocated_size = le64_to_cpu(a->data.non_resident.allocated_size); 11561e9ea7e0SNamjae Jeon } else { /* Resident attribute. */ 1157af0db57dSNamjae Jeon vi->i_size = ni->data_size = ni->initialized_size = le32_to_cpu( 11581e9ea7e0SNamjae Jeon a->data.resident.value_length); 11591e9ea7e0SNamjae Jeon ni->allocated_size = le32_to_cpu(a->length) - 11601e9ea7e0SNamjae Jeon le16_to_cpu( 11611e9ea7e0SNamjae Jeon a->data.resident.value_offset); 11621e9ea7e0SNamjae Jeon if (vi->i_size > ni->allocated_size) { 1163af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1164af0db57dSNamjae Jeon "Resident data attribute is corrupt (size exceeds allocation)."); 11651e9ea7e0SNamjae Jeon goto unm_err_out; 11661e9ea7e0SNamjae Jeon } 11671e9ea7e0SNamjae Jeon } 11681e9ea7e0SNamjae Jeon no_data_attr_special_case: 11691e9ea7e0SNamjae Jeon /* We are done with the mft record, so we release it. */ 11701e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 11711e9ea7e0SNamjae Jeon unmap_mft_record(ni); 11721e9ea7e0SNamjae Jeon m = NULL; 11731e9ea7e0SNamjae Jeon ctx = NULL; 11741e9ea7e0SNamjae Jeon /* Setup the operations for this inode. */ 1175af0db57dSNamjae Jeon ntfs_set_vfs_operations(vi, vi->i_mode, dev); 11761e9ea7e0SNamjae Jeon } 1177af0db57dSNamjae Jeon 1178af0db57dSNamjae Jeon if (NVolSysImmutable(vol) && (ni->flags & FILE_ATTR_SYSTEM) && 1179af0db57dSNamjae Jeon !S_ISFIFO(vi->i_mode) && !S_ISSOCK(vi->i_mode) && !S_ISLNK(vi->i_mode)) 1180af0db57dSNamjae Jeon vi->i_flags |= S_IMMUTABLE; 1181af0db57dSNamjae Jeon 11821e9ea7e0SNamjae Jeon /* 11831e9ea7e0SNamjae Jeon * The number of 512-byte blocks used on disk (for stat). This is in so 11841e9ea7e0SNamjae Jeon * far inaccurate as it doesn't account for any named streams or other 11851e9ea7e0SNamjae Jeon * special non-resident attributes, but that is how Windows works, too, 11861e9ea7e0SNamjae Jeon * so we are at least consistent with Windows, if not entirely 11871e9ea7e0SNamjae Jeon * consistent with the Linux Way. Doing it the Linux Way would cause a 11881e9ea7e0SNamjae Jeon * significant slowdown as it would involve iterating over all 11891e9ea7e0SNamjae Jeon * attributes in the mft record and adding the allocated/compressed 11901e9ea7e0SNamjae Jeon * sizes of all non-resident attributes present to give us the Linux 11911e9ea7e0SNamjae Jeon * correct size that should go into i_blocks (after division by 512). 11921e9ea7e0SNamjae Jeon */ 11931e9ea7e0SNamjae Jeon if (S_ISREG(vi->i_mode) && (NInoCompressed(ni) || NInoSparse(ni))) 11941e9ea7e0SNamjae Jeon vi->i_blocks = ni->itype.compressed.size >> 9; 11951e9ea7e0SNamjae Jeon else 11961e9ea7e0SNamjae Jeon vi->i_blocks = ni->allocated_size >> 9; 1197af0db57dSNamjae Jeon 11981e9ea7e0SNamjae Jeon ntfs_debug("Done."); 11991e9ea7e0SNamjae Jeon return 0; 12001e9ea7e0SNamjae Jeon unm_err_out: 12011e9ea7e0SNamjae Jeon if (!err) 12021e9ea7e0SNamjae Jeon err = -EIO; 12031e9ea7e0SNamjae Jeon if (ctx) 12041e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 12051e9ea7e0SNamjae Jeon if (m) 12061e9ea7e0SNamjae Jeon unmap_mft_record(ni); 12071e9ea7e0SNamjae Jeon err_out: 1208af0db57dSNamjae Jeon if (err != -EOPNOTSUPP && err != -ENOMEM && vol_err == true) { 1209af0db57dSNamjae Jeon ntfs_error(vol->sb, 1210e7d82353SNamjae Jeon "Failed with error code %i. Marking corrupt inode 0x%llx as bad. Run chkdsk.", 1211e7d82353SNamjae Jeon err, ni->mft_no); 12121e9ea7e0SNamjae Jeon NVolSetErrors(vol); 1213af0db57dSNamjae Jeon } 12141e9ea7e0SNamjae Jeon return err; 12151e9ea7e0SNamjae Jeon } 12161e9ea7e0SNamjae Jeon 1217af0db57dSNamjae Jeon /* 12181e9ea7e0SNamjae Jeon * ntfs_read_locked_attr_inode - read an attribute inode from its base inode 12191e9ea7e0SNamjae Jeon * @base_vi: base inode 12201e9ea7e0SNamjae Jeon * @vi: attribute inode to read 12211e9ea7e0SNamjae Jeon * 12221e9ea7e0SNamjae Jeon * ntfs_read_locked_attr_inode() is called from ntfs_attr_iget() to read the 12231e9ea7e0SNamjae Jeon * attribute inode described by @vi into memory from the base mft record 12241e9ea7e0SNamjae Jeon * described by @base_ni. 12251e9ea7e0SNamjae Jeon * 12261e9ea7e0SNamjae Jeon * ntfs_read_locked_attr_inode() maps, pins and locks the base inode for 12271e9ea7e0SNamjae Jeon * reading and looks up the attribute described by @vi before setting up the 12281e9ea7e0SNamjae Jeon * necessary fields in @vi as well as initializing the ntfs inode. 12291e9ea7e0SNamjae Jeon * 12301e9ea7e0SNamjae Jeon * Q: What locks are held when the function is called? 12311e9ea7e0SNamjae Jeon * A: i_state has I_NEW set, hence the inode is locked, also 12321e9ea7e0SNamjae Jeon * i_count is set to 1, so it is not going to go away 12331e9ea7e0SNamjae Jeon * 1234af0db57dSNamjae Jeon * Return 0 on success and -errno on error. 12351e9ea7e0SNamjae Jeon * 12361e9ea7e0SNamjae Jeon * Note this cannot be called for AT_INDEX_ALLOCATION. 12371e9ea7e0SNamjae Jeon */ 12381e9ea7e0SNamjae Jeon static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) 12391e9ea7e0SNamjae Jeon { 1240af0db57dSNamjae Jeon struct ntfs_volume *vol = NTFS_SB(vi->i_sb); 1241af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi), *base_ni = NTFS_I(base_vi); 1242af0db57dSNamjae Jeon struct mft_record *m; 1243af0db57dSNamjae Jeon struct attr_record *a; 1244af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 12451e9ea7e0SNamjae Jeon int err = 0; 12461e9ea7e0SNamjae Jeon 1247e7d82353SNamjae Jeon ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no); 12481e9ea7e0SNamjae Jeon 12491e9ea7e0SNamjae Jeon ntfs_init_big_inode(vi); 12501e9ea7e0SNamjae Jeon 12511e9ea7e0SNamjae Jeon /* Just mirror the values from the base inode. */ 12521e9ea7e0SNamjae Jeon vi->i_uid = base_vi->i_uid; 12531e9ea7e0SNamjae Jeon vi->i_gid = base_vi->i_gid; 12541e9ea7e0SNamjae Jeon set_nlink(vi, base_vi->i_nlink); 12551e9ea7e0SNamjae Jeon inode_set_mtime_to_ts(vi, inode_get_mtime(base_vi)); 12561e9ea7e0SNamjae Jeon inode_set_ctime_to_ts(vi, inode_get_ctime(base_vi)); 12571e9ea7e0SNamjae Jeon inode_set_atime_to_ts(vi, inode_get_atime(base_vi)); 12581e9ea7e0SNamjae Jeon vi->i_generation = ni->seq_no = base_ni->seq_no; 12591e9ea7e0SNamjae Jeon 12601e9ea7e0SNamjae Jeon /* Set inode type to zero but preserve permissions. */ 12611e9ea7e0SNamjae Jeon vi->i_mode = base_vi->i_mode & ~S_IFMT; 12621e9ea7e0SNamjae Jeon 12631e9ea7e0SNamjae Jeon m = map_mft_record(base_ni); 12641e9ea7e0SNamjae Jeon if (IS_ERR(m)) { 12651e9ea7e0SNamjae Jeon err = PTR_ERR(m); 12661e9ea7e0SNamjae Jeon goto err_out; 12671e9ea7e0SNamjae Jeon } 12681e9ea7e0SNamjae Jeon ctx = ntfs_attr_get_search_ctx(base_ni, m); 12691e9ea7e0SNamjae Jeon if (!ctx) { 12701e9ea7e0SNamjae Jeon err = -ENOMEM; 12711e9ea7e0SNamjae Jeon goto unm_err_out; 12721e9ea7e0SNamjae Jeon } 12731e9ea7e0SNamjae Jeon /* Find the attribute. */ 12741e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 12751e9ea7e0SNamjae Jeon CASE_SENSITIVE, 0, NULL, 0, ctx); 12761e9ea7e0SNamjae Jeon if (unlikely(err)) 12771e9ea7e0SNamjae Jeon goto unm_err_out; 12781e9ea7e0SNamjae Jeon a = ctx->attr; 12791e9ea7e0SNamjae Jeon if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) { 12801e9ea7e0SNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK) { 12811e9ea7e0SNamjae Jeon NInoSetCompressed(ni); 1282af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_COMPRESSED; 12831e9ea7e0SNamjae Jeon if ((ni->type != AT_DATA) || (ni->type == AT_DATA && 12841e9ea7e0SNamjae Jeon ni->name_len)) { 1285af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1286af0db57dSNamjae Jeon "Found compressed non-data or named data attribute."); 12871e9ea7e0SNamjae Jeon goto unm_err_out; 12881e9ea7e0SNamjae Jeon } 12891e9ea7e0SNamjae Jeon if (vol->cluster_size > 4096) { 1290af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1291af0db57dSNamjae Jeon "Found compressed attribute but compression is disabled due to cluster size (%i) > 4kiB.", 12921e9ea7e0SNamjae Jeon vol->cluster_size); 12931e9ea7e0SNamjae Jeon goto unm_err_out; 12941e9ea7e0SNamjae Jeon } 12951e9ea7e0SNamjae Jeon if ((a->flags & ATTR_COMPRESSION_MASK) != 12961e9ea7e0SNamjae Jeon ATTR_IS_COMPRESSED) { 1297af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Found unknown compression method."); 12981e9ea7e0SNamjae Jeon goto unm_err_out; 12991e9ea7e0SNamjae Jeon } 13001e9ea7e0SNamjae Jeon } 13011e9ea7e0SNamjae Jeon /* 13021e9ea7e0SNamjae Jeon * The compressed/sparse flag set in an index root just means 13031e9ea7e0SNamjae Jeon * to compress all files. 13041e9ea7e0SNamjae Jeon */ 13051e9ea7e0SNamjae Jeon if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) { 1306af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1307af0db57dSNamjae Jeon "Found mst protected attribute but the attribute is %s.", 1308af0db57dSNamjae Jeon NInoCompressed(ni) ? "compressed" : "sparse"); 13091e9ea7e0SNamjae Jeon goto unm_err_out; 13101e9ea7e0SNamjae Jeon } 1311af0db57dSNamjae Jeon if (a->flags & ATTR_IS_SPARSE) { 13121e9ea7e0SNamjae Jeon NInoSetSparse(ni); 1313af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_SPARSE_FILE; 1314af0db57dSNamjae Jeon } 13151e9ea7e0SNamjae Jeon } 13161e9ea7e0SNamjae Jeon if (a->flags & ATTR_IS_ENCRYPTED) { 13171e9ea7e0SNamjae Jeon if (NInoCompressed(ni)) { 1318af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Found encrypted and compressed data."); 13191e9ea7e0SNamjae Jeon goto unm_err_out; 13201e9ea7e0SNamjae Jeon } 13211e9ea7e0SNamjae Jeon /* 13221e9ea7e0SNamjae Jeon * The encryption flag set in an index root just means to 13231e9ea7e0SNamjae Jeon * encrypt all files. 13241e9ea7e0SNamjae Jeon */ 13251e9ea7e0SNamjae Jeon if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) { 1326af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1327af0db57dSNamjae Jeon "Found mst protected attribute but the attribute is encrypted."); 13281e9ea7e0SNamjae Jeon goto unm_err_out; 13291e9ea7e0SNamjae Jeon } 13301e9ea7e0SNamjae Jeon if (ni->type != AT_DATA) { 1331af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1332af0db57dSNamjae Jeon "Found encrypted non-data attribute."); 13331e9ea7e0SNamjae Jeon goto unm_err_out; 13341e9ea7e0SNamjae Jeon } 13351e9ea7e0SNamjae Jeon NInoSetEncrypted(ni); 1336af0db57dSNamjae Jeon ni->flags |= FILE_ATTR_ENCRYPTED; 13371e9ea7e0SNamjae Jeon } 13381e9ea7e0SNamjae Jeon if (!a->non_resident) { 13391e9ea7e0SNamjae Jeon /* Ensure the attribute name is placed before the value. */ 13401e9ea7e0SNamjae Jeon if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= 13411e9ea7e0SNamjae Jeon le16_to_cpu(a->data.resident.value_offset)))) { 1342af0db57dSNamjae Jeon ntfs_error(vol->sb, 1343af0db57dSNamjae Jeon "Attribute name is placed after the attribute value."); 13441e9ea7e0SNamjae Jeon goto unm_err_out; 13451e9ea7e0SNamjae Jeon } 13461e9ea7e0SNamjae Jeon if (NInoMstProtected(ni)) { 1347af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1348af0db57dSNamjae Jeon "Found mst protected attribute but the attribute is resident."); 13491e9ea7e0SNamjae Jeon goto unm_err_out; 13501e9ea7e0SNamjae Jeon } 1351af0db57dSNamjae Jeon vi->i_size = ni->initialized_size = ni->data_size = le32_to_cpu( 13521e9ea7e0SNamjae Jeon a->data.resident.value_length); 13531e9ea7e0SNamjae Jeon ni->allocated_size = le32_to_cpu(a->length) - 13541e9ea7e0SNamjae Jeon le16_to_cpu(a->data.resident.value_offset); 13551e9ea7e0SNamjae Jeon if (vi->i_size > ni->allocated_size) { 1356af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1357af0db57dSNamjae Jeon "Resident attribute is corrupt (size exceeds allocation)."); 13581e9ea7e0SNamjae Jeon goto unm_err_out; 13591e9ea7e0SNamjae Jeon } 13601e9ea7e0SNamjae Jeon } else { 13611e9ea7e0SNamjae Jeon NInoSetNonResident(ni); 13621e9ea7e0SNamjae Jeon /* 13631e9ea7e0SNamjae Jeon * Ensure the attribute name is placed before the mapping pairs 13641e9ea7e0SNamjae Jeon * array. 13651e9ea7e0SNamjae Jeon */ 13661e9ea7e0SNamjae Jeon if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= 13671e9ea7e0SNamjae Jeon le16_to_cpu( 13681e9ea7e0SNamjae Jeon a->data.non_resident.mapping_pairs_offset)))) { 1369af0db57dSNamjae Jeon ntfs_error(vol->sb, 1370af0db57dSNamjae Jeon "Attribute name is placed after the mapping pairs array."); 13711e9ea7e0SNamjae Jeon goto unm_err_out; 13721e9ea7e0SNamjae Jeon } 13731e9ea7e0SNamjae Jeon if (NInoCompressed(ni) || NInoSparse(ni)) { 1374af0db57dSNamjae Jeon if (NInoCompressed(ni) && a->data.non_resident.compression_unit != 4) { 1375af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1376af0db57dSNamjae Jeon "Found non-standard compression unit (%u instead of 4). Cannot handle this.", 1377af0db57dSNamjae Jeon a->data.non_resident.compression_unit); 13781e9ea7e0SNamjae Jeon err = -EOPNOTSUPP; 13791e9ea7e0SNamjae Jeon goto unm_err_out; 13801e9ea7e0SNamjae Jeon } 13811e9ea7e0SNamjae Jeon if (a->data.non_resident.compression_unit) { 13821e9ea7e0SNamjae Jeon ni->itype.compressed.block_size = 1U << 1383af0db57dSNamjae Jeon (a->data.non_resident.compression_unit + 13841e9ea7e0SNamjae Jeon vol->cluster_size_bits); 13851e9ea7e0SNamjae Jeon ni->itype.compressed.block_size_bits = 1386af0db57dSNamjae Jeon ffs(ni->itype.compressed.block_size) - 1; 13871e9ea7e0SNamjae Jeon ni->itype.compressed.block_clusters = 1U << 1388af0db57dSNamjae Jeon a->data.non_resident.compression_unit; 13891e9ea7e0SNamjae Jeon } else { 13901e9ea7e0SNamjae Jeon ni->itype.compressed.block_size = 0; 13911e9ea7e0SNamjae Jeon ni->itype.compressed.block_size_bits = 0; 13921e9ea7e0SNamjae Jeon ni->itype.compressed.block_clusters = 0; 13931e9ea7e0SNamjae Jeon } 1394af0db57dSNamjae Jeon ni->itype.compressed.size = le64_to_cpu( 13951e9ea7e0SNamjae Jeon a->data.non_resident.compressed_size); 13961e9ea7e0SNamjae Jeon } 13971e9ea7e0SNamjae Jeon if (a->data.non_resident.lowest_vcn) { 1398af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "First extent of attribute has non-zero lowest_vcn."); 13991e9ea7e0SNamjae Jeon goto unm_err_out; 14001e9ea7e0SNamjae Jeon } 1401af0db57dSNamjae Jeon vi->i_size = ni->data_size = le64_to_cpu(a->data.non_resident.data_size); 1402af0db57dSNamjae Jeon ni->initialized_size = le64_to_cpu(a->data.non_resident.initialized_size); 1403af0db57dSNamjae Jeon ni->allocated_size = le64_to_cpu(a->data.non_resident.allocated_size); 14041e9ea7e0SNamjae Jeon } 1405af0db57dSNamjae Jeon vi->i_mapping->a_ops = &ntfs_aops; 14061e9ea7e0SNamjae Jeon if ((NInoCompressed(ni) || NInoSparse(ni)) && ni->type != AT_INDEX_ROOT) 14071e9ea7e0SNamjae Jeon vi->i_blocks = ni->itype.compressed.size >> 9; 14081e9ea7e0SNamjae Jeon else 14091e9ea7e0SNamjae Jeon vi->i_blocks = ni->allocated_size >> 9; 14101e9ea7e0SNamjae Jeon /* 14111e9ea7e0SNamjae Jeon * Make sure the base inode does not go away and attach it to the 14121e9ea7e0SNamjae Jeon * attribute inode. 14131e9ea7e0SNamjae Jeon */ 1414af0db57dSNamjae Jeon if (!igrab(base_vi)) { 1415af0db57dSNamjae Jeon err = -ENOENT; 1416af0db57dSNamjae Jeon goto unm_err_out; 1417af0db57dSNamjae Jeon } 14181e9ea7e0SNamjae Jeon ni->ext.base_ntfs_ino = base_ni; 14191e9ea7e0SNamjae Jeon ni->nr_extents = -1; 14201e9ea7e0SNamjae Jeon 14211e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 14221e9ea7e0SNamjae Jeon unmap_mft_record(base_ni); 14231e9ea7e0SNamjae Jeon 14241e9ea7e0SNamjae Jeon ntfs_debug("Done."); 14251e9ea7e0SNamjae Jeon return 0; 14261e9ea7e0SNamjae Jeon 14271e9ea7e0SNamjae Jeon unm_err_out: 14281e9ea7e0SNamjae Jeon if (!err) 14291e9ea7e0SNamjae Jeon err = -EIO; 14301e9ea7e0SNamjae Jeon if (ctx) 14311e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 14321e9ea7e0SNamjae Jeon unmap_mft_record(base_ni); 14331e9ea7e0SNamjae Jeon err_out: 1434af0db57dSNamjae Jeon if (err != -ENOENT) 1435af0db57dSNamjae Jeon ntfs_error(vol->sb, 1436d9038d99SNamjae Jeon "Failed with error code %i while reading attribute inode (mft_no 0x%llx, type 0x%x, name_len %i). Marking corrupt inode and base inode 0x%llx as bad. Run chkdsk.", 1437d9038d99SNamjae Jeon err, ni->mft_no, ni->type, ni->name_len, 1438d9038d99SNamjae Jeon base_ni->mft_no); 1439af0db57dSNamjae Jeon if (err != -ENOENT && err != -ENOMEM) 14401e9ea7e0SNamjae Jeon NVolSetErrors(vol); 14411e9ea7e0SNamjae Jeon return err; 14421e9ea7e0SNamjae Jeon } 14431e9ea7e0SNamjae Jeon 1444af0db57dSNamjae Jeon /* 14451e9ea7e0SNamjae Jeon * ntfs_read_locked_index_inode - read an index inode from its base inode 14461e9ea7e0SNamjae Jeon * @base_vi: base inode 14471e9ea7e0SNamjae Jeon * @vi: index inode to read 14481e9ea7e0SNamjae Jeon * 14491e9ea7e0SNamjae Jeon * ntfs_read_locked_index_inode() is called from ntfs_index_iget() to read the 14501e9ea7e0SNamjae Jeon * index inode described by @vi into memory from the base mft record described 14511e9ea7e0SNamjae Jeon * by @base_ni. 14521e9ea7e0SNamjae Jeon * 14531e9ea7e0SNamjae Jeon * ntfs_read_locked_index_inode() maps, pins and locks the base inode for 14541e9ea7e0SNamjae Jeon * reading and looks up the attributes relating to the index described by @vi 14551e9ea7e0SNamjae Jeon * before setting up the necessary fields in @vi as well as initializing the 14561e9ea7e0SNamjae Jeon * ntfs inode. 14571e9ea7e0SNamjae Jeon * 14581e9ea7e0SNamjae Jeon * Note, index inodes are essentially attribute inodes (NInoAttr() is true) 14591e9ea7e0SNamjae Jeon * with the attribute type set to AT_INDEX_ALLOCATION. Apart from that, they 14601e9ea7e0SNamjae Jeon * are setup like directory inodes since directories are a special case of 14611e9ea7e0SNamjae Jeon * indices ao they need to be treated in much the same way. Most importantly, 14621e9ea7e0SNamjae Jeon * for small indices the index allocation attribute might not actually exist. 14631e9ea7e0SNamjae Jeon * However, the index root attribute always exists but this does not need to 14641e9ea7e0SNamjae Jeon * have an inode associated with it and this is why we define a new inode type 14651e9ea7e0SNamjae Jeon * index. Also, like for directories, we need to have an attribute inode for 14661e9ea7e0SNamjae Jeon * the bitmap attribute corresponding to the index allocation attribute and we 14671e9ea7e0SNamjae Jeon * can store this in the appropriate field of the inode, just like we do for 14681e9ea7e0SNamjae Jeon * normal directory inodes. 14691e9ea7e0SNamjae Jeon * 14701e9ea7e0SNamjae Jeon * Q: What locks are held when the function is called? 14711e9ea7e0SNamjae Jeon * A: i_state has I_NEW set, hence the inode is locked, also 14721e9ea7e0SNamjae Jeon * i_count is set to 1, so it is not going to go away 14731e9ea7e0SNamjae Jeon * 1474af0db57dSNamjae Jeon * Return 0 on success and -errno on error. 14751e9ea7e0SNamjae Jeon */ 14761e9ea7e0SNamjae Jeon static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) 14771e9ea7e0SNamjae Jeon { 14781e9ea7e0SNamjae Jeon loff_t bvi_size; 1479af0db57dSNamjae Jeon struct ntfs_volume *vol = NTFS_SB(vi->i_sb); 1480af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi), *base_ni = NTFS_I(base_vi), *bni; 14811e9ea7e0SNamjae Jeon struct inode *bvi; 1482af0db57dSNamjae Jeon struct mft_record *m; 1483af0db57dSNamjae Jeon struct attr_record *a; 1484af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 1485af0db57dSNamjae Jeon struct index_root *ir; 14861e9ea7e0SNamjae Jeon u8 *ir_end, *index_end; 14871e9ea7e0SNamjae Jeon int err = 0; 14881e9ea7e0SNamjae Jeon 1489e7d82353SNamjae Jeon ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no); 1490af0db57dSNamjae Jeon lockdep_assert_held(&base_ni->mrec_lock); 1491af0db57dSNamjae Jeon 14921e9ea7e0SNamjae Jeon ntfs_init_big_inode(vi); 14931e9ea7e0SNamjae Jeon /* Just mirror the values from the base inode. */ 14941e9ea7e0SNamjae Jeon vi->i_uid = base_vi->i_uid; 14951e9ea7e0SNamjae Jeon vi->i_gid = base_vi->i_gid; 14961e9ea7e0SNamjae Jeon set_nlink(vi, base_vi->i_nlink); 14971e9ea7e0SNamjae Jeon inode_set_mtime_to_ts(vi, inode_get_mtime(base_vi)); 14981e9ea7e0SNamjae Jeon inode_set_ctime_to_ts(vi, inode_get_ctime(base_vi)); 14991e9ea7e0SNamjae Jeon inode_set_atime_to_ts(vi, inode_get_atime(base_vi)); 15001e9ea7e0SNamjae Jeon vi->i_generation = ni->seq_no = base_ni->seq_no; 15011e9ea7e0SNamjae Jeon /* Set inode type to zero but preserve permissions. */ 15021e9ea7e0SNamjae Jeon vi->i_mode = base_vi->i_mode & ~S_IFMT; 15031e9ea7e0SNamjae Jeon /* Map the mft record for the base inode. */ 15041e9ea7e0SNamjae Jeon m = map_mft_record(base_ni); 15051e9ea7e0SNamjae Jeon if (IS_ERR(m)) { 15061e9ea7e0SNamjae Jeon err = PTR_ERR(m); 15071e9ea7e0SNamjae Jeon goto err_out; 15081e9ea7e0SNamjae Jeon } 15091e9ea7e0SNamjae Jeon ctx = ntfs_attr_get_search_ctx(base_ni, m); 15101e9ea7e0SNamjae Jeon if (!ctx) { 15111e9ea7e0SNamjae Jeon err = -ENOMEM; 15121e9ea7e0SNamjae Jeon goto unm_err_out; 15131e9ea7e0SNamjae Jeon } 15141e9ea7e0SNamjae Jeon /* Find the index root attribute. */ 15151e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(AT_INDEX_ROOT, ni->name, ni->name_len, 15161e9ea7e0SNamjae Jeon CASE_SENSITIVE, 0, NULL, 0, ctx); 15171e9ea7e0SNamjae Jeon if (unlikely(err)) { 15181e9ea7e0SNamjae Jeon if (err == -ENOENT) 1519af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is missing."); 15201e9ea7e0SNamjae Jeon goto unm_err_out; 15211e9ea7e0SNamjae Jeon } 15221e9ea7e0SNamjae Jeon a = ctx->attr; 15231e9ea7e0SNamjae Jeon /* Set up the state. */ 15241e9ea7e0SNamjae Jeon if (unlikely(a->non_resident)) { 15251e9ea7e0SNamjae Jeon ntfs_error(vol->sb, "$INDEX_ROOT attribute is not resident."); 15261e9ea7e0SNamjae Jeon goto unm_err_out; 15271e9ea7e0SNamjae Jeon } 15281e9ea7e0SNamjae Jeon /* Ensure the attribute name is placed before the value. */ 15291e9ea7e0SNamjae Jeon if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= 15301e9ea7e0SNamjae Jeon le16_to_cpu(a->data.resident.value_offset)))) { 1531af0db57dSNamjae Jeon ntfs_error(vol->sb, 1532af0db57dSNamjae Jeon "$INDEX_ROOT attribute name is placed after the attribute value."); 15331e9ea7e0SNamjae Jeon goto unm_err_out; 15341e9ea7e0SNamjae Jeon } 1535af0db57dSNamjae Jeon 1536af0db57dSNamjae Jeon ir = (struct index_root *)((u8 *)a + le16_to_cpu(a->data.resident.value_offset)); 15371e9ea7e0SNamjae Jeon ir_end = (u8 *)ir + le32_to_cpu(a->data.resident.value_length); 15381e9ea7e0SNamjae Jeon index_end = (u8 *)&ir->index + le32_to_cpu(ir->index.index_length); 15391e9ea7e0SNamjae Jeon if (index_end > ir_end) { 15401e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Index is corrupt."); 15411e9ea7e0SNamjae Jeon goto unm_err_out; 15421e9ea7e0SNamjae Jeon } 1543af0db57dSNamjae Jeon 15441e9ea7e0SNamjae Jeon ni->itype.index.collation_rule = ir->collation_rule; 15451e9ea7e0SNamjae Jeon ntfs_debug("Index collation rule is 0x%x.", 15461e9ea7e0SNamjae Jeon le32_to_cpu(ir->collation_rule)); 15471e9ea7e0SNamjae Jeon ni->itype.index.block_size = le32_to_cpu(ir->index_block_size); 15481e9ea7e0SNamjae Jeon if (!is_power_of_2(ni->itype.index.block_size)) { 1549af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Index block size (%u) is not a power of two.", 1550af0db57dSNamjae Jeon ni->itype.index.block_size); 15511e9ea7e0SNamjae Jeon goto unm_err_out; 15521e9ea7e0SNamjae Jeon } 15531e9ea7e0SNamjae Jeon if (ni->itype.index.block_size > PAGE_SIZE) { 1554af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Index block size (%u) > PAGE_SIZE (%ld) is not supported.", 15551e9ea7e0SNamjae Jeon ni->itype.index.block_size, PAGE_SIZE); 15561e9ea7e0SNamjae Jeon err = -EOPNOTSUPP; 15571e9ea7e0SNamjae Jeon goto unm_err_out; 15581e9ea7e0SNamjae Jeon } 15591e9ea7e0SNamjae Jeon if (ni->itype.index.block_size < NTFS_BLOCK_SIZE) { 1560af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1561af0db57dSNamjae Jeon "Index block size (%u) < NTFS_BLOCK_SIZE (%i) is not supported.", 15621e9ea7e0SNamjae Jeon ni->itype.index.block_size, NTFS_BLOCK_SIZE); 15631e9ea7e0SNamjae Jeon err = -EOPNOTSUPP; 15641e9ea7e0SNamjae Jeon goto unm_err_out; 15651e9ea7e0SNamjae Jeon } 15661e9ea7e0SNamjae Jeon ni->itype.index.block_size_bits = ffs(ni->itype.index.block_size) - 1; 15671e9ea7e0SNamjae Jeon /* Determine the size of a vcn in the index. */ 15681e9ea7e0SNamjae Jeon if (vol->cluster_size <= ni->itype.index.block_size) { 15691e9ea7e0SNamjae Jeon ni->itype.index.vcn_size = vol->cluster_size; 15701e9ea7e0SNamjae Jeon ni->itype.index.vcn_size_bits = vol->cluster_size_bits; 15711e9ea7e0SNamjae Jeon } else { 15721e9ea7e0SNamjae Jeon ni->itype.index.vcn_size = vol->sector_size; 15731e9ea7e0SNamjae Jeon ni->itype.index.vcn_size_bits = vol->sector_size_bits; 15741e9ea7e0SNamjae Jeon } 1575af0db57dSNamjae Jeon 1576af0db57dSNamjae Jeon /* Find index allocation attribute. */ 1577af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 1578af0db57dSNamjae Jeon err = ntfs_attr_lookup(AT_INDEX_ALLOCATION, ni->name, ni->name_len, 1579af0db57dSNamjae Jeon CASE_SENSITIVE, 0, NULL, 0, ctx); 1580af0db57dSNamjae Jeon if (unlikely(err)) { 1581af0db57dSNamjae Jeon if (err == -ENOENT) { 15821e9ea7e0SNamjae Jeon /* No index allocation. */ 15831e9ea7e0SNamjae Jeon vi->i_size = ni->initialized_size = ni->allocated_size = 0; 15841e9ea7e0SNamjae Jeon /* We are done with the mft record, so we release it. */ 15851e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 15861e9ea7e0SNamjae Jeon unmap_mft_record(base_ni); 15871e9ea7e0SNamjae Jeon m = NULL; 15881e9ea7e0SNamjae Jeon ctx = NULL; 15891e9ea7e0SNamjae Jeon goto skip_large_index_stuff; 1590af0db57dSNamjae Jeon } else 1591af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to lookup $INDEX_ALLOCATION attribute."); 15921e9ea7e0SNamjae Jeon goto unm_err_out; 15931e9ea7e0SNamjae Jeon } 1594af0db57dSNamjae Jeon NInoSetIndexAllocPresent(ni); 1595af0db57dSNamjae Jeon NInoSetNonResident(ni); 1596af0db57dSNamjae Jeon ni->type = AT_INDEX_ALLOCATION; 1597af0db57dSNamjae Jeon 15981e9ea7e0SNamjae Jeon a = ctx->attr; 15991e9ea7e0SNamjae Jeon if (!a->non_resident) { 1600af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is resident."); 16011e9ea7e0SNamjae Jeon goto unm_err_out; 16021e9ea7e0SNamjae Jeon } 16031e9ea7e0SNamjae Jeon /* 16041e9ea7e0SNamjae Jeon * Ensure the attribute name is placed before the mapping pairs array. 16051e9ea7e0SNamjae Jeon */ 16061e9ea7e0SNamjae Jeon if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= 1607af0db57dSNamjae Jeon le16_to_cpu(a->data.non_resident.mapping_pairs_offset)))) { 1608af0db57dSNamjae Jeon ntfs_error(vol->sb, 1609af0db57dSNamjae Jeon "$INDEX_ALLOCATION attribute name is placed after the mapping pairs array."); 16101e9ea7e0SNamjae Jeon goto unm_err_out; 16111e9ea7e0SNamjae Jeon } 16121e9ea7e0SNamjae Jeon if (a->flags & ATTR_IS_ENCRYPTED) { 1613af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is encrypted."); 16141e9ea7e0SNamjae Jeon goto unm_err_out; 16151e9ea7e0SNamjae Jeon } 16161e9ea7e0SNamjae Jeon if (a->flags & ATTR_IS_SPARSE) { 16171e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is sparse."); 16181e9ea7e0SNamjae Jeon goto unm_err_out; 16191e9ea7e0SNamjae Jeon } 16201e9ea7e0SNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK) { 1621af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1622af0db57dSNamjae Jeon "$INDEX_ALLOCATION attribute is compressed."); 16231e9ea7e0SNamjae Jeon goto unm_err_out; 16241e9ea7e0SNamjae Jeon } 16251e9ea7e0SNamjae Jeon if (a->data.non_resident.lowest_vcn) { 1626af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1627af0db57dSNamjae Jeon "First extent of $INDEX_ALLOCATION attribute has non zero lowest_vcn."); 16281e9ea7e0SNamjae Jeon goto unm_err_out; 16291e9ea7e0SNamjae Jeon } 1630af0db57dSNamjae Jeon vi->i_size = ni->data_size = le64_to_cpu(a->data.non_resident.data_size); 1631af0db57dSNamjae Jeon ni->initialized_size = le64_to_cpu(a->data.non_resident.initialized_size); 1632af0db57dSNamjae Jeon ni->allocated_size = le64_to_cpu(a->data.non_resident.allocated_size); 16331e9ea7e0SNamjae Jeon /* 16341e9ea7e0SNamjae Jeon * We are done with the mft record, so we release it. Otherwise 16351e9ea7e0SNamjae Jeon * we would deadlock in ntfs_attr_iget(). 16361e9ea7e0SNamjae Jeon */ 16371e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 16381e9ea7e0SNamjae Jeon unmap_mft_record(base_ni); 16391e9ea7e0SNamjae Jeon m = NULL; 16401e9ea7e0SNamjae Jeon ctx = NULL; 16411e9ea7e0SNamjae Jeon /* Get the index bitmap attribute inode. */ 16421e9ea7e0SNamjae Jeon bvi = ntfs_attr_iget(base_vi, AT_BITMAP, ni->name, ni->name_len); 16431e9ea7e0SNamjae Jeon if (IS_ERR(bvi)) { 16441e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Failed to get bitmap attribute."); 16451e9ea7e0SNamjae Jeon err = PTR_ERR(bvi); 16461e9ea7e0SNamjae Jeon goto unm_err_out; 16471e9ea7e0SNamjae Jeon } 16481e9ea7e0SNamjae Jeon bni = NTFS_I(bvi); 16491e9ea7e0SNamjae Jeon if (NInoCompressed(bni) || NInoEncrypted(bni) || 16501e9ea7e0SNamjae Jeon NInoSparse(bni)) { 1651af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1652af0db57dSNamjae Jeon "$BITMAP attribute is compressed and/or encrypted and/or sparse."); 16531e9ea7e0SNamjae Jeon goto iput_unm_err_out; 16541e9ea7e0SNamjae Jeon } 16551e9ea7e0SNamjae Jeon /* Consistency check bitmap size vs. index allocation size. */ 16561e9ea7e0SNamjae Jeon bvi_size = i_size_read(bvi); 16571e9ea7e0SNamjae Jeon if ((bvi_size << 3) < (vi->i_size >> ni->itype.index.block_size_bits)) { 1658af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1659af0db57dSNamjae Jeon "Index bitmap too small (0x%llx) for index allocation (0x%llx).", 1660af0db57dSNamjae Jeon bvi_size << 3, vi->i_size); 16611e9ea7e0SNamjae Jeon goto iput_unm_err_out; 16621e9ea7e0SNamjae Jeon } 16631e9ea7e0SNamjae Jeon iput(bvi); 16641e9ea7e0SNamjae Jeon skip_large_index_stuff: 16651e9ea7e0SNamjae Jeon /* Setup the operations for this index inode. */ 1666af0db57dSNamjae Jeon ntfs_set_vfs_operations(vi, S_IFDIR, 0); 16671e9ea7e0SNamjae Jeon vi->i_blocks = ni->allocated_size >> 9; 16681e9ea7e0SNamjae Jeon /* 16691e9ea7e0SNamjae Jeon * Make sure the base inode doesn't go away and attach it to the 16701e9ea7e0SNamjae Jeon * index inode. 16711e9ea7e0SNamjae Jeon */ 1672af0db57dSNamjae Jeon if (!igrab(base_vi)) 1673af0db57dSNamjae Jeon goto unm_err_out; 16741e9ea7e0SNamjae Jeon ni->ext.base_ntfs_ino = base_ni; 16751e9ea7e0SNamjae Jeon ni->nr_extents = -1; 16761e9ea7e0SNamjae Jeon 16771e9ea7e0SNamjae Jeon ntfs_debug("Done."); 16781e9ea7e0SNamjae Jeon return 0; 16791e9ea7e0SNamjae Jeon iput_unm_err_out: 16801e9ea7e0SNamjae Jeon iput(bvi); 16811e9ea7e0SNamjae Jeon unm_err_out: 16821e9ea7e0SNamjae Jeon if (!err) 16831e9ea7e0SNamjae Jeon err = -EIO; 16841e9ea7e0SNamjae Jeon if (ctx) 16851e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 16861e9ea7e0SNamjae Jeon if (m) 16871e9ea7e0SNamjae Jeon unmap_mft_record(base_ni); 16881e9ea7e0SNamjae Jeon err_out: 1689af0db57dSNamjae Jeon ntfs_error(vi->i_sb, 1690d9038d99SNamjae Jeon "Failed with error code %i while reading index inode (mft_no 0x%llx, name_len %i.", 1691d9038d99SNamjae Jeon err, ni->mft_no, ni->name_len); 16921e9ea7e0SNamjae Jeon if (err != -EOPNOTSUPP && err != -ENOMEM) 16931e9ea7e0SNamjae Jeon NVolSetErrors(vol); 16941e9ea7e0SNamjae Jeon return err; 16951e9ea7e0SNamjae Jeon } 16961e9ea7e0SNamjae Jeon 16971e9ea7e0SNamjae Jeon /* 1698af0db57dSNamjae Jeon * load_attribute_list_mount - load an attribute list into memory 1699af0db57dSNamjae Jeon * @vol: ntfs volume from which to read 1700af0db57dSNamjae Jeon * @rl: runlist of the attribute list 1701af0db57dSNamjae Jeon * @al_start: destination buffer 1702af0db57dSNamjae Jeon * @size: size of the destination buffer in bytes 1703af0db57dSNamjae Jeon * @initialized_size: initialized size of the attribute list 1704af0db57dSNamjae Jeon * 1705af0db57dSNamjae Jeon * Walk the runlist @rl and load all clusters from it copying them into 1706af0db57dSNamjae Jeon * the linear buffer @al. The maximum number of bytes copied to @al is @size 1707af0db57dSNamjae Jeon * bytes. Note, @size does not need to be a multiple of the cluster size. If 1708af0db57dSNamjae Jeon * @initialized_size is less than @size, the region in @al between 1709af0db57dSNamjae Jeon * @initialized_size and @size will be zeroed and not read from disk. 1710af0db57dSNamjae Jeon * 1711af0db57dSNamjae Jeon * Return 0 on success or -errno on error. 1712af0db57dSNamjae Jeon */ 1713af0db57dSNamjae Jeon static int load_attribute_list_mount(struct ntfs_volume *vol, 1714af0db57dSNamjae Jeon struct runlist_element *rl, u8 *al_start, const s64 size, 1715af0db57dSNamjae Jeon const s64 initialized_size) 1716af0db57dSNamjae Jeon { 1717af0db57dSNamjae Jeon s64 lcn; 1718af0db57dSNamjae Jeon u8 *al = al_start; 1719af0db57dSNamjae Jeon u8 *al_end = al + initialized_size; 1720af0db57dSNamjae Jeon struct super_block *sb; 1721af0db57dSNamjae Jeon int err = 0; 1722af0db57dSNamjae Jeon loff_t rl_byte_off, rl_byte_len; 1723af0db57dSNamjae Jeon 1724af0db57dSNamjae Jeon ntfs_debug("Entering."); 1725af0db57dSNamjae Jeon if (!vol || !rl || !al || size <= 0 || initialized_size < 0 || 1726af0db57dSNamjae Jeon initialized_size > size) 1727af0db57dSNamjae Jeon return -EINVAL; 1728af0db57dSNamjae Jeon if (!initialized_size) { 1729af0db57dSNamjae Jeon memset(al, 0, size); 1730af0db57dSNamjae Jeon return 0; 1731af0db57dSNamjae Jeon } 1732af0db57dSNamjae Jeon sb = vol->sb; 1733af0db57dSNamjae Jeon 1734af0db57dSNamjae Jeon /* Read all clusters specified by the runlist one run at a time. */ 1735af0db57dSNamjae Jeon while (rl->length) { 1736af0db57dSNamjae Jeon lcn = ntfs_rl_vcn_to_lcn(rl, rl->vcn); 1737af0db57dSNamjae Jeon ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.", 1738af0db57dSNamjae Jeon (unsigned long long)rl->vcn, 1739af0db57dSNamjae Jeon (unsigned long long)lcn); 1740af0db57dSNamjae Jeon /* The attribute list cannot be sparse. */ 1741af0db57dSNamjae Jeon if (lcn < 0) { 1742af0db57dSNamjae Jeon ntfs_error(sb, "ntfs_rl_vcn_to_lcn() failed. Cannot read attribute list."); 1743*77f58db7SHyunchul Lee return -EIO; 1744af0db57dSNamjae Jeon } 1745af0db57dSNamjae Jeon 1746af0db57dSNamjae Jeon rl_byte_off = ntfs_cluster_to_bytes(vol, lcn); 1747af0db57dSNamjae Jeon rl_byte_len = ntfs_cluster_to_bytes(vol, rl->length); 1748af0db57dSNamjae Jeon 1749af0db57dSNamjae Jeon if (al + rl_byte_len > al_end) 1750af0db57dSNamjae Jeon rl_byte_len = al_end - al; 1751af0db57dSNamjae Jeon 1752af0db57dSNamjae Jeon err = ntfs_bdev_read(sb->s_bdev, al, rl_byte_off, 1753af0db57dSNamjae Jeon round_up(rl_byte_len, SECTOR_SIZE)); 1754af0db57dSNamjae Jeon if (err) { 1755af0db57dSNamjae Jeon ntfs_error(sb, "Cannot read attribute list."); 1756*77f58db7SHyunchul Lee return -EIO; 1757af0db57dSNamjae Jeon } 1758af0db57dSNamjae Jeon 1759af0db57dSNamjae Jeon if (al + rl_byte_len >= al_end) { 1760af0db57dSNamjae Jeon if (initialized_size < size) 1761af0db57dSNamjae Jeon goto initialize; 1762af0db57dSNamjae Jeon goto done; 1763af0db57dSNamjae Jeon } 1764af0db57dSNamjae Jeon 1765af0db57dSNamjae Jeon al += rl_byte_len; 1766af0db57dSNamjae Jeon rl++; 1767af0db57dSNamjae Jeon } 1768af0db57dSNamjae Jeon if (initialized_size < size) { 1769af0db57dSNamjae Jeon initialize: 1770af0db57dSNamjae Jeon memset(al_start + initialized_size, 0, size - initialized_size); 1771af0db57dSNamjae Jeon } 1772af0db57dSNamjae Jeon done: 1773af0db57dSNamjae Jeon return err; 1774af0db57dSNamjae Jeon } 1775af0db57dSNamjae Jeon 1776af0db57dSNamjae Jeon /* 17771e9ea7e0SNamjae Jeon * The MFT inode has special locking, so teach the lock validator 17781e9ea7e0SNamjae Jeon * about this by splitting off the locking rules of the MFT from 17791e9ea7e0SNamjae Jeon * the locking rules of other inodes. The MFT inode can never be 17801e9ea7e0SNamjae Jeon * accessed from the VFS side (or even internally), only by the 17811e9ea7e0SNamjae Jeon * map_mft functions. 17821e9ea7e0SNamjae Jeon */ 17831e9ea7e0SNamjae Jeon static struct lock_class_key mft_ni_runlist_lock_key, mft_ni_mrec_lock_key; 17841e9ea7e0SNamjae Jeon 1785af0db57dSNamjae Jeon /* 17861e9ea7e0SNamjae Jeon * ntfs_read_inode_mount - special read_inode for mount time use only 17871e9ea7e0SNamjae Jeon * @vi: inode to read 17881e9ea7e0SNamjae Jeon * 17891e9ea7e0SNamjae Jeon * Read inode FILE_MFT at mount time, only called with super_block lock 17901e9ea7e0SNamjae Jeon * held from within the read_super() code path. 17911e9ea7e0SNamjae Jeon * 17921e9ea7e0SNamjae Jeon * This function exists because when it is called the page cache for $MFT/$DATA 17931e9ea7e0SNamjae Jeon * is not initialized and hence we cannot get at the contents of mft records 17941e9ea7e0SNamjae Jeon * by calling map_mft_record*(). 17951e9ea7e0SNamjae Jeon * 17961e9ea7e0SNamjae Jeon * Further it needs to cope with the circular references problem, i.e. cannot 17971e9ea7e0SNamjae Jeon * load any attributes other than $ATTRIBUTE_LIST until $DATA is loaded, because 17981e9ea7e0SNamjae Jeon * we do not know where the other extent mft records are yet and again, because 17991e9ea7e0SNamjae Jeon * we cannot call map_mft_record*() yet. Obviously this applies only when an 18001e9ea7e0SNamjae Jeon * attribute list is actually present in $MFT inode. 18011e9ea7e0SNamjae Jeon * 18021e9ea7e0SNamjae Jeon * We solve these problems by starting with the $DATA attribute before anything 18031e9ea7e0SNamjae Jeon * else and iterating using ntfs_attr_lookup($DATA) over all extents. As each 18041e9ea7e0SNamjae Jeon * extent is found, we ntfs_mapping_pairs_decompress() including the implied 18051e9ea7e0SNamjae Jeon * ntfs_runlists_merge(). Each step of the iteration necessarily provides 18061e9ea7e0SNamjae Jeon * sufficient information for the next step to complete. 18071e9ea7e0SNamjae Jeon * 18081e9ea7e0SNamjae Jeon * This should work but there are two possible pit falls (see inline comments 18091e9ea7e0SNamjae Jeon * below), but only time will tell if they are real pits or just smoke... 18101e9ea7e0SNamjae Jeon */ 18111e9ea7e0SNamjae Jeon int ntfs_read_inode_mount(struct inode *vi) 18121e9ea7e0SNamjae Jeon { 1813af0db57dSNamjae Jeon s64 next_vcn, last_vcn, highest_vcn; 18141e9ea7e0SNamjae Jeon struct super_block *sb = vi->i_sb; 1815af0db57dSNamjae Jeon struct ntfs_volume *vol = NTFS_SB(sb); 1816af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 1817af0db57dSNamjae Jeon struct mft_record *m = NULL; 1818af0db57dSNamjae Jeon struct attr_record *a; 1819af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 18201e9ea7e0SNamjae Jeon unsigned int i, nr_blocks; 18211e9ea7e0SNamjae Jeon int err; 1822af0db57dSNamjae Jeon size_t new_rl_count; 18231e9ea7e0SNamjae Jeon 18241e9ea7e0SNamjae Jeon ntfs_debug("Entering."); 18251e9ea7e0SNamjae Jeon 18261e9ea7e0SNamjae Jeon /* Initialize the ntfs specific part of @vi. */ 18271e9ea7e0SNamjae Jeon ntfs_init_big_inode(vi); 18281e9ea7e0SNamjae Jeon 18291e9ea7e0SNamjae Jeon 18301e9ea7e0SNamjae Jeon /* Setup the data attribute. It is special as it is mst protected. */ 18311e9ea7e0SNamjae Jeon NInoSetNonResident(ni); 18321e9ea7e0SNamjae Jeon NInoSetMstProtected(ni); 18331e9ea7e0SNamjae Jeon NInoSetSparseDisabled(ni); 18341e9ea7e0SNamjae Jeon ni->type = AT_DATA; 1835af0db57dSNamjae Jeon ni->name = AT_UNNAMED; 18361e9ea7e0SNamjae Jeon ni->name_len = 0; 18371e9ea7e0SNamjae Jeon /* 18381e9ea7e0SNamjae Jeon * This sets up our little cheat allowing us to reuse the async read io 18391e9ea7e0SNamjae Jeon * completion handler for directories. 18401e9ea7e0SNamjae Jeon */ 18411e9ea7e0SNamjae Jeon ni->itype.index.block_size = vol->mft_record_size; 18421e9ea7e0SNamjae Jeon ni->itype.index.block_size_bits = vol->mft_record_size_bits; 18431e9ea7e0SNamjae Jeon 18441e9ea7e0SNamjae Jeon /* Very important! Needed to be able to call map_mft_record*(). */ 18451e9ea7e0SNamjae Jeon vol->mft_ino = vi; 18461e9ea7e0SNamjae Jeon 18471e9ea7e0SNamjae Jeon /* Allocate enough memory to read the first mft record. */ 18481e9ea7e0SNamjae Jeon if (vol->mft_record_size > 64 * 1024) { 18491e9ea7e0SNamjae Jeon ntfs_error(sb, "Unsupported mft record size %i (max 64kiB).", 18501e9ea7e0SNamjae Jeon vol->mft_record_size); 18511e9ea7e0SNamjae Jeon goto err_out; 18521e9ea7e0SNamjae Jeon } 1853af0db57dSNamjae Jeon 18541e9ea7e0SNamjae Jeon i = vol->mft_record_size; 18551e9ea7e0SNamjae Jeon if (i < sb->s_blocksize) 18561e9ea7e0SNamjae Jeon i = sb->s_blocksize; 1857af0db57dSNamjae Jeon 1858af0db57dSNamjae Jeon m = kzalloc(i, GFP_NOFS); 18591e9ea7e0SNamjae Jeon if (!m) { 18601e9ea7e0SNamjae Jeon ntfs_error(sb, "Failed to allocate buffer for $MFT record 0."); 18611e9ea7e0SNamjae Jeon goto err_out; 18621e9ea7e0SNamjae Jeon } 18631e9ea7e0SNamjae Jeon 18641e9ea7e0SNamjae Jeon /* Determine the first block of the $MFT/$DATA attribute. */ 1865af0db57dSNamjae Jeon nr_blocks = ntfs_bytes_to_sector(vol, vol->mft_record_size); 18661e9ea7e0SNamjae Jeon if (!nr_blocks) 18671e9ea7e0SNamjae Jeon nr_blocks = 1; 18681e9ea7e0SNamjae Jeon 18691e9ea7e0SNamjae Jeon /* Load $MFT/$DATA's first mft record. */ 1870af0db57dSNamjae Jeon err = ntfs_bdev_read(sb->s_bdev, (char *)m, 1871af0db57dSNamjae Jeon ntfs_cluster_to_bytes(vol, vol->mft_lcn), i); 1872af0db57dSNamjae Jeon if (err) { 18731e9ea7e0SNamjae Jeon ntfs_error(sb, "Device read failed."); 18741e9ea7e0SNamjae Jeon goto err_out; 18751e9ea7e0SNamjae Jeon } 18761e9ea7e0SNamjae Jeon 18771e9ea7e0SNamjae Jeon if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) { 18781e9ea7e0SNamjae Jeon ntfs_error(sb, "Incorrect mft record size %u in superblock, should be %u.", 18791e9ea7e0SNamjae Jeon le32_to_cpu(m->bytes_allocated), vol->mft_record_size); 18801e9ea7e0SNamjae Jeon goto err_out; 18811e9ea7e0SNamjae Jeon } 18821e9ea7e0SNamjae Jeon 18831e9ea7e0SNamjae Jeon /* Apply the mst fixups. */ 1884af0db57dSNamjae Jeon if (post_read_mst_fixup((struct ntfs_record *)m, vol->mft_record_size)) { 18851e9ea7e0SNamjae Jeon ntfs_error(sb, "MST fixup failed. $MFT is corrupt."); 18861e9ea7e0SNamjae Jeon goto err_out; 18871e9ea7e0SNamjae Jeon } 18881e9ea7e0SNamjae Jeon 1889af0db57dSNamjae Jeon if (ntfs_mft_record_check(vol, m, FILE_MFT)) { 1890af0db57dSNamjae Jeon ntfs_error(sb, "ntfs_mft_record_check failed. $MFT is corrupt."); 18911e9ea7e0SNamjae Jeon goto err_out; 18921e9ea7e0SNamjae Jeon } 18931e9ea7e0SNamjae Jeon 18941e9ea7e0SNamjae Jeon /* Need this to sanity check attribute list references to $MFT. */ 18951e9ea7e0SNamjae Jeon vi->i_generation = ni->seq_no = le16_to_cpu(m->sequence_number); 18961e9ea7e0SNamjae Jeon 18971e9ea7e0SNamjae Jeon /* Provides read_folio() for map_mft_record(). */ 1898af0db57dSNamjae Jeon vi->i_mapping->a_ops = &ntfs_mft_aops; 18991e9ea7e0SNamjae Jeon 19001e9ea7e0SNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, m); 19011e9ea7e0SNamjae Jeon if (!ctx) { 19021e9ea7e0SNamjae Jeon err = -ENOMEM; 19031e9ea7e0SNamjae Jeon goto err_out; 19041e9ea7e0SNamjae Jeon } 19051e9ea7e0SNamjae Jeon 19061e9ea7e0SNamjae Jeon /* Find the attribute list attribute if present. */ 19071e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx); 19081e9ea7e0SNamjae Jeon if (err) { 19091e9ea7e0SNamjae Jeon if (unlikely(err != -ENOENT)) { 1910af0db57dSNamjae Jeon ntfs_error(sb, 1911af0db57dSNamjae Jeon "Failed to lookup attribute list attribute. You should run chkdsk."); 19121e9ea7e0SNamjae Jeon goto put_err_out; 19131e9ea7e0SNamjae Jeon } 19141e9ea7e0SNamjae Jeon } else /* if (!err) */ { 1915af0db57dSNamjae Jeon struct attr_list_entry *al_entry, *next_al_entry; 19161e9ea7e0SNamjae Jeon u8 *al_end; 1917af0db57dSNamjae Jeon static const char *es = " Not allowed. $MFT is corrupt. You should run chkdsk."; 19181e9ea7e0SNamjae Jeon 19191e9ea7e0SNamjae Jeon ntfs_debug("Attribute list attribute found in $MFT."); 19201e9ea7e0SNamjae Jeon NInoSetAttrList(ni); 19211e9ea7e0SNamjae Jeon a = ctx->attr; 19221e9ea7e0SNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK) { 1923af0db57dSNamjae Jeon ntfs_error(sb, 1924af0db57dSNamjae Jeon "Attribute list attribute is compressed.%s", 1925af0db57dSNamjae Jeon es); 19261e9ea7e0SNamjae Jeon goto put_err_out; 19271e9ea7e0SNamjae Jeon } 19281e9ea7e0SNamjae Jeon if (a->flags & ATTR_IS_ENCRYPTED || 19291e9ea7e0SNamjae Jeon a->flags & ATTR_IS_SPARSE) { 19301e9ea7e0SNamjae Jeon if (a->non_resident) { 1931af0db57dSNamjae Jeon ntfs_error(sb, 1932af0db57dSNamjae Jeon "Non-resident attribute list attribute is encrypted/sparse.%s", 1933af0db57dSNamjae Jeon es); 19341e9ea7e0SNamjae Jeon goto put_err_out; 19351e9ea7e0SNamjae Jeon } 1936af0db57dSNamjae Jeon ntfs_warning(sb, 1937af0db57dSNamjae Jeon "Resident attribute list attribute in $MFT system file is marked encrypted/sparse which is not true. However, Windows allows this and chkdsk does not detect or correct it so we will just ignore the invalid flags and pretend they are not set."); 19381e9ea7e0SNamjae Jeon } 19391e9ea7e0SNamjae Jeon /* Now allocate memory for the attribute list. */ 19401e9ea7e0SNamjae Jeon ni->attr_list_size = (u32)ntfs_attr_size(a); 19411e9ea7e0SNamjae Jeon if (!ni->attr_list_size) { 19421e9ea7e0SNamjae Jeon ntfs_error(sb, "Attr_list_size is zero"); 19431e9ea7e0SNamjae Jeon goto put_err_out; 19441e9ea7e0SNamjae Jeon } 1945af0db57dSNamjae Jeon ni->attr_list = kvzalloc(round_up(ni->attr_list_size, SECTOR_SIZE), 1946af0db57dSNamjae Jeon GFP_NOFS); 19471e9ea7e0SNamjae Jeon if (!ni->attr_list) { 1948af0db57dSNamjae Jeon ntfs_error(sb, "Not enough memory to allocate buffer for attribute list."); 19491e9ea7e0SNamjae Jeon goto put_err_out; 19501e9ea7e0SNamjae Jeon } 19511e9ea7e0SNamjae Jeon if (a->non_resident) { 1952af0db57dSNamjae Jeon struct runlist_element *rl; 1953af0db57dSNamjae Jeon size_t new_rl_count; 1954af0db57dSNamjae Jeon 19551e9ea7e0SNamjae Jeon NInoSetAttrListNonResident(ni); 19561e9ea7e0SNamjae Jeon if (a->data.non_resident.lowest_vcn) { 1957af0db57dSNamjae Jeon ntfs_error(sb, 1958af0db57dSNamjae Jeon "Attribute list has non zero lowest_vcn. $MFT is corrupt. You should run chkdsk."); 19591e9ea7e0SNamjae Jeon goto put_err_out; 19601e9ea7e0SNamjae Jeon } 1961af0db57dSNamjae Jeon 1962af0db57dSNamjae Jeon rl = ntfs_mapping_pairs_decompress(vol, a, NULL, &new_rl_count); 1963af0db57dSNamjae Jeon if (IS_ERR(rl)) { 1964af0db57dSNamjae Jeon err = PTR_ERR(rl); 1965af0db57dSNamjae Jeon ntfs_error(sb, 1966af0db57dSNamjae Jeon "Mapping pairs decompression failed with error code %i.", 19671e9ea7e0SNamjae Jeon -err); 19681e9ea7e0SNamjae Jeon goto put_err_out; 19691e9ea7e0SNamjae Jeon } 1970af0db57dSNamjae Jeon 1971af0db57dSNamjae Jeon err = load_attribute_list_mount(vol, rl, ni->attr_list, ni->attr_list_size, 1972af0db57dSNamjae Jeon le64_to_cpu(a->data.non_resident.initialized_size)); 1973af0db57dSNamjae Jeon kvfree(rl); 1974af0db57dSNamjae Jeon if (err) { 1975af0db57dSNamjae Jeon ntfs_error(sb, 1976af0db57dSNamjae Jeon "Failed to load attribute list with error code %i.", 19771e9ea7e0SNamjae Jeon -err); 19781e9ea7e0SNamjae Jeon goto put_err_out; 19791e9ea7e0SNamjae Jeon } 19801e9ea7e0SNamjae Jeon } else /* if (!ctx.attr->non_resident) */ { 19811e9ea7e0SNamjae Jeon /* Now copy the attribute list. */ 19821e9ea7e0SNamjae Jeon memcpy(ni->attr_list, (u8 *)a + le16_to_cpu( 19831e9ea7e0SNamjae Jeon a->data.resident.value_offset), 1984af0db57dSNamjae Jeon le32_to_cpu(a->data.resident.value_length)); 19851e9ea7e0SNamjae Jeon } 19861e9ea7e0SNamjae Jeon /* The attribute list is now setup in memory. */ 1987af0db57dSNamjae Jeon al_entry = (struct attr_list_entry *)ni->attr_list; 19881e9ea7e0SNamjae Jeon al_end = (u8 *)al_entry + ni->attr_list_size; 19891e9ea7e0SNamjae Jeon for (;; al_entry = next_al_entry) { 19901e9ea7e0SNamjae Jeon /* Out of bounds check. */ 19911e9ea7e0SNamjae Jeon if ((u8 *)al_entry < ni->attr_list || 19921e9ea7e0SNamjae Jeon (u8 *)al_entry > al_end) 19931e9ea7e0SNamjae Jeon goto em_put_err_out; 19941e9ea7e0SNamjae Jeon /* Catch the end of the attribute list. */ 19951e9ea7e0SNamjae Jeon if ((u8 *)al_entry == al_end) 19961e9ea7e0SNamjae Jeon goto em_put_err_out; 19971e9ea7e0SNamjae Jeon if (!al_entry->length) 19981e9ea7e0SNamjae Jeon goto em_put_err_out; 1999af0db57dSNamjae Jeon if ((u8 *)al_entry + 6 > al_end || 2000af0db57dSNamjae Jeon (u8 *)al_entry + le16_to_cpu(al_entry->length) > al_end) 20011e9ea7e0SNamjae Jeon goto em_put_err_out; 2002af0db57dSNamjae Jeon next_al_entry = (struct attr_list_entry *)((u8 *)al_entry + 20031e9ea7e0SNamjae Jeon le16_to_cpu(al_entry->length)); 20041e9ea7e0SNamjae Jeon if (le32_to_cpu(al_entry->type) > le32_to_cpu(AT_DATA)) 20051e9ea7e0SNamjae Jeon goto em_put_err_out; 2006af0db57dSNamjae Jeon if (al_entry->type != AT_DATA) 20071e9ea7e0SNamjae Jeon continue; 20081e9ea7e0SNamjae Jeon /* We want an unnamed attribute. */ 20091e9ea7e0SNamjae Jeon if (al_entry->name_length) 20101e9ea7e0SNamjae Jeon goto em_put_err_out; 20111e9ea7e0SNamjae Jeon /* Want the first entry, i.e. lowest_vcn == 0. */ 20121e9ea7e0SNamjae Jeon if (al_entry->lowest_vcn) 20131e9ea7e0SNamjae Jeon goto em_put_err_out; 20141e9ea7e0SNamjae Jeon /* First entry has to be in the base mft record. */ 20151e9ea7e0SNamjae Jeon if (MREF_LE(al_entry->mft_reference) != vi->i_ino) { 20161e9ea7e0SNamjae Jeon /* MFT references do not match, logic fails. */ 2017af0db57dSNamjae Jeon ntfs_error(sb, 2018af0db57dSNamjae Jeon "BUG: The first $DATA extent of $MFT is not in the base mft record."); 20191e9ea7e0SNamjae Jeon goto put_err_out; 20201e9ea7e0SNamjae Jeon } else { 20211e9ea7e0SNamjae Jeon /* Sequence numbers must match. */ 20221e9ea7e0SNamjae Jeon if (MSEQNO_LE(al_entry->mft_reference) != 20231e9ea7e0SNamjae Jeon ni->seq_no) 20241e9ea7e0SNamjae Jeon goto em_put_err_out; 20251e9ea7e0SNamjae Jeon /* Got it. All is ok. We can stop now. */ 20261e9ea7e0SNamjae Jeon break; 20271e9ea7e0SNamjae Jeon } 20281e9ea7e0SNamjae Jeon } 20291e9ea7e0SNamjae Jeon } 20301e9ea7e0SNamjae Jeon 20311e9ea7e0SNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 20321e9ea7e0SNamjae Jeon 20331e9ea7e0SNamjae Jeon /* Now load all attribute extents. */ 20341e9ea7e0SNamjae Jeon a = NULL; 20351e9ea7e0SNamjae Jeon next_vcn = last_vcn = highest_vcn = 0; 20361e9ea7e0SNamjae Jeon while (!(err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0, 20371e9ea7e0SNamjae Jeon ctx))) { 2038af0db57dSNamjae Jeon struct runlist_element *nrl; 20391e9ea7e0SNamjae Jeon 20401e9ea7e0SNamjae Jeon /* Cache the current attribute. */ 20411e9ea7e0SNamjae Jeon a = ctx->attr; 20421e9ea7e0SNamjae Jeon /* $MFT must be non-resident. */ 20431e9ea7e0SNamjae Jeon if (!a->non_resident) { 2044af0db57dSNamjae Jeon ntfs_error(sb, 2045af0db57dSNamjae Jeon "$MFT must be non-resident but a resident extent was found. $MFT is corrupt. Run chkdsk."); 20461e9ea7e0SNamjae Jeon goto put_err_out; 20471e9ea7e0SNamjae Jeon } 20481e9ea7e0SNamjae Jeon /* $MFT must be uncompressed and unencrypted. */ 20491e9ea7e0SNamjae Jeon if (a->flags & ATTR_COMPRESSION_MASK || 20501e9ea7e0SNamjae Jeon a->flags & ATTR_IS_ENCRYPTED || 20511e9ea7e0SNamjae Jeon a->flags & ATTR_IS_SPARSE) { 2052af0db57dSNamjae Jeon ntfs_error(sb, 2053af0db57dSNamjae Jeon "$MFT must be uncompressed, non-sparse, and unencrypted but a compressed/sparse/encrypted extent was found. $MFT is corrupt. Run chkdsk."); 20541e9ea7e0SNamjae Jeon goto put_err_out; 20551e9ea7e0SNamjae Jeon } 20561e9ea7e0SNamjae Jeon /* 20571e9ea7e0SNamjae Jeon * Decompress the mapping pairs array of this extent and merge 20581e9ea7e0SNamjae Jeon * the result into the existing runlist. No need for locking 20591e9ea7e0SNamjae Jeon * as we have exclusive access to the inode at this time and we 20601e9ea7e0SNamjae Jeon * are a mount in progress task, too. 20611e9ea7e0SNamjae Jeon */ 2062af0db57dSNamjae Jeon nrl = ntfs_mapping_pairs_decompress(vol, a, &ni->runlist, 2063af0db57dSNamjae Jeon &new_rl_count); 20641e9ea7e0SNamjae Jeon if (IS_ERR(nrl)) { 2065af0db57dSNamjae Jeon ntfs_error(sb, 2066af0db57dSNamjae Jeon "ntfs_mapping_pairs_decompress() failed with error code %ld.", 2067af0db57dSNamjae Jeon PTR_ERR(nrl)); 20681e9ea7e0SNamjae Jeon goto put_err_out; 20691e9ea7e0SNamjae Jeon } 20701e9ea7e0SNamjae Jeon ni->runlist.rl = nrl; 2071af0db57dSNamjae Jeon ni->runlist.count = new_rl_count; 20721e9ea7e0SNamjae Jeon 20731e9ea7e0SNamjae Jeon /* Are we in the first extent? */ 20741e9ea7e0SNamjae Jeon if (!next_vcn) { 20751e9ea7e0SNamjae Jeon if (a->data.non_resident.lowest_vcn) { 2076af0db57dSNamjae Jeon ntfs_error(sb, 2077af0db57dSNamjae Jeon "First extent of $DATA attribute has non zero lowest_vcn. $MFT is corrupt. You should run chkdsk."); 20781e9ea7e0SNamjae Jeon goto put_err_out; 20791e9ea7e0SNamjae Jeon } 20801e9ea7e0SNamjae Jeon /* Get the last vcn in the $DATA attribute. */ 2081af0db57dSNamjae Jeon last_vcn = ntfs_bytes_to_cluster(vol, 2082af0db57dSNamjae Jeon le64_to_cpu(a->data.non_resident.allocated_size)); 20831e9ea7e0SNamjae Jeon /* Fill in the inode size. */ 2084af0db57dSNamjae Jeon vi->i_size = le64_to_cpu(a->data.non_resident.data_size); 2085af0db57dSNamjae Jeon ni->initialized_size = le64_to_cpu(a->data.non_resident.initialized_size); 2086af0db57dSNamjae Jeon ni->allocated_size = le64_to_cpu(a->data.non_resident.allocated_size); 20871e9ea7e0SNamjae Jeon /* 20881e9ea7e0SNamjae Jeon * Verify the number of mft records does not exceed 20891e9ea7e0SNamjae Jeon * 2^32 - 1. 20901e9ea7e0SNamjae Jeon */ 20911e9ea7e0SNamjae Jeon if ((vi->i_size >> vol->mft_record_size_bits) >= 20921e9ea7e0SNamjae Jeon (1ULL << 32)) { 20931e9ea7e0SNamjae Jeon ntfs_error(sb, "$MFT is too big! Aborting."); 20941e9ea7e0SNamjae Jeon goto put_err_out; 20951e9ea7e0SNamjae Jeon } 20961e9ea7e0SNamjae Jeon /* 20971e9ea7e0SNamjae Jeon * We have got the first extent of the runlist for 20981e9ea7e0SNamjae Jeon * $MFT which means it is now relatively safe to call 20991e9ea7e0SNamjae Jeon * the normal ntfs_read_inode() function. 21001e9ea7e0SNamjae Jeon * Complete reading the inode, this will actually 21011e9ea7e0SNamjae Jeon * re-read the mft record for $MFT, this time entering 21021e9ea7e0SNamjae Jeon * it into the page cache with which we complete the 21031e9ea7e0SNamjae Jeon * kick start of the volume. It should be safe to do 21041e9ea7e0SNamjae Jeon * this now as the first extent of $MFT/$DATA is 21051e9ea7e0SNamjae Jeon * already known and we would hope that we don't need 21061e9ea7e0SNamjae Jeon * further extents in order to find the other 21071e9ea7e0SNamjae Jeon * attributes belonging to $MFT. Only time will tell if 21081e9ea7e0SNamjae Jeon * this is really the case. If not we will have to play 21091e9ea7e0SNamjae Jeon * magic at this point, possibly duplicating a lot of 21101e9ea7e0SNamjae Jeon * ntfs_read_inode() at this point. We will need to 21111e9ea7e0SNamjae Jeon * ensure we do enough of its work to be able to call 21121e9ea7e0SNamjae Jeon * ntfs_read_inode() on extents of $MFT/$DATA. But lets 21131e9ea7e0SNamjae Jeon * hope this never happens... 21141e9ea7e0SNamjae Jeon */ 2115af0db57dSNamjae Jeon err = ntfs_read_locked_inode(vi); 2116af0db57dSNamjae Jeon if (err) { 2117af0db57dSNamjae Jeon ntfs_error(sb, "ntfs_read_inode() of $MFT failed.\n"); 21181e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 21191e9ea7e0SNamjae Jeon /* Revert to the safe super operations. */ 2120af0db57dSNamjae Jeon kfree(m); 21211e9ea7e0SNamjae Jeon return -1; 21221e9ea7e0SNamjae Jeon } 21231e9ea7e0SNamjae Jeon /* 21241e9ea7e0SNamjae Jeon * Re-initialize some specifics about $MFT's inode as 21251e9ea7e0SNamjae Jeon * ntfs_read_inode() will have set up the default ones. 21261e9ea7e0SNamjae Jeon */ 21271e9ea7e0SNamjae Jeon /* Set uid and gid to root. */ 21281e9ea7e0SNamjae Jeon vi->i_uid = GLOBAL_ROOT_UID; 21291e9ea7e0SNamjae Jeon vi->i_gid = GLOBAL_ROOT_GID; 21301e9ea7e0SNamjae Jeon /* Regular file. No access for anyone. */ 21311e9ea7e0SNamjae Jeon vi->i_mode = S_IFREG; 21321e9ea7e0SNamjae Jeon /* No VFS initiated operations allowed for $MFT. */ 21331e9ea7e0SNamjae Jeon vi->i_op = &ntfs_empty_inode_ops; 21341e9ea7e0SNamjae Jeon vi->i_fop = &ntfs_empty_file_ops; 21351e9ea7e0SNamjae Jeon } 21361e9ea7e0SNamjae Jeon 21371e9ea7e0SNamjae Jeon /* Get the lowest vcn for the next extent. */ 2138af0db57dSNamjae Jeon highest_vcn = le64_to_cpu(a->data.non_resident.highest_vcn); 21391e9ea7e0SNamjae Jeon next_vcn = highest_vcn + 1; 21401e9ea7e0SNamjae Jeon 21411e9ea7e0SNamjae Jeon /* Only one extent or error, which we catch below. */ 21421e9ea7e0SNamjae Jeon if (next_vcn <= 0) 21431e9ea7e0SNamjae Jeon break; 21441e9ea7e0SNamjae Jeon 21451e9ea7e0SNamjae Jeon /* Avoid endless loops due to corruption. */ 2146af0db57dSNamjae Jeon if (next_vcn < le64_to_cpu(a->data.non_resident.lowest_vcn)) { 2147af0db57dSNamjae Jeon ntfs_error(sb, "$MFT has corrupt attribute list attribute. Run chkdsk."); 21481e9ea7e0SNamjae Jeon goto put_err_out; 21491e9ea7e0SNamjae Jeon } 21501e9ea7e0SNamjae Jeon } 21511e9ea7e0SNamjae Jeon if (err != -ENOENT) { 2152af0db57dSNamjae Jeon ntfs_error(sb, "Failed to lookup $MFT/$DATA attribute extent. Run chkdsk.\n"); 21531e9ea7e0SNamjae Jeon goto put_err_out; 21541e9ea7e0SNamjae Jeon } 21551e9ea7e0SNamjae Jeon if (!a) { 2156af0db57dSNamjae Jeon ntfs_error(sb, "$MFT/$DATA attribute not found. $MFT is corrupt. Run chkdsk."); 21571e9ea7e0SNamjae Jeon goto put_err_out; 21581e9ea7e0SNamjae Jeon } 21591e9ea7e0SNamjae Jeon if (highest_vcn && highest_vcn != last_vcn - 1) { 2160af0db57dSNamjae Jeon ntfs_error(sb, "Failed to load the complete runlist for $MFT/$DATA. Run chkdsk."); 21611e9ea7e0SNamjae Jeon ntfs_debug("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx", 21621e9ea7e0SNamjae Jeon (unsigned long long)highest_vcn, 21631e9ea7e0SNamjae Jeon (unsigned long long)last_vcn - 1); 21641e9ea7e0SNamjae Jeon goto put_err_out; 21651e9ea7e0SNamjae Jeon } 21661e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 21671e9ea7e0SNamjae Jeon ntfs_debug("Done."); 2168af0db57dSNamjae Jeon kfree(m); 21691e9ea7e0SNamjae Jeon 21701e9ea7e0SNamjae Jeon /* 21711e9ea7e0SNamjae Jeon * Split the locking rules of the MFT inode from the 21721e9ea7e0SNamjae Jeon * locking rules of other inodes: 21731e9ea7e0SNamjae Jeon */ 21741e9ea7e0SNamjae Jeon lockdep_set_class(&ni->runlist.lock, &mft_ni_runlist_lock_key); 21751e9ea7e0SNamjae Jeon lockdep_set_class(&ni->mrec_lock, &mft_ni_mrec_lock_key); 21761e9ea7e0SNamjae Jeon 21771e9ea7e0SNamjae Jeon return 0; 21781e9ea7e0SNamjae Jeon 21791e9ea7e0SNamjae Jeon em_put_err_out: 2180af0db57dSNamjae Jeon ntfs_error(sb, 2181af0db57dSNamjae Jeon "Couldn't find first extent of $DATA attribute in attribute list. $MFT is corrupt. Run chkdsk."); 21821e9ea7e0SNamjae Jeon put_err_out: 21831e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 21841e9ea7e0SNamjae Jeon err_out: 21851e9ea7e0SNamjae Jeon ntfs_error(sb, "Failed. Marking inode as bad."); 2186af0db57dSNamjae Jeon kfree(m); 21871e9ea7e0SNamjae Jeon return -1; 21881e9ea7e0SNamjae Jeon } 21891e9ea7e0SNamjae Jeon 2190af0db57dSNamjae Jeon static void __ntfs_clear_inode(struct ntfs_inode *ni) 21911e9ea7e0SNamjae Jeon { 21921e9ea7e0SNamjae Jeon /* Free all alocated memory. */ 2193af0db57dSNamjae Jeon if (NInoNonResident(ni) && ni->runlist.rl) { 2194af0db57dSNamjae Jeon kvfree(ni->runlist.rl); 21951e9ea7e0SNamjae Jeon ni->runlist.rl = NULL; 21961e9ea7e0SNamjae Jeon } 21971e9ea7e0SNamjae Jeon 21981e9ea7e0SNamjae Jeon if (ni->attr_list) { 2199af0db57dSNamjae Jeon kvfree(ni->attr_list); 22001e9ea7e0SNamjae Jeon ni->attr_list = NULL; 22011e9ea7e0SNamjae Jeon } 22021e9ea7e0SNamjae Jeon 2203af0db57dSNamjae Jeon if (ni->name_len && ni->name != I30 && 2204af0db57dSNamjae Jeon ni->name != reparse_index_name && 2205af0db57dSNamjae Jeon ni->name != objid_index_name) { 2206af0db57dSNamjae Jeon WARN_ON(!ni->name); 22071e9ea7e0SNamjae Jeon kfree(ni->name); 22081e9ea7e0SNamjae Jeon } 22091e9ea7e0SNamjae Jeon } 22101e9ea7e0SNamjae Jeon 2211af0db57dSNamjae Jeon void ntfs_clear_extent_inode(struct ntfs_inode *ni) 22121e9ea7e0SNamjae Jeon { 2213d9038d99SNamjae Jeon ntfs_debug("Entering for inode 0x%llx.", ni->mft_no); 22141e9ea7e0SNamjae Jeon 2215af0db57dSNamjae Jeon WARN_ON(NInoAttr(ni)); 2216af0db57dSNamjae Jeon WARN_ON(ni->nr_extents != -1); 22171e9ea7e0SNamjae Jeon 22181e9ea7e0SNamjae Jeon __ntfs_clear_inode(ni); 22191e9ea7e0SNamjae Jeon ntfs_destroy_extent_inode(ni); 22201e9ea7e0SNamjae Jeon } 22211e9ea7e0SNamjae Jeon 2222af0db57dSNamjae Jeon static int ntfs_delete_base_inode(struct ntfs_inode *ni) 2223af0db57dSNamjae Jeon { 2224af0db57dSNamjae Jeon struct super_block *sb = ni->vol->sb; 2225af0db57dSNamjae Jeon int err; 2226af0db57dSNamjae Jeon 2227af0db57dSNamjae Jeon if (NInoAttr(ni) || ni->nr_extents == -1) 2228af0db57dSNamjae Jeon return 0; 2229af0db57dSNamjae Jeon 2230af0db57dSNamjae Jeon err = ntfs_non_resident_dealloc_clusters(ni); 2231af0db57dSNamjae Jeon 2232af0db57dSNamjae Jeon /* 2233af0db57dSNamjae Jeon * Deallocate extent mft records and free extent inodes. 2234af0db57dSNamjae Jeon * No need to lock as no one else has a reference. 2235af0db57dSNamjae Jeon */ 2236af0db57dSNamjae Jeon while (ni->nr_extents) { 2237af0db57dSNamjae Jeon err = ntfs_mft_record_free(ni->vol, *(ni->ext.extent_ntfs_inos)); 2238af0db57dSNamjae Jeon if (err) 2239af0db57dSNamjae Jeon ntfs_error(sb, 2240af0db57dSNamjae Jeon "Failed to free extent MFT record. Leaving inconsistent metadata.\n"); 2241af0db57dSNamjae Jeon ntfs_inode_close(*(ni->ext.extent_ntfs_inos)); 2242af0db57dSNamjae Jeon } 2243af0db57dSNamjae Jeon 2244af0db57dSNamjae Jeon /* Deallocate base mft record */ 2245af0db57dSNamjae Jeon err = ntfs_mft_record_free(ni->vol, ni); 2246af0db57dSNamjae Jeon if (err) 2247af0db57dSNamjae Jeon ntfs_error(sb, "Failed to free base MFT record. Leaving inconsistent metadata.\n"); 2248af0db57dSNamjae Jeon return err; 2249af0db57dSNamjae Jeon } 2250af0db57dSNamjae Jeon 2251af0db57dSNamjae Jeon /* 22521e9ea7e0SNamjae Jeon * ntfs_evict_big_inode - clean up the ntfs specific part of an inode 22531e9ea7e0SNamjae Jeon * @vi: vfs inode pending annihilation 22541e9ea7e0SNamjae Jeon * 22551e9ea7e0SNamjae Jeon * When the VFS is going to remove an inode from memory, ntfs_clear_big_inode() 22561e9ea7e0SNamjae Jeon * is called, which deallocates all memory belonging to the NTFS specific part 22571e9ea7e0SNamjae Jeon * of the inode and returns. 22581e9ea7e0SNamjae Jeon * 22591e9ea7e0SNamjae Jeon * If the MFT record is dirty, we commit it before doing anything else. 22601e9ea7e0SNamjae Jeon */ 22611e9ea7e0SNamjae Jeon void ntfs_evict_big_inode(struct inode *vi) 22621e9ea7e0SNamjae Jeon { 2263af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 22641e9ea7e0SNamjae Jeon 22651e9ea7e0SNamjae Jeon truncate_inode_pages_final(&vi->i_data); 22661e9ea7e0SNamjae Jeon 2267af0db57dSNamjae Jeon if (!vi->i_nlink) { 2268af0db57dSNamjae Jeon if (!NInoAttr(ni)) { 2269af0db57dSNamjae Jeon /* Never called with extent inodes */ 2270af0db57dSNamjae Jeon WARN_ON(ni->nr_extents == -1); 2271af0db57dSNamjae Jeon ntfs_delete_base_inode(ni); 2272af0db57dSNamjae Jeon } 2273af0db57dSNamjae Jeon goto release; 2274af0db57dSNamjae Jeon } 2275af0db57dSNamjae Jeon 22761e9ea7e0SNamjae Jeon if (NInoDirty(ni)) { 22771e9ea7e0SNamjae Jeon /* Committing the inode also commits all extent inodes. */ 22781e9ea7e0SNamjae Jeon ntfs_commit_inode(vi); 22791e9ea7e0SNamjae Jeon 2280af0db57dSNamjae Jeon if (NInoDirty(ni)) { 2281e7d82353SNamjae Jeon ntfs_debug("Failed to commit dirty inode 0x%llx. Losing data!", 2282e7d82353SNamjae Jeon ni->mft_no); 2283af0db57dSNamjae Jeon NInoClearAttrListDirty(ni); 2284af0db57dSNamjae Jeon NInoClearDirty(ni); 22851e9ea7e0SNamjae Jeon } 22861e9ea7e0SNamjae Jeon } 22871e9ea7e0SNamjae Jeon 22881e9ea7e0SNamjae Jeon /* No need to lock at this stage as no one else has a reference. */ 22891e9ea7e0SNamjae Jeon if (ni->nr_extents > 0) { 22901e9ea7e0SNamjae Jeon int i; 22911e9ea7e0SNamjae Jeon 2292af0db57dSNamjae Jeon for (i = 0; i < ni->nr_extents; i++) { 2293af0db57dSNamjae Jeon if (ni->ext.extent_ntfs_inos[i]) 22941e9ea7e0SNamjae Jeon ntfs_clear_extent_inode(ni->ext.extent_ntfs_inos[i]); 2295af0db57dSNamjae Jeon } 2296af0db57dSNamjae Jeon ni->nr_extents = 0; 2297af0db57dSNamjae Jeon kvfree(ni->ext.extent_ntfs_inos); 22981e9ea7e0SNamjae Jeon } 22991e9ea7e0SNamjae Jeon 2300af0db57dSNamjae Jeon release: 2301af0db57dSNamjae Jeon clear_inode(vi); 23021e9ea7e0SNamjae Jeon __ntfs_clear_inode(ni); 23031e9ea7e0SNamjae Jeon 23041e9ea7e0SNamjae Jeon if (NInoAttr(ni)) { 23051e9ea7e0SNamjae Jeon /* Release the base inode if we are holding it. */ 23061e9ea7e0SNamjae Jeon if (ni->nr_extents == -1) { 23071e9ea7e0SNamjae Jeon iput(VFS_I(ni->ext.base_ntfs_ino)); 23081e9ea7e0SNamjae Jeon ni->nr_extents = 0; 23091e9ea7e0SNamjae Jeon ni->ext.base_ntfs_ino = NULL; 23101e9ea7e0SNamjae Jeon } 23111e9ea7e0SNamjae Jeon } 2312af0db57dSNamjae Jeon 23131e9ea7e0SNamjae Jeon if (!atomic_dec_and_test(&ni->count)) 2314af0db57dSNamjae Jeon WARN_ON(1); 2315af0db57dSNamjae Jeon if (ni->folio) 2316af0db57dSNamjae Jeon folio_put(ni->folio); 2317af0db57dSNamjae Jeon kfree(ni->mrec); 2318af0db57dSNamjae Jeon kvfree(ni->target); 23191e9ea7e0SNamjae Jeon } 23201e9ea7e0SNamjae Jeon 2321af0db57dSNamjae Jeon /* 23221e9ea7e0SNamjae Jeon * ntfs_show_options - show mount options in /proc/mounts 23231e9ea7e0SNamjae Jeon * @sf: seq_file in which to write our mount options 23241e9ea7e0SNamjae Jeon * @root: root of the mounted tree whose mount options to display 23251e9ea7e0SNamjae Jeon * 23261e9ea7e0SNamjae Jeon * Called by the VFS once for each mounted ntfs volume when someone reads 23271e9ea7e0SNamjae Jeon * /proc/mounts in order to display the NTFS specific mount options of each 23281e9ea7e0SNamjae Jeon * mount. The mount options of fs specified by @root are written to the seq file 23291e9ea7e0SNamjae Jeon * @sf and success is returned. 23301e9ea7e0SNamjae Jeon */ 23311e9ea7e0SNamjae Jeon int ntfs_show_options(struct seq_file *sf, struct dentry *root) 23321e9ea7e0SNamjae Jeon { 2333af0db57dSNamjae Jeon struct ntfs_volume *vol = NTFS_SB(root->d_sb); 23341e9ea7e0SNamjae Jeon int i; 23351e9ea7e0SNamjae Jeon 2336af0db57dSNamjae Jeon if (uid_valid(vol->uid)) 23371e9ea7e0SNamjae Jeon seq_printf(sf, ",uid=%i", from_kuid_munged(&init_user_ns, vol->uid)); 2338af0db57dSNamjae Jeon if (gid_valid(vol->gid)) 23391e9ea7e0SNamjae Jeon seq_printf(sf, ",gid=%i", from_kgid_munged(&init_user_ns, vol->gid)); 23401e9ea7e0SNamjae Jeon if (vol->fmask == vol->dmask) 23411e9ea7e0SNamjae Jeon seq_printf(sf, ",umask=0%o", vol->fmask); 23421e9ea7e0SNamjae Jeon else { 23431e9ea7e0SNamjae Jeon seq_printf(sf, ",fmask=0%o", vol->fmask); 23441e9ea7e0SNamjae Jeon seq_printf(sf, ",dmask=0%o", vol->dmask); 23451e9ea7e0SNamjae Jeon } 2346af0db57dSNamjae Jeon seq_printf(sf, ",iocharset=%s", vol->nls_map->charset); 23471e9ea7e0SNamjae Jeon if (NVolCaseSensitive(vol)) 2348af0db57dSNamjae Jeon seq_puts(sf, ",case_sensitive"); 2349af0db57dSNamjae Jeon else 2350af0db57dSNamjae Jeon seq_puts(sf, ",nocase"); 23511e9ea7e0SNamjae Jeon if (NVolShowSystemFiles(vol)) 2352af0db57dSNamjae Jeon seq_puts(sf, ",show_sys_files,showmeta"); 23531e9ea7e0SNamjae Jeon for (i = 0; on_errors_arr[i].val; i++) { 2354af0db57dSNamjae Jeon if (on_errors_arr[i].val == vol->on_errors) 23551e9ea7e0SNamjae Jeon seq_printf(sf, ",errors=%s", on_errors_arr[i].str); 23561e9ea7e0SNamjae Jeon } 23571e9ea7e0SNamjae Jeon seq_printf(sf, ",mft_zone_multiplier=%i", vol->mft_zone_multiplier); 2358af0db57dSNamjae Jeon if (NVolSysImmutable(vol)) 2359af0db57dSNamjae Jeon seq_puts(sf, ",sys_immutable"); 2360af0db57dSNamjae Jeon if (!NVolShowHiddenFiles(vol)) 2361af0db57dSNamjae Jeon seq_puts(sf, ",nohidden"); 2362af0db57dSNamjae Jeon if (NVolHideDotFiles(vol)) 2363af0db57dSNamjae Jeon seq_puts(sf, ",hide_dot_files"); 2364af0db57dSNamjae Jeon if (NVolCheckWindowsNames(vol)) 2365af0db57dSNamjae Jeon seq_puts(sf, ",windows_names"); 2366af0db57dSNamjae Jeon if (NVolDiscard(vol)) 2367af0db57dSNamjae Jeon seq_puts(sf, ",discard"); 2368af0db57dSNamjae Jeon if (NVolDisableSparse(vol)) 2369af0db57dSNamjae Jeon seq_puts(sf, ",disable_sparse"); 2370af0db57dSNamjae Jeon if (vol->sb->s_flags & SB_POSIXACL) 2371af0db57dSNamjae Jeon seq_puts(sf, ",acl"); 23721e9ea7e0SNamjae Jeon return 0; 23731e9ea7e0SNamjae Jeon } 23741e9ea7e0SNamjae Jeon 2375af0db57dSNamjae Jeon int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset, 2376af0db57dSNamjae Jeon const loff_t new_size, bool bsync) 23771e9ea7e0SNamjae Jeon { 2378af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 2379af0db57dSNamjae Jeon loff_t old_init_size; 23801e9ea7e0SNamjae Jeon unsigned long flags; 23811e9ea7e0SNamjae Jeon int err; 23821e9ea7e0SNamjae Jeon 2383af0db57dSNamjae Jeon read_lock_irqsave(&ni->size_lock, flags); 2384af0db57dSNamjae Jeon old_init_size = ni->initialized_size; 2385af0db57dSNamjae Jeon read_unlock_irqrestore(&ni->size_lock, flags); 2386af0db57dSNamjae Jeon 2387af0db57dSNamjae Jeon if (!NInoNonResident(ni)) 2388af0db57dSNamjae Jeon return -EINVAL; 2389af0db57dSNamjae Jeon if (old_init_size >= new_size) 2390af0db57dSNamjae Jeon return 0; 2391af0db57dSNamjae Jeon 2392af0db57dSNamjae Jeon err = ntfs_attr_map_whole_runlist(ni); 23931e9ea7e0SNamjae Jeon if (err) 2394af0db57dSNamjae Jeon return err; 2395af0db57dSNamjae Jeon 2396af0db57dSNamjae Jeon if (!NInoCompressed(ni) && old_init_size < offset) { 2397af0db57dSNamjae Jeon err = iomap_zero_range(vi, old_init_size, 2398af0db57dSNamjae Jeon offset - old_init_size, 2399af0db57dSNamjae Jeon NULL, &ntfs_seek_iomap_ops, 2400af0db57dSNamjae Jeon &ntfs_iomap_folio_ops, NULL); 2401af0db57dSNamjae Jeon if (err) 2402af0db57dSNamjae Jeon return err; 2403af0db57dSNamjae Jeon if (bsync) 2404af0db57dSNamjae Jeon err = filemap_write_and_wait_range(vi->i_mapping, 2405af0db57dSNamjae Jeon old_init_size, 2406af0db57dSNamjae Jeon offset - 1); 24071e9ea7e0SNamjae Jeon } 2408af0db57dSNamjae Jeon 2409af0db57dSNamjae Jeon 2410af0db57dSNamjae Jeon mutex_lock(&ni->mrec_lock); 2411af0db57dSNamjae Jeon err = ntfs_attr_set_initialized_size(ni, new_size); 2412af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 2413af0db57dSNamjae Jeon if (err) 2414af0db57dSNamjae Jeon truncate_setsize(vi, old_init_size); 24151e9ea7e0SNamjae Jeon return err; 24161e9ea7e0SNamjae Jeon } 24171e9ea7e0SNamjae Jeon 2418af0db57dSNamjae Jeon int ntfs_truncate_vfs(struct inode *vi, loff_t new_size, loff_t i_size) 24191e9ea7e0SNamjae Jeon { 2420af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 2421af0db57dSNamjae Jeon int err; 2422af0db57dSNamjae Jeon 2423af0db57dSNamjae Jeon mutex_lock(&ni->mrec_lock); 2424af0db57dSNamjae Jeon err = __ntfs_attr_truncate_vfs(ni, new_size, i_size); 2425af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 2426af0db57dSNamjae Jeon if (err < 0) 2427af0db57dSNamjae Jeon return err; 2428af0db57dSNamjae Jeon 2429af0db57dSNamjae Jeon inode_set_mtime_to_ts(vi, inode_set_ctime_current(vi)); 2430af0db57dSNamjae Jeon return 0; 2431af0db57dSNamjae Jeon } 2432af0db57dSNamjae Jeon 2433af0db57dSNamjae Jeon /* 2434af0db57dSNamjae Jeon * ntfs_inode_sync_standard_information - update standard information attribute 2435af0db57dSNamjae Jeon * @vi: inode to update standard information 2436af0db57dSNamjae Jeon * @m: mft record 2437af0db57dSNamjae Jeon * 2438af0db57dSNamjae Jeon * Return 0 on success or -errno on error. 2439af0db57dSNamjae Jeon */ 2440af0db57dSNamjae Jeon static int ntfs_inode_sync_standard_information(struct inode *vi, struct mft_record *m) 2441af0db57dSNamjae Jeon { 2442af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 2443af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 2444af0db57dSNamjae Jeon struct standard_information *si; 2445af0db57dSNamjae Jeon __le64 nt; 24461e9ea7e0SNamjae Jeon int err = 0; 24471e9ea7e0SNamjae Jeon bool modified = false; 24481e9ea7e0SNamjae Jeon 24491e9ea7e0SNamjae Jeon /* Update the access times in the standard information attribute. */ 24501e9ea7e0SNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, m); 2451af0db57dSNamjae Jeon if (unlikely(!ctx)) 2452af0db57dSNamjae Jeon return -ENOMEM; 24531e9ea7e0SNamjae Jeon err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0, 24541e9ea7e0SNamjae Jeon CASE_SENSITIVE, 0, NULL, 0, ctx); 24551e9ea7e0SNamjae Jeon if (unlikely(err)) { 24561e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 2457af0db57dSNamjae Jeon return err; 24581e9ea7e0SNamjae Jeon } 2459af0db57dSNamjae Jeon si = (struct standard_information *)((u8 *)ctx->attr + 24601e9ea7e0SNamjae Jeon le16_to_cpu(ctx->attr->data.resident.value_offset)); 2461af0db57dSNamjae Jeon if (si->file_attributes != ni->flags) { 2462af0db57dSNamjae Jeon si->file_attributes = ni->flags; 2463af0db57dSNamjae Jeon modified = true; 2464af0db57dSNamjae Jeon } 2465af0db57dSNamjae Jeon 2466af0db57dSNamjae Jeon /* Update the creation times if they have changed. */ 2467af0db57dSNamjae Jeon nt = utc2ntfs(ni->i_crtime); 2468af0db57dSNamjae Jeon if (si->creation_time != nt) { 2469e7d82353SNamjae Jeon ntfs_debug("Updating creation time for inode 0x%llx: old = 0x%llx, new = 0x%llx", 2470e7d82353SNamjae Jeon ni->mft_no, le64_to_cpu(si->creation_time), 2471af0db57dSNamjae Jeon le64_to_cpu(nt)); 2472af0db57dSNamjae Jeon si->creation_time = nt; 2473af0db57dSNamjae Jeon modified = true; 2474af0db57dSNamjae Jeon } 2475af0db57dSNamjae Jeon 24761e9ea7e0SNamjae Jeon /* Update the access times if they have changed. */ 24771e9ea7e0SNamjae Jeon nt = utc2ntfs(inode_get_mtime(vi)); 24781e9ea7e0SNamjae Jeon if (si->last_data_change_time != nt) { 2479e7d82353SNamjae Jeon ntfs_debug("Updating mtime for inode 0x%llx: old = 0x%llx, new = 0x%llx", 2480e7d82353SNamjae Jeon ni->mft_no, le64_to_cpu(si->last_data_change_time), 2481af0db57dSNamjae Jeon le64_to_cpu(nt)); 24821e9ea7e0SNamjae Jeon si->last_data_change_time = nt; 24831e9ea7e0SNamjae Jeon modified = true; 24841e9ea7e0SNamjae Jeon } 2485af0db57dSNamjae Jeon 24861e9ea7e0SNamjae Jeon nt = utc2ntfs(inode_get_ctime(vi)); 24871e9ea7e0SNamjae Jeon if (si->last_mft_change_time != nt) { 2488e7d82353SNamjae Jeon ntfs_debug("Updating ctime for inode 0x%llx: old = 0x%llx, new = 0x%llx", 2489e7d82353SNamjae Jeon ni->mft_no, le64_to_cpu(si->last_mft_change_time), 2490af0db57dSNamjae Jeon le64_to_cpu(nt)); 24911e9ea7e0SNamjae Jeon si->last_mft_change_time = nt; 24921e9ea7e0SNamjae Jeon modified = true; 24931e9ea7e0SNamjae Jeon } 24941e9ea7e0SNamjae Jeon nt = utc2ntfs(inode_get_atime(vi)); 24951e9ea7e0SNamjae Jeon if (si->last_access_time != nt) { 2496e7d82353SNamjae Jeon ntfs_debug("Updating atime for inode 0x%llx: old = 0x%llx, new = 0x%llx", 2497e7d82353SNamjae Jeon ni->mft_no, 2498af0db57dSNamjae Jeon le64_to_cpu(si->last_access_time), 2499af0db57dSNamjae Jeon le64_to_cpu(nt)); 25001e9ea7e0SNamjae Jeon si->last_access_time = nt; 25011e9ea7e0SNamjae Jeon modified = true; 25021e9ea7e0SNamjae Jeon } 2503af0db57dSNamjae Jeon 25041e9ea7e0SNamjae Jeon /* 25051e9ea7e0SNamjae Jeon * If we just modified the standard information attribute we need to 25061e9ea7e0SNamjae Jeon * mark the mft record it is in dirty. We do this manually so that 25071e9ea7e0SNamjae Jeon * mark_inode_dirty() is not called which would redirty the inode and 25081e9ea7e0SNamjae Jeon * hence result in an infinite loop of trying to write the inode. 25091e9ea7e0SNamjae Jeon * There is no need to mark the base inode nor the base mft record 25101e9ea7e0SNamjae Jeon * dirty, since we are going to write this mft record below in any case 25111e9ea7e0SNamjae Jeon * and the base mft record may actually not have been modified so it 25121e9ea7e0SNamjae Jeon * might not need to be written out. 25131e9ea7e0SNamjae Jeon * NOTE: It is not a problem when the inode for $MFT itself is being 2514af0db57dSNamjae Jeon * written out as ntfs_mft_mark_dirty() will only set I_DIRTY_PAGES 2515af0db57dSNamjae Jeon * on the $MFT inode and hence ntfs_write_inode() will not be 25161e9ea7e0SNamjae Jeon * re-invoked because of it which in turn is ok since the dirtied mft 25171e9ea7e0SNamjae Jeon * record will be cleaned and written out to disk below, i.e. before 25181e9ea7e0SNamjae Jeon * this function returns. 25191e9ea7e0SNamjae Jeon */ 2520af0db57dSNamjae Jeon if (modified) 2521af0db57dSNamjae Jeon NInoSetDirty(ctx->ntfs_ino); 25221e9ea7e0SNamjae Jeon ntfs_attr_put_search_ctx(ctx); 2523af0db57dSNamjae Jeon 2524af0db57dSNamjae Jeon return err; 2525af0db57dSNamjae Jeon } 2526af0db57dSNamjae Jeon 2527af0db57dSNamjae Jeon /* 2528af0db57dSNamjae Jeon * ntfs_inode_sync_filename - update FILE_NAME attributes 2529af0db57dSNamjae Jeon * @ni: ntfs inode to update FILE_NAME attributes 2530af0db57dSNamjae Jeon * 2531af0db57dSNamjae Jeon * Update all FILE_NAME attributes for inode @ni in the index. 2532af0db57dSNamjae Jeon * 2533af0db57dSNamjae Jeon * Return 0 on success or error. 2534af0db57dSNamjae Jeon */ 2535af0db57dSNamjae Jeon int ntfs_inode_sync_filename(struct ntfs_inode *ni) 2536af0db57dSNamjae Jeon { 2537af0db57dSNamjae Jeon struct inode *index_vi; 2538af0db57dSNamjae Jeon struct super_block *sb = VFS_I(ni)->i_sb; 2539af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx = NULL; 2540af0db57dSNamjae Jeon struct ntfs_index_context *ictx; 2541af0db57dSNamjae Jeon struct ntfs_inode *index_ni; 2542af0db57dSNamjae Jeon struct file_name_attr *fn; 2543af0db57dSNamjae Jeon struct file_name_attr *fnx; 2544af0db57dSNamjae Jeon struct reparse_point *rpp; 2545af0db57dSNamjae Jeon __le32 reparse_tag; 2546af0db57dSNamjae Jeon int err = 0; 2547af0db57dSNamjae Jeon unsigned long flags; 2548af0db57dSNamjae Jeon 2549d9038d99SNamjae Jeon ntfs_debug("Entering for inode %llu\n", ni->mft_no); 2550af0db57dSNamjae Jeon 2551af0db57dSNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, NULL); 2552af0db57dSNamjae Jeon if (!ctx) 2553af0db57dSNamjae Jeon return -ENOMEM; 2554af0db57dSNamjae Jeon 2555af0db57dSNamjae Jeon /* Collect the reparse tag, if any */ 2556af0db57dSNamjae Jeon reparse_tag = cpu_to_le32(0); 2557af0db57dSNamjae Jeon if (ni->flags & FILE_ATTR_REPARSE_POINT) { 2558af0db57dSNamjae Jeon if (!ntfs_attr_lookup(AT_REPARSE_POINT, NULL, 2559af0db57dSNamjae Jeon 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { 2560af0db57dSNamjae Jeon rpp = (struct reparse_point *)((u8 *)ctx->attr + 2561af0db57dSNamjae Jeon le16_to_cpu(ctx->attr->data.resident.value_offset)); 2562af0db57dSNamjae Jeon reparse_tag = rpp->reparse_tag; 2563af0db57dSNamjae Jeon } 2564af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 2565af0db57dSNamjae Jeon } 2566af0db57dSNamjae Jeon 2567af0db57dSNamjae Jeon /* Walk through all FILE_NAME attributes and update them. */ 2568af0db57dSNamjae Jeon while (!(err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx))) { 2569af0db57dSNamjae Jeon fn = (struct file_name_attr *)((u8 *)ctx->attr + 2570af0db57dSNamjae Jeon le16_to_cpu(ctx->attr->data.resident.value_offset)); 2571af0db57dSNamjae Jeon if (MREF_LE(fn->parent_directory) == ni->mft_no) 2572af0db57dSNamjae Jeon continue; 2573af0db57dSNamjae Jeon 2574af0db57dSNamjae Jeon index_vi = ntfs_iget(sb, MREF_LE(fn->parent_directory)); 2575af0db57dSNamjae Jeon if (IS_ERR(index_vi)) { 2576af0db57dSNamjae Jeon ntfs_error(sb, "Failed to open inode %lld with index", 2577af0db57dSNamjae Jeon (long long)MREF_LE(fn->parent_directory)); 2578af0db57dSNamjae Jeon continue; 2579af0db57dSNamjae Jeon } 2580af0db57dSNamjae Jeon 2581af0db57dSNamjae Jeon index_ni = NTFS_I(index_vi); 2582af0db57dSNamjae Jeon 2583af0db57dSNamjae Jeon mutex_lock_nested(&index_ni->mrec_lock, NTFS_INODE_MUTEX_PARENT); 2584af0db57dSNamjae Jeon if (NInoBeingDeleted(ni)) { 2585af0db57dSNamjae Jeon iput(index_vi); 2586af0db57dSNamjae Jeon mutex_unlock(&index_ni->mrec_lock); 2587af0db57dSNamjae Jeon continue; 2588af0db57dSNamjae Jeon } 2589af0db57dSNamjae Jeon 2590af0db57dSNamjae Jeon ictx = ntfs_index_ctx_get(index_ni, I30, 4); 2591af0db57dSNamjae Jeon if (!ictx) { 2592d9038d99SNamjae Jeon ntfs_error(sb, "Failed to get index ctx, inode %llu", 2593d9038d99SNamjae Jeon index_ni->mft_no); 2594af0db57dSNamjae Jeon iput(index_vi); 2595af0db57dSNamjae Jeon mutex_unlock(&index_ni->mrec_lock); 2596af0db57dSNamjae Jeon continue; 2597af0db57dSNamjae Jeon } 2598af0db57dSNamjae Jeon 2599af0db57dSNamjae Jeon err = ntfs_index_lookup(fn, sizeof(struct file_name_attr), ictx); 2600af0db57dSNamjae Jeon if (err) { 2601d9038d99SNamjae Jeon ntfs_debug("Index lookup failed, inode %llu", 2602d9038d99SNamjae Jeon index_ni->mft_no); 2603af0db57dSNamjae Jeon ntfs_index_ctx_put(ictx); 2604af0db57dSNamjae Jeon iput(index_vi); 2605af0db57dSNamjae Jeon mutex_unlock(&index_ni->mrec_lock); 2606af0db57dSNamjae Jeon continue; 2607af0db57dSNamjae Jeon } 2608af0db57dSNamjae Jeon /* Update flags and file size. */ 2609af0db57dSNamjae Jeon fnx = (struct file_name_attr *)ictx->data; 2610af0db57dSNamjae Jeon fnx->file_attributes = 2611af0db57dSNamjae Jeon (fnx->file_attributes & ~FILE_ATTR_VALID_FLAGS) | 2612af0db57dSNamjae Jeon (ni->flags & FILE_ATTR_VALID_FLAGS); 2613af0db57dSNamjae Jeon if (ctx->mrec->flags & MFT_RECORD_IS_DIRECTORY) 2614af0db57dSNamjae Jeon fnx->data_size = fnx->allocated_size = 0; 2615af0db57dSNamjae Jeon else { 2616af0db57dSNamjae Jeon read_lock_irqsave(&ni->size_lock, flags); 2617af0db57dSNamjae Jeon if (NInoSparse(ni) || NInoCompressed(ni)) 2618af0db57dSNamjae Jeon fnx->allocated_size = cpu_to_le64(ni->itype.compressed.size); 2619af0db57dSNamjae Jeon else 2620af0db57dSNamjae Jeon fnx->allocated_size = cpu_to_le64(ni->allocated_size); 2621af0db57dSNamjae Jeon fnx->data_size = cpu_to_le64(ni->data_size); 2622af0db57dSNamjae Jeon 2623af0db57dSNamjae Jeon /* 2624af0db57dSNamjae Jeon * The file name record has also to be fixed if some 2625af0db57dSNamjae Jeon * attribute update implied the unnamed data to be 2626af0db57dSNamjae Jeon * made non-resident 2627af0db57dSNamjae Jeon */ 2628af0db57dSNamjae Jeon fn->allocated_size = fnx->allocated_size; 2629af0db57dSNamjae Jeon fn->data_size = fnx->data_size; 2630af0db57dSNamjae Jeon read_unlock_irqrestore(&ni->size_lock, flags); 2631af0db57dSNamjae Jeon } 2632af0db57dSNamjae Jeon 2633af0db57dSNamjae Jeon /* update or clear the reparse tag in the index */ 2634af0db57dSNamjae Jeon fnx->type.rp.reparse_point_tag = reparse_tag; 2635af0db57dSNamjae Jeon fnx->creation_time = fn->creation_time; 2636af0db57dSNamjae Jeon fnx->last_data_change_time = fn->last_data_change_time; 2637af0db57dSNamjae Jeon fnx->last_mft_change_time = fn->last_mft_change_time; 2638af0db57dSNamjae Jeon fnx->last_access_time = fn->last_access_time; 2639af0db57dSNamjae Jeon ntfs_index_entry_mark_dirty(ictx); 2640af0db57dSNamjae Jeon ntfs_icx_ib_sync_write(ictx); 2641af0db57dSNamjae Jeon NInoSetDirty(ctx->ntfs_ino); 2642af0db57dSNamjae Jeon ntfs_index_ctx_put(ictx); 2643af0db57dSNamjae Jeon mutex_unlock(&index_ni->mrec_lock); 2644af0db57dSNamjae Jeon iput(index_vi); 2645af0db57dSNamjae Jeon } 2646af0db57dSNamjae Jeon /* Check for real error occurred. */ 2647af0db57dSNamjae Jeon if (err != -ENOENT) { 2648d9038d99SNamjae Jeon ntfs_error(sb, "Attribute lookup failed, err : %d, inode %llu", err, 2649d9038d99SNamjae Jeon ni->mft_no); 2650af0db57dSNamjae Jeon } else 2651af0db57dSNamjae Jeon err = 0; 2652af0db57dSNamjae Jeon 2653af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 2654af0db57dSNamjae Jeon return err; 2655af0db57dSNamjae Jeon } 2656af0db57dSNamjae Jeon 2657af0db57dSNamjae Jeon int ntfs_get_block_mft_record(struct ntfs_inode *mft_ni, struct ntfs_inode *ni) 2658af0db57dSNamjae Jeon { 2659af0db57dSNamjae Jeon s64 vcn; 2660af0db57dSNamjae Jeon struct runlist_element *rl; 2661af0db57dSNamjae Jeon 2662af0db57dSNamjae Jeon if (ni->mft_lcn[0] != LCN_RL_NOT_MAPPED) 2663af0db57dSNamjae Jeon return 0; 2664af0db57dSNamjae Jeon 2665af0db57dSNamjae Jeon vcn = (s64)ni->mft_no << mft_ni->vol->mft_record_size_bits >> 2666af0db57dSNamjae Jeon mft_ni->vol->cluster_size_bits; 2667af0db57dSNamjae Jeon 2668af0db57dSNamjae Jeon rl = mft_ni->runlist.rl; 2669af0db57dSNamjae Jeon if (!rl) { 2670af0db57dSNamjae Jeon ntfs_error(mft_ni->vol->sb, "$MFT runlist is not present"); 2671af0db57dSNamjae Jeon return -EIO; 2672af0db57dSNamjae Jeon } 2673af0db57dSNamjae Jeon 2674af0db57dSNamjae Jeon /* Seek to element containing target vcn. */ 2675af0db57dSNamjae Jeon while (rl->length && rl[1].vcn <= vcn) 2676af0db57dSNamjae Jeon rl++; 2677af0db57dSNamjae Jeon ni->mft_lcn[0] = ntfs_rl_vcn_to_lcn(rl, vcn); 2678af0db57dSNamjae Jeon ni->mft_lcn_count = 1; 2679af0db57dSNamjae Jeon 2680af0db57dSNamjae Jeon if (mft_ni->vol->cluster_size < mft_ni->vol->mft_record_size && 2681af0db57dSNamjae Jeon (rl->length - (vcn - rl->vcn)) <= 1) { 2682af0db57dSNamjae Jeon rl++; 2683af0db57dSNamjae Jeon ni->mft_lcn[1] = ntfs_rl_vcn_to_lcn(rl, vcn + 1); 2684af0db57dSNamjae Jeon ni->mft_lcn_count++; 2685af0db57dSNamjae Jeon } 2686af0db57dSNamjae Jeon return 0; 2687af0db57dSNamjae Jeon } 2688af0db57dSNamjae Jeon 2689af0db57dSNamjae Jeon /* 2690af0db57dSNamjae Jeon * __ntfs_write_inode - write out a dirty inode 2691af0db57dSNamjae Jeon * @vi: inode to write out 2692af0db57dSNamjae Jeon * @sync: if true, write out synchronously 2693af0db57dSNamjae Jeon * 2694af0db57dSNamjae Jeon * Write out a dirty inode to disk including any extent inodes if present. 2695af0db57dSNamjae Jeon * 2696af0db57dSNamjae Jeon * If @sync is true, commit the inode to disk and wait for io completion. This 2697af0db57dSNamjae Jeon * is done using write_mft_record(). 2698af0db57dSNamjae Jeon * 2699af0db57dSNamjae Jeon * If @sync is false, just schedule the write to happen but do not wait for i/o 2700af0db57dSNamjae Jeon * completion. 2701af0db57dSNamjae Jeon * 2702af0db57dSNamjae Jeon * Return 0 on success and -errno on error. 2703af0db57dSNamjae Jeon */ 2704af0db57dSNamjae Jeon int __ntfs_write_inode(struct inode *vi, int sync) 2705af0db57dSNamjae Jeon { 2706af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 2707af0db57dSNamjae Jeon struct ntfs_inode *mft_ni = NTFS_I(ni->vol->mft_ino); 2708af0db57dSNamjae Jeon struct mft_record *m; 2709af0db57dSNamjae Jeon int err = 0; 2710af0db57dSNamjae Jeon bool need_iput = false; 2711af0db57dSNamjae Jeon 2712e7d82353SNamjae Jeon ntfs_debug("Entering for %sinode 0x%llx.", NInoAttr(ni) ? "attr " : "", 2713e7d82353SNamjae Jeon ni->mft_no); 2714af0db57dSNamjae Jeon 2715af0db57dSNamjae Jeon if (NVolShutdown(ni->vol)) 2716af0db57dSNamjae Jeon return -EIO; 2717af0db57dSNamjae Jeon 2718af0db57dSNamjae Jeon /* 2719af0db57dSNamjae Jeon * Dirty attribute inodes are written via their real inodes so just 2720af0db57dSNamjae Jeon * clean them here. Access time updates are taken care off when the 2721af0db57dSNamjae Jeon * real inode is written. 2722af0db57dSNamjae Jeon */ 2723af0db57dSNamjae Jeon if (NInoAttr(ni) || ni->nr_extents == -1) { 2724af0db57dSNamjae Jeon NInoClearDirty(ni); 2725af0db57dSNamjae Jeon ntfs_debug("Done."); 2726af0db57dSNamjae Jeon return 0; 2727af0db57dSNamjae Jeon } 2728af0db57dSNamjae Jeon 2729af0db57dSNamjae Jeon /* igrab prevents vi from being evicted while mrec_lock is hold. */ 2730af0db57dSNamjae Jeon if (igrab(vi) != NULL) 2731af0db57dSNamjae Jeon need_iput = true; 2732af0db57dSNamjae Jeon 2733af0db57dSNamjae Jeon mutex_lock_nested(&ni->mrec_lock, NTFS_INODE_MUTEX_NORMAL); 2734af0db57dSNamjae Jeon /* Map, pin, and lock the mft record belonging to the inode. */ 2735af0db57dSNamjae Jeon m = map_mft_record(ni); 2736af0db57dSNamjae Jeon if (IS_ERR(m)) { 2737af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 2738af0db57dSNamjae Jeon err = PTR_ERR(m); 2739af0db57dSNamjae Jeon goto err_out; 2740af0db57dSNamjae Jeon } 2741af0db57dSNamjae Jeon 2742af0db57dSNamjae Jeon if (NInoNonResident(ni) && NInoRunlistDirty(ni)) { 2743af0db57dSNamjae Jeon down_write(&ni->runlist.lock); 2744af0db57dSNamjae Jeon err = ntfs_attr_update_mapping_pairs(ni, 0); 2745af0db57dSNamjae Jeon if (!err) 2746af0db57dSNamjae Jeon NInoClearRunlistDirty(ni); 2747af0db57dSNamjae Jeon up_write(&ni->runlist.lock); 2748af0db57dSNamjae Jeon } 2749af0db57dSNamjae Jeon 2750af0db57dSNamjae Jeon err = ntfs_inode_sync_standard_information(vi, m); 2751af0db57dSNamjae Jeon if (err) 2752af0db57dSNamjae Jeon goto unm_err_out; 2753af0db57dSNamjae Jeon 2754af0db57dSNamjae Jeon /* 2755af0db57dSNamjae Jeon * when being umounted and inodes are evicted, write_inode() 2756af0db57dSNamjae Jeon * is called with all inodes being marked with I_FREEING. 2757af0db57dSNamjae Jeon * then ntfs_inode_sync_filename() waits infinitly because 2758af0db57dSNamjae Jeon * of ntfs_iget. This situation happens only where sync_filesysem() 2759af0db57dSNamjae Jeon * from umount fails because of a disk unplug and etc. 2760af0db57dSNamjae Jeon * the absent of SB_ACTIVE means umounting. 2761af0db57dSNamjae Jeon */ 2762af0db57dSNamjae Jeon if ((vi->i_sb->s_flags & SB_ACTIVE) && NInoTestClearFileNameDirty(ni)) 2763af0db57dSNamjae Jeon ntfs_inode_sync_filename(ni); 2764af0db57dSNamjae Jeon 27651e9ea7e0SNamjae Jeon /* Now the access times are updated, write the base mft record. */ 2766af0db57dSNamjae Jeon if (NInoDirty(ni)) { 2767af0db57dSNamjae Jeon down_read(&mft_ni->runlist.lock); 2768af0db57dSNamjae Jeon err = ntfs_get_block_mft_record(mft_ni, ni); 2769af0db57dSNamjae Jeon up_read(&mft_ni->runlist.lock); 2770af0db57dSNamjae Jeon if (err) 2771af0db57dSNamjae Jeon goto unm_err_out; 2772af0db57dSNamjae Jeon 27731e9ea7e0SNamjae Jeon err = write_mft_record(ni, m, sync); 2774af0db57dSNamjae Jeon if (err) 2775af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "write_mft_record failed, err : %d\n", err); 2776af0db57dSNamjae Jeon } 2777af0db57dSNamjae Jeon unmap_mft_record(ni); 2778af0db57dSNamjae Jeon 2779af0db57dSNamjae Jeon /* Map any unmapped extent mft records with LCNs. */ 2780af0db57dSNamjae Jeon down_read(&mft_ni->runlist.lock); 2781af0db57dSNamjae Jeon mutex_lock(&ni->extent_lock); 2782af0db57dSNamjae Jeon if (ni->nr_extents > 0) { 2783af0db57dSNamjae Jeon int i; 2784af0db57dSNamjae Jeon 2785af0db57dSNamjae Jeon for (i = 0; i < ni->nr_extents; i++) { 2786af0db57dSNamjae Jeon err = ntfs_get_block_mft_record(mft_ni, 2787af0db57dSNamjae Jeon ni->ext.extent_ntfs_inos[i]); 2788af0db57dSNamjae Jeon if (err) { 2789af0db57dSNamjae Jeon mutex_unlock(&ni->extent_lock); 2790af0db57dSNamjae Jeon up_read(&mft_ni->runlist.lock); 2791af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 2792af0db57dSNamjae Jeon goto err_out; 2793af0db57dSNamjae Jeon } 2794af0db57dSNamjae Jeon } 2795af0db57dSNamjae Jeon } 2796af0db57dSNamjae Jeon mutex_unlock(&ni->extent_lock); 2797af0db57dSNamjae Jeon up_read(&mft_ni->runlist.lock); 2798af0db57dSNamjae Jeon 27991e9ea7e0SNamjae Jeon /* Write all attached extent mft records. */ 28001e9ea7e0SNamjae Jeon mutex_lock(&ni->extent_lock); 28011e9ea7e0SNamjae Jeon if (ni->nr_extents > 0) { 2802af0db57dSNamjae Jeon struct ntfs_inode **extent_nis = ni->ext.extent_ntfs_inos; 28031e9ea7e0SNamjae Jeon int i; 28041e9ea7e0SNamjae Jeon 28051e9ea7e0SNamjae Jeon ntfs_debug("Writing %i extent inodes.", ni->nr_extents); 28061e9ea7e0SNamjae Jeon for (i = 0; i < ni->nr_extents; i++) { 2807af0db57dSNamjae Jeon struct ntfs_inode *tni = extent_nis[i]; 28081e9ea7e0SNamjae Jeon 28091e9ea7e0SNamjae Jeon if (NInoDirty(tni)) { 2810af0db57dSNamjae Jeon struct mft_record *tm; 28111e9ea7e0SNamjae Jeon int ret; 28121e9ea7e0SNamjae Jeon 2813af0db57dSNamjae Jeon mutex_lock(&tni->mrec_lock); 2814af0db57dSNamjae Jeon tm = map_mft_record(tni); 28151e9ea7e0SNamjae Jeon if (IS_ERR(tm)) { 2816af0db57dSNamjae Jeon mutex_unlock(&tni->mrec_lock); 28171e9ea7e0SNamjae Jeon if (!err || err == -ENOMEM) 28181e9ea7e0SNamjae Jeon err = PTR_ERR(tm); 28191e9ea7e0SNamjae Jeon continue; 28201e9ea7e0SNamjae Jeon } 2821af0db57dSNamjae Jeon 28221e9ea7e0SNamjae Jeon ret = write_mft_record(tni, tm, sync); 28231e9ea7e0SNamjae Jeon unmap_mft_record(tni); 2824af0db57dSNamjae Jeon mutex_unlock(&tni->mrec_lock); 2825af0db57dSNamjae Jeon 28261e9ea7e0SNamjae Jeon if (unlikely(ret)) { 28271e9ea7e0SNamjae Jeon if (!err || err == -ENOMEM) 28281e9ea7e0SNamjae Jeon err = ret; 28291e9ea7e0SNamjae Jeon } 28301e9ea7e0SNamjae Jeon } 28311e9ea7e0SNamjae Jeon } 28321e9ea7e0SNamjae Jeon } 28331e9ea7e0SNamjae Jeon mutex_unlock(&ni->extent_lock); 2834af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 2835af0db57dSNamjae Jeon 28361e9ea7e0SNamjae Jeon if (unlikely(err)) 28371e9ea7e0SNamjae Jeon goto err_out; 2838af0db57dSNamjae Jeon if (need_iput) 2839af0db57dSNamjae Jeon iput(vi); 28401e9ea7e0SNamjae Jeon ntfs_debug("Done."); 28411e9ea7e0SNamjae Jeon return 0; 28421e9ea7e0SNamjae Jeon unm_err_out: 28431e9ea7e0SNamjae Jeon unmap_mft_record(ni); 2844af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 28451e9ea7e0SNamjae Jeon err_out: 2846af0db57dSNamjae Jeon if (err == -ENOMEM) 28471e9ea7e0SNamjae Jeon mark_inode_dirty(vi); 2848af0db57dSNamjae Jeon else { 28491e9ea7e0SNamjae Jeon ntfs_error(vi->i_sb, "Failed (error %i): Run chkdsk.", -err); 28501e9ea7e0SNamjae Jeon NVolSetErrors(ni->vol); 28511e9ea7e0SNamjae Jeon } 2852af0db57dSNamjae Jeon if (need_iput) 2853af0db57dSNamjae Jeon iput(vi); 28541e9ea7e0SNamjae Jeon return err; 28551e9ea7e0SNamjae Jeon } 28561e9ea7e0SNamjae Jeon 2857af0db57dSNamjae Jeon /* 2858af0db57dSNamjae Jeon * ntfs_extent_inode_open - load an extent inode and attach it to its base 2859af0db57dSNamjae Jeon * @base_ni: base ntfs inode 2860af0db57dSNamjae Jeon * @mref: mft reference of the extent inode to load (in little endian) 2861af0db57dSNamjae Jeon * 2862af0db57dSNamjae Jeon * First check if the extent inode @mref is already attached to the base ntfs 2863af0db57dSNamjae Jeon * inode @base_ni, and if so, return a pointer to the attached extent inode. 2864af0db57dSNamjae Jeon * 2865af0db57dSNamjae Jeon * If the extent inode is not already attached to the base inode, allocate an 2866af0db57dSNamjae Jeon * ntfs_inode structure and initialize it for the given inode @mref. @mref 2867af0db57dSNamjae Jeon * specifies the inode number / mft record to read, including the sequence 2868af0db57dSNamjae Jeon * number, which can be 0 if no sequence number checking is to be performed. 2869af0db57dSNamjae Jeon * 2870af0db57dSNamjae Jeon * Then, allocate a buffer for the mft record, read the mft record from the 2871af0db57dSNamjae Jeon * volume @base_ni->vol, and attach it to the ntfs_inode structure (->mrec). 2872af0db57dSNamjae Jeon * The mft record is mst deprotected and sanity checked for validity and we 2873af0db57dSNamjae Jeon * abort if deprotection or checks fail. 2874af0db57dSNamjae Jeon * 2875af0db57dSNamjae Jeon * Finally attach the ntfs inode to its base inode @base_ni and return a 2876af0db57dSNamjae Jeon * pointer to the ntfs_inode structure on success or NULL on error, with errno 2877af0db57dSNamjae Jeon * set to the error code. 2878af0db57dSNamjae Jeon * 2879af0db57dSNamjae Jeon * Note, extent inodes are never closed directly. They are automatically 2880af0db57dSNamjae Jeon * disposed off by the closing of the base inode. 2881af0db57dSNamjae Jeon */ 2882af0db57dSNamjae Jeon static struct ntfs_inode *ntfs_extent_inode_open(struct ntfs_inode *base_ni, 2883af0db57dSNamjae Jeon const __le64 mref) 2884af0db57dSNamjae Jeon { 2885af0db57dSNamjae Jeon u64 mft_no = MREF_LE(mref); 2886af0db57dSNamjae Jeon struct ntfs_inode *ni = NULL; 2887af0db57dSNamjae Jeon struct ntfs_inode **extent_nis; 2888af0db57dSNamjae Jeon int i; 2889af0db57dSNamjae Jeon struct mft_record *ni_mrec; 2890af0db57dSNamjae Jeon struct super_block *sb; 2891af0db57dSNamjae Jeon 2892af0db57dSNamjae Jeon if (!base_ni) 2893af0db57dSNamjae Jeon return NULL; 2894af0db57dSNamjae Jeon 2895af0db57dSNamjae Jeon sb = base_ni->vol->sb; 2896d9038d99SNamjae Jeon ntfs_debug("Opening extent inode %llu (base mft record %llu).\n", 2897d9038d99SNamjae Jeon mft_no, base_ni->mft_no); 2898af0db57dSNamjae Jeon 2899af0db57dSNamjae Jeon /* Is the extent inode already open and attached to the base inode? */ 2900af0db57dSNamjae Jeon if (base_ni->nr_extents > 0) { 2901af0db57dSNamjae Jeon extent_nis = base_ni->ext.extent_ntfs_inos; 2902af0db57dSNamjae Jeon for (i = 0; i < base_ni->nr_extents; i++) { 2903af0db57dSNamjae Jeon u16 seq_no; 2904af0db57dSNamjae Jeon 2905af0db57dSNamjae Jeon ni = extent_nis[i]; 2906af0db57dSNamjae Jeon if (mft_no != ni->mft_no) 2907af0db57dSNamjae Jeon continue; 2908af0db57dSNamjae Jeon ni_mrec = map_mft_record(ni); 2909af0db57dSNamjae Jeon if (IS_ERR(ni_mrec)) { 2910d9038d99SNamjae Jeon ntfs_error(sb, "failed to map mft record for %llu", 2911af0db57dSNamjae Jeon ni->mft_no); 2912af0db57dSNamjae Jeon goto out; 2913af0db57dSNamjae Jeon } 2914af0db57dSNamjae Jeon /* Verify the sequence number if given. */ 2915af0db57dSNamjae Jeon seq_no = MSEQNO_LE(mref); 2916af0db57dSNamjae Jeon if (seq_no && 2917af0db57dSNamjae Jeon seq_no != le16_to_cpu(ni_mrec->sequence_number)) { 2918d9038d99SNamjae Jeon ntfs_error(sb, "Found stale extent mft reference mft=%llu", 2919d9038d99SNamjae Jeon ni->mft_no); 2920af0db57dSNamjae Jeon unmap_mft_record(ni); 2921af0db57dSNamjae Jeon goto out; 2922af0db57dSNamjae Jeon } 2923af0db57dSNamjae Jeon unmap_mft_record(ni); 2924af0db57dSNamjae Jeon goto out; 2925af0db57dSNamjae Jeon } 2926af0db57dSNamjae Jeon } 2927af0db57dSNamjae Jeon /* Wasn't there, we need to load the extent inode. */ 2928af0db57dSNamjae Jeon ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no); 2929af0db57dSNamjae Jeon if (!ni) 2930af0db57dSNamjae Jeon goto out; 2931af0db57dSNamjae Jeon 2932af0db57dSNamjae Jeon ni->seq_no = (u16)MSEQNO_LE(mref); 2933af0db57dSNamjae Jeon ni->nr_extents = -1; 2934af0db57dSNamjae Jeon ni->ext.base_ntfs_ino = base_ni; 2935af0db57dSNamjae Jeon /* Attach extent inode to base inode, reallocating memory if needed. */ 2936af0db57dSNamjae Jeon if (!(base_ni->nr_extents & 3)) { 2937af0db57dSNamjae Jeon i = (base_ni->nr_extents + 4) * sizeof(struct ntfs_inode *); 2938af0db57dSNamjae Jeon 2939af0db57dSNamjae Jeon extent_nis = kvzalloc(i, GFP_NOFS); 2940af0db57dSNamjae Jeon if (!extent_nis) 2941af0db57dSNamjae Jeon goto err_out; 2942af0db57dSNamjae Jeon if (base_ni->nr_extents) { 2943af0db57dSNamjae Jeon memcpy(extent_nis, base_ni->ext.extent_ntfs_inos, 2944af0db57dSNamjae Jeon i - 4 * sizeof(struct ntfs_inode *)); 2945af0db57dSNamjae Jeon kvfree(base_ni->ext.extent_ntfs_inos); 2946af0db57dSNamjae Jeon } 2947af0db57dSNamjae Jeon base_ni->ext.extent_ntfs_inos = extent_nis; 2948af0db57dSNamjae Jeon } 2949af0db57dSNamjae Jeon base_ni->ext.extent_ntfs_inos[base_ni->nr_extents++] = ni; 2950af0db57dSNamjae Jeon 2951af0db57dSNamjae Jeon out: 2952af0db57dSNamjae Jeon ntfs_debug("\n"); 2953af0db57dSNamjae Jeon return ni; 2954af0db57dSNamjae Jeon err_out: 2955af0db57dSNamjae Jeon ntfs_destroy_ext_inode(ni); 2956af0db57dSNamjae Jeon ni = NULL; 2957af0db57dSNamjae Jeon goto out; 2958af0db57dSNamjae Jeon } 2959af0db57dSNamjae Jeon 2960af0db57dSNamjae Jeon /* 2961af0db57dSNamjae Jeon * ntfs_inode_attach_all_extents - attach all extents for target inode 2962af0db57dSNamjae Jeon * @ni: opened ntfs inode for which perform attach 2963af0db57dSNamjae Jeon * 2964af0db57dSNamjae Jeon * Return 0 on success and error. 2965af0db57dSNamjae Jeon */ 2966af0db57dSNamjae Jeon int ntfs_inode_attach_all_extents(struct ntfs_inode *ni) 2967af0db57dSNamjae Jeon { 2968af0db57dSNamjae Jeon struct attr_list_entry *ale; 2969af0db57dSNamjae Jeon u64 prev_attached = 0; 2970af0db57dSNamjae Jeon 2971af0db57dSNamjae Jeon if (!ni) { 2972af0db57dSNamjae Jeon ntfs_debug("Invalid arguments.\n"); 2973af0db57dSNamjae Jeon return -EINVAL; 2974af0db57dSNamjae Jeon } 2975af0db57dSNamjae Jeon 2976af0db57dSNamjae Jeon if (NInoAttr(ni)) 2977af0db57dSNamjae Jeon ni = ni->ext.base_ntfs_ino; 2978af0db57dSNamjae Jeon 2979d9038d99SNamjae Jeon ntfs_debug("Entering for inode 0x%llx.\n", ni->mft_no); 2980af0db57dSNamjae Jeon 2981af0db57dSNamjae Jeon /* Inode haven't got attribute list, thus nothing to attach. */ 2982af0db57dSNamjae Jeon if (!NInoAttrList(ni)) 2983af0db57dSNamjae Jeon return 0; 2984af0db57dSNamjae Jeon 2985af0db57dSNamjae Jeon if (!ni->attr_list) { 2986af0db57dSNamjae Jeon ntfs_debug("Corrupt in-memory struct.\n"); 2987af0db57dSNamjae Jeon return -EINVAL; 2988af0db57dSNamjae Jeon } 2989af0db57dSNamjae Jeon 2990af0db57dSNamjae Jeon /* Walk through attribute list and attach all extents. */ 2991af0db57dSNamjae Jeon ale = (struct attr_list_entry *)ni->attr_list; 2992af0db57dSNamjae Jeon while ((u8 *)ale < ni->attr_list + ni->attr_list_size) { 2993af0db57dSNamjae Jeon if (ni->mft_no != MREF_LE(ale->mft_reference) && 2994af0db57dSNamjae Jeon prev_attached != MREF_LE(ale->mft_reference)) { 2995af0db57dSNamjae Jeon if (!ntfs_extent_inode_open(ni, ale->mft_reference)) { 2996af0db57dSNamjae Jeon ntfs_debug("Couldn't attach extent inode.\n"); 2997af0db57dSNamjae Jeon return -1; 2998af0db57dSNamjae Jeon } 2999af0db57dSNamjae Jeon prev_attached = MREF_LE(ale->mft_reference); 3000af0db57dSNamjae Jeon } 3001af0db57dSNamjae Jeon ale = (struct attr_list_entry *)((u8 *)ale + le16_to_cpu(ale->length)); 3002af0db57dSNamjae Jeon } 3003af0db57dSNamjae Jeon return 0; 3004af0db57dSNamjae Jeon } 3005af0db57dSNamjae Jeon 3006af0db57dSNamjae Jeon /* 3007af0db57dSNamjae Jeon * ntfs_inode_add_attrlist - add attribute list to inode and fill it 3008af0db57dSNamjae Jeon * @ni: opened ntfs inode to which add attribute list 3009af0db57dSNamjae Jeon * 3010af0db57dSNamjae Jeon * Return 0 on success or error. 3011af0db57dSNamjae Jeon */ 3012af0db57dSNamjae Jeon int ntfs_inode_add_attrlist(struct ntfs_inode *ni) 3013af0db57dSNamjae Jeon { 3014af0db57dSNamjae Jeon int err; 3015af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 3016af0db57dSNamjae Jeon u8 *al = NULL, *aln; 3017af0db57dSNamjae Jeon int al_len = 0; 3018af0db57dSNamjae Jeon struct attr_list_entry *ale = NULL; 3019af0db57dSNamjae Jeon struct mft_record *ni_mrec; 3020af0db57dSNamjae Jeon u32 attr_al_len; 3021af0db57dSNamjae Jeon 3022af0db57dSNamjae Jeon if (!ni) 3023af0db57dSNamjae Jeon return -EINVAL; 3024af0db57dSNamjae Jeon 3025d9038d99SNamjae Jeon ntfs_debug("inode %llu\n", ni->mft_no); 3026af0db57dSNamjae Jeon 3027af0db57dSNamjae Jeon if (NInoAttrList(ni) || ni->nr_extents) { 3028af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Inode already has attribute list"); 3029af0db57dSNamjae Jeon return -EEXIST; 3030af0db57dSNamjae Jeon } 3031af0db57dSNamjae Jeon 3032af0db57dSNamjae Jeon ni_mrec = map_mft_record(ni); 3033af0db57dSNamjae Jeon if (IS_ERR(ni_mrec)) 3034af0db57dSNamjae Jeon return -EIO; 3035af0db57dSNamjae Jeon 3036af0db57dSNamjae Jeon /* Form attribute list. */ 3037af0db57dSNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, ni_mrec); 3038af0db57dSNamjae Jeon if (!ctx) { 3039af0db57dSNamjae Jeon err = -ENOMEM; 3040af0db57dSNamjae Jeon goto err_out; 3041af0db57dSNamjae Jeon } 3042af0db57dSNamjae Jeon 3043af0db57dSNamjae Jeon /* Walk through all attributes. */ 3044af0db57dSNamjae Jeon while (!(err = ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx))) { 3045af0db57dSNamjae Jeon int ale_size; 3046af0db57dSNamjae Jeon 3047af0db57dSNamjae Jeon if (ctx->attr->type == AT_ATTRIBUTE_LIST) { 3048af0db57dSNamjae Jeon err = -EIO; 3049af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Attribute list already present"); 3050af0db57dSNamjae Jeon goto put_err_out; 3051af0db57dSNamjae Jeon } 3052af0db57dSNamjae Jeon 3053af0db57dSNamjae Jeon ale_size = (sizeof(struct attr_list_entry) + sizeof(__le16) * 3054af0db57dSNamjae Jeon ctx->attr->name_length + 7) & ~7; 3055af0db57dSNamjae Jeon al_len += ale_size; 3056af0db57dSNamjae Jeon 3057af0db57dSNamjae Jeon aln = kvrealloc(al, al_len, GFP_NOFS); 3058af0db57dSNamjae Jeon if (!aln) { 3059af0db57dSNamjae Jeon err = -ENOMEM; 3060af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Failed to realloc %d bytes", al_len); 3061af0db57dSNamjae Jeon goto put_err_out; 3062af0db57dSNamjae Jeon } 3063af0db57dSNamjae Jeon ale = (struct attr_list_entry *)(aln + ((u8 *)ale - al)); 3064af0db57dSNamjae Jeon al = aln; 3065af0db57dSNamjae Jeon 3066af0db57dSNamjae Jeon memset(ale, 0, ale_size); 3067af0db57dSNamjae Jeon 3068af0db57dSNamjae Jeon /* Add attribute to attribute list. */ 3069af0db57dSNamjae Jeon ale->type = ctx->attr->type; 3070af0db57dSNamjae Jeon ale->length = cpu_to_le16((sizeof(struct attr_list_entry) + 3071af0db57dSNamjae Jeon sizeof(__le16) * ctx->attr->name_length + 7) & ~7); 3072af0db57dSNamjae Jeon ale->name_length = ctx->attr->name_length; 3073af0db57dSNamjae Jeon ale->name_offset = (u8 *)ale->name - (u8 *)ale; 3074af0db57dSNamjae Jeon if (ctx->attr->non_resident) 3075af0db57dSNamjae Jeon ale->lowest_vcn = 3076af0db57dSNamjae Jeon ctx->attr->data.non_resident.lowest_vcn; 3077af0db57dSNamjae Jeon else 3078af0db57dSNamjae Jeon ale->lowest_vcn = 0; 3079af0db57dSNamjae Jeon ale->mft_reference = MK_LE_MREF(ni->mft_no, 3080af0db57dSNamjae Jeon le16_to_cpu(ni_mrec->sequence_number)); 3081af0db57dSNamjae Jeon ale->instance = ctx->attr->instance; 3082af0db57dSNamjae Jeon memcpy(ale->name, (u8 *)ctx->attr + 3083af0db57dSNamjae Jeon le16_to_cpu(ctx->attr->name_offset), 3084af0db57dSNamjae Jeon ctx->attr->name_length * sizeof(__le16)); 3085af0db57dSNamjae Jeon ale = (struct attr_list_entry *)(al + al_len); 3086af0db57dSNamjae Jeon } 3087af0db57dSNamjae Jeon 3088af0db57dSNamjae Jeon /* Check for real error occurred. */ 3089af0db57dSNamjae Jeon if (err != -ENOENT) { 3090d9038d99SNamjae Jeon ntfs_error(ni->vol->sb, "%s: Attribute lookup failed, inode %llu", 3091d9038d99SNamjae Jeon __func__, ni->mft_no); 3092af0db57dSNamjae Jeon goto put_err_out; 3093af0db57dSNamjae Jeon } 3094af0db57dSNamjae Jeon 3095af0db57dSNamjae Jeon /* Set in-memory attribute list. */ 3096af0db57dSNamjae Jeon ni->attr_list = al; 3097af0db57dSNamjae Jeon ni->attr_list_size = al_len; 3098af0db57dSNamjae Jeon NInoSetAttrList(ni); 3099af0db57dSNamjae Jeon 3100af0db57dSNamjae Jeon attr_al_len = offsetof(struct attr_record, data.resident.reserved) + 1 + 3101af0db57dSNamjae Jeon ((al_len + 7) & ~7); 3102af0db57dSNamjae Jeon /* Free space if there is not enough it for $ATTRIBUTE_LIST. */ 3103af0db57dSNamjae Jeon if (le32_to_cpu(ni_mrec->bytes_allocated) - 3104af0db57dSNamjae Jeon le32_to_cpu(ni_mrec->bytes_in_use) < attr_al_len) { 3105af0db57dSNamjae Jeon if (ntfs_inode_free_space(ni, (int)attr_al_len)) { 3106af0db57dSNamjae Jeon /* Failed to free space. */ 3107af0db57dSNamjae Jeon err = -ENOSPC; 3108af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Failed to free space for attrlist"); 3109af0db57dSNamjae Jeon goto rollback; 3110af0db57dSNamjae Jeon } 3111af0db57dSNamjae Jeon } 3112af0db57dSNamjae Jeon 3113af0db57dSNamjae Jeon /* Add $ATTRIBUTE_LIST to mft record. */ 3114af0db57dSNamjae Jeon err = ntfs_resident_attr_record_add(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 3115af0db57dSNamjae Jeon NULL, al_len, 0); 3116af0db57dSNamjae Jeon if (err < 0) { 3117af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Couldn't add $ATTRIBUTE_LIST to MFT"); 3118af0db57dSNamjae Jeon goto rollback; 3119af0db57dSNamjae Jeon } 3120af0db57dSNamjae Jeon 3121af0db57dSNamjae Jeon err = ntfs_attrlist_update(ni); 3122af0db57dSNamjae Jeon if (err < 0) 3123af0db57dSNamjae Jeon goto remove_attrlist_record; 3124af0db57dSNamjae Jeon 3125af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3126af0db57dSNamjae Jeon unmap_mft_record(ni); 3127af0db57dSNamjae Jeon return 0; 3128af0db57dSNamjae Jeon 3129af0db57dSNamjae Jeon remove_attrlist_record: 3130af0db57dSNamjae Jeon /* Prevent ntfs_attr_recorm_rm from freeing attribute list. */ 3131af0db57dSNamjae Jeon ni->attr_list = NULL; 3132af0db57dSNamjae Jeon NInoClearAttrList(ni); 3133af0db57dSNamjae Jeon /* Remove $ATTRIBUTE_LIST record. */ 3134af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 3135af0db57dSNamjae Jeon if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 3136af0db57dSNamjae Jeon CASE_SENSITIVE, 0, NULL, 0, ctx)) { 3137af0db57dSNamjae Jeon if (ntfs_attr_record_rm(ctx)) 3138af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Rollback failed to remove attrlist"); 3139af0db57dSNamjae Jeon } else { 3140af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Rollback failed to find attrlist"); 3141af0db57dSNamjae Jeon } 3142af0db57dSNamjae Jeon 3143af0db57dSNamjae Jeon /* Setup back in-memory runlist. */ 3144af0db57dSNamjae Jeon ni->attr_list = al; 3145af0db57dSNamjae Jeon ni->attr_list_size = al_len; 3146af0db57dSNamjae Jeon NInoSetAttrList(ni); 3147af0db57dSNamjae Jeon rollback: 3148af0db57dSNamjae Jeon /* 3149af0db57dSNamjae Jeon * Scan attribute list for attributes that placed not in the base MFT 3150af0db57dSNamjae Jeon * record and move them to it. 3151af0db57dSNamjae Jeon */ 3152af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 3153af0db57dSNamjae Jeon ale = (struct attr_list_entry *)al; 3154af0db57dSNamjae Jeon while ((u8 *)ale < al + al_len) { 3155af0db57dSNamjae Jeon if (MREF_LE(ale->mft_reference) != ni->mft_no) { 3156af0db57dSNamjae Jeon if (!ntfs_attr_lookup(ale->type, ale->name, 3157af0db57dSNamjae Jeon ale->name_length, 3158af0db57dSNamjae Jeon CASE_SENSITIVE, 3159af0db57dSNamjae Jeon le64_to_cpu(ale->lowest_vcn), 3160af0db57dSNamjae Jeon NULL, 0, ctx)) { 3161af0db57dSNamjae Jeon if (ntfs_attr_record_move_to(ctx, ni)) 3162af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, 3163af0db57dSNamjae Jeon "Rollback failed to move attribute"); 3164af0db57dSNamjae Jeon } else { 3165af0db57dSNamjae Jeon ntfs_error(ni->vol->sb, "Rollback failed to find attr"); 3166af0db57dSNamjae Jeon } 3167af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 3168af0db57dSNamjae Jeon } 3169af0db57dSNamjae Jeon ale = (struct attr_list_entry *)((u8 *)ale + le16_to_cpu(ale->length)); 3170af0db57dSNamjae Jeon } 3171af0db57dSNamjae Jeon 3172af0db57dSNamjae Jeon /* Remove in-memory attribute list. */ 3173af0db57dSNamjae Jeon ni->attr_list = NULL; 3174af0db57dSNamjae Jeon ni->attr_list_size = 0; 3175af0db57dSNamjae Jeon NInoClearAttrList(ni); 3176af0db57dSNamjae Jeon NInoClearAttrListDirty(ni); 3177af0db57dSNamjae Jeon put_err_out: 3178af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3179af0db57dSNamjae Jeon err_out: 3180af0db57dSNamjae Jeon kvfree(al); 3181af0db57dSNamjae Jeon unmap_mft_record(ni); 3182af0db57dSNamjae Jeon return err; 3183af0db57dSNamjae Jeon } 3184af0db57dSNamjae Jeon 3185af0db57dSNamjae Jeon /* 3186af0db57dSNamjae Jeon * ntfs_inode_close - close an ntfs inode and free all associated memory 3187af0db57dSNamjae Jeon * @ni: ntfs inode to close 3188af0db57dSNamjae Jeon * 3189af0db57dSNamjae Jeon * Make sure the ntfs inode @ni is clean. 3190af0db57dSNamjae Jeon * 3191af0db57dSNamjae Jeon * If the ntfs inode @ni is a base inode, close all associated extent inodes, 3192af0db57dSNamjae Jeon * then deallocate all memory attached to it, and finally free the ntfs inode 3193af0db57dSNamjae Jeon * structure itself. 3194af0db57dSNamjae Jeon * 3195af0db57dSNamjae Jeon * If it is an extent inode, we disconnect it from its base inode before we 3196af0db57dSNamjae Jeon * destroy it. 3197af0db57dSNamjae Jeon * 3198af0db57dSNamjae Jeon * It is OK to pass NULL to this function, it is just noop in this case. 3199af0db57dSNamjae Jeon * 3200af0db57dSNamjae Jeon * Return 0 on success or error. 3201af0db57dSNamjae Jeon */ 3202af0db57dSNamjae Jeon int ntfs_inode_close(struct ntfs_inode *ni) 3203af0db57dSNamjae Jeon { 3204af0db57dSNamjae Jeon int err = -1; 3205af0db57dSNamjae Jeon struct ntfs_inode **tmp_nis; 3206af0db57dSNamjae Jeon struct ntfs_inode *base_ni; 3207af0db57dSNamjae Jeon s32 i; 3208af0db57dSNamjae Jeon 3209af0db57dSNamjae Jeon if (!ni) 3210af0db57dSNamjae Jeon return 0; 3211af0db57dSNamjae Jeon 3212d9038d99SNamjae Jeon ntfs_debug("Entering for inode %llu\n", ni->mft_no); 3213af0db57dSNamjae Jeon 3214af0db57dSNamjae Jeon /* Is this a base inode with mapped extent inodes? */ 3215af0db57dSNamjae Jeon /* 3216af0db57dSNamjae Jeon * If the inode is an extent inode, disconnect it from the 3217af0db57dSNamjae Jeon * base inode before destroying it. 3218af0db57dSNamjae Jeon */ 3219af0db57dSNamjae Jeon base_ni = ni->ext.base_ntfs_ino; 3220af0db57dSNamjae Jeon tmp_nis = base_ni->ext.extent_ntfs_inos; 32214e59f8a1SHyunchul Lee if (!tmp_nis) 32224e59f8a1SHyunchul Lee goto out; 32234e59f8a1SHyunchul Lee for (i = 0; i < base_ni->nr_extents; ++i) { 3224af0db57dSNamjae Jeon if (tmp_nis[i] != ni) 3225af0db57dSNamjae Jeon continue; 3226af0db57dSNamjae Jeon /* Found it. Disconnect. */ 3227af0db57dSNamjae Jeon memmove(tmp_nis + i, tmp_nis + i + 1, 3228af0db57dSNamjae Jeon (base_ni->nr_extents - i - 1) * 3229af0db57dSNamjae Jeon sizeof(struct ntfs_inode *)); 3230af0db57dSNamjae Jeon /* Buffer should be for multiple of four extents. */ 3231af0db57dSNamjae Jeon if ((--base_ni->nr_extents) & 3) 3232af0db57dSNamjae Jeon break; 3233af0db57dSNamjae Jeon /* 3234af0db57dSNamjae Jeon * ElectricFence is unhappy with realloc(x,0) as free(x) 3235af0db57dSNamjae Jeon * thus we explicitly separate these two cases. 3236af0db57dSNamjae Jeon */ 3237af0db57dSNamjae Jeon if (base_ni->nr_extents) { 3238af0db57dSNamjae Jeon /* Resize the memory buffer. */ 3239af0db57dSNamjae Jeon tmp_nis = kvrealloc(tmp_nis, base_ni->nr_extents * 3240af0db57dSNamjae Jeon sizeof(struct ntfs_inode *), GFP_NOFS); 3241af0db57dSNamjae Jeon /* Ignore errors, they don't really matter. */ 3242af0db57dSNamjae Jeon if (tmp_nis) 3243af0db57dSNamjae Jeon base_ni->ext.extent_ntfs_inos = tmp_nis; 3244af0db57dSNamjae Jeon } else if (tmp_nis) { 3245af0db57dSNamjae Jeon kvfree(tmp_nis); 3246af0db57dSNamjae Jeon base_ni->ext.extent_ntfs_inos = NULL; 3247af0db57dSNamjae Jeon } 3248af0db57dSNamjae Jeon break; 3249af0db57dSNamjae Jeon } 3250af0db57dSNamjae Jeon 32514e59f8a1SHyunchul Lee out: 3252af0db57dSNamjae Jeon if (NInoDirty(ni)) 3253d9038d99SNamjae Jeon ntfs_error(ni->vol->sb, "Releasing dirty inode %llu!\n", 3254d9038d99SNamjae Jeon ni->mft_no); 3255af0db57dSNamjae Jeon if (NInoAttrList(ni) && ni->attr_list) 3256af0db57dSNamjae Jeon kvfree(ni->attr_list); 3257af0db57dSNamjae Jeon ntfs_destroy_ext_inode(ni); 3258af0db57dSNamjae Jeon err = 0; 3259af0db57dSNamjae Jeon ntfs_debug("\n"); 3260af0db57dSNamjae Jeon return err; 3261af0db57dSNamjae Jeon } 3262af0db57dSNamjae Jeon 3263af0db57dSNamjae Jeon void ntfs_destroy_ext_inode(struct ntfs_inode *ni) 3264af0db57dSNamjae Jeon { 3265af0db57dSNamjae Jeon ntfs_debug("Entering."); 3266af0db57dSNamjae Jeon if (ni == NULL) 3267af0db57dSNamjae Jeon return; 3268af0db57dSNamjae Jeon 3269af0db57dSNamjae Jeon ntfs_attr_close(ni); 3270af0db57dSNamjae Jeon 3271af0db57dSNamjae Jeon if (NInoDirty(ni)) 3272d9038d99SNamjae Jeon ntfs_error(ni->vol->sb, "Releasing dirty ext inode %llu!\n", 3273d9038d99SNamjae Jeon ni->mft_no); 3274af0db57dSNamjae Jeon if (NInoAttrList(ni) && ni->attr_list) 3275af0db57dSNamjae Jeon kvfree(ni->attr_list); 3276af0db57dSNamjae Jeon kfree(ni->mrec); 3277af0db57dSNamjae Jeon kmem_cache_free(ntfs_inode_cache, ni); 3278af0db57dSNamjae Jeon } 3279af0db57dSNamjae Jeon 3280af0db57dSNamjae Jeon static struct ntfs_inode *ntfs_inode_base(struct ntfs_inode *ni) 3281af0db57dSNamjae Jeon { 3282af0db57dSNamjae Jeon if (ni->nr_extents == -1) 3283af0db57dSNamjae Jeon return ni->ext.base_ntfs_ino; 3284af0db57dSNamjae Jeon return ni; 3285af0db57dSNamjae Jeon } 3286af0db57dSNamjae Jeon 3287af0db57dSNamjae Jeon static int ntfs_attr_position(__le32 type, struct ntfs_attr_search_ctx *ctx) 3288af0db57dSNamjae Jeon { 3289af0db57dSNamjae Jeon int err; 3290af0db57dSNamjae Jeon 3291af0db57dSNamjae Jeon err = ntfs_attr_lookup(type, NULL, 0, CASE_SENSITIVE, 0, NULL, 3292af0db57dSNamjae Jeon 0, ctx); 3293af0db57dSNamjae Jeon if (err) { 3294af0db57dSNamjae Jeon __le32 atype; 3295af0db57dSNamjae Jeon 3296af0db57dSNamjae Jeon if (err != -ENOENT) 3297af0db57dSNamjae Jeon return err; 3298af0db57dSNamjae Jeon 3299af0db57dSNamjae Jeon atype = ctx->attr->type; 3300af0db57dSNamjae Jeon if (atype == AT_END) 3301af0db57dSNamjae Jeon return -ENOSPC; 3302af0db57dSNamjae Jeon 3303af0db57dSNamjae Jeon /* 3304af0db57dSNamjae Jeon * if ntfs_external_attr_lookup return -ENOENT, ctx->al_entry 3305af0db57dSNamjae Jeon * could point to an attribute in an extent mft record, but 3306af0db57dSNamjae Jeon * ctx->attr and ctx->ntfs_ino always points to an attibute in 3307af0db57dSNamjae Jeon * a base mft record. 3308af0db57dSNamjae Jeon */ 3309af0db57dSNamjae Jeon if (ctx->al_entry && 3310af0db57dSNamjae Jeon MREF_LE(ctx->al_entry->mft_reference) != ctx->ntfs_ino->mft_no) { 3311af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 3312af0db57dSNamjae Jeon err = ntfs_attr_lookup(atype, NULL, 0, CASE_SENSITIVE, 0, NULL, 3313af0db57dSNamjae Jeon 0, ctx); 3314af0db57dSNamjae Jeon if (err) 3315af0db57dSNamjae Jeon return err; 3316af0db57dSNamjae Jeon } 3317af0db57dSNamjae Jeon } 3318af0db57dSNamjae Jeon return 0; 3319af0db57dSNamjae Jeon } 3320af0db57dSNamjae Jeon 3321af0db57dSNamjae Jeon /* 3322af0db57dSNamjae Jeon * ntfs_inode_free_space - free space in the MFT record of inode 3323af0db57dSNamjae Jeon * @ni: ntfs inode in which MFT record free space 3324af0db57dSNamjae Jeon * @size: amount of space needed to free 3325af0db57dSNamjae Jeon * 3326af0db57dSNamjae Jeon * Return 0 on success or error. 3327af0db57dSNamjae Jeon */ 3328af0db57dSNamjae Jeon int ntfs_inode_free_space(struct ntfs_inode *ni, int size) 3329af0db57dSNamjae Jeon { 3330af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 3331af0db57dSNamjae Jeon int freed, err; 3332af0db57dSNamjae Jeon struct mft_record *ni_mrec; 3333af0db57dSNamjae Jeon struct super_block *sb; 3334af0db57dSNamjae Jeon 3335af0db57dSNamjae Jeon if (!ni || size < 0) 3336af0db57dSNamjae Jeon return -EINVAL; 3337d9038d99SNamjae Jeon ntfs_debug("Entering for inode %llu, size %d\n", ni->mft_no, size); 3338af0db57dSNamjae Jeon 3339af0db57dSNamjae Jeon sb = ni->vol->sb; 3340af0db57dSNamjae Jeon ni_mrec = map_mft_record(ni); 3341af0db57dSNamjae Jeon if (IS_ERR(ni_mrec)) 3342af0db57dSNamjae Jeon return -EIO; 3343af0db57dSNamjae Jeon 3344af0db57dSNamjae Jeon freed = (le32_to_cpu(ni_mrec->bytes_allocated) - 3345af0db57dSNamjae Jeon le32_to_cpu(ni_mrec->bytes_in_use)); 3346af0db57dSNamjae Jeon 3347af0db57dSNamjae Jeon unmap_mft_record(ni); 3348af0db57dSNamjae Jeon 3349af0db57dSNamjae Jeon if (size <= freed) 3350af0db57dSNamjae Jeon return 0; 3351af0db57dSNamjae Jeon 3352af0db57dSNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni, NULL); 3353af0db57dSNamjae Jeon if (!ctx) { 3354af0db57dSNamjae Jeon ntfs_error(sb, "%s, Failed to get search context", __func__); 3355af0db57dSNamjae Jeon return -ENOMEM; 3356af0db57dSNamjae Jeon } 3357af0db57dSNamjae Jeon 3358af0db57dSNamjae Jeon /* 3359af0db57dSNamjae Jeon * Chkdsk complain if $STANDARD_INFORMATION is not in the base MFT 3360af0db57dSNamjae Jeon * record. 3361af0db57dSNamjae Jeon * 3362af0db57dSNamjae Jeon * Also we can't move $ATTRIBUTE_LIST from base MFT_RECORD, so position 3363af0db57dSNamjae Jeon * search context on first attribute after $STANDARD_INFORMATION and 3364af0db57dSNamjae Jeon * $ATTRIBUTE_LIST. 3365af0db57dSNamjae Jeon * 3366af0db57dSNamjae Jeon * Why we reposition instead of simply skip this attributes during 3367af0db57dSNamjae Jeon * enumeration? Because in case we have got only in-memory attribute 3368af0db57dSNamjae Jeon * list ntfs_attr_lookup will fail when it will try to find 3369af0db57dSNamjae Jeon * $ATTRIBUTE_LIST. 3370af0db57dSNamjae Jeon */ 3371af0db57dSNamjae Jeon err = ntfs_attr_position(AT_FILE_NAME, ctx); 3372af0db57dSNamjae Jeon if (err) 3373af0db57dSNamjae Jeon goto put_err_out; 3374af0db57dSNamjae Jeon 3375af0db57dSNamjae Jeon while (1) { 3376af0db57dSNamjae Jeon int record_size; 3377af0db57dSNamjae Jeon 3378af0db57dSNamjae Jeon /* 3379af0db57dSNamjae Jeon * Check whether attribute is from different MFT record. If so, 3380af0db57dSNamjae Jeon * find next, because we don't need such. 3381af0db57dSNamjae Jeon */ 3382af0db57dSNamjae Jeon while (ctx->ntfs_ino->mft_no != ni->mft_no) { 3383af0db57dSNamjae Jeon retry: 3384af0db57dSNamjae Jeon err = ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 3385af0db57dSNamjae Jeon 0, NULL, 0, ctx); 3386af0db57dSNamjae Jeon if (err) { 3387af0db57dSNamjae Jeon if (err != -ENOENT) 3388af0db57dSNamjae Jeon ntfs_error(sb, "Attr lookup failed #2"); 3389af0db57dSNamjae Jeon else if (ctx->attr->type == AT_END) 3390af0db57dSNamjae Jeon err = -ENOSPC; 3391af0db57dSNamjae Jeon else 3392af0db57dSNamjae Jeon err = 0; 3393af0db57dSNamjae Jeon 3394af0db57dSNamjae Jeon if (err) 3395af0db57dSNamjae Jeon goto put_err_out; 3396af0db57dSNamjae Jeon } 3397af0db57dSNamjae Jeon } 3398af0db57dSNamjae Jeon 3399af0db57dSNamjae Jeon if (ntfs_inode_base(ctx->ntfs_ino)->mft_no == FILE_MFT && 3400af0db57dSNamjae Jeon ctx->attr->type == AT_DATA) 3401af0db57dSNamjae Jeon goto retry; 3402af0db57dSNamjae Jeon 3403af0db57dSNamjae Jeon if (ctx->attr->type == AT_INDEX_ROOT) 3404af0db57dSNamjae Jeon goto retry; 3405af0db57dSNamjae Jeon 3406af0db57dSNamjae Jeon record_size = le32_to_cpu(ctx->attr->length); 3407af0db57dSNamjae Jeon 3408af0db57dSNamjae Jeon /* Move away attribute. */ 3409af0db57dSNamjae Jeon err = ntfs_attr_record_move_away(ctx, 0); 3410af0db57dSNamjae Jeon if (err) { 3411af0db57dSNamjae Jeon ntfs_error(sb, "Failed to move out attribute #2"); 3412af0db57dSNamjae Jeon break; 3413af0db57dSNamjae Jeon } 3414af0db57dSNamjae Jeon freed += record_size; 3415af0db57dSNamjae Jeon 3416af0db57dSNamjae Jeon /* Check whether we done. */ 3417af0db57dSNamjae Jeon if (size <= freed) { 3418af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3419af0db57dSNamjae Jeon return 0; 3420af0db57dSNamjae Jeon } 3421af0db57dSNamjae Jeon 3422af0db57dSNamjae Jeon /* 3423af0db57dSNamjae Jeon * Reposition to first attribute after $STANDARD_INFORMATION and 3424af0db57dSNamjae Jeon * $ATTRIBUTE_LIST (see comments upwards). 3425af0db57dSNamjae Jeon */ 3426af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 3427af0db57dSNamjae Jeon err = ntfs_attr_position(AT_FILE_NAME, ctx); 3428af0db57dSNamjae Jeon if (err) 3429af0db57dSNamjae Jeon break; 3430af0db57dSNamjae Jeon } 3431af0db57dSNamjae Jeon put_err_out: 3432af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3433af0db57dSNamjae Jeon if (err == -ENOSPC) 3434af0db57dSNamjae Jeon ntfs_debug("No attributes left that can be moved out.\n"); 3435af0db57dSNamjae Jeon return err; 3436af0db57dSNamjae Jeon } 3437af0db57dSNamjae Jeon 3438af0db57dSNamjae Jeon s64 ntfs_inode_attr_pread(struct inode *vi, s64 pos, s64 count, u8 *buf) 3439af0db57dSNamjae Jeon { 3440af0db57dSNamjae Jeon struct address_space *mapping = vi->i_mapping; 3441af0db57dSNamjae Jeon struct folio *folio; 3442af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 3443af0db57dSNamjae Jeon s64 isize; 3444af0db57dSNamjae Jeon u32 attr_len, total = 0, offset; 3445af0db57dSNamjae Jeon pgoff_t index; 3446af0db57dSNamjae Jeon int err = 0; 3447af0db57dSNamjae Jeon 3448af0db57dSNamjae Jeon WARN_ON(!NInoAttr(ni)); 3449af0db57dSNamjae Jeon if (!count) 3450af0db57dSNamjae Jeon return 0; 3451af0db57dSNamjae Jeon 3452af0db57dSNamjae Jeon mutex_lock(&ni->mrec_lock); 3453af0db57dSNamjae Jeon isize = i_size_read(vi); 3454af0db57dSNamjae Jeon if (pos > isize) { 3455af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 3456af0db57dSNamjae Jeon return -EINVAL; 3457af0db57dSNamjae Jeon } 3458af0db57dSNamjae Jeon if (pos + count > isize) 3459af0db57dSNamjae Jeon count = isize - pos; 3460af0db57dSNamjae Jeon 3461af0db57dSNamjae Jeon if (!NInoNonResident(ni)) { 3462af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 3463af0db57dSNamjae Jeon u8 *attr; 3464af0db57dSNamjae Jeon 3465af0db57dSNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni->ext.base_ntfs_ino, NULL); 3466af0db57dSNamjae Jeon if (!ctx) { 3467af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to get attr search ctx"); 3468af0db57dSNamjae Jeon err = -ENOMEM; 3469af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 3470af0db57dSNamjae Jeon goto out; 3471af0db57dSNamjae Jeon } 3472af0db57dSNamjae Jeon 3473af0db57dSNamjae Jeon err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, 3474af0db57dSNamjae Jeon 0, NULL, 0, ctx); 3475af0db57dSNamjae Jeon if (err) { 3476af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to look up attr %#x", ni->type); 3477af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3478af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 3479af0db57dSNamjae Jeon goto out; 3480af0db57dSNamjae Jeon } 3481af0db57dSNamjae Jeon 3482af0db57dSNamjae Jeon attr = (u8 *)ctx->attr + le16_to_cpu(ctx->attr->data.resident.value_offset); 3483af0db57dSNamjae Jeon memcpy(buf, (u8 *)attr + pos, count); 3484af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3485af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 3486af0db57dSNamjae Jeon return count; 3487af0db57dSNamjae Jeon } 3488af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 3489af0db57dSNamjae Jeon 3490af0db57dSNamjae Jeon index = pos >> PAGE_SHIFT; 3491af0db57dSNamjae Jeon do { 3492af0db57dSNamjae Jeon /* Update @index and get the next folio. */ 3493af0db57dSNamjae Jeon folio = read_mapping_folio(mapping, index, NULL); 3494af0db57dSNamjae Jeon if (IS_ERR(folio)) 3495af0db57dSNamjae Jeon break; 3496af0db57dSNamjae Jeon 3497af0db57dSNamjae Jeon offset = offset_in_folio(folio, pos); 3498af0db57dSNamjae Jeon attr_len = min_t(size_t, (size_t)count, folio_size(folio) - offset); 3499af0db57dSNamjae Jeon 3500af0db57dSNamjae Jeon folio_lock(folio); 3501af0db57dSNamjae Jeon memcpy_from_folio(buf, folio, offset, attr_len); 3502af0db57dSNamjae Jeon folio_unlock(folio); 3503af0db57dSNamjae Jeon folio_put(folio); 3504af0db57dSNamjae Jeon 3505af0db57dSNamjae Jeon total += attr_len; 3506af0db57dSNamjae Jeon buf += attr_len; 3507af0db57dSNamjae Jeon pos += attr_len; 3508af0db57dSNamjae Jeon count -= attr_len; 3509af0db57dSNamjae Jeon index++; 3510af0db57dSNamjae Jeon } while (count); 3511af0db57dSNamjae Jeon out: 3512af0db57dSNamjae Jeon return err ? (s64)err : total; 3513af0db57dSNamjae Jeon } 3514af0db57dSNamjae Jeon 3515af0db57dSNamjae Jeon static inline int ntfs_enlarge_attribute(struct inode *vi, s64 pos, s64 count, 3516af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx) 3517af0db57dSNamjae Jeon { 3518af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 3519af0db57dSNamjae Jeon struct super_block *sb = vi->i_sb; 3520af0db57dSNamjae Jeon int ret; 3521af0db57dSNamjae Jeon 3522af0db57dSNamjae Jeon if (pos + count <= ni->initialized_size) 3523af0db57dSNamjae Jeon return 0; 3524af0db57dSNamjae Jeon 3525af0db57dSNamjae Jeon if (NInoEncrypted(ni) && NInoNonResident(ni)) 3526af0db57dSNamjae Jeon return -EACCES; 3527af0db57dSNamjae Jeon 3528af0db57dSNamjae Jeon if (NInoCompressed(ni)) 3529af0db57dSNamjae Jeon return -EOPNOTSUPP; 3530af0db57dSNamjae Jeon 3531af0db57dSNamjae Jeon if (pos + count > ni->data_size) { 3532af0db57dSNamjae Jeon if (ntfs_attr_truncate(ni, pos + count)) { 3533af0db57dSNamjae Jeon ntfs_debug("Failed to truncate attribute"); 3534af0db57dSNamjae Jeon return -1; 3535af0db57dSNamjae Jeon } 3536af0db57dSNamjae Jeon 3537af0db57dSNamjae Jeon ntfs_attr_reinit_search_ctx(ctx); 3538af0db57dSNamjae Jeon ret = ntfs_attr_lookup(ni->type, 3539af0db57dSNamjae Jeon ni->name, ni->name_len, CASE_SENSITIVE, 3540af0db57dSNamjae Jeon 0, NULL, 0, ctx); 3541af0db57dSNamjae Jeon if (ret) { 3542af0db57dSNamjae Jeon ntfs_error(sb, "Failed to look up attr %#x", ni->type); 3543af0db57dSNamjae Jeon return ret; 3544af0db57dSNamjae Jeon } 3545af0db57dSNamjae Jeon } 3546af0db57dSNamjae Jeon 3547af0db57dSNamjae Jeon if (!NInoNonResident(ni)) { 3548af0db57dSNamjae Jeon if (likely(i_size_read(vi) < ni->data_size)) 3549af0db57dSNamjae Jeon i_size_write(vi, ni->data_size); 3550af0db57dSNamjae Jeon return 0; 3551af0db57dSNamjae Jeon } 3552af0db57dSNamjae Jeon 3553af0db57dSNamjae Jeon if (pos + count > ni->initialized_size) { 3554af0db57dSNamjae Jeon ctx->attr->data.non_resident.initialized_size = cpu_to_le64(pos + count); 3555af0db57dSNamjae Jeon mark_mft_record_dirty(ctx->ntfs_ino); 3556af0db57dSNamjae Jeon ni->initialized_size = pos + count; 3557af0db57dSNamjae Jeon if (i_size_read(vi) < ni->initialized_size) 3558af0db57dSNamjae Jeon i_size_write(vi, ni->initialized_size); 3559af0db57dSNamjae Jeon } 3560af0db57dSNamjae Jeon return 0; 3561af0db57dSNamjae Jeon } 3562af0db57dSNamjae Jeon 3563af0db57dSNamjae Jeon static s64 __ntfs_inode_resident_attr_pwrite(struct inode *vi, 3564af0db57dSNamjae Jeon s64 pos, s64 count, u8 *buf, 3565af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx) 3566af0db57dSNamjae Jeon { 3567af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 3568af0db57dSNamjae Jeon struct folio *folio; 3569af0db57dSNamjae Jeon struct address_space *mapping = vi->i_mapping; 3570af0db57dSNamjae Jeon u8 *addr; 3571af0db57dSNamjae Jeon int err = 0; 3572af0db57dSNamjae Jeon 3573af0db57dSNamjae Jeon WARN_ON(NInoNonResident(ni)); 3574af0db57dSNamjae Jeon if (pos + count > PAGE_SIZE) { 3575af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Out of write into resident attr %#x", ni->type); 3576af0db57dSNamjae Jeon return -EINVAL; 3577af0db57dSNamjae Jeon } 3578af0db57dSNamjae Jeon 3579af0db57dSNamjae Jeon /* Copy to mft record page */ 3580af0db57dSNamjae Jeon addr = (u8 *)ctx->attr + le16_to_cpu(ctx->attr->data.resident.value_offset); 3581af0db57dSNamjae Jeon memcpy(addr + pos, buf, count); 3582af0db57dSNamjae Jeon mark_mft_record_dirty(ctx->ntfs_ino); 3583af0db57dSNamjae Jeon 3584af0db57dSNamjae Jeon /* Keep the first page clean and uptodate */ 3585af0db57dSNamjae Jeon folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS, 3586af0db57dSNamjae Jeon mapping_gfp_mask(mapping)); 3587af0db57dSNamjae Jeon if (IS_ERR(folio)) { 3588af0db57dSNamjae Jeon err = PTR_ERR(folio); 3589af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to read a page 0 for attr %#x: %d", 3590af0db57dSNamjae Jeon ni->type, err); 3591af0db57dSNamjae Jeon goto out; 3592af0db57dSNamjae Jeon } 3593af0db57dSNamjae Jeon if (!folio_test_uptodate(folio)) 3594af0db57dSNamjae Jeon folio_fill_tail(folio, 0, addr, 3595af0db57dSNamjae Jeon le32_to_cpu(ctx->attr->data.resident.value_length)); 3596af0db57dSNamjae Jeon else 3597af0db57dSNamjae Jeon memcpy_to_folio(folio, offset_in_folio(folio, pos), buf, count); 3598af0db57dSNamjae Jeon folio_mark_uptodate(folio); 3599af0db57dSNamjae Jeon folio_unlock(folio); 3600af0db57dSNamjae Jeon folio_put(folio); 3601af0db57dSNamjae Jeon out: 3602af0db57dSNamjae Jeon return err ? err : count; 3603af0db57dSNamjae Jeon } 3604af0db57dSNamjae Jeon 3605af0db57dSNamjae Jeon static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi, 3606af0db57dSNamjae Jeon s64 pos, s64 count, u8 *buf, 3607af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx, 3608af0db57dSNamjae Jeon bool sync) 3609af0db57dSNamjae Jeon { 3610af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 3611af0db57dSNamjae Jeon struct address_space *mapping = vi->i_mapping; 3612af0db57dSNamjae Jeon struct folio *folio; 3613af0db57dSNamjae Jeon pgoff_t index; 3614af0db57dSNamjae Jeon unsigned long offset, length; 3615af0db57dSNamjae Jeon size_t attr_len; 3616af0db57dSNamjae Jeon s64 ret = 0, written = 0; 3617af0db57dSNamjae Jeon 3618af0db57dSNamjae Jeon WARN_ON(!NInoNonResident(ni)); 3619af0db57dSNamjae Jeon 3620af0db57dSNamjae Jeon index = pos >> PAGE_SHIFT; 3621af0db57dSNamjae Jeon while (count) { 3622af0db57dSNamjae Jeon if (count == PAGE_SIZE) { 3623af0db57dSNamjae Jeon folio = __filemap_get_folio(vi->i_mapping, index, 3624af0db57dSNamjae Jeon FGP_CREAT | FGP_LOCK, 3625af0db57dSNamjae Jeon mapping_gfp_mask(mapping)); 3626af0db57dSNamjae Jeon if (IS_ERR(folio)) { 3627af0db57dSNamjae Jeon ret = -ENOMEM; 3628af0db57dSNamjae Jeon break; 3629af0db57dSNamjae Jeon } 3630af0db57dSNamjae Jeon } else { 3631af0db57dSNamjae Jeon folio = read_mapping_folio(mapping, index, NULL); 3632af0db57dSNamjae Jeon if (IS_ERR(folio)) { 3633af0db57dSNamjae Jeon ret = PTR_ERR(folio); 3634af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to read a page %lu for attr %#x: %ld", 3635af0db57dSNamjae Jeon index, ni->type, PTR_ERR(folio)); 3636af0db57dSNamjae Jeon break; 3637af0db57dSNamjae Jeon } 3638af0db57dSNamjae Jeon 3639af0db57dSNamjae Jeon folio_lock(folio); 3640af0db57dSNamjae Jeon } 3641af0db57dSNamjae Jeon 3642af0db57dSNamjae Jeon if (count == PAGE_SIZE) { 3643af0db57dSNamjae Jeon offset = 0; 3644af0db57dSNamjae Jeon attr_len = count; 3645af0db57dSNamjae Jeon } else { 3646af0db57dSNamjae Jeon offset = offset_in_folio(folio, pos); 3647af0db57dSNamjae Jeon attr_len = min_t(size_t, (size_t)count, folio_size(folio) - offset); 3648af0db57dSNamjae Jeon } 3649af0db57dSNamjae Jeon memcpy_to_folio(folio, offset, buf, attr_len); 3650af0db57dSNamjae Jeon 3651af0db57dSNamjae Jeon if (sync) { 3652af0db57dSNamjae Jeon struct ntfs_volume *vol = ni->vol; 3653af0db57dSNamjae Jeon s64 lcn, lcn_count; 3654af0db57dSNamjae Jeon unsigned int lcn_folio_off = 0; 3655af0db57dSNamjae Jeon struct bio *bio; 3656af0db57dSNamjae Jeon u64 rl_length = 0; 3657af0db57dSNamjae Jeon s64 vcn; 3658af0db57dSNamjae Jeon struct runlist_element *rl; 3659af0db57dSNamjae Jeon 3660af0db57dSNamjae Jeon lcn_count = max_t(s64, 1, ntfs_bytes_to_cluster(vol, attr_len)); 3661af0db57dSNamjae Jeon vcn = ntfs_pidx_to_cluster(vol, folio->index); 3662af0db57dSNamjae Jeon 3663af0db57dSNamjae Jeon do { 3664af0db57dSNamjae Jeon down_write(&ni->runlist.lock); 3665af0db57dSNamjae Jeon rl = ntfs_attr_vcn_to_rl(ni, vcn, &lcn); 3666af0db57dSNamjae Jeon if (IS_ERR(rl)) { 3667af0db57dSNamjae Jeon ret = PTR_ERR(rl); 3668af0db57dSNamjae Jeon up_write(&ni->runlist.lock); 3669af0db57dSNamjae Jeon goto err_unlock_folio; 3670af0db57dSNamjae Jeon } 3671af0db57dSNamjae Jeon 3672af0db57dSNamjae Jeon rl_length = rl->length - (vcn - rl->vcn); 3673af0db57dSNamjae Jeon if (rl_length < lcn_count) { 3674af0db57dSNamjae Jeon lcn_count -= rl_length; 3675af0db57dSNamjae Jeon } else { 3676af0db57dSNamjae Jeon rl_length = lcn_count; 3677af0db57dSNamjae Jeon lcn_count = 0; 3678af0db57dSNamjae Jeon } 3679af0db57dSNamjae Jeon up_write(&ni->runlist.lock); 3680af0db57dSNamjae Jeon 3681af0db57dSNamjae Jeon if (vol->cluster_size_bits > PAGE_SHIFT) { 3682af0db57dSNamjae Jeon lcn_folio_off = folio->index << PAGE_SHIFT; 3683af0db57dSNamjae Jeon lcn_folio_off &= vol->cluster_size_mask; 3684af0db57dSNamjae Jeon } 3685af0db57dSNamjae Jeon 3686af0db57dSNamjae Jeon bio = bio_alloc(vol->sb->s_bdev, 1, REQ_OP_WRITE, 3687af0db57dSNamjae Jeon GFP_NOIO); 3688af0db57dSNamjae Jeon bio->bi_iter.bi_sector = 3689af0db57dSNamjae Jeon ntfs_bytes_to_sector(vol, 3690af0db57dSNamjae Jeon ntfs_cluster_to_bytes(vol, lcn) + 3691af0db57dSNamjae Jeon lcn_folio_off); 3692af0db57dSNamjae Jeon 3693af0db57dSNamjae Jeon length = min_t(unsigned long, 3694af0db57dSNamjae Jeon ntfs_cluster_to_bytes(vol, rl_length), 3695af0db57dSNamjae Jeon folio_size(folio)); 3696af0db57dSNamjae Jeon if (!bio_add_folio(bio, folio, length, offset)) { 3697af0db57dSNamjae Jeon ret = -EIO; 3698af0db57dSNamjae Jeon bio_put(bio); 3699af0db57dSNamjae Jeon goto err_unlock_folio; 3700af0db57dSNamjae Jeon } 3701af0db57dSNamjae Jeon 3702af0db57dSNamjae Jeon submit_bio_wait(bio); 3703af0db57dSNamjae Jeon bio_put(bio); 3704af0db57dSNamjae Jeon vcn += rl_length; 3705af0db57dSNamjae Jeon offset += length; 3706af0db57dSNamjae Jeon } while (lcn_count != 0); 3707af0db57dSNamjae Jeon 3708af0db57dSNamjae Jeon folio_mark_uptodate(folio); 3709af0db57dSNamjae Jeon } else { 3710af0db57dSNamjae Jeon folio_mark_uptodate(folio); 3711af0db57dSNamjae Jeon folio_mark_dirty(folio); 3712af0db57dSNamjae Jeon } 3713af0db57dSNamjae Jeon err_unlock_folio: 3714af0db57dSNamjae Jeon folio_unlock(folio); 3715af0db57dSNamjae Jeon folio_put(folio); 3716af0db57dSNamjae Jeon 3717af0db57dSNamjae Jeon if (ret) 3718af0db57dSNamjae Jeon break; 3719af0db57dSNamjae Jeon 3720af0db57dSNamjae Jeon written += attr_len; 3721af0db57dSNamjae Jeon buf += attr_len; 3722af0db57dSNamjae Jeon pos += attr_len; 3723af0db57dSNamjae Jeon count -= attr_len; 3724af0db57dSNamjae Jeon index++; 3725af0db57dSNamjae Jeon 3726af0db57dSNamjae Jeon cond_resched(); 3727af0db57dSNamjae Jeon } 3728af0db57dSNamjae Jeon 3729af0db57dSNamjae Jeon return ret ? ret : written; 3730af0db57dSNamjae Jeon } 3731af0db57dSNamjae Jeon 3732af0db57dSNamjae Jeon s64 ntfs_inode_attr_pwrite(struct inode *vi, s64 pos, s64 count, u8 *buf, bool sync) 3733af0db57dSNamjae Jeon { 3734af0db57dSNamjae Jeon struct ntfs_inode *ni = NTFS_I(vi); 3735af0db57dSNamjae Jeon struct ntfs_attr_search_ctx *ctx; 3736af0db57dSNamjae Jeon s64 ret; 3737af0db57dSNamjae Jeon 3738af0db57dSNamjae Jeon WARN_ON(!NInoAttr(ni)); 3739af0db57dSNamjae Jeon 3740af0db57dSNamjae Jeon ctx = ntfs_attr_get_search_ctx(ni->ext.base_ntfs_ino, NULL); 3741af0db57dSNamjae Jeon if (!ctx) { 3742af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to get attr search ctx"); 3743af0db57dSNamjae Jeon return -ENOMEM; 3744af0db57dSNamjae Jeon } 3745af0db57dSNamjae Jeon 3746af0db57dSNamjae Jeon ret = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, 3747af0db57dSNamjae Jeon 0, NULL, 0, ctx); 3748af0db57dSNamjae Jeon if (ret) { 3749af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3750af0db57dSNamjae Jeon ntfs_error(vi->i_sb, "Failed to look up attr %#x", ni->type); 3751af0db57dSNamjae Jeon return ret; 3752af0db57dSNamjae Jeon } 3753af0db57dSNamjae Jeon 3754af0db57dSNamjae Jeon mutex_lock(&ni->mrec_lock); 3755af0db57dSNamjae Jeon ret = ntfs_enlarge_attribute(vi, pos, count, ctx); 3756af0db57dSNamjae Jeon mutex_unlock(&ni->mrec_lock); 3757af0db57dSNamjae Jeon if (ret) 3758af0db57dSNamjae Jeon goto out; 3759af0db57dSNamjae Jeon 3760af0db57dSNamjae Jeon if (NInoNonResident(ni)) 3761af0db57dSNamjae Jeon ret = __ntfs_inode_non_resident_attr_pwrite(vi, pos, count, buf, ctx, sync); 3762af0db57dSNamjae Jeon else 3763af0db57dSNamjae Jeon ret = __ntfs_inode_resident_attr_pwrite(vi, pos, count, buf, ctx); 3764af0db57dSNamjae Jeon out: 3765af0db57dSNamjae Jeon ntfs_attr_put_search_ctx(ctx); 3766af0db57dSNamjae Jeon return ret; 3767af0db57dSNamjae Jeon } 3768af0db57dSNamjae Jeon 3769af0db57dSNamjae Jeon struct folio *ntfs_get_locked_folio(struct address_space *mapping, 3770af0db57dSNamjae Jeon pgoff_t index, pgoff_t end_index, struct file_ra_state *ra) 3771af0db57dSNamjae Jeon { 3772af0db57dSNamjae Jeon struct folio *folio; 3773af0db57dSNamjae Jeon 3774af0db57dSNamjae Jeon folio = filemap_lock_folio(mapping, index); 3775af0db57dSNamjae Jeon if (IS_ERR(folio)) { 3776af0db57dSNamjae Jeon if (PTR_ERR(folio) != -ENOENT) 3777af0db57dSNamjae Jeon return folio; 3778af0db57dSNamjae Jeon 3779af0db57dSNamjae Jeon page_cache_sync_readahead(mapping, ra, NULL, index, 3780af0db57dSNamjae Jeon end_index - index); 3781af0db57dSNamjae Jeon folio = read_mapping_folio(mapping, index, NULL); 3782af0db57dSNamjae Jeon if (!IS_ERR(folio)) 3783af0db57dSNamjae Jeon folio_lock(folio); 3784af0db57dSNamjae Jeon } 3785af0db57dSNamjae Jeon 3786af0db57dSNamjae Jeon return folio; 3787af0db57dSNamjae Jeon } 3788