182cae269SKonstantin Komarov // SPDX-License-Identifier: GPL-2.0 282cae269SKonstantin Komarov /* 382cae269SKonstantin Komarov * 482cae269SKonstantin Komarov * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. 582cae269SKonstantin Komarov * 682cae269SKonstantin Komarov */ 782cae269SKonstantin Komarov 882cae269SKonstantin Komarov #include <linux/buffer_head.h> 982cae269SKonstantin Komarov #include <linux/fs.h> 1082cae269SKonstantin Komarov #include <linux/mpage.h> 1182cae269SKonstantin Komarov #include <linux/namei.h> 1282cae269SKonstantin Komarov #include <linux/nls.h> 1382cae269SKonstantin Komarov #include <linux/uio.h> 1482cae269SKonstantin Komarov #include <linux/writeback.h> 1582cae269SKonstantin Komarov 1682cae269SKonstantin Komarov #include "debug.h" 1782cae269SKonstantin Komarov #include "ntfs.h" 1882cae269SKonstantin Komarov #include "ntfs_fs.h" 1982cae269SKonstantin Komarov 2082cae269SKonstantin Komarov /* 21e8b8e97fSKari Argillander * ntfs_read_mft - Read record and parses MFT. 2282cae269SKonstantin Komarov */ 2382cae269SKonstantin Komarov static struct inode *ntfs_read_mft(struct inode *inode, 2482cae269SKonstantin Komarov const struct cpu_str *name, 2582cae269SKonstantin Komarov const struct MFT_REF *ref) 2682cae269SKonstantin Komarov { 2782cae269SKonstantin Komarov int err = 0; 2882cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 2982cae269SKonstantin Komarov struct super_block *sb = inode->i_sb; 3082cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 3182cae269SKonstantin Komarov mode_t mode = 0; 3282cae269SKonstantin Komarov struct ATTR_STD_INFO5 *std5 = NULL; 3382cae269SKonstantin Komarov struct ATTR_LIST_ENTRY *le; 3482cae269SKonstantin Komarov struct ATTRIB *attr; 3582cae269SKonstantin Komarov bool is_match = false; 3682cae269SKonstantin Komarov bool is_root = false; 3782cae269SKonstantin Komarov bool is_dir; 3882cae269SKonstantin Komarov unsigned long ino = inode->i_ino; 3982cae269SKonstantin Komarov u32 rp_fa = 0, asize, t32; 4082cae269SKonstantin Komarov u16 roff, rsize, names = 0; 4182cae269SKonstantin Komarov const struct ATTR_FILE_NAME *fname = NULL; 4282cae269SKonstantin Komarov const struct INDEX_ROOT *root; 4382cae269SKonstantin Komarov struct REPARSE_DATA_BUFFER rp; // 0x18 bytes 4482cae269SKonstantin Komarov u64 t64; 4582cae269SKonstantin Komarov struct MFT_REC *rec; 4682cae269SKonstantin Komarov struct runs_tree *run; 4782cae269SKonstantin Komarov 4882cae269SKonstantin Komarov inode->i_op = NULL; 4982cae269SKonstantin Komarov /* Setup 'uid' and 'gid' */ 50564c97bdSKari Argillander inode->i_uid = sbi->options->fs_uid; 51564c97bdSKari Argillander inode->i_gid = sbi->options->fs_gid; 5282cae269SKonstantin Komarov 5382cae269SKonstantin Komarov err = mi_init(&ni->mi, sbi, ino); 5482cae269SKonstantin Komarov if (err) 5582cae269SKonstantin Komarov goto out; 5682cae269SKonstantin Komarov 5782cae269SKonstantin Komarov if (!sbi->mft.ni && ino == MFT_REC_MFT && !sb->s_root) { 5882cae269SKonstantin Komarov t64 = sbi->mft.lbo >> sbi->cluster_bits; 5982cae269SKonstantin Komarov t32 = bytes_to_cluster(sbi, MFT_REC_VOL * sbi->record_size); 6082cae269SKonstantin Komarov sbi->mft.ni = ni; 6182cae269SKonstantin Komarov init_rwsem(&ni->file.run_lock); 6282cae269SKonstantin Komarov 6382cae269SKonstantin Komarov if (!run_add_entry(&ni->file.run, 0, t64, t32, true)) { 6482cae269SKonstantin Komarov err = -ENOMEM; 6582cae269SKonstantin Komarov goto out; 6682cae269SKonstantin Komarov } 6782cae269SKonstantin Komarov } 6882cae269SKonstantin Komarov 6982cae269SKonstantin Komarov err = mi_read(&ni->mi, ino == MFT_REC_MFT); 7082cae269SKonstantin Komarov 7182cae269SKonstantin Komarov if (err) 7282cae269SKonstantin Komarov goto out; 7382cae269SKonstantin Komarov 7482cae269SKonstantin Komarov rec = ni->mi.mrec; 7582cae269SKonstantin Komarov 7682cae269SKonstantin Komarov if (sbi->flags & NTFS_FLAGS_LOG_REPLAYING) { 7782cae269SKonstantin Komarov ; 7882cae269SKonstantin Komarov } else if (ref->seq != rec->seq) { 7982cae269SKonstantin Komarov err = -EINVAL; 8082cae269SKonstantin Komarov ntfs_err(sb, "MFT: r=%lx, expect seq=%x instead of %x!", ino, 8182cae269SKonstantin Komarov le16_to_cpu(ref->seq), le16_to_cpu(rec->seq)); 8282cae269SKonstantin Komarov goto out; 8382cae269SKonstantin Komarov } else if (!is_rec_inuse(rec)) { 8482cae269SKonstantin Komarov err = -EINVAL; 8582cae269SKonstantin Komarov ntfs_err(sb, "Inode r=%x is not in use!", (u32)ino); 8682cae269SKonstantin Komarov goto out; 8782cae269SKonstantin Komarov } 8882cae269SKonstantin Komarov 8982cae269SKonstantin Komarov if (le32_to_cpu(rec->total) != sbi->record_size) { 90d3624466SKonstantin Komarov /* Bad inode? */ 9182cae269SKonstantin Komarov err = -EINVAL; 9282cae269SKonstantin Komarov goto out; 9382cae269SKonstantin Komarov } 9482cae269SKonstantin Komarov 9582cae269SKonstantin Komarov if (!is_rec_base(rec)) 9682cae269SKonstantin Komarov goto Ok; 9782cae269SKonstantin Komarov 98e8b8e97fSKari Argillander /* Record should contain $I30 root. */ 9982cae269SKonstantin Komarov is_dir = rec->flags & RECORD_FLAG_DIR; 10082cae269SKonstantin Komarov 10182cae269SKonstantin Komarov inode->i_generation = le16_to_cpu(rec->seq); 10282cae269SKonstantin Komarov 103e8b8e97fSKari Argillander /* Enumerate all struct Attributes MFT. */ 10482cae269SKonstantin Komarov le = NULL; 10582cae269SKonstantin Komarov attr = NULL; 10682cae269SKonstantin Komarov 10782cae269SKonstantin Komarov /* 108e8b8e97fSKari Argillander * To reduce tab pressure use goto instead of 10982cae269SKonstantin Komarov * while( (attr = ni_enum_attr_ex(ni, attr, &le, NULL) )) 11082cae269SKonstantin Komarov */ 11182cae269SKonstantin Komarov next_attr: 11282cae269SKonstantin Komarov run = NULL; 11382cae269SKonstantin Komarov err = -EINVAL; 11482cae269SKonstantin Komarov attr = ni_enum_attr_ex(ni, attr, &le, NULL); 11582cae269SKonstantin Komarov if (!attr) 11682cae269SKonstantin Komarov goto end_enum; 11782cae269SKonstantin Komarov 11882cae269SKonstantin Komarov if (le && le->vcn) { 119e8b8e97fSKari Argillander /* This is non primary attribute segment. Ignore if not MFT. */ 12082cae269SKonstantin Komarov if (ino != MFT_REC_MFT || attr->type != ATTR_DATA) 12182cae269SKonstantin Komarov goto next_attr; 12282cae269SKonstantin Komarov 12382cae269SKonstantin Komarov run = &ni->file.run; 12482cae269SKonstantin Komarov asize = le32_to_cpu(attr->size); 12582cae269SKonstantin Komarov goto attr_unpack_run; 12682cae269SKonstantin Komarov } 12782cae269SKonstantin Komarov 12882cae269SKonstantin Komarov roff = attr->non_res ? 0 : le16_to_cpu(attr->res.data_off); 12982cae269SKonstantin Komarov rsize = attr->non_res ? 0 : le32_to_cpu(attr->res.data_size); 13082cae269SKonstantin Komarov asize = le32_to_cpu(attr->size); 13182cae269SKonstantin Komarov 13282cae269SKonstantin Komarov switch (attr->type) { 13382cae269SKonstantin Komarov case ATTR_STD: 13482cae269SKonstantin Komarov if (attr->non_res || 13582cae269SKonstantin Komarov asize < sizeof(struct ATTR_STD_INFO) + roff || 13682cae269SKonstantin Komarov rsize < sizeof(struct ATTR_STD_INFO)) 13782cae269SKonstantin Komarov goto out; 13882cae269SKonstantin Komarov 13982cae269SKonstantin Komarov if (std5) 14082cae269SKonstantin Komarov goto next_attr; 14182cae269SKonstantin Komarov 14282cae269SKonstantin Komarov std5 = Add2Ptr(attr, roff); 14382cae269SKonstantin Komarov 14482cae269SKonstantin Komarov #ifdef STATX_BTIME 14582cae269SKonstantin Komarov nt2kernel(std5->cr_time, &ni->i_crtime); 14682cae269SKonstantin Komarov #endif 14782cae269SKonstantin Komarov nt2kernel(std5->a_time, &inode->i_atime); 14882cae269SKonstantin Komarov nt2kernel(std5->c_time, &inode->i_ctime); 14982cae269SKonstantin Komarov nt2kernel(std5->m_time, &inode->i_mtime); 15082cae269SKonstantin Komarov 15182cae269SKonstantin Komarov ni->std_fa = std5->fa; 15282cae269SKonstantin Komarov 15382cae269SKonstantin Komarov if (asize >= sizeof(struct ATTR_STD_INFO5) + roff && 15482cae269SKonstantin Komarov rsize >= sizeof(struct ATTR_STD_INFO5)) 15582cae269SKonstantin Komarov ni->std_security_id = std5->security_id; 15682cae269SKonstantin Komarov goto next_attr; 15782cae269SKonstantin Komarov 15882cae269SKonstantin Komarov case ATTR_LIST: 15982cae269SKonstantin Komarov if (attr->name_len || le || ino == MFT_REC_LOG) 16082cae269SKonstantin Komarov goto out; 16182cae269SKonstantin Komarov 16282cae269SKonstantin Komarov err = ntfs_load_attr_list(ni, attr); 16382cae269SKonstantin Komarov if (err) 16482cae269SKonstantin Komarov goto out; 16582cae269SKonstantin Komarov 16682cae269SKonstantin Komarov le = NULL; 16782cae269SKonstantin Komarov attr = NULL; 16882cae269SKonstantin Komarov goto next_attr; 16982cae269SKonstantin Komarov 17082cae269SKonstantin Komarov case ATTR_NAME: 17182cae269SKonstantin Komarov if (attr->non_res || asize < SIZEOF_ATTRIBUTE_FILENAME + roff || 17282cae269SKonstantin Komarov rsize < SIZEOF_ATTRIBUTE_FILENAME) 17382cae269SKonstantin Komarov goto out; 17482cae269SKonstantin Komarov 17582cae269SKonstantin Komarov fname = Add2Ptr(attr, roff); 17682cae269SKonstantin Komarov if (fname->type == FILE_NAME_DOS) 17782cae269SKonstantin Komarov goto next_attr; 17882cae269SKonstantin Komarov 17982cae269SKonstantin Komarov names += 1; 18082cae269SKonstantin Komarov if (name && name->len == fname->name_len && 18182cae269SKonstantin Komarov !ntfs_cmp_names_cpu(name, (struct le_str *)&fname->name_len, 18282cae269SKonstantin Komarov NULL, false)) 18382cae269SKonstantin Komarov is_match = true; 18482cae269SKonstantin Komarov 18582cae269SKonstantin Komarov goto next_attr; 18682cae269SKonstantin Komarov 18782cae269SKonstantin Komarov case ATTR_DATA: 18882cae269SKonstantin Komarov if (is_dir) { 189e8b8e97fSKari Argillander /* Ignore data attribute in dir record. */ 19082cae269SKonstantin Komarov goto next_attr; 19182cae269SKonstantin Komarov } 19282cae269SKonstantin Komarov 19382cae269SKonstantin Komarov if (ino == MFT_REC_BADCLUST && !attr->non_res) 19482cae269SKonstantin Komarov goto next_attr; 19582cae269SKonstantin Komarov 19682cae269SKonstantin Komarov if (attr->name_len && 19782cae269SKonstantin Komarov ((ino != MFT_REC_BADCLUST || !attr->non_res || 19882cae269SKonstantin Komarov attr->name_len != ARRAY_SIZE(BAD_NAME) || 19982cae269SKonstantin Komarov memcmp(attr_name(attr), BAD_NAME, sizeof(BAD_NAME))) && 20082cae269SKonstantin Komarov (ino != MFT_REC_SECURE || !attr->non_res || 20182cae269SKonstantin Komarov attr->name_len != ARRAY_SIZE(SDS_NAME) || 20282cae269SKonstantin Komarov memcmp(attr_name(attr), SDS_NAME, sizeof(SDS_NAME))))) { 203e8b8e97fSKari Argillander /* File contains stream attribute. Ignore it. */ 20482cae269SKonstantin Komarov goto next_attr; 20582cae269SKonstantin Komarov } 20682cae269SKonstantin Komarov 20782cae269SKonstantin Komarov if (is_attr_sparsed(attr)) 20882cae269SKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_SPARSE_FILE; 20982cae269SKonstantin Komarov else 21082cae269SKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_SPARSE_FILE; 21182cae269SKonstantin Komarov 21282cae269SKonstantin Komarov if (is_attr_compressed(attr)) 21382cae269SKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_COMPRESSED; 21482cae269SKonstantin Komarov else 21582cae269SKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_COMPRESSED; 21682cae269SKonstantin Komarov 21782cae269SKonstantin Komarov if (is_attr_encrypted(attr)) 21882cae269SKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_ENCRYPTED; 21982cae269SKonstantin Komarov else 22082cae269SKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_ENCRYPTED; 22182cae269SKonstantin Komarov 22282cae269SKonstantin Komarov if (!attr->non_res) { 22382cae269SKonstantin Komarov ni->i_valid = inode->i_size = rsize; 22482cae269SKonstantin Komarov inode_set_bytes(inode, rsize); 22582cae269SKonstantin Komarov } 22682cae269SKonstantin Komarov 227564c97bdSKari Argillander mode = S_IFREG | (0777 & sbi->options->fs_fmask_inv); 22882cae269SKonstantin Komarov 22982cae269SKonstantin Komarov if (!attr->non_res) { 23082cae269SKonstantin Komarov ni->ni_flags |= NI_FLAG_RESIDENT; 23182cae269SKonstantin Komarov goto next_attr; 23282cae269SKonstantin Komarov } 23382cae269SKonstantin Komarov 23482cae269SKonstantin Komarov inode_set_bytes(inode, attr_ondisk_size(attr)); 23582cae269SKonstantin Komarov 23682cae269SKonstantin Komarov ni->i_valid = le64_to_cpu(attr->nres.valid_size); 23782cae269SKonstantin Komarov inode->i_size = le64_to_cpu(attr->nres.data_size); 23882cae269SKonstantin Komarov if (!attr->nres.alloc_size) 23982cae269SKonstantin Komarov goto next_attr; 24082cae269SKonstantin Komarov 24182cae269SKonstantin Komarov run = ino == MFT_REC_BITMAP ? &sbi->used.bitmap.run 24282cae269SKonstantin Komarov : &ni->file.run; 24382cae269SKonstantin Komarov break; 24482cae269SKonstantin Komarov 24582cae269SKonstantin Komarov case ATTR_ROOT: 24682cae269SKonstantin Komarov if (attr->non_res) 24782cae269SKonstantin Komarov goto out; 24882cae269SKonstantin Komarov 24982cae269SKonstantin Komarov root = Add2Ptr(attr, roff); 25082cae269SKonstantin Komarov is_root = true; 25182cae269SKonstantin Komarov 25282cae269SKonstantin Komarov if (attr->name_len != ARRAY_SIZE(I30_NAME) || 25382cae269SKonstantin Komarov memcmp(attr_name(attr), I30_NAME, sizeof(I30_NAME))) 25482cae269SKonstantin Komarov goto next_attr; 25582cae269SKonstantin Komarov 25682cae269SKonstantin Komarov if (root->type != ATTR_NAME || 25782cae269SKonstantin Komarov root->rule != NTFS_COLLATION_TYPE_FILENAME) 25882cae269SKonstantin Komarov goto out; 25982cae269SKonstantin Komarov 26082cae269SKonstantin Komarov if (!is_dir) 26182cae269SKonstantin Komarov goto next_attr; 26282cae269SKonstantin Komarov 26382cae269SKonstantin Komarov ni->ni_flags |= NI_FLAG_DIR; 26482cae269SKonstantin Komarov 26582cae269SKonstantin Komarov err = indx_init(&ni->dir, sbi, attr, INDEX_MUTEX_I30); 26682cae269SKonstantin Komarov if (err) 26782cae269SKonstantin Komarov goto out; 26882cae269SKonstantin Komarov 26982cae269SKonstantin Komarov mode = sb->s_root 270564c97bdSKari Argillander ? (S_IFDIR | (0777 & sbi->options->fs_dmask_inv)) 27182cae269SKonstantin Komarov : (S_IFDIR | 0777); 27282cae269SKonstantin Komarov goto next_attr; 27382cae269SKonstantin Komarov 27482cae269SKonstantin Komarov case ATTR_ALLOC: 27582cae269SKonstantin Komarov if (!is_root || attr->name_len != ARRAY_SIZE(I30_NAME) || 27682cae269SKonstantin Komarov memcmp(attr_name(attr), I30_NAME, sizeof(I30_NAME))) 27782cae269SKonstantin Komarov goto next_attr; 27882cae269SKonstantin Komarov 27982cae269SKonstantin Komarov inode->i_size = le64_to_cpu(attr->nres.data_size); 28082cae269SKonstantin Komarov ni->i_valid = le64_to_cpu(attr->nres.valid_size); 28182cae269SKonstantin Komarov inode_set_bytes(inode, le64_to_cpu(attr->nres.alloc_size)); 28282cae269SKonstantin Komarov 28382cae269SKonstantin Komarov run = &ni->dir.alloc_run; 28482cae269SKonstantin Komarov break; 28582cae269SKonstantin Komarov 28682cae269SKonstantin Komarov case ATTR_BITMAP: 28782cae269SKonstantin Komarov if (ino == MFT_REC_MFT) { 28882cae269SKonstantin Komarov if (!attr->non_res) 28982cae269SKonstantin Komarov goto out; 29082cae269SKonstantin Komarov #ifndef CONFIG_NTFS3_64BIT_CLUSTER 29182cae269SKonstantin Komarov /* 0x20000000 = 2^32 / 8 */ 29282cae269SKonstantin Komarov if (le64_to_cpu(attr->nres.alloc_size) >= 0x20000000) 29382cae269SKonstantin Komarov goto out; 29482cae269SKonstantin Komarov #endif 29582cae269SKonstantin Komarov run = &sbi->mft.bitmap.run; 29682cae269SKonstantin Komarov break; 29782cae269SKonstantin Komarov } else if (is_dir && attr->name_len == ARRAY_SIZE(I30_NAME) && 29882cae269SKonstantin Komarov !memcmp(attr_name(attr), I30_NAME, 29982cae269SKonstantin Komarov sizeof(I30_NAME)) && 30082cae269SKonstantin Komarov attr->non_res) { 30182cae269SKonstantin Komarov run = &ni->dir.bitmap_run; 30282cae269SKonstantin Komarov break; 30382cae269SKonstantin Komarov } 30482cae269SKonstantin Komarov goto next_attr; 30582cae269SKonstantin Komarov 30682cae269SKonstantin Komarov case ATTR_REPARSE: 30782cae269SKonstantin Komarov if (attr->name_len) 30882cae269SKonstantin Komarov goto next_attr; 30982cae269SKonstantin Komarov 31082cae269SKonstantin Komarov rp_fa = ni_parse_reparse(ni, attr, &rp); 31182cae269SKonstantin Komarov switch (rp_fa) { 31282cae269SKonstantin Komarov case REPARSE_LINK: 31322b05f1aSKonstantin Komarov /* 31422b05f1aSKonstantin Komarov * Normal symlink. 31522b05f1aSKonstantin Komarov * Assume one unicode symbol == one utf8. 31622b05f1aSKonstantin Komarov */ 31722b05f1aSKonstantin Komarov inode->i_size = le16_to_cpu(rp.SymbolicLinkReparseBuffer 31822b05f1aSKonstantin Komarov .PrintNameLength) / 31922b05f1aSKonstantin Komarov sizeof(u16); 32082cae269SKonstantin Komarov 32182cae269SKonstantin Komarov ni->i_valid = inode->i_size; 32282cae269SKonstantin Komarov 323e8b8e97fSKari Argillander /* Clear directory bit. */ 32482cae269SKonstantin Komarov if (ni->ni_flags & NI_FLAG_DIR) { 32582cae269SKonstantin Komarov indx_clear(&ni->dir); 32682cae269SKonstantin Komarov memset(&ni->dir, 0, sizeof(ni->dir)); 32782cae269SKonstantin Komarov ni->ni_flags &= ~NI_FLAG_DIR; 32882cae269SKonstantin Komarov } else { 32982cae269SKonstantin Komarov run_close(&ni->file.run); 33082cae269SKonstantin Komarov } 33182cae269SKonstantin Komarov mode = S_IFLNK | 0777; 33282cae269SKonstantin Komarov is_dir = false; 33382cae269SKonstantin Komarov if (attr->non_res) { 33482cae269SKonstantin Komarov run = &ni->file.run; 335e8b8e97fSKari Argillander goto attr_unpack_run; // Double break. 33682cae269SKonstantin Komarov } 33782cae269SKonstantin Komarov break; 33882cae269SKonstantin Komarov 33982cae269SKonstantin Komarov case REPARSE_COMPRESSED: 34082cae269SKonstantin Komarov break; 34182cae269SKonstantin Komarov 34282cae269SKonstantin Komarov case REPARSE_DEDUPLICATED: 34382cae269SKonstantin Komarov break; 34482cae269SKonstantin Komarov } 34582cae269SKonstantin Komarov goto next_attr; 34682cae269SKonstantin Komarov 34782cae269SKonstantin Komarov case ATTR_EA_INFO: 34882cae269SKonstantin Komarov if (!attr->name_len && 34982cae269SKonstantin Komarov resident_data_ex(attr, sizeof(struct EA_INFO))) { 35082cae269SKonstantin Komarov ni->ni_flags |= NI_FLAG_EA; 35182cae269SKonstantin Komarov /* 35282cae269SKonstantin Komarov * ntfs_get_wsl_perm updates inode->i_uid, inode->i_gid, inode->i_mode 35382cae269SKonstantin Komarov */ 35482cae269SKonstantin Komarov inode->i_mode = mode; 35582cae269SKonstantin Komarov ntfs_get_wsl_perm(inode); 35682cae269SKonstantin Komarov mode = inode->i_mode; 35782cae269SKonstantin Komarov } 35882cae269SKonstantin Komarov goto next_attr; 35982cae269SKonstantin Komarov 36082cae269SKonstantin Komarov default: 36182cae269SKonstantin Komarov goto next_attr; 36282cae269SKonstantin Komarov } 36382cae269SKonstantin Komarov 36482cae269SKonstantin Komarov attr_unpack_run: 36582cae269SKonstantin Komarov roff = le16_to_cpu(attr->nres.run_off); 36682cae269SKonstantin Komarov 367*6db62086SEdward Lo if (roff > asize) { 368*6db62086SEdward Lo err = -EINVAL; 369*6db62086SEdward Lo goto out; 370*6db62086SEdward Lo } 371*6db62086SEdward Lo 37282cae269SKonstantin Komarov t64 = le64_to_cpu(attr->nres.svcn); 37382cae269SKonstantin Komarov err = run_unpack_ex(run, sbi, ino, t64, le64_to_cpu(attr->nres.evcn), 37482cae269SKonstantin Komarov t64, Add2Ptr(attr, roff), asize - roff); 37582cae269SKonstantin Komarov if (err < 0) 37682cae269SKonstantin Komarov goto out; 37782cae269SKonstantin Komarov err = 0; 37882cae269SKonstantin Komarov goto next_attr; 37982cae269SKonstantin Komarov 38082cae269SKonstantin Komarov end_enum: 38182cae269SKonstantin Komarov 38282cae269SKonstantin Komarov if (!std5) 38382cae269SKonstantin Komarov goto out; 38482cae269SKonstantin Komarov 38582cae269SKonstantin Komarov if (!is_match && name) { 386e8b8e97fSKari Argillander /* Reuse rec as buffer for ascii name. */ 38782cae269SKonstantin Komarov err = -ENOENT; 38882cae269SKonstantin Komarov goto out; 38982cae269SKonstantin Komarov } 39082cae269SKonstantin Komarov 39182cae269SKonstantin Komarov if (std5->fa & FILE_ATTRIBUTE_READONLY) 39282cae269SKonstantin Komarov mode &= ~0222; 39382cae269SKonstantin Komarov 39482cae269SKonstantin Komarov if (!names) { 39582cae269SKonstantin Komarov err = -EINVAL; 39682cae269SKonstantin Komarov goto out; 39782cae269SKonstantin Komarov } 39882cae269SKonstantin Komarov 39978ab59feSKonstantin Komarov if (names != le16_to_cpu(rec->hard_links)) { 40078ab59feSKonstantin Komarov /* Correct minor error on the fly. Do not mark inode as dirty. */ 40178ab59feSKonstantin Komarov rec->hard_links = cpu_to_le16(names); 40278ab59feSKonstantin Komarov ni->mi.dirty = true; 40378ab59feSKonstantin Komarov } 40478ab59feSKonstantin Komarov 40582cae269SKonstantin Komarov set_nlink(inode, names); 40682cae269SKonstantin Komarov 40782cae269SKonstantin Komarov if (S_ISDIR(mode)) { 40882cae269SKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_DIRECTORY; 40982cae269SKonstantin Komarov 41082cae269SKonstantin Komarov /* 411e8b8e97fSKari Argillander * Dot and dot-dot should be included in count but was not 41282cae269SKonstantin Komarov * included in enumeration. 413e8b8e97fSKari Argillander * Usually a hard links to directories are disabled. 41482cae269SKonstantin Komarov */ 41582cae269SKonstantin Komarov inode->i_op = &ntfs_dir_inode_operations; 41682cae269SKonstantin Komarov inode->i_fop = &ntfs_dir_operations; 41782cae269SKonstantin Komarov ni->i_valid = 0; 41882cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 41982cae269SKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; 42082cae269SKonstantin Komarov inode->i_op = &ntfs_link_inode_operations; 42182cae269SKonstantin Komarov inode->i_fop = NULL; 42222b05f1aSKonstantin Komarov inode_nohighmem(inode); 42382cae269SKonstantin Komarov } else if (S_ISREG(mode)) { 42482cae269SKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; 42582cae269SKonstantin Komarov inode->i_op = &ntfs_file_inode_operations; 42682cae269SKonstantin Komarov inode->i_fop = &ntfs_file_operations; 42782cae269SKonstantin Komarov inode->i_mapping->a_ops = 42882cae269SKonstantin Komarov is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops; 42982cae269SKonstantin Komarov if (ino != MFT_REC_MFT) 43082cae269SKonstantin Komarov init_rwsem(&ni->file.run_lock); 43182cae269SKonstantin Komarov } else if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) || 43282cae269SKonstantin Komarov S_ISSOCK(mode)) { 43382cae269SKonstantin Komarov inode->i_op = &ntfs_special_inode_operations; 43482cae269SKonstantin Komarov init_special_inode(inode, mode, inode->i_rdev); 43582cae269SKonstantin Komarov } else if (fname && fname->home.low == cpu_to_le32(MFT_REC_EXTEND) && 43682cae269SKonstantin Komarov fname->home.seq == cpu_to_le16(MFT_REC_EXTEND)) { 437e8b8e97fSKari Argillander /* Records in $Extend are not a files or general directories. */ 43837a530bfSKonstantin Komarov inode->i_op = &ntfs_file_inode_operations; 43982cae269SKonstantin Komarov } else { 44082cae269SKonstantin Komarov err = -EINVAL; 44182cae269SKonstantin Komarov goto out; 44282cae269SKonstantin Komarov } 44382cae269SKonstantin Komarov 444564c97bdSKari Argillander if ((sbi->options->sys_immutable && 44582cae269SKonstantin Komarov (std5->fa & FILE_ATTRIBUTE_SYSTEM)) && 44682cae269SKonstantin Komarov !S_ISFIFO(mode) && !S_ISSOCK(mode) && !S_ISLNK(mode)) { 44782cae269SKonstantin Komarov inode->i_flags |= S_IMMUTABLE; 44882cae269SKonstantin Komarov } else { 44982cae269SKonstantin Komarov inode->i_flags &= ~S_IMMUTABLE; 45082cae269SKonstantin Komarov } 45182cae269SKonstantin Komarov 45282cae269SKonstantin Komarov inode->i_mode = mode; 45382cae269SKonstantin Komarov if (!(ni->ni_flags & NI_FLAG_EA)) { 454e8b8e97fSKari Argillander /* If no xattr then no security (stored in xattr). */ 45582cae269SKonstantin Komarov inode->i_flags |= S_NOSEC; 45682cae269SKonstantin Komarov } 45782cae269SKonstantin Komarov 45882cae269SKonstantin Komarov Ok: 45982cae269SKonstantin Komarov if (ino == MFT_REC_MFT && !sb->s_root) 46082cae269SKonstantin Komarov sbi->mft.ni = NULL; 46182cae269SKonstantin Komarov 46282cae269SKonstantin Komarov unlock_new_inode(inode); 46382cae269SKonstantin Komarov 46482cae269SKonstantin Komarov return inode; 46582cae269SKonstantin Komarov 46682cae269SKonstantin Komarov out: 46782cae269SKonstantin Komarov if (ino == MFT_REC_MFT && !sb->s_root) 46882cae269SKonstantin Komarov sbi->mft.ni = NULL; 46982cae269SKonstantin Komarov 47082cae269SKonstantin Komarov iget_failed(inode); 47182cae269SKonstantin Komarov return ERR_PTR(err); 47282cae269SKonstantin Komarov } 47382cae269SKonstantin Komarov 474e8b8e97fSKari Argillander /* 475e8b8e97fSKari Argillander * ntfs_test_inode 476e8b8e97fSKari Argillander * 477e8b8e97fSKari Argillander * Return: 1 if match. 478e8b8e97fSKari Argillander */ 47982cae269SKonstantin Komarov static int ntfs_test_inode(struct inode *inode, void *data) 48082cae269SKonstantin Komarov { 48182cae269SKonstantin Komarov struct MFT_REF *ref = data; 48282cae269SKonstantin Komarov 48382cae269SKonstantin Komarov return ino_get(ref) == inode->i_ino; 48482cae269SKonstantin Komarov } 48582cae269SKonstantin Komarov 48682cae269SKonstantin Komarov static int ntfs_set_inode(struct inode *inode, void *data) 48782cae269SKonstantin Komarov { 48882cae269SKonstantin Komarov const struct MFT_REF *ref = data; 48982cae269SKonstantin Komarov 49082cae269SKonstantin Komarov inode->i_ino = ino_get(ref); 49182cae269SKonstantin Komarov return 0; 49282cae269SKonstantin Komarov } 49382cae269SKonstantin Komarov 49482cae269SKonstantin Komarov struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref, 49582cae269SKonstantin Komarov const struct cpu_str *name) 49682cae269SKonstantin Komarov { 49782cae269SKonstantin Komarov struct inode *inode; 49882cae269SKonstantin Komarov 49982cae269SKonstantin Komarov inode = iget5_locked(sb, ino_get(ref), ntfs_test_inode, ntfs_set_inode, 50082cae269SKonstantin Komarov (void *)ref); 50182cae269SKonstantin Komarov if (unlikely(!inode)) 50282cae269SKonstantin Komarov return ERR_PTR(-ENOMEM); 50382cae269SKonstantin Komarov 50482cae269SKonstantin Komarov /* If this is a freshly allocated inode, need to read it now. */ 50582cae269SKonstantin Komarov if (inode->i_state & I_NEW) 50682cae269SKonstantin Komarov inode = ntfs_read_mft(inode, name, ref); 50782cae269SKonstantin Komarov else if (ref->seq != ntfs_i(inode)->mi.mrec->seq) { 508e8b8e97fSKari Argillander /* Inode overlaps? */ 509c12df45eSKonstantin Komarov _ntfs_bad_inode(inode); 51082cae269SKonstantin Komarov } 51182cae269SKonstantin Komarov 51282cae269SKonstantin Komarov return inode; 51382cae269SKonstantin Komarov } 51482cae269SKonstantin Komarov 51582cae269SKonstantin Komarov enum get_block_ctx { 51682cae269SKonstantin Komarov GET_BLOCK_GENERAL = 0, 51782cae269SKonstantin Komarov GET_BLOCK_WRITE_BEGIN = 1, 51882cae269SKonstantin Komarov GET_BLOCK_DIRECT_IO_R = 2, 51982cae269SKonstantin Komarov GET_BLOCK_DIRECT_IO_W = 3, 52082cae269SKonstantin Komarov GET_BLOCK_BMAP = 4, 52182cae269SKonstantin Komarov }; 52282cae269SKonstantin Komarov 52382cae269SKonstantin Komarov static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo, 52482cae269SKonstantin Komarov struct buffer_head *bh, int create, 52582cae269SKonstantin Komarov enum get_block_ctx ctx) 52682cae269SKonstantin Komarov { 52782cae269SKonstantin Komarov struct super_block *sb = inode->i_sb; 52882cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 52982cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 53082cae269SKonstantin Komarov struct page *page = bh->b_page; 53182cae269SKonstantin Komarov u8 cluster_bits = sbi->cluster_bits; 53282cae269SKonstantin Komarov u32 block_size = sb->s_blocksize; 53382cae269SKonstantin Komarov u64 bytes, lbo, valid; 53482cae269SKonstantin Komarov u32 off; 53582cae269SKonstantin Komarov int err; 53682cae269SKonstantin Komarov CLST vcn, lcn, len; 53782cae269SKonstantin Komarov bool new; 53882cae269SKonstantin Komarov 539e8b8e97fSKari Argillander /* Clear previous state. */ 54082cae269SKonstantin Komarov clear_buffer_new(bh); 54182cae269SKonstantin Komarov clear_buffer_uptodate(bh); 54282cae269SKonstantin Komarov 543e8b8e97fSKari Argillander /* Direct write uses 'create=0'. */ 54482cae269SKonstantin Komarov if (!create && vbo >= ni->i_valid) { 545e8b8e97fSKari Argillander /* Out of valid. */ 54682cae269SKonstantin Komarov return 0; 54782cae269SKonstantin Komarov } 54882cae269SKonstantin Komarov 54982cae269SKonstantin Komarov if (vbo >= inode->i_size) { 550e8b8e97fSKari Argillander /* Out of size. */ 55182cae269SKonstantin Komarov return 0; 55282cae269SKonstantin Komarov } 55382cae269SKonstantin Komarov 55482cae269SKonstantin Komarov if (is_resident(ni)) { 55582cae269SKonstantin Komarov ni_lock(ni); 55682cae269SKonstantin Komarov err = attr_data_read_resident(ni, page); 55782cae269SKonstantin Komarov ni_unlock(ni); 55882cae269SKonstantin Komarov 55982cae269SKonstantin Komarov if (!err) 56082cae269SKonstantin Komarov set_buffer_uptodate(bh); 56182cae269SKonstantin Komarov bh->b_size = block_size; 56282cae269SKonstantin Komarov return err; 56382cae269SKonstantin Komarov } 56482cae269SKonstantin Komarov 56582cae269SKonstantin Komarov vcn = vbo >> cluster_bits; 56682cae269SKonstantin Komarov off = vbo & sbi->cluster_mask; 56782cae269SKonstantin Komarov new = false; 56882cae269SKonstantin Komarov 56982cae269SKonstantin Komarov err = attr_data_get_block(ni, vcn, 1, &lcn, &len, create ? &new : NULL); 57082cae269SKonstantin Komarov if (err) 57182cae269SKonstantin Komarov goto out; 57282cae269SKonstantin Komarov 57382cae269SKonstantin Komarov if (!len) 57482cae269SKonstantin Komarov return 0; 57582cae269SKonstantin Komarov 57682cae269SKonstantin Komarov bytes = ((u64)len << cluster_bits) - off; 57782cae269SKonstantin Komarov 57882cae269SKonstantin Komarov if (lcn == SPARSE_LCN) { 57982cae269SKonstantin Komarov if (!create) { 58082cae269SKonstantin Komarov if (bh->b_size > bytes) 58182cae269SKonstantin Komarov bh->b_size = bytes; 58282cae269SKonstantin Komarov return 0; 58382cae269SKonstantin Komarov } 58482cae269SKonstantin Komarov WARN_ON(1); 58582cae269SKonstantin Komarov } 58682cae269SKonstantin Komarov 58782cae269SKonstantin Komarov if (new) { 58882cae269SKonstantin Komarov set_buffer_new(bh); 58982cae269SKonstantin Komarov if ((len << cluster_bits) > block_size) 59082cae269SKonstantin Komarov ntfs_sparse_cluster(inode, page, vcn, len); 59182cae269SKonstantin Komarov } 59282cae269SKonstantin Komarov 59382cae269SKonstantin Komarov lbo = ((u64)lcn << cluster_bits) + off; 59482cae269SKonstantin Komarov 59582cae269SKonstantin Komarov set_buffer_mapped(bh); 59682cae269SKonstantin Komarov bh->b_bdev = sb->s_bdev; 59782cae269SKonstantin Komarov bh->b_blocknr = lbo >> sb->s_blocksize_bits; 59882cae269SKonstantin Komarov 59982cae269SKonstantin Komarov valid = ni->i_valid; 60082cae269SKonstantin Komarov 60182cae269SKonstantin Komarov if (ctx == GET_BLOCK_DIRECT_IO_W) { 602e8b8e97fSKari Argillander /* ntfs_direct_IO will update ni->i_valid. */ 60382cae269SKonstantin Komarov if (vbo >= valid) 60482cae269SKonstantin Komarov set_buffer_new(bh); 60582cae269SKonstantin Komarov } else if (create) { 606d3624466SKonstantin Komarov /* Normal write. */ 60782cae269SKonstantin Komarov if (bytes > bh->b_size) 60882cae269SKonstantin Komarov bytes = bh->b_size; 60982cae269SKonstantin Komarov 61082cae269SKonstantin Komarov if (vbo >= valid) 61182cae269SKonstantin Komarov set_buffer_new(bh); 61282cae269SKonstantin Komarov 61382cae269SKonstantin Komarov if (vbo + bytes > valid) { 61482cae269SKonstantin Komarov ni->i_valid = vbo + bytes; 61582cae269SKonstantin Komarov mark_inode_dirty(inode); 61682cae269SKonstantin Komarov } 61782cae269SKonstantin Komarov } else if (vbo >= valid) { 618e8b8e97fSKari Argillander /* Read out of valid data. */ 619e8b8e97fSKari Argillander /* Should never be here 'cause already checked. */ 62082cae269SKonstantin Komarov clear_buffer_mapped(bh); 62182cae269SKonstantin Komarov } else if (vbo + bytes <= valid) { 622e8b8e97fSKari Argillander /* Normal read. */ 62382cae269SKonstantin Komarov } else if (vbo + block_size <= valid) { 624e8b8e97fSKari Argillander /* Normal short read. */ 62582cae269SKonstantin Komarov bytes = block_size; 62682cae269SKonstantin Komarov } else { 62782cae269SKonstantin Komarov /* 628e8b8e97fSKari Argillander * Read across valid size: vbo < valid && valid < vbo + block_size 62982cae269SKonstantin Komarov */ 63082cae269SKonstantin Komarov bytes = block_size; 63182cae269SKonstantin Komarov 63282cae269SKonstantin Komarov if (page) { 63382cae269SKonstantin Komarov u32 voff = valid - vbo; 63482cae269SKonstantin Komarov 63582cae269SKonstantin Komarov bh->b_size = block_size; 63682cae269SKonstantin Komarov off = vbo & (PAGE_SIZE - 1); 63782cae269SKonstantin Komarov set_bh_page(bh, page, off); 6381420c4a5SBart Van Assche ll_rw_block(REQ_OP_READ, 1, &bh); 63982cae269SKonstantin Komarov wait_on_buffer(bh); 64082cae269SKonstantin Komarov if (!buffer_uptodate(bh)) { 64182cae269SKonstantin Komarov err = -EIO; 64282cae269SKonstantin Komarov goto out; 64382cae269SKonstantin Komarov } 64482cae269SKonstantin Komarov zero_user_segment(page, off + voff, off + block_size); 64582cae269SKonstantin Komarov } 64682cae269SKonstantin Komarov } 64782cae269SKonstantin Komarov 64882cae269SKonstantin Komarov if (bh->b_size > bytes) 64982cae269SKonstantin Komarov bh->b_size = bytes; 65082cae269SKonstantin Komarov 65182cae269SKonstantin Komarov #ifndef __LP64__ 65282cae269SKonstantin Komarov if (ctx == GET_BLOCK_DIRECT_IO_W || ctx == GET_BLOCK_DIRECT_IO_R) { 65382cae269SKonstantin Komarov static_assert(sizeof(size_t) < sizeof(loff_t)); 65482cae269SKonstantin Komarov if (bytes > 0x40000000u) 65582cae269SKonstantin Komarov bh->b_size = 0x40000000u; 65682cae269SKonstantin Komarov } 65782cae269SKonstantin Komarov #endif 65882cae269SKonstantin Komarov 65982cae269SKonstantin Komarov return 0; 66082cae269SKonstantin Komarov 66182cae269SKonstantin Komarov out: 66282cae269SKonstantin Komarov return err; 66382cae269SKonstantin Komarov } 66482cae269SKonstantin Komarov 66582cae269SKonstantin Komarov int ntfs_get_block(struct inode *inode, sector_t vbn, 66682cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 66782cae269SKonstantin Komarov { 66882cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, (u64)vbn << inode->i_blkbits, 66982cae269SKonstantin Komarov bh_result, create, GET_BLOCK_GENERAL); 67082cae269SKonstantin Komarov } 67182cae269SKonstantin Komarov 67282cae269SKonstantin Komarov static int ntfs_get_block_bmap(struct inode *inode, sector_t vsn, 67382cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 67482cae269SKonstantin Komarov { 67582cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, 67682cae269SKonstantin Komarov (u64)vsn << inode->i_sb->s_blocksize_bits, 67782cae269SKonstantin Komarov bh_result, create, GET_BLOCK_BMAP); 67882cae269SKonstantin Komarov } 67982cae269SKonstantin Komarov 68082cae269SKonstantin Komarov static sector_t ntfs_bmap(struct address_space *mapping, sector_t block) 68182cae269SKonstantin Komarov { 68282cae269SKonstantin Komarov return generic_block_bmap(mapping, block, ntfs_get_block_bmap); 68382cae269SKonstantin Komarov } 68482cae269SKonstantin Komarov 685f132ab7dSMatthew Wilcox (Oracle) static int ntfs_read_folio(struct file *file, struct folio *folio) 68682cae269SKonstantin Komarov { 687f132ab7dSMatthew Wilcox (Oracle) struct page *page = &folio->page; 68882cae269SKonstantin Komarov int err; 68982cae269SKonstantin Komarov struct address_space *mapping = page->mapping; 69082cae269SKonstantin Komarov struct inode *inode = mapping->host; 69182cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 69282cae269SKonstantin Komarov 69382cae269SKonstantin Komarov if (is_resident(ni)) { 69482cae269SKonstantin Komarov ni_lock(ni); 69582cae269SKonstantin Komarov err = attr_data_read_resident(ni, page); 69682cae269SKonstantin Komarov ni_unlock(ni); 69782cae269SKonstantin Komarov if (err != E_NTFS_NONRESIDENT) { 69882cae269SKonstantin Komarov unlock_page(page); 69982cae269SKonstantin Komarov return err; 70082cae269SKonstantin Komarov } 70182cae269SKonstantin Komarov } 70282cae269SKonstantin Komarov 70382cae269SKonstantin Komarov if (is_compressed(ni)) { 70482cae269SKonstantin Komarov ni_lock(ni); 70582cae269SKonstantin Komarov err = ni_readpage_cmpr(ni, page); 70682cae269SKonstantin Komarov ni_unlock(ni); 70782cae269SKonstantin Komarov return err; 70882cae269SKonstantin Komarov } 70982cae269SKonstantin Komarov 710e8b8e97fSKari Argillander /* Normal + sparse files. */ 711f132ab7dSMatthew Wilcox (Oracle) return mpage_read_folio(folio, ntfs_get_block); 71282cae269SKonstantin Komarov } 71382cae269SKonstantin Komarov 71482cae269SKonstantin Komarov static void ntfs_readahead(struct readahead_control *rac) 71582cae269SKonstantin Komarov { 71682cae269SKonstantin Komarov struct address_space *mapping = rac->mapping; 71782cae269SKonstantin Komarov struct inode *inode = mapping->host; 71882cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 71982cae269SKonstantin Komarov u64 valid; 72082cae269SKonstantin Komarov loff_t pos; 72182cae269SKonstantin Komarov 72282cae269SKonstantin Komarov if (is_resident(ni)) { 723e8b8e97fSKari Argillander /* No readahead for resident. */ 72482cae269SKonstantin Komarov return; 72582cae269SKonstantin Komarov } 72682cae269SKonstantin Komarov 72782cae269SKonstantin Komarov if (is_compressed(ni)) { 728e8b8e97fSKari Argillander /* No readahead for compressed. */ 72982cae269SKonstantin Komarov return; 73082cae269SKonstantin Komarov } 73182cae269SKonstantin Komarov 73282cae269SKonstantin Komarov valid = ni->i_valid; 73382cae269SKonstantin Komarov pos = readahead_pos(rac); 73482cae269SKonstantin Komarov 73582cae269SKonstantin Komarov if (valid < i_size_read(inode) && pos <= valid && 73682cae269SKonstantin Komarov valid < pos + readahead_length(rac)) { 737e8b8e97fSKari Argillander /* Range cross 'valid'. Read it page by page. */ 73882cae269SKonstantin Komarov return; 73982cae269SKonstantin Komarov } 74082cae269SKonstantin Komarov 74182cae269SKonstantin Komarov mpage_readahead(rac, ntfs_get_block); 74282cae269SKonstantin Komarov } 74382cae269SKonstantin Komarov 74482cae269SKonstantin Komarov static int ntfs_get_block_direct_IO_R(struct inode *inode, sector_t iblock, 74582cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 74682cae269SKonstantin Komarov { 74782cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, (u64)iblock << inode->i_blkbits, 74882cae269SKonstantin Komarov bh_result, create, GET_BLOCK_DIRECT_IO_R); 74982cae269SKonstantin Komarov } 75082cae269SKonstantin Komarov 75182cae269SKonstantin Komarov static int ntfs_get_block_direct_IO_W(struct inode *inode, sector_t iblock, 75282cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 75382cae269SKonstantin Komarov { 75482cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, (u64)iblock << inode->i_blkbits, 75582cae269SKonstantin Komarov bh_result, create, GET_BLOCK_DIRECT_IO_W); 75682cae269SKonstantin Komarov } 75782cae269SKonstantin Komarov 75882cae269SKonstantin Komarov static ssize_t ntfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 75982cae269SKonstantin Komarov { 76082cae269SKonstantin Komarov struct file *file = iocb->ki_filp; 76182cae269SKonstantin Komarov struct address_space *mapping = file->f_mapping; 76282cae269SKonstantin Komarov struct inode *inode = mapping->host; 76382cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 76482cae269SKonstantin Komarov loff_t vbo = iocb->ki_pos; 76582cae269SKonstantin Komarov loff_t end; 76682cae269SKonstantin Komarov int wr = iov_iter_rw(iter) & WRITE; 76752e00ea6SKonstantin Komarov size_t iter_count = iov_iter_count(iter); 76882cae269SKonstantin Komarov loff_t valid; 76982cae269SKonstantin Komarov ssize_t ret; 77082cae269SKonstantin Komarov 77182cae269SKonstantin Komarov if (is_resident(ni)) { 772e8b8e97fSKari Argillander /* Switch to buffered write. */ 77382cae269SKonstantin Komarov ret = 0; 77482cae269SKonstantin Komarov goto out; 77582cae269SKonstantin Komarov } 77682cae269SKonstantin Komarov 77782cae269SKonstantin Komarov ret = blockdev_direct_IO(iocb, inode, iter, 77882cae269SKonstantin Komarov wr ? ntfs_get_block_direct_IO_W 77982cae269SKonstantin Komarov : ntfs_get_block_direct_IO_R); 78082cae269SKonstantin Komarov 78152e00ea6SKonstantin Komarov if (ret > 0) 78252e00ea6SKonstantin Komarov end = vbo + ret; 78352e00ea6SKonstantin Komarov else if (wr && ret == -EIOCBQUEUED) 78452e00ea6SKonstantin Komarov end = vbo + iter_count; 78552e00ea6SKonstantin Komarov else 78682cae269SKonstantin Komarov goto out; 78782cae269SKonstantin Komarov 78882cae269SKonstantin Komarov valid = ni->i_valid; 78982cae269SKonstantin Komarov if (wr) { 79082cae269SKonstantin Komarov if (end > valid && !S_ISBLK(inode->i_mode)) { 79182cae269SKonstantin Komarov ni->i_valid = end; 79282cae269SKonstantin Komarov mark_inode_dirty(inode); 79382cae269SKonstantin Komarov } 79482cae269SKonstantin Komarov } else if (vbo < valid && valid < end) { 795e8b8e97fSKari Argillander /* Fix page. */ 79682cae269SKonstantin Komarov iov_iter_revert(iter, end - valid); 79782cae269SKonstantin Komarov iov_iter_zero(end - valid, iter); 79882cae269SKonstantin Komarov } 79982cae269SKonstantin Komarov 80082cae269SKonstantin Komarov out: 80182cae269SKonstantin Komarov return ret; 80282cae269SKonstantin Komarov } 80382cae269SKonstantin Komarov 80482cae269SKonstantin Komarov int ntfs_set_size(struct inode *inode, u64 new_size) 80582cae269SKonstantin Komarov { 80682cae269SKonstantin Komarov struct super_block *sb = inode->i_sb; 80782cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 80882cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 80982cae269SKonstantin Komarov int err; 81082cae269SKonstantin Komarov 811e8b8e97fSKari Argillander /* Check for maximum file size. */ 81282cae269SKonstantin Komarov if (is_sparsed(ni) || is_compressed(ni)) { 81382cae269SKonstantin Komarov if (new_size > sbi->maxbytes_sparse) { 81482cae269SKonstantin Komarov err = -EFBIG; 81582cae269SKonstantin Komarov goto out; 81682cae269SKonstantin Komarov } 81782cae269SKonstantin Komarov } else if (new_size > sbi->maxbytes) { 81882cae269SKonstantin Komarov err = -EFBIG; 81982cae269SKonstantin Komarov goto out; 82082cae269SKonstantin Komarov } 82182cae269SKonstantin Komarov 82282cae269SKonstantin Komarov ni_lock(ni); 82382cae269SKonstantin Komarov down_write(&ni->file.run_lock); 82482cae269SKonstantin Komarov 82582cae269SKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size, 82682cae269SKonstantin Komarov &ni->i_valid, true, NULL); 82782cae269SKonstantin Komarov 82882cae269SKonstantin Komarov up_write(&ni->file.run_lock); 82982cae269SKonstantin Komarov ni_unlock(ni); 83082cae269SKonstantin Komarov 83182cae269SKonstantin Komarov mark_inode_dirty(inode); 83282cae269SKonstantin Komarov 83382cae269SKonstantin Komarov out: 83482cae269SKonstantin Komarov return err; 83582cae269SKonstantin Komarov } 83682cae269SKonstantin Komarov 83782cae269SKonstantin Komarov static int ntfs_writepage(struct page *page, struct writeback_control *wbc) 83882cae269SKonstantin Komarov { 83982cae269SKonstantin Komarov struct address_space *mapping = page->mapping; 84082cae269SKonstantin Komarov struct inode *inode = mapping->host; 84182cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 84282cae269SKonstantin Komarov int err; 84382cae269SKonstantin Komarov 84482cae269SKonstantin Komarov if (is_resident(ni)) { 84582cae269SKonstantin Komarov ni_lock(ni); 84682cae269SKonstantin Komarov err = attr_data_write_resident(ni, page); 84782cae269SKonstantin Komarov ni_unlock(ni); 84882cae269SKonstantin Komarov if (err != E_NTFS_NONRESIDENT) { 84982cae269SKonstantin Komarov unlock_page(page); 85082cae269SKonstantin Komarov return err; 85182cae269SKonstantin Komarov } 85282cae269SKonstantin Komarov } 85382cae269SKonstantin Komarov 85482cae269SKonstantin Komarov return block_write_full_page(page, ntfs_get_block, wbc); 85582cae269SKonstantin Komarov } 85682cae269SKonstantin Komarov 85782cae269SKonstantin Komarov static int ntfs_writepages(struct address_space *mapping, 85882cae269SKonstantin Komarov struct writeback_control *wbc) 85982cae269SKonstantin Komarov { 860e8b8e97fSKari Argillander /* Redirect call to 'ntfs_writepage' for resident files. */ 86191397101SChristoph Hellwig if (is_resident(ntfs_i(mapping->host))) 86291397101SChristoph Hellwig return generic_writepages(mapping, wbc); 86391397101SChristoph Hellwig return mpage_writepages(mapping, wbc, ntfs_get_block); 86482cae269SKonstantin Komarov } 86582cae269SKonstantin Komarov 86682cae269SKonstantin Komarov static int ntfs_get_block_write_begin(struct inode *inode, sector_t vbn, 86782cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 86882cae269SKonstantin Komarov { 86982cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, (u64)vbn << inode->i_blkbits, 87082cae269SKonstantin Komarov bh_result, create, GET_BLOCK_WRITE_BEGIN); 87182cae269SKonstantin Komarov } 87282cae269SKonstantin Komarov 87344ab23b9SMatthew Wilcox (Oracle) int ntfs_write_begin(struct file *file, struct address_space *mapping, 87444ab23b9SMatthew Wilcox (Oracle) loff_t pos, u32 len, struct page **pagep, void **fsdata) 87582cae269SKonstantin Komarov { 87682cae269SKonstantin Komarov int err; 87782cae269SKonstantin Komarov struct inode *inode = mapping->host; 87882cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 87982cae269SKonstantin Komarov 88082cae269SKonstantin Komarov *pagep = NULL; 88182cae269SKonstantin Komarov if (is_resident(ni)) { 88282cae269SKonstantin Komarov struct page *page = grab_cache_page_write_begin( 883b7446e7cSMatthew Wilcox (Oracle) mapping, pos >> PAGE_SHIFT); 88482cae269SKonstantin Komarov 88582cae269SKonstantin Komarov if (!page) { 88682cae269SKonstantin Komarov err = -ENOMEM; 88782cae269SKonstantin Komarov goto out; 88882cae269SKonstantin Komarov } 88982cae269SKonstantin Komarov 89082cae269SKonstantin Komarov ni_lock(ni); 89182cae269SKonstantin Komarov err = attr_data_read_resident(ni, page); 89282cae269SKonstantin Komarov ni_unlock(ni); 89382cae269SKonstantin Komarov 89482cae269SKonstantin Komarov if (!err) { 89582cae269SKonstantin Komarov *pagep = page; 89682cae269SKonstantin Komarov goto out; 89782cae269SKonstantin Komarov } 89882cae269SKonstantin Komarov unlock_page(page); 89982cae269SKonstantin Komarov put_page(page); 90082cae269SKonstantin Komarov 90182cae269SKonstantin Komarov if (err != E_NTFS_NONRESIDENT) 90282cae269SKonstantin Komarov goto out; 90382cae269SKonstantin Komarov } 90482cae269SKonstantin Komarov 905b3992d1eSMatthew Wilcox (Oracle) err = block_write_begin(mapping, pos, len, pagep, 90682cae269SKonstantin Komarov ntfs_get_block_write_begin); 90782cae269SKonstantin Komarov 90882cae269SKonstantin Komarov out: 90982cae269SKonstantin Komarov return err; 91082cae269SKonstantin Komarov } 91182cae269SKonstantin Komarov 912e8b8e97fSKari Argillander /* 913e8b8e97fSKari Argillander * ntfs_write_end - Address_space_operations::write_end. 914e8b8e97fSKari Argillander */ 91544ab23b9SMatthew Wilcox (Oracle) int ntfs_write_end(struct file *file, struct address_space *mapping, 91682cae269SKonstantin Komarov loff_t pos, u32 len, u32 copied, struct page *page, 91782cae269SKonstantin Komarov void *fsdata) 91882cae269SKonstantin Komarov { 91982cae269SKonstantin Komarov struct inode *inode = mapping->host; 92082cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 92182cae269SKonstantin Komarov u64 valid = ni->i_valid; 92282cae269SKonstantin Komarov bool dirty = false; 92382cae269SKonstantin Komarov int err; 92482cae269SKonstantin Komarov 92582cae269SKonstantin Komarov if (is_resident(ni)) { 92682cae269SKonstantin Komarov ni_lock(ni); 92782cae269SKonstantin Komarov err = attr_data_write_resident(ni, page); 92882cae269SKonstantin Komarov ni_unlock(ni); 92982cae269SKonstantin Komarov if (!err) { 93082cae269SKonstantin Komarov dirty = true; 931e8b8e97fSKari Argillander /* Clear any buffers in page. */ 93282cae269SKonstantin Komarov if (page_has_buffers(page)) { 93382cae269SKonstantin Komarov struct buffer_head *head, *bh; 93482cae269SKonstantin Komarov 93582cae269SKonstantin Komarov bh = head = page_buffers(page); 93682cae269SKonstantin Komarov do { 93782cae269SKonstantin Komarov clear_buffer_dirty(bh); 93882cae269SKonstantin Komarov clear_buffer_mapped(bh); 93982cae269SKonstantin Komarov set_buffer_uptodate(bh); 94082cae269SKonstantin Komarov } while (head != (bh = bh->b_this_page)); 94182cae269SKonstantin Komarov } 94282cae269SKonstantin Komarov SetPageUptodate(page); 94382cae269SKonstantin Komarov err = copied; 94482cae269SKonstantin Komarov } 94582cae269SKonstantin Komarov unlock_page(page); 94682cae269SKonstantin Komarov put_page(page); 94782cae269SKonstantin Komarov } else { 94882cae269SKonstantin Komarov err = generic_write_end(file, mapping, pos, len, copied, page, 94982cae269SKonstantin Komarov fsdata); 95082cae269SKonstantin Komarov } 95182cae269SKonstantin Komarov 95282cae269SKonstantin Komarov if (err >= 0) { 95382cae269SKonstantin Komarov if (!(ni->std_fa & FILE_ATTRIBUTE_ARCHIVE)) { 95482cae269SKonstantin Komarov inode->i_ctime = inode->i_mtime = current_time(inode); 95582cae269SKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE; 95682cae269SKonstantin Komarov dirty = true; 95782cae269SKonstantin Komarov } 95882cae269SKonstantin Komarov 95982cae269SKonstantin Komarov if (valid != ni->i_valid) { 960e8b8e97fSKari Argillander /* ni->i_valid is changed in ntfs_get_block_vbo. */ 96182cae269SKonstantin Komarov dirty = true; 96282cae269SKonstantin Komarov } 96382cae269SKonstantin Komarov 96482cae269SKonstantin Komarov if (dirty) 96582cae269SKonstantin Komarov mark_inode_dirty(inode); 96682cae269SKonstantin Komarov } 96782cae269SKonstantin Komarov 96882cae269SKonstantin Komarov return err; 96982cae269SKonstantin Komarov } 97082cae269SKonstantin Komarov 97182cae269SKonstantin Komarov int reset_log_file(struct inode *inode) 97282cae269SKonstantin Komarov { 97382cae269SKonstantin Komarov int err; 97482cae269SKonstantin Komarov loff_t pos = 0; 97582cae269SKonstantin Komarov u32 log_size = inode->i_size; 97682cae269SKonstantin Komarov struct address_space *mapping = inode->i_mapping; 97782cae269SKonstantin Komarov 97882cae269SKonstantin Komarov for (;;) { 97982cae269SKonstantin Komarov u32 len; 98082cae269SKonstantin Komarov void *kaddr; 98182cae269SKonstantin Komarov struct page *page; 98282cae269SKonstantin Komarov 98382cae269SKonstantin Komarov len = pos + PAGE_SIZE > log_size ? (log_size - pos) : PAGE_SIZE; 98482cae269SKonstantin Komarov 985b3992d1eSMatthew Wilcox (Oracle) err = block_write_begin(mapping, pos, len, &page, 98682cae269SKonstantin Komarov ntfs_get_block_write_begin); 98782cae269SKonstantin Komarov if (err) 98882cae269SKonstantin Komarov goto out; 98982cae269SKonstantin Komarov 99082cae269SKonstantin Komarov kaddr = kmap_atomic(page); 99182cae269SKonstantin Komarov memset(kaddr, -1, len); 99282cae269SKonstantin Komarov kunmap_atomic(kaddr); 99382cae269SKonstantin Komarov flush_dcache_page(page); 99482cae269SKonstantin Komarov 99582cae269SKonstantin Komarov err = block_write_end(NULL, mapping, pos, len, len, page, NULL); 99682cae269SKonstantin Komarov if (err < 0) 99782cae269SKonstantin Komarov goto out; 99882cae269SKonstantin Komarov pos += len; 99982cae269SKonstantin Komarov 100082cae269SKonstantin Komarov if (pos >= log_size) 100182cae269SKonstantin Komarov break; 100282cae269SKonstantin Komarov balance_dirty_pages_ratelimited(mapping); 100382cae269SKonstantin Komarov } 100482cae269SKonstantin Komarov out: 100582cae269SKonstantin Komarov mark_inode_dirty_sync(inode); 100682cae269SKonstantin Komarov 100782cae269SKonstantin Komarov return err; 100882cae269SKonstantin Komarov } 100982cae269SKonstantin Komarov 101082cae269SKonstantin Komarov int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc) 101182cae269SKonstantin Komarov { 101282cae269SKonstantin Komarov return _ni_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); 101382cae269SKonstantin Komarov } 101482cae269SKonstantin Komarov 101582cae269SKonstantin Komarov int ntfs_sync_inode(struct inode *inode) 101682cae269SKonstantin Komarov { 101782cae269SKonstantin Komarov return _ni_write_inode(inode, 1); 101882cae269SKonstantin Komarov } 101982cae269SKonstantin Komarov 102082cae269SKonstantin Komarov /* 1021e8b8e97fSKari Argillander * writeback_inode - Helper function for ntfs_flush_inodes(). 1022e8b8e97fSKari Argillander * 1023e8b8e97fSKari Argillander * This writes both the inode and the file data blocks, waiting 1024e8b8e97fSKari Argillander * for in flight data blocks before the start of the call. It 1025e8b8e97fSKari Argillander * does not wait for any io started during the call. 102682cae269SKonstantin Komarov */ 102782cae269SKonstantin Komarov static int writeback_inode(struct inode *inode) 102882cae269SKonstantin Komarov { 102982cae269SKonstantin Komarov int ret = sync_inode_metadata(inode, 0); 103082cae269SKonstantin Komarov 103182cae269SKonstantin Komarov if (!ret) 103282cae269SKonstantin Komarov ret = filemap_fdatawrite(inode->i_mapping); 103382cae269SKonstantin Komarov return ret; 103482cae269SKonstantin Komarov } 103582cae269SKonstantin Komarov 103682cae269SKonstantin Komarov /* 1037e8b8e97fSKari Argillander * ntfs_flush_inodes 1038e8b8e97fSKari Argillander * 1039e8b8e97fSKari Argillander * Write data and metadata corresponding to i1 and i2. The io is 104082cae269SKonstantin Komarov * started but we do not wait for any of it to finish. 104182cae269SKonstantin Komarov * 1042e8b8e97fSKari Argillander * filemap_flush() is used for the block device, so if there is a dirty 104382cae269SKonstantin Komarov * page for a block already in flight, we will not wait and start the 1044e8b8e97fSKari Argillander * io over again. 104582cae269SKonstantin Komarov */ 104682cae269SKonstantin Komarov int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, 104782cae269SKonstantin Komarov struct inode *i2) 104882cae269SKonstantin Komarov { 104982cae269SKonstantin Komarov int ret = 0; 105082cae269SKonstantin Komarov 105182cae269SKonstantin Komarov if (i1) 105282cae269SKonstantin Komarov ret = writeback_inode(i1); 105382cae269SKonstantin Komarov if (!ret && i2) 105482cae269SKonstantin Komarov ret = writeback_inode(i2); 105582cae269SKonstantin Komarov if (!ret) 1056680e667bSChristoph Hellwig ret = sync_blockdev_nowait(sb->s_bdev); 105782cae269SKonstantin Komarov return ret; 105882cae269SKonstantin Komarov } 105982cae269SKonstantin Komarov 106082cae269SKonstantin Komarov int inode_write_data(struct inode *inode, const void *data, size_t bytes) 106182cae269SKonstantin Komarov { 106282cae269SKonstantin Komarov pgoff_t idx; 106382cae269SKonstantin Komarov 1064e8b8e97fSKari Argillander /* Write non resident data. */ 106582cae269SKonstantin Komarov for (idx = 0; bytes; idx++) { 106682cae269SKonstantin Komarov size_t op = bytes > PAGE_SIZE ? PAGE_SIZE : bytes; 106782cae269SKonstantin Komarov struct page *page = ntfs_map_page(inode->i_mapping, idx); 106882cae269SKonstantin Komarov 106982cae269SKonstantin Komarov if (IS_ERR(page)) 107082cae269SKonstantin Komarov return PTR_ERR(page); 107182cae269SKonstantin Komarov 107282cae269SKonstantin Komarov lock_page(page); 107382cae269SKonstantin Komarov WARN_ON(!PageUptodate(page)); 107482cae269SKonstantin Komarov ClearPageUptodate(page); 107582cae269SKonstantin Komarov 107682cae269SKonstantin Komarov memcpy(page_address(page), data, op); 107782cae269SKonstantin Komarov 107882cae269SKonstantin Komarov flush_dcache_page(page); 107982cae269SKonstantin Komarov SetPageUptodate(page); 108082cae269SKonstantin Komarov unlock_page(page); 108182cae269SKonstantin Komarov 108282cae269SKonstantin Komarov ntfs_unmap_page(page); 108382cae269SKonstantin Komarov 108482cae269SKonstantin Komarov bytes -= op; 108582cae269SKonstantin Komarov data = Add2Ptr(data, PAGE_SIZE); 108682cae269SKonstantin Komarov } 108782cae269SKonstantin Komarov return 0; 108882cae269SKonstantin Komarov } 108982cae269SKonstantin Komarov 109082cae269SKonstantin Komarov /* 1091e8b8e97fSKari Argillander * ntfs_reparse_bytes 1092e8b8e97fSKari Argillander * 1093d3624466SKonstantin Komarov * Number of bytes for REPARSE_DATA_BUFFER(IO_REPARSE_TAG_SYMLINK) 1094e8b8e97fSKari Argillander * for unicode string of @uni_len length. 109582cae269SKonstantin Komarov */ 109682cae269SKonstantin Komarov static inline u32 ntfs_reparse_bytes(u32 uni_len) 109782cae269SKonstantin Komarov { 1098e8b8e97fSKari Argillander /* Header + unicode string + decorated unicode string. */ 109982cae269SKonstantin Komarov return sizeof(short) * (2 * uni_len + 4) + 110082cae269SKonstantin Komarov offsetof(struct REPARSE_DATA_BUFFER, 110182cae269SKonstantin Komarov SymbolicLinkReparseBuffer.PathBuffer); 110282cae269SKonstantin Komarov } 110382cae269SKonstantin Komarov 110482cae269SKonstantin Komarov static struct REPARSE_DATA_BUFFER * 110582cae269SKonstantin Komarov ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname, 110682cae269SKonstantin Komarov u32 size, u16 *nsize) 110782cae269SKonstantin Komarov { 110882cae269SKonstantin Komarov int i, err; 110982cae269SKonstantin Komarov struct REPARSE_DATA_BUFFER *rp; 111082cae269SKonstantin Komarov __le16 *rp_name; 111182cae269SKonstantin Komarov typeof(rp->SymbolicLinkReparseBuffer) *rs; 111282cae269SKonstantin Komarov 1113195c52bdSKari Argillander rp = kzalloc(ntfs_reparse_bytes(2 * size + 2), GFP_NOFS); 111482cae269SKonstantin Komarov if (!rp) 111582cae269SKonstantin Komarov return ERR_PTR(-ENOMEM); 111682cae269SKonstantin Komarov 111782cae269SKonstantin Komarov rs = &rp->SymbolicLinkReparseBuffer; 111882cae269SKonstantin Komarov rp_name = rs->PathBuffer; 111982cae269SKonstantin Komarov 1120e8b8e97fSKari Argillander /* Convert link name to UTF-16. */ 112182cae269SKonstantin Komarov err = ntfs_nls_to_utf16(sbi, symname, size, 112282cae269SKonstantin Komarov (struct cpu_str *)(rp_name - 1), 2 * size, 112382cae269SKonstantin Komarov UTF16_LITTLE_ENDIAN); 112482cae269SKonstantin Komarov if (err < 0) 112582cae269SKonstantin Komarov goto out; 112682cae269SKonstantin Komarov 1127e8b8e97fSKari Argillander /* err = the length of unicode name of symlink. */ 112882cae269SKonstantin Komarov *nsize = ntfs_reparse_bytes(err); 112982cae269SKonstantin Komarov 113082cae269SKonstantin Komarov if (*nsize > sbi->reparse.max_size) { 113182cae269SKonstantin Komarov err = -EFBIG; 113282cae269SKonstantin Komarov goto out; 113382cae269SKonstantin Komarov } 113482cae269SKonstantin Komarov 1135e8b8e97fSKari Argillander /* Translate Linux '/' into Windows '\'. */ 113682cae269SKonstantin Komarov for (i = 0; i < err; i++) { 113782cae269SKonstantin Komarov if (rp_name[i] == cpu_to_le16('/')) 113882cae269SKonstantin Komarov rp_name[i] = cpu_to_le16('\\'); 113982cae269SKonstantin Komarov } 114082cae269SKonstantin Komarov 114182cae269SKonstantin Komarov rp->ReparseTag = IO_REPARSE_TAG_SYMLINK; 114282cae269SKonstantin Komarov rp->ReparseDataLength = 114382cae269SKonstantin Komarov cpu_to_le16(*nsize - offsetof(struct REPARSE_DATA_BUFFER, 114482cae269SKonstantin Komarov SymbolicLinkReparseBuffer)); 114582cae269SKonstantin Komarov 1146e8b8e97fSKari Argillander /* PrintName + SubstituteName. */ 114782cae269SKonstantin Komarov rs->SubstituteNameOffset = cpu_to_le16(sizeof(short) * err); 114882cae269SKonstantin Komarov rs->SubstituteNameLength = cpu_to_le16(sizeof(short) * err + 8); 114982cae269SKonstantin Komarov rs->PrintNameLength = rs->SubstituteNameOffset; 115082cae269SKonstantin Komarov 115182cae269SKonstantin Komarov /* 1152e8b8e97fSKari Argillander * TODO: Use relative path if possible to allow Windows to 1153e8b8e97fSKari Argillander * parse this path. 1154e8b8e97fSKari Argillander * 0-absolute path 1- relative path (SYMLINK_FLAG_RELATIVE). 115582cae269SKonstantin Komarov */ 115682cae269SKonstantin Komarov rs->Flags = 0; 115782cae269SKonstantin Komarov 115882cae269SKonstantin Komarov memmove(rp_name + err + 4, rp_name, sizeof(short) * err); 115982cae269SKonstantin Komarov 1160e8b8e97fSKari Argillander /* Decorate SubstituteName. */ 116182cae269SKonstantin Komarov rp_name += err; 116282cae269SKonstantin Komarov rp_name[0] = cpu_to_le16('\\'); 116382cae269SKonstantin Komarov rp_name[1] = cpu_to_le16('?'); 116482cae269SKonstantin Komarov rp_name[2] = cpu_to_le16('?'); 116582cae269SKonstantin Komarov rp_name[3] = cpu_to_le16('\\'); 116682cae269SKonstantin Komarov 116782cae269SKonstantin Komarov return rp; 116882cae269SKonstantin Komarov out: 1169195c52bdSKari Argillander kfree(rp); 117082cae269SKonstantin Komarov return ERR_PTR(err); 117182cae269SKonstantin Komarov } 117282cae269SKonstantin Komarov 117382cae269SKonstantin Komarov struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, 117482cae269SKonstantin Komarov struct inode *dir, struct dentry *dentry, 117582cae269SKonstantin Komarov const struct cpu_str *uni, umode_t mode, 117682cae269SKonstantin Komarov dev_t dev, const char *symname, u32 size, 117782cae269SKonstantin Komarov struct ntfs_fnd *fnd) 117882cae269SKonstantin Komarov { 117982cae269SKonstantin Komarov int err; 118082cae269SKonstantin Komarov struct super_block *sb = dir->i_sb; 118182cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 118282cae269SKonstantin Komarov const struct qstr *name = &dentry->d_name; 118382cae269SKonstantin Komarov CLST ino = 0; 118482cae269SKonstantin Komarov struct ntfs_inode *dir_ni = ntfs_i(dir); 118582cae269SKonstantin Komarov struct ntfs_inode *ni = NULL; 118682cae269SKonstantin Komarov struct inode *inode = NULL; 118782cae269SKonstantin Komarov struct ATTRIB *attr; 118882cae269SKonstantin Komarov struct ATTR_STD_INFO5 *std5; 118982cae269SKonstantin Komarov struct ATTR_FILE_NAME *fname; 119082cae269SKonstantin Komarov struct MFT_REC *rec; 119182cae269SKonstantin Komarov u32 asize, dsize, sd_size; 119282cae269SKonstantin Komarov enum FILE_ATTRIBUTE fa; 119382cae269SKonstantin Komarov __le32 security_id = SECURITY_ID_INVALID; 119482cae269SKonstantin Komarov CLST vcn; 119582cae269SKonstantin Komarov const void *sd; 119682cae269SKonstantin Komarov u16 t16, nsize = 0, aid = 0; 119782cae269SKonstantin Komarov struct INDEX_ROOT *root, *dir_root; 119882cae269SKonstantin Komarov struct NTFS_DE *e, *new_de = NULL; 119982cae269SKonstantin Komarov struct REPARSE_DATA_BUFFER *rp = NULL; 120082cae269SKonstantin Komarov bool rp_inserted = false; 120182cae269SKonstantin Komarov 1202d562e901SKonstantin Komarov ni_lock_dir(dir_ni); 1203d562e901SKonstantin Komarov 120482cae269SKonstantin Komarov dir_root = indx_get_root(&dir_ni->dir, dir_ni, NULL, NULL); 1205d562e901SKonstantin Komarov if (!dir_root) { 1206d562e901SKonstantin Komarov err = -EINVAL; 1207d562e901SKonstantin Komarov goto out1; 1208d562e901SKonstantin Komarov } 120982cae269SKonstantin Komarov 121082cae269SKonstantin Komarov if (S_ISDIR(mode)) { 1211d3624466SKonstantin Komarov /* Use parent's directory attributes. */ 121282cae269SKonstantin Komarov fa = dir_ni->std_fa | FILE_ATTRIBUTE_DIRECTORY | 121382cae269SKonstantin Komarov FILE_ATTRIBUTE_ARCHIVE; 121482cae269SKonstantin Komarov /* 1215d3624466SKonstantin Komarov * By default child directory inherits parent attributes. 1216d3624466SKonstantin Komarov * Root directory is hidden + system. 1217d3624466SKonstantin Komarov * Make an exception for children in root. 121882cae269SKonstantin Komarov */ 121982cae269SKonstantin Komarov if (dir->i_ino == MFT_REC_ROOT) 122082cae269SKonstantin Komarov fa &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); 122182cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 122282cae269SKonstantin Komarov /* It is good idea that link should be the same type (file/dir) as target */ 122382cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_REPARSE_POINT; 122482cae269SKonstantin Komarov 122582cae269SKonstantin Komarov /* 1226d3624466SKonstantin Komarov * Linux: there are dir/file/symlink and so on. 1227d3624466SKonstantin Komarov * NTFS: symlinks are "dir + reparse" or "file + reparse" 122882cae269SKonstantin Komarov * It is good idea to create: 122982cae269SKonstantin Komarov * dir + reparse if 'symname' points to directory 123082cae269SKonstantin Komarov * or 123182cae269SKonstantin Komarov * file + reparse if 'symname' points to file 1232e8b8e97fSKari Argillander * Unfortunately kern_path hangs if symname contains 'dir'. 123382cae269SKonstantin Komarov */ 123482cae269SKonstantin Komarov 123582cae269SKonstantin Komarov /* 123682cae269SKonstantin Komarov * struct path path; 123782cae269SKonstantin Komarov * 123882cae269SKonstantin Komarov * if (!kern_path(symname, LOOKUP_FOLLOW, &path)){ 123982cae269SKonstantin Komarov * struct inode *target = d_inode(path.dentry); 124082cae269SKonstantin Komarov * 124182cae269SKonstantin Komarov * if (S_ISDIR(target->i_mode)) 124282cae269SKonstantin Komarov * fa |= FILE_ATTRIBUTE_DIRECTORY; 124382cae269SKonstantin Komarov * // if ( target->i_sb == sb ){ 124482cae269SKonstantin Komarov * // use relative path? 124582cae269SKonstantin Komarov * // } 124682cae269SKonstantin Komarov * path_put(&path); 124782cae269SKonstantin Komarov * } 124882cae269SKonstantin Komarov */ 124982cae269SKonstantin Komarov } else if (S_ISREG(mode)) { 1250564c97bdSKari Argillander if (sbi->options->sparse) { 1251e8b8e97fSKari Argillander /* Sparsed regular file, cause option 'sparse'. */ 125282cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_SPARSE_FILE | 125382cae269SKonstantin Komarov FILE_ATTRIBUTE_ARCHIVE; 125482cae269SKonstantin Komarov } else if (dir_ni->std_fa & FILE_ATTRIBUTE_COMPRESSED) { 1255e8b8e97fSKari Argillander /* Compressed regular file, if parent is compressed. */ 125682cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ARCHIVE; 125782cae269SKonstantin Komarov } else { 1258e8b8e97fSKari Argillander /* Regular file, default attributes. */ 125982cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_ARCHIVE; 126082cae269SKonstantin Komarov } 126182cae269SKonstantin Komarov } else { 126282cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_ARCHIVE; 126382cae269SKonstantin Komarov } 126482cae269SKonstantin Komarov 1265098250dbSKonstantin Komarov /* If option "hidedotfiles" then set hidden attribute for dot files. */ 1266098250dbSKonstantin Komarov if (sbi->options->hide_dot_files && name->name[0] == '.') 1267098250dbSKonstantin Komarov fa |= FILE_ATTRIBUTE_HIDDEN; 1268098250dbSKonstantin Komarov 126982cae269SKonstantin Komarov if (!(mode & 0222)) 127082cae269SKonstantin Komarov fa |= FILE_ATTRIBUTE_READONLY; 127182cae269SKonstantin Komarov 1272e8b8e97fSKari Argillander /* Allocate PATH_MAX bytes. */ 127382cae269SKonstantin Komarov new_de = __getname(); 127482cae269SKonstantin Komarov if (!new_de) { 127582cae269SKonstantin Komarov err = -ENOMEM; 127682cae269SKonstantin Komarov goto out1; 127782cae269SKonstantin Komarov } 127882cae269SKonstantin Komarov 1279e8b8e97fSKari Argillander /* Mark rw ntfs as dirty. it will be cleared at umount. */ 128082cae269SKonstantin Komarov ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); 128182cae269SKonstantin Komarov 1282e8b8e97fSKari Argillander /* Step 1: allocate and fill new mft record. */ 128382cae269SKonstantin Komarov err = ntfs_look_free_mft(sbi, &ino, false, NULL, NULL); 128482cae269SKonstantin Komarov if (err) 128582cae269SKonstantin Komarov goto out2; 128682cae269SKonstantin Komarov 128782cae269SKonstantin Komarov ni = ntfs_new_inode(sbi, ino, fa & FILE_ATTRIBUTE_DIRECTORY); 128882cae269SKonstantin Komarov if (IS_ERR(ni)) { 128982cae269SKonstantin Komarov err = PTR_ERR(ni); 129082cae269SKonstantin Komarov ni = NULL; 129182cae269SKonstantin Komarov goto out3; 129282cae269SKonstantin Komarov } 129382cae269SKonstantin Komarov inode = &ni->vfs_inode; 129482cae269SKonstantin Komarov inode_init_owner(mnt_userns, inode, dir, mode); 129578ab59feSKonstantin Komarov mode = inode->i_mode; 129682cae269SKonstantin Komarov 129782cae269SKonstantin Komarov inode->i_atime = inode->i_mtime = inode->i_ctime = ni->i_crtime = 129882cae269SKonstantin Komarov current_time(inode); 129982cae269SKonstantin Komarov 130082cae269SKonstantin Komarov rec = ni->mi.mrec; 130182cae269SKonstantin Komarov rec->hard_links = cpu_to_le16(1); 130282cae269SKonstantin Komarov attr = Add2Ptr(rec, le16_to_cpu(rec->attr_off)); 130382cae269SKonstantin Komarov 1304e8b8e97fSKari Argillander /* Get default security id. */ 130582cae269SKonstantin Komarov sd = s_default_security; 130682cae269SKonstantin Komarov sd_size = sizeof(s_default_security); 130782cae269SKonstantin Komarov 130882cae269SKonstantin Komarov if (is_ntfs3(sbi)) { 130982cae269SKonstantin Komarov security_id = dir_ni->std_security_id; 131082cae269SKonstantin Komarov if (le32_to_cpu(security_id) < SECURITY_ID_FIRST) { 131182cae269SKonstantin Komarov security_id = sbi->security.def_security_id; 131282cae269SKonstantin Komarov 131382cae269SKonstantin Komarov if (security_id == SECURITY_ID_INVALID && 131482cae269SKonstantin Komarov !ntfs_insert_security(sbi, sd, sd_size, 131582cae269SKonstantin Komarov &security_id, NULL)) 131682cae269SKonstantin Komarov sbi->security.def_security_id = security_id; 131782cae269SKonstantin Komarov } 131882cae269SKonstantin Komarov } 131982cae269SKonstantin Komarov 1320e8b8e97fSKari Argillander /* Insert standard info. */ 132182cae269SKonstantin Komarov std5 = Add2Ptr(attr, SIZEOF_RESIDENT); 132282cae269SKonstantin Komarov 132382cae269SKonstantin Komarov if (security_id == SECURITY_ID_INVALID) { 132482cae269SKonstantin Komarov dsize = sizeof(struct ATTR_STD_INFO); 132582cae269SKonstantin Komarov } else { 132682cae269SKonstantin Komarov dsize = sizeof(struct ATTR_STD_INFO5); 132782cae269SKonstantin Komarov std5->security_id = security_id; 132882cae269SKonstantin Komarov ni->std_security_id = security_id; 132982cae269SKonstantin Komarov } 133082cae269SKonstantin Komarov asize = SIZEOF_RESIDENT + dsize; 133182cae269SKonstantin Komarov 133282cae269SKonstantin Komarov attr->type = ATTR_STD; 133382cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 133482cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 133582cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 133682cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(dsize); 133782cae269SKonstantin Komarov 133882cae269SKonstantin Komarov std5->cr_time = std5->m_time = std5->c_time = std5->a_time = 133982cae269SKonstantin Komarov kernel2nt(&inode->i_atime); 134082cae269SKonstantin Komarov 134182cae269SKonstantin Komarov ni->std_fa = fa; 134282cae269SKonstantin Komarov std5->fa = fa; 134382cae269SKonstantin Komarov 134482cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 134582cae269SKonstantin Komarov 1346e8b8e97fSKari Argillander /* Insert file name. */ 134782cae269SKonstantin Komarov err = fill_name_de(sbi, new_de, name, uni); 134882cae269SKonstantin Komarov if (err) 134982cae269SKonstantin Komarov goto out4; 135082cae269SKonstantin Komarov 135182cae269SKonstantin Komarov mi_get_ref(&ni->mi, &new_de->ref); 135282cae269SKonstantin Komarov 135382cae269SKonstantin Komarov fname = (struct ATTR_FILE_NAME *)(new_de + 1); 135482cae269SKonstantin Komarov mi_get_ref(&dir_ni->mi, &fname->home); 135582cae269SKonstantin Komarov fname->dup.cr_time = fname->dup.m_time = fname->dup.c_time = 135682cae269SKonstantin Komarov fname->dup.a_time = std5->cr_time; 135782cae269SKonstantin Komarov fname->dup.alloc_size = fname->dup.data_size = 0; 135882cae269SKonstantin Komarov fname->dup.fa = std5->fa; 135982cae269SKonstantin Komarov fname->dup.ea_size = fname->dup.reparse = 0; 136082cae269SKonstantin Komarov 136182cae269SKonstantin Komarov dsize = le16_to_cpu(new_de->key_size); 1362fa3cacf5SKari Argillander asize = ALIGN(SIZEOF_RESIDENT + dsize, 8); 136382cae269SKonstantin Komarov 136482cae269SKonstantin Komarov attr->type = ATTR_NAME; 136582cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 136682cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 136782cae269SKonstantin Komarov attr->res.flags = RESIDENT_FLAG_INDEXED; 136882cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 136982cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(dsize); 137082cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), fname, dsize); 137182cae269SKonstantin Komarov 137282cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 137382cae269SKonstantin Komarov 137482cae269SKonstantin Komarov if (security_id == SECURITY_ID_INVALID) { 1375e8b8e97fSKari Argillander /* Insert security attribute. */ 1376fa3cacf5SKari Argillander asize = SIZEOF_RESIDENT + ALIGN(sd_size, 8); 137782cae269SKonstantin Komarov 137882cae269SKonstantin Komarov attr->type = ATTR_SECURE; 137982cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 138082cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 138182cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 138282cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(sd_size); 138382cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), sd, sd_size); 138482cae269SKonstantin Komarov 138582cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 138682cae269SKonstantin Komarov } 138782cae269SKonstantin Komarov 138878ab59feSKonstantin Komarov attr->id = cpu_to_le16(aid++); 138982cae269SKonstantin Komarov if (fa & FILE_ATTRIBUTE_DIRECTORY) { 139082cae269SKonstantin Komarov /* 1391e8b8e97fSKari Argillander * Regular directory or symlink to directory. 1392e8b8e97fSKari Argillander * Create root attribute. 139382cae269SKonstantin Komarov */ 139482cae269SKonstantin Komarov dsize = sizeof(struct INDEX_ROOT) + sizeof(struct NTFS_DE); 139582cae269SKonstantin Komarov asize = sizeof(I30_NAME) + SIZEOF_RESIDENT + dsize; 139682cae269SKonstantin Komarov 139782cae269SKonstantin Komarov attr->type = ATTR_ROOT; 139882cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 139982cae269SKonstantin Komarov 140082cae269SKonstantin Komarov attr->name_len = ARRAY_SIZE(I30_NAME); 140182cae269SKonstantin Komarov attr->name_off = SIZEOF_RESIDENT_LE; 140282cae269SKonstantin Komarov attr->res.data_off = 140382cae269SKonstantin Komarov cpu_to_le16(sizeof(I30_NAME) + SIZEOF_RESIDENT); 140482cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(dsize); 140582cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), I30_NAME, 140682cae269SKonstantin Komarov sizeof(I30_NAME)); 140782cae269SKonstantin Komarov 140882cae269SKonstantin Komarov root = Add2Ptr(attr, sizeof(I30_NAME) + SIZEOF_RESIDENT); 140982cae269SKonstantin Komarov memcpy(root, dir_root, offsetof(struct INDEX_ROOT, ihdr)); 141082cae269SKonstantin Komarov root->ihdr.de_off = 141182cae269SKonstantin Komarov cpu_to_le32(sizeof(struct INDEX_HDR)); // 0x10 141282cae269SKonstantin Komarov root->ihdr.used = cpu_to_le32(sizeof(struct INDEX_HDR) + 141382cae269SKonstantin Komarov sizeof(struct NTFS_DE)); 141482cae269SKonstantin Komarov root->ihdr.total = root->ihdr.used; 141582cae269SKonstantin Komarov 141682cae269SKonstantin Komarov e = Add2Ptr(root, sizeof(struct INDEX_ROOT)); 141782cae269SKonstantin Komarov e->size = cpu_to_le16(sizeof(struct NTFS_DE)); 141882cae269SKonstantin Komarov e->flags = NTFS_IE_LAST; 141982cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 142082cae269SKonstantin Komarov /* 1421e8b8e97fSKari Argillander * Symlink to file. 1422e8b8e97fSKari Argillander * Create empty resident data attribute. 142382cae269SKonstantin Komarov */ 142482cae269SKonstantin Komarov asize = SIZEOF_RESIDENT; 142582cae269SKonstantin Komarov 1426e8b8e97fSKari Argillander /* Insert empty ATTR_DATA */ 142782cae269SKonstantin Komarov attr->type = ATTR_DATA; 142882cae269SKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_RESIDENT); 142982cae269SKonstantin Komarov attr->name_off = SIZEOF_RESIDENT_LE; 143082cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 143178ab59feSKonstantin Komarov } else if (S_ISREG(mode)) { 143282cae269SKonstantin Komarov /* 143378ab59feSKonstantin Komarov * Regular file. Create empty non resident data attribute. 143482cae269SKonstantin Komarov */ 143582cae269SKonstantin Komarov attr->type = ATTR_DATA; 143682cae269SKonstantin Komarov attr->non_res = 1; 143782cae269SKonstantin Komarov attr->nres.evcn = cpu_to_le64(-1ll); 143882cae269SKonstantin Komarov if (fa & FILE_ATTRIBUTE_SPARSE_FILE) { 143978ab59feSKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8); 144082cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_EX_LE; 144182cae269SKonstantin Komarov attr->flags = ATTR_FLAG_SPARSED; 144282cae269SKonstantin Komarov asize = SIZEOF_NONRESIDENT_EX + 8; 144382cae269SKonstantin Komarov } else if (fa & FILE_ATTRIBUTE_COMPRESSED) { 144478ab59feSKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8); 144582cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_EX_LE; 144682cae269SKonstantin Komarov attr->flags = ATTR_FLAG_COMPRESSED; 144782cae269SKonstantin Komarov attr->nres.c_unit = COMPRESSION_UNIT; 144882cae269SKonstantin Komarov asize = SIZEOF_NONRESIDENT_EX + 8; 144982cae269SKonstantin Komarov } else { 145078ab59feSKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_NONRESIDENT + 8); 145182cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_LE; 145282cae269SKonstantin Komarov asize = SIZEOF_NONRESIDENT + 8; 145382cae269SKonstantin Komarov } 145482cae269SKonstantin Komarov attr->nres.run_off = attr->name_off; 145582cae269SKonstantin Komarov } else { 145678ab59feSKonstantin Komarov /* 145778ab59feSKonstantin Komarov * Node. Create empty resident data attribute. 145878ab59feSKonstantin Komarov */ 145978ab59feSKonstantin Komarov attr->type = ATTR_DATA; 146082cae269SKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_RESIDENT); 146182cae269SKonstantin Komarov attr->name_off = SIZEOF_RESIDENT_LE; 146282cae269SKonstantin Komarov if (fa & FILE_ATTRIBUTE_SPARSE_FILE) 146382cae269SKonstantin Komarov attr->flags = ATTR_FLAG_SPARSED; 146482cae269SKonstantin Komarov else if (fa & FILE_ATTRIBUTE_COMPRESSED) 146582cae269SKonstantin Komarov attr->flags = ATTR_FLAG_COMPRESSED; 146682cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 146782cae269SKonstantin Komarov asize = SIZEOF_RESIDENT; 146882cae269SKonstantin Komarov ni->ni_flags |= NI_FLAG_RESIDENT; 146982cae269SKonstantin Komarov } 147082cae269SKonstantin Komarov 147182cae269SKonstantin Komarov if (S_ISDIR(mode)) { 147282cae269SKonstantin Komarov ni->ni_flags |= NI_FLAG_DIR; 147382cae269SKonstantin Komarov err = indx_init(&ni->dir, sbi, attr, INDEX_MUTEX_I30); 147482cae269SKonstantin Komarov if (err) 147582cae269SKonstantin Komarov goto out4; 147682cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 147782cae269SKonstantin Komarov rp = ntfs_create_reparse_buffer(sbi, symname, size, &nsize); 147882cae269SKonstantin Komarov 147982cae269SKonstantin Komarov if (IS_ERR(rp)) { 148082cae269SKonstantin Komarov err = PTR_ERR(rp); 148182cae269SKonstantin Komarov rp = NULL; 148282cae269SKonstantin Komarov goto out4; 148382cae269SKonstantin Komarov } 148482cae269SKonstantin Komarov 148582cae269SKonstantin Komarov /* 1486e8b8e97fSKari Argillander * Insert ATTR_REPARSE. 148782cae269SKonstantin Komarov */ 148882cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 148982cae269SKonstantin Komarov attr->type = ATTR_REPARSE; 149082cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 149182cae269SKonstantin Komarov 1492e8b8e97fSKari Argillander /* Resident or non resident? */ 1493fa3cacf5SKari Argillander asize = ALIGN(SIZEOF_RESIDENT + nsize, 8); 149482cae269SKonstantin Komarov t16 = PtrOffset(rec, attr); 149582cae269SKonstantin Komarov 149614a98119SKonstantin Komarov /* 149714a98119SKonstantin Komarov * Below function 'ntfs_save_wsl_perm' requires 0x78 bytes. 149814a98119SKonstantin Komarov * It is good idea to keep extened attributes resident. 149914a98119SKonstantin Komarov */ 150078ab59feSKonstantin Komarov if (asize + t16 + 0x78 + 8 > sbi->record_size) { 150182cae269SKonstantin Komarov CLST alen; 150282cae269SKonstantin Komarov CLST clst = bytes_to_cluster(sbi, nsize); 150382cae269SKonstantin Komarov 1504e8b8e97fSKari Argillander /* Bytes per runs. */ 150582cae269SKonstantin Komarov t16 = sbi->record_size - t16 - SIZEOF_NONRESIDENT; 150682cae269SKonstantin Komarov 150782cae269SKonstantin Komarov attr->non_res = 1; 150882cae269SKonstantin Komarov attr->nres.evcn = cpu_to_le64(clst - 1); 150982cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_LE; 151082cae269SKonstantin Komarov attr->nres.run_off = attr->name_off; 151182cae269SKonstantin Komarov attr->nres.data_size = cpu_to_le64(nsize); 151282cae269SKonstantin Komarov attr->nres.valid_size = attr->nres.data_size; 151382cae269SKonstantin Komarov attr->nres.alloc_size = 151482cae269SKonstantin Komarov cpu_to_le64(ntfs_up_cluster(sbi, nsize)); 151582cae269SKonstantin Komarov 151682cae269SKonstantin Komarov err = attr_allocate_clusters(sbi, &ni->file.run, 0, 0, 151782cae269SKonstantin Komarov clst, NULL, 0, &alen, 0, 151882cae269SKonstantin Komarov NULL); 151982cae269SKonstantin Komarov if (err) 152082cae269SKonstantin Komarov goto out5; 152182cae269SKonstantin Komarov 152282cae269SKonstantin Komarov err = run_pack(&ni->file.run, 0, clst, 152382cae269SKonstantin Komarov Add2Ptr(attr, SIZEOF_NONRESIDENT), t16, 152482cae269SKonstantin Komarov &vcn); 152582cae269SKonstantin Komarov if (err < 0) 152682cae269SKonstantin Komarov goto out5; 152782cae269SKonstantin Komarov 152882cae269SKonstantin Komarov if (vcn != clst) { 152982cae269SKonstantin Komarov err = -EINVAL; 153082cae269SKonstantin Komarov goto out5; 153182cae269SKonstantin Komarov } 153282cae269SKonstantin Komarov 1533fa3cacf5SKari Argillander asize = SIZEOF_NONRESIDENT + ALIGN(err, 8); 153482cae269SKonstantin Komarov } else { 153582cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 153682cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(nsize); 153782cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), rp, nsize); 153882cae269SKonstantin Komarov nsize = 0; 153982cae269SKonstantin Komarov } 154014a98119SKonstantin Komarov /* Size of symlink equals the length of input string. */ 154114a98119SKonstantin Komarov inode->i_size = size; 154282cae269SKonstantin Komarov 154382cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 154482cae269SKonstantin Komarov 154582cae269SKonstantin Komarov err = ntfs_insert_reparse(sbi, IO_REPARSE_TAG_SYMLINK, 154682cae269SKonstantin Komarov &new_de->ref); 154782cae269SKonstantin Komarov if (err) 154882cae269SKonstantin Komarov goto out5; 154982cae269SKonstantin Komarov 155082cae269SKonstantin Komarov rp_inserted = true; 155182cae269SKonstantin Komarov } 155282cae269SKonstantin Komarov 155382cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 155482cae269SKonstantin Komarov attr->type = ATTR_END; 155582cae269SKonstantin Komarov 155682cae269SKonstantin Komarov rec->used = cpu_to_le32(PtrOffset(rec, attr) + 8); 155782cae269SKonstantin Komarov rec->next_attr_id = cpu_to_le16(aid); 155882cae269SKonstantin Komarov 1559e8b8e97fSKari Argillander /* Step 2: Add new name in index. */ 156078ab59feSKonstantin Komarov err = indx_insert_entry(&dir_ni->dir, dir_ni, new_de, sbi, fnd, 0); 156182cae269SKonstantin Komarov if (err) 156282cae269SKonstantin Komarov goto out6; 156382cae269SKonstantin Komarov 1564d562e901SKonstantin Komarov /* Unlock parent directory before ntfs_init_acl. */ 1565d562e901SKonstantin Komarov ni_unlock(dir_ni); 1566d562e901SKonstantin Komarov 156782cae269SKonstantin Komarov inode->i_generation = le16_to_cpu(rec->seq); 156882cae269SKonstantin Komarov 156982cae269SKonstantin Komarov dir->i_mtime = dir->i_ctime = inode->i_atime; 157082cae269SKonstantin Komarov 157182cae269SKonstantin Komarov if (S_ISDIR(mode)) { 157282cae269SKonstantin Komarov inode->i_op = &ntfs_dir_inode_operations; 157382cae269SKonstantin Komarov inode->i_fop = &ntfs_dir_operations; 157482cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 157582cae269SKonstantin Komarov inode->i_op = &ntfs_link_inode_operations; 157682cae269SKonstantin Komarov inode->i_fop = NULL; 157782cae269SKonstantin Komarov inode->i_mapping->a_ops = &ntfs_aops; 157814a98119SKonstantin Komarov inode->i_size = size; 157914a98119SKonstantin Komarov inode_nohighmem(inode); 158082cae269SKonstantin Komarov } else if (S_ISREG(mode)) { 158182cae269SKonstantin Komarov inode->i_op = &ntfs_file_inode_operations; 158282cae269SKonstantin Komarov inode->i_fop = &ntfs_file_operations; 158382cae269SKonstantin Komarov inode->i_mapping->a_ops = 158482cae269SKonstantin Komarov is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops; 158582cae269SKonstantin Komarov init_rwsem(&ni->file.run_lock); 158682cae269SKonstantin Komarov } else { 158782cae269SKonstantin Komarov inode->i_op = &ntfs_special_inode_operations; 158882cae269SKonstantin Komarov init_special_inode(inode, mode, dev); 158982cae269SKonstantin Komarov } 159082cae269SKonstantin Komarov 159182cae269SKonstantin Komarov #ifdef CONFIG_NTFS3_FS_POSIX_ACL 159282cae269SKonstantin Komarov if (!S_ISLNK(mode) && (sb->s_flags & SB_POSIXACL)) { 159382cae269SKonstantin Komarov err = ntfs_init_acl(mnt_userns, inode, dir); 159482cae269SKonstantin Komarov if (err) 15956c1ee4d3SKonstantin Komarov goto out7; 159682cae269SKonstantin Komarov } else 159782cae269SKonstantin Komarov #endif 159882cae269SKonstantin Komarov { 159982cae269SKonstantin Komarov inode->i_flags |= S_NOSEC; 160082cae269SKonstantin Komarov } 160182cae269SKonstantin Komarov 1602e8b8e97fSKari Argillander /* Write non resident data. */ 160382cae269SKonstantin Komarov if (nsize) { 160463544672SKonstantin Komarov err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rp, nsize, 0); 160582cae269SKonstantin Komarov if (err) 160682cae269SKonstantin Komarov goto out7; 160782cae269SKonstantin Komarov } 160882cae269SKonstantin Komarov 1609e8b8e97fSKari Argillander /* 1610e8b8e97fSKari Argillander * Call 'd_instantiate' after inode->i_op is set 1611e8b8e97fSKari Argillander * but before finish_open. 1612e8b8e97fSKari Argillander */ 161382cae269SKonstantin Komarov d_instantiate(dentry, inode); 161482cae269SKonstantin Komarov 161582cae269SKonstantin Komarov ntfs_save_wsl_perm(inode); 161682cae269SKonstantin Komarov mark_inode_dirty(dir); 161778ab59feSKonstantin Komarov mark_inode_dirty(inode); 161882cae269SKonstantin Komarov 1619e8b8e97fSKari Argillander /* Normal exit. */ 162082cae269SKonstantin Komarov goto out2; 162182cae269SKonstantin Komarov 162282cae269SKonstantin Komarov out7: 162382cae269SKonstantin Komarov 1624e8b8e97fSKari Argillander /* Undo 'indx_insert_entry'. */ 1625d562e901SKonstantin Komarov ni_lock_dir(dir_ni); 162682cae269SKonstantin Komarov indx_delete_entry(&dir_ni->dir, dir_ni, new_de + 1, 162782cae269SKonstantin Komarov le16_to_cpu(new_de->key_size), sbi); 1628d562e901SKonstantin Komarov /* ni_unlock(dir_ni); will be called later. */ 162982cae269SKonstantin Komarov out6: 163082cae269SKonstantin Komarov if (rp_inserted) 163182cae269SKonstantin Komarov ntfs_remove_reparse(sbi, IO_REPARSE_TAG_SYMLINK, &new_de->ref); 163282cae269SKonstantin Komarov 163382cae269SKonstantin Komarov out5: 163482cae269SKonstantin Komarov if (S_ISDIR(mode) || run_is_empty(&ni->file.run)) 163582cae269SKonstantin Komarov goto out4; 163682cae269SKonstantin Komarov 163782cae269SKonstantin Komarov run_deallocate(sbi, &ni->file.run, false); 163882cae269SKonstantin Komarov 163982cae269SKonstantin Komarov out4: 164082cae269SKonstantin Komarov clear_rec_inuse(rec); 164182cae269SKonstantin Komarov clear_nlink(inode); 164282cae269SKonstantin Komarov ni->mi.dirty = false; 164382cae269SKonstantin Komarov discard_new_inode(inode); 164482cae269SKonstantin Komarov out3: 1645071100eaSKonstantin Komarov ntfs_mark_rec_free(sbi, ino, false); 164682cae269SKonstantin Komarov 164782cae269SKonstantin Komarov out2: 164882cae269SKonstantin Komarov __putname(new_de); 1649195c52bdSKari Argillander kfree(rp); 165082cae269SKonstantin Komarov 165182cae269SKonstantin Komarov out1: 1652d562e901SKonstantin Komarov if (err) { 1653d562e901SKonstantin Komarov ni_unlock(dir_ni); 165482cae269SKonstantin Komarov return ERR_PTR(err); 1655d562e901SKonstantin Komarov } 165682cae269SKonstantin Komarov 165782cae269SKonstantin Komarov unlock_new_inode(inode); 165882cae269SKonstantin Komarov 165982cae269SKonstantin Komarov return inode; 166082cae269SKonstantin Komarov } 166182cae269SKonstantin Komarov 166282cae269SKonstantin Komarov int ntfs_link_inode(struct inode *inode, struct dentry *dentry) 166382cae269SKonstantin Komarov { 166482cae269SKonstantin Komarov int err; 166582cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 166678ab59feSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 166778ab59feSKonstantin Komarov struct NTFS_DE *de; 166882cae269SKonstantin Komarov 1669e8b8e97fSKari Argillander /* Allocate PATH_MAX bytes. */ 167078ab59feSKonstantin Komarov de = __getname(); 167178ab59feSKonstantin Komarov if (!de) 167282cae269SKonstantin Komarov return -ENOMEM; 167382cae269SKonstantin Komarov 1674e8b8e97fSKari Argillander /* Mark rw ntfs as dirty. It will be cleared at umount. */ 167578ab59feSKonstantin Komarov ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); 167682cae269SKonstantin Komarov 167778ab59feSKonstantin Komarov /* Construct 'de'. */ 167878ab59feSKonstantin Komarov err = fill_name_de(sbi, de, &dentry->d_name, NULL); 167982cae269SKonstantin Komarov if (err) 168082cae269SKonstantin Komarov goto out; 168182cae269SKonstantin Komarov 168278ab59feSKonstantin Komarov err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de); 168382cae269SKonstantin Komarov out: 168478ab59feSKonstantin Komarov __putname(de); 168582cae269SKonstantin Komarov return err; 168682cae269SKonstantin Komarov } 168782cae269SKonstantin Komarov 168882cae269SKonstantin Komarov /* 168982cae269SKonstantin Komarov * ntfs_unlink_inode 169082cae269SKonstantin Komarov * 169182cae269SKonstantin Komarov * inode_operations::unlink 169282cae269SKonstantin Komarov * inode_operations::rmdir 169382cae269SKonstantin Komarov */ 169482cae269SKonstantin Komarov int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry) 169582cae269SKonstantin Komarov { 169682cae269SKonstantin Komarov int err; 169778ab59feSKonstantin Komarov struct ntfs_sb_info *sbi = dir->i_sb->s_fs_info; 169882cae269SKonstantin Komarov struct inode *inode = d_inode(dentry); 169982cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 170082cae269SKonstantin Komarov struct ntfs_inode *dir_ni = ntfs_i(dir); 170178ab59feSKonstantin Komarov struct NTFS_DE *de, *de2 = NULL; 170278ab59feSKonstantin Komarov int undo_remove; 170382cae269SKonstantin Komarov 170478ab59feSKonstantin Komarov if (ntfs_is_meta_file(sbi, ni->mi.rno)) 170582cae269SKonstantin Komarov return -EINVAL; 170682cae269SKonstantin Komarov 170778ab59feSKonstantin Komarov /* Allocate PATH_MAX bytes. */ 170878ab59feSKonstantin Komarov de = __getname(); 170978ab59feSKonstantin Komarov if (!de) 171078ab59feSKonstantin Komarov return -ENOMEM; 171178ab59feSKonstantin Komarov 171282cae269SKonstantin Komarov ni_lock(ni); 171382cae269SKonstantin Komarov 171478ab59feSKonstantin Komarov if (S_ISDIR(inode->i_mode) && !dir_is_empty(inode)) { 171582cae269SKonstantin Komarov err = -ENOTEMPTY; 171678ab59feSKonstantin Komarov goto out; 171782cae269SKonstantin Komarov } 171882cae269SKonstantin Komarov 171978ab59feSKonstantin Komarov err = fill_name_de(sbi, de, &dentry->d_name, NULL); 172082cae269SKonstantin Komarov if (err < 0) 172178ab59feSKonstantin Komarov goto out; 172282cae269SKonstantin Komarov 172378ab59feSKonstantin Komarov undo_remove = 0; 172478ab59feSKonstantin Komarov err = ni_remove_name(dir_ni, ni, de, &de2, &undo_remove); 172582cae269SKonstantin Komarov 172678ab59feSKonstantin Komarov if (!err) { 172782cae269SKonstantin Komarov drop_nlink(inode); 172882cae269SKonstantin Komarov dir->i_mtime = dir->i_ctime = current_time(dir); 172982cae269SKonstantin Komarov mark_inode_dirty(dir); 173082cae269SKonstantin Komarov inode->i_ctime = dir->i_ctime; 173182cae269SKonstantin Komarov if (inode->i_nlink) 173282cae269SKonstantin Komarov mark_inode_dirty(inode); 173378ab59feSKonstantin Komarov } else if (!ni_remove_name_undo(dir_ni, ni, de, de2, undo_remove)) { 1734c12df45eSKonstantin Komarov _ntfs_bad_inode(inode); 173578ab59feSKonstantin Komarov } else { 173678ab59feSKonstantin Komarov if (ni_is_dirty(dir)) 173778ab59feSKonstantin Komarov mark_inode_dirty(dir); 173878ab59feSKonstantin Komarov if (ni_is_dirty(inode)) 173978ab59feSKonstantin Komarov mark_inode_dirty(inode); 174078ab59feSKonstantin Komarov } 174182cae269SKonstantin Komarov 174278ab59feSKonstantin Komarov out: 174382cae269SKonstantin Komarov ni_unlock(ni); 174478ab59feSKonstantin Komarov __putname(de); 174582cae269SKonstantin Komarov return err; 174682cae269SKonstantin Komarov } 174782cae269SKonstantin Komarov 174882cae269SKonstantin Komarov void ntfs_evict_inode(struct inode *inode) 174982cae269SKonstantin Komarov { 175082cae269SKonstantin Komarov truncate_inode_pages_final(&inode->i_data); 175182cae269SKonstantin Komarov 175282cae269SKonstantin Komarov if (inode->i_nlink) 175382cae269SKonstantin Komarov _ni_write_inode(inode, inode_needs_sync(inode)); 175482cae269SKonstantin Komarov 175582cae269SKonstantin Komarov invalidate_inode_buffers(inode); 175682cae269SKonstantin Komarov clear_inode(inode); 175782cae269SKonstantin Komarov 175882cae269SKonstantin Komarov ni_clear(ntfs_i(inode)); 175982cae269SKonstantin Komarov } 176082cae269SKonstantin Komarov 176182cae269SKonstantin Komarov static noinline int ntfs_readlink_hlp(struct inode *inode, char *buffer, 176282cae269SKonstantin Komarov int buflen) 176382cae269SKonstantin Komarov { 17644dbe8e44SKonstantin Komarov int i, err = -EINVAL; 176582cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 176682cae269SKonstantin Komarov struct super_block *sb = inode->i_sb; 176782cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 17684dbe8e44SKonstantin Komarov u64 size; 17694dbe8e44SKonstantin Komarov u16 ulen = 0; 177082cae269SKonstantin Komarov void *to_free = NULL; 177182cae269SKonstantin Komarov struct REPARSE_DATA_BUFFER *rp; 17724dbe8e44SKonstantin Komarov const __le16 *uname; 177382cae269SKonstantin Komarov struct ATTRIB *attr; 177482cae269SKonstantin Komarov 1775e8b8e97fSKari Argillander /* Reparse data present. Try to parse it. */ 177682cae269SKonstantin Komarov static_assert(!offsetof(struct REPARSE_DATA_BUFFER, ReparseTag)); 177782cae269SKonstantin Komarov static_assert(sizeof(u32) == sizeof(rp->ReparseTag)); 177882cae269SKonstantin Komarov 177982cae269SKonstantin Komarov *buffer = 0; 178082cae269SKonstantin Komarov 178182cae269SKonstantin Komarov attr = ni_find_attr(ni, NULL, NULL, ATTR_REPARSE, NULL, 0, NULL, NULL); 17824dbe8e44SKonstantin Komarov if (!attr) 178382cae269SKonstantin Komarov goto out; 178482cae269SKonstantin Komarov 178582cae269SKonstantin Komarov if (!attr->non_res) { 17864dbe8e44SKonstantin Komarov rp = resident_data_ex(attr, sizeof(struct REPARSE_DATA_BUFFER)); 17874dbe8e44SKonstantin Komarov if (!rp) 178882cae269SKonstantin Komarov goto out; 17894dbe8e44SKonstantin Komarov size = le32_to_cpu(attr->res.data_size); 179082cae269SKonstantin Komarov } else { 17914dbe8e44SKonstantin Komarov size = le64_to_cpu(attr->nres.data_size); 17924dbe8e44SKonstantin Komarov rp = NULL; 17934dbe8e44SKonstantin Komarov } 17944dbe8e44SKonstantin Komarov 17954dbe8e44SKonstantin Komarov if (size > sbi->reparse.max_size || size <= sizeof(u32)) 17964dbe8e44SKonstantin Komarov goto out; 17974dbe8e44SKonstantin Komarov 17984dbe8e44SKonstantin Komarov if (!rp) { 17994dbe8e44SKonstantin Komarov rp = kmalloc(size, GFP_NOFS); 180082cae269SKonstantin Komarov if (!rp) { 180182cae269SKonstantin Komarov err = -ENOMEM; 180282cae269SKonstantin Komarov goto out; 180382cae269SKonstantin Komarov } 180482cae269SKonstantin Komarov to_free = rp; 18054dbe8e44SKonstantin Komarov /* Read into temporal buffer. */ 18064dbe8e44SKonstantin Komarov err = ntfs_read_run_nb(sbi, &ni->file.run, 0, rp, size, NULL); 180782cae269SKonstantin Komarov if (err) 180882cae269SKonstantin Komarov goto out; 180982cae269SKonstantin Komarov } 181082cae269SKonstantin Komarov 1811e8b8e97fSKari Argillander /* Microsoft Tag. */ 181282cae269SKonstantin Komarov switch (rp->ReparseTag) { 181382cae269SKonstantin Komarov case IO_REPARSE_TAG_MOUNT_POINT: 1814e8b8e97fSKari Argillander /* Mount points and junctions. */ 181582cae269SKonstantin Komarov /* Can we use 'Rp->MountPointReparseBuffer.PrintNameLength'? */ 18164dbe8e44SKonstantin Komarov if (size <= offsetof(struct REPARSE_DATA_BUFFER, 181782cae269SKonstantin Komarov MountPointReparseBuffer.PathBuffer)) 181882cae269SKonstantin Komarov goto out; 18194dbe8e44SKonstantin Komarov uname = Add2Ptr(rp, 182082cae269SKonstantin Komarov offsetof(struct REPARSE_DATA_BUFFER, 182182cae269SKonstantin Komarov MountPointReparseBuffer.PathBuffer) + 182282cae269SKonstantin Komarov le16_to_cpu(rp->MountPointReparseBuffer 18234dbe8e44SKonstantin Komarov .PrintNameOffset)); 18244dbe8e44SKonstantin Komarov ulen = le16_to_cpu(rp->MountPointReparseBuffer.PrintNameLength); 182582cae269SKonstantin Komarov break; 182682cae269SKonstantin Komarov 182782cae269SKonstantin Komarov case IO_REPARSE_TAG_SYMLINK: 182882cae269SKonstantin Komarov /* FolderSymbolicLink */ 182982cae269SKonstantin Komarov /* Can we use 'Rp->SymbolicLinkReparseBuffer.PrintNameLength'? */ 18304dbe8e44SKonstantin Komarov if (size <= offsetof(struct REPARSE_DATA_BUFFER, 183182cae269SKonstantin Komarov SymbolicLinkReparseBuffer.PathBuffer)) 183282cae269SKonstantin Komarov goto out; 18334dbe8e44SKonstantin Komarov uname = Add2Ptr( 18344dbe8e44SKonstantin Komarov rp, offsetof(struct REPARSE_DATA_BUFFER, 183582cae269SKonstantin Komarov SymbolicLinkReparseBuffer.PathBuffer) + 183682cae269SKonstantin Komarov le16_to_cpu(rp->SymbolicLinkReparseBuffer 18374dbe8e44SKonstantin Komarov .PrintNameOffset)); 18384dbe8e44SKonstantin Komarov ulen = le16_to_cpu( 183982cae269SKonstantin Komarov rp->SymbolicLinkReparseBuffer.PrintNameLength); 184082cae269SKonstantin Komarov break; 184182cae269SKonstantin Komarov 184282cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD: 184382cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_1: 184482cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_2: 184582cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_3: 184682cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_4: 184782cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_5: 184882cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_6: 184982cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_7: 185082cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_8: 185182cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_9: 185282cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_A: 185382cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_B: 185482cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_C: 185582cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_D: 185682cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_E: 185782cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_F: 185882cae269SKonstantin Komarov err = sizeof("OneDrive") - 1; 185982cae269SKonstantin Komarov if (err > buflen) 186082cae269SKonstantin Komarov err = buflen; 186182cae269SKonstantin Komarov memcpy(buffer, "OneDrive", err); 186282cae269SKonstantin Komarov goto out; 186382cae269SKonstantin Komarov 186482cae269SKonstantin Komarov default: 186582cae269SKonstantin Komarov if (IsReparseTagMicrosoft(rp->ReparseTag)) { 1866d3624466SKonstantin Komarov /* Unknown Microsoft Tag. */ 186782cae269SKonstantin Komarov goto out; 186882cae269SKonstantin Komarov } 186982cae269SKonstantin Komarov if (!IsReparseTagNameSurrogate(rp->ReparseTag) || 18704dbe8e44SKonstantin Komarov size <= sizeof(struct REPARSE_POINT)) { 187182cae269SKonstantin Komarov goto out; 187282cae269SKonstantin Komarov } 187382cae269SKonstantin Komarov 1874e8b8e97fSKari Argillander /* Users tag. */ 18754dbe8e44SKonstantin Komarov uname = Add2Ptr(rp, sizeof(struct REPARSE_POINT)); 18764dbe8e44SKonstantin Komarov ulen = le16_to_cpu(rp->ReparseDataLength) - 187782cae269SKonstantin Komarov sizeof(struct REPARSE_POINT); 187882cae269SKonstantin Komarov } 187982cae269SKonstantin Komarov 1880e8b8e97fSKari Argillander /* Convert nlen from bytes to UNICODE chars. */ 18814dbe8e44SKonstantin Komarov ulen >>= 1; 188282cae269SKonstantin Komarov 1883e8b8e97fSKari Argillander /* Check that name is available. */ 18844dbe8e44SKonstantin Komarov if (!ulen || uname + ulen > (__le16 *)Add2Ptr(rp, size)) 188582cae269SKonstantin Komarov goto out; 188682cae269SKonstantin Komarov 1887e8b8e97fSKari Argillander /* If name is already zero terminated then truncate it now. */ 18884dbe8e44SKonstantin Komarov if (!uname[ulen - 1]) 18894dbe8e44SKonstantin Komarov ulen -= 1; 189082cae269SKonstantin Komarov 18914dbe8e44SKonstantin Komarov err = ntfs_utf16_to_nls(sbi, uname, ulen, buffer, buflen); 189282cae269SKonstantin Komarov 189382cae269SKonstantin Komarov if (err < 0) 189482cae269SKonstantin Komarov goto out; 189582cae269SKonstantin Komarov 1896e8b8e97fSKari Argillander /* Translate Windows '\' into Linux '/'. */ 189782cae269SKonstantin Komarov for (i = 0; i < err; i++) { 189882cae269SKonstantin Komarov if (buffer[i] == '\\') 189982cae269SKonstantin Komarov buffer[i] = '/'; 190082cae269SKonstantin Komarov } 190182cae269SKonstantin Komarov 1902e8b8e97fSKari Argillander /* Always set last zero. */ 190382cae269SKonstantin Komarov buffer[err] = 0; 190482cae269SKonstantin Komarov out: 1905195c52bdSKari Argillander kfree(to_free); 190682cae269SKonstantin Komarov return err; 190782cae269SKonstantin Komarov } 190882cae269SKonstantin Komarov 190982cae269SKonstantin Komarov static const char *ntfs_get_link(struct dentry *de, struct inode *inode, 191082cae269SKonstantin Komarov struct delayed_call *done) 191182cae269SKonstantin Komarov { 191282cae269SKonstantin Komarov int err; 191382cae269SKonstantin Komarov char *ret; 191482cae269SKonstantin Komarov 191582cae269SKonstantin Komarov if (!de) 191682cae269SKonstantin Komarov return ERR_PTR(-ECHILD); 191782cae269SKonstantin Komarov 191882cae269SKonstantin Komarov ret = kmalloc(PAGE_SIZE, GFP_NOFS); 191982cae269SKonstantin Komarov if (!ret) 192082cae269SKonstantin Komarov return ERR_PTR(-ENOMEM); 192182cae269SKonstantin Komarov 192282cae269SKonstantin Komarov err = ntfs_readlink_hlp(inode, ret, PAGE_SIZE); 192382cae269SKonstantin Komarov if (err < 0) { 192482cae269SKonstantin Komarov kfree(ret); 192582cae269SKonstantin Komarov return ERR_PTR(err); 192682cae269SKonstantin Komarov } 192782cae269SKonstantin Komarov 192882cae269SKonstantin Komarov set_delayed_call(done, kfree_link, ret); 192982cae269SKonstantin Komarov 193082cae269SKonstantin Komarov return ret; 193182cae269SKonstantin Komarov } 193282cae269SKonstantin Komarov 193382cae269SKonstantin Komarov // clang-format off 193482cae269SKonstantin Komarov const struct inode_operations ntfs_link_inode_operations = { 193582cae269SKonstantin Komarov .get_link = ntfs_get_link, 193682cae269SKonstantin Komarov .setattr = ntfs3_setattr, 193782cae269SKonstantin Komarov .listxattr = ntfs_listxattr, 193882cae269SKonstantin Komarov .permission = ntfs_permission, 193982cae269SKonstantin Komarov .get_acl = ntfs_get_acl, 194082cae269SKonstantin Komarov .set_acl = ntfs_set_acl, 194182cae269SKonstantin Komarov }; 194282cae269SKonstantin Komarov 194382cae269SKonstantin Komarov const struct address_space_operations ntfs_aops = { 1944f132ab7dSMatthew Wilcox (Oracle) .read_folio = ntfs_read_folio, 194582cae269SKonstantin Komarov .readahead = ntfs_readahead, 194682cae269SKonstantin Komarov .writepage = ntfs_writepage, 194782cae269SKonstantin Komarov .writepages = ntfs_writepages, 194882cae269SKonstantin Komarov .write_begin = ntfs_write_begin, 194982cae269SKonstantin Komarov .write_end = ntfs_write_end, 195082cae269SKonstantin Komarov .direct_IO = ntfs_direct_IO, 195182cae269SKonstantin Komarov .bmap = ntfs_bmap, 1952e621900aSMatthew Wilcox (Oracle) .dirty_folio = block_dirty_folio, 1953724bbe49SMikulas Patocka .invalidate_folio = block_invalidate_folio, 195482cae269SKonstantin Komarov }; 195582cae269SKonstantin Komarov 195682cae269SKonstantin Komarov const struct address_space_operations ntfs_aops_cmpr = { 1957f132ab7dSMatthew Wilcox (Oracle) .read_folio = ntfs_read_folio, 195882cae269SKonstantin Komarov .readahead = ntfs_readahead, 195982cae269SKonstantin Komarov }; 196082cae269SKonstantin Komarov // clang-format on 1961