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 36782cae269SKonstantin Komarov t64 = le64_to_cpu(attr->nres.svcn); 36882cae269SKonstantin Komarov err = run_unpack_ex(run, sbi, ino, t64, le64_to_cpu(attr->nres.evcn), 36982cae269SKonstantin Komarov t64, Add2Ptr(attr, roff), asize - roff); 37082cae269SKonstantin Komarov if (err < 0) 37182cae269SKonstantin Komarov goto out; 37282cae269SKonstantin Komarov err = 0; 37382cae269SKonstantin Komarov goto next_attr; 37482cae269SKonstantin Komarov 37582cae269SKonstantin Komarov end_enum: 37682cae269SKonstantin Komarov 37782cae269SKonstantin Komarov if (!std5) 37882cae269SKonstantin Komarov goto out; 37982cae269SKonstantin Komarov 38082cae269SKonstantin Komarov if (!is_match && name) { 381e8b8e97fSKari Argillander /* Reuse rec as buffer for ascii name. */ 38282cae269SKonstantin Komarov err = -ENOENT; 38382cae269SKonstantin Komarov goto out; 38482cae269SKonstantin Komarov } 38582cae269SKonstantin Komarov 38682cae269SKonstantin Komarov if (std5->fa & FILE_ATTRIBUTE_READONLY) 38782cae269SKonstantin Komarov mode &= ~0222; 38882cae269SKonstantin Komarov 38982cae269SKonstantin Komarov if (!names) { 39082cae269SKonstantin Komarov err = -EINVAL; 39182cae269SKonstantin Komarov goto out; 39282cae269SKonstantin Komarov } 39382cae269SKonstantin Komarov 39478ab59feSKonstantin Komarov if (names != le16_to_cpu(rec->hard_links)) { 39578ab59feSKonstantin Komarov /* Correct minor error on the fly. Do not mark inode as dirty. */ 39678ab59feSKonstantin Komarov rec->hard_links = cpu_to_le16(names); 39778ab59feSKonstantin Komarov ni->mi.dirty = true; 39878ab59feSKonstantin Komarov } 39978ab59feSKonstantin Komarov 40082cae269SKonstantin Komarov set_nlink(inode, names); 40182cae269SKonstantin Komarov 40282cae269SKonstantin Komarov if (S_ISDIR(mode)) { 40382cae269SKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_DIRECTORY; 40482cae269SKonstantin Komarov 40582cae269SKonstantin Komarov /* 406e8b8e97fSKari Argillander * Dot and dot-dot should be included in count but was not 40782cae269SKonstantin Komarov * included in enumeration. 408e8b8e97fSKari Argillander * Usually a hard links to directories are disabled. 40982cae269SKonstantin Komarov */ 41082cae269SKonstantin Komarov inode->i_op = &ntfs_dir_inode_operations; 41182cae269SKonstantin Komarov inode->i_fop = &ntfs_dir_operations; 41282cae269SKonstantin Komarov ni->i_valid = 0; 41382cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 41482cae269SKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; 41582cae269SKonstantin Komarov inode->i_op = &ntfs_link_inode_operations; 41682cae269SKonstantin Komarov inode->i_fop = NULL; 41722b05f1aSKonstantin Komarov inode_nohighmem(inode); 41882cae269SKonstantin Komarov } else if (S_ISREG(mode)) { 41982cae269SKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; 42082cae269SKonstantin Komarov inode->i_op = &ntfs_file_inode_operations; 42182cae269SKonstantin Komarov inode->i_fop = &ntfs_file_operations; 42282cae269SKonstantin Komarov inode->i_mapping->a_ops = 42382cae269SKonstantin Komarov is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops; 42482cae269SKonstantin Komarov if (ino != MFT_REC_MFT) 42582cae269SKonstantin Komarov init_rwsem(&ni->file.run_lock); 42682cae269SKonstantin Komarov } else if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) || 42782cae269SKonstantin Komarov S_ISSOCK(mode)) { 42882cae269SKonstantin Komarov inode->i_op = &ntfs_special_inode_operations; 42982cae269SKonstantin Komarov init_special_inode(inode, mode, inode->i_rdev); 43082cae269SKonstantin Komarov } else if (fname && fname->home.low == cpu_to_le32(MFT_REC_EXTEND) && 43182cae269SKonstantin Komarov fname->home.seq == cpu_to_le16(MFT_REC_EXTEND)) { 432e8b8e97fSKari Argillander /* Records in $Extend are not a files or general directories. */ 43382cae269SKonstantin Komarov } else { 43482cae269SKonstantin Komarov err = -EINVAL; 43582cae269SKonstantin Komarov goto out; 43682cae269SKonstantin Komarov } 43782cae269SKonstantin Komarov 438564c97bdSKari Argillander if ((sbi->options->sys_immutable && 43982cae269SKonstantin Komarov (std5->fa & FILE_ATTRIBUTE_SYSTEM)) && 44082cae269SKonstantin Komarov !S_ISFIFO(mode) && !S_ISSOCK(mode) && !S_ISLNK(mode)) { 44182cae269SKonstantin Komarov inode->i_flags |= S_IMMUTABLE; 44282cae269SKonstantin Komarov } else { 44382cae269SKonstantin Komarov inode->i_flags &= ~S_IMMUTABLE; 44482cae269SKonstantin Komarov } 44582cae269SKonstantin Komarov 44682cae269SKonstantin Komarov inode->i_mode = mode; 44782cae269SKonstantin Komarov if (!(ni->ni_flags & NI_FLAG_EA)) { 448e8b8e97fSKari Argillander /* If no xattr then no security (stored in xattr). */ 44982cae269SKonstantin Komarov inode->i_flags |= S_NOSEC; 45082cae269SKonstantin Komarov } 45182cae269SKonstantin Komarov 45282cae269SKonstantin Komarov Ok: 45382cae269SKonstantin Komarov if (ino == MFT_REC_MFT && !sb->s_root) 45482cae269SKonstantin Komarov sbi->mft.ni = NULL; 45582cae269SKonstantin Komarov 45682cae269SKonstantin Komarov unlock_new_inode(inode); 45782cae269SKonstantin Komarov 45882cae269SKonstantin Komarov return inode; 45982cae269SKonstantin Komarov 46082cae269SKonstantin Komarov out: 46182cae269SKonstantin Komarov if (ino == MFT_REC_MFT && !sb->s_root) 46282cae269SKonstantin Komarov sbi->mft.ni = NULL; 46382cae269SKonstantin Komarov 46482cae269SKonstantin Komarov iget_failed(inode); 46582cae269SKonstantin Komarov return ERR_PTR(err); 46682cae269SKonstantin Komarov } 46782cae269SKonstantin Komarov 468e8b8e97fSKari Argillander /* 469e8b8e97fSKari Argillander * ntfs_test_inode 470e8b8e97fSKari Argillander * 471e8b8e97fSKari Argillander * Return: 1 if match. 472e8b8e97fSKari Argillander */ 47382cae269SKonstantin Komarov static int ntfs_test_inode(struct inode *inode, void *data) 47482cae269SKonstantin Komarov { 47582cae269SKonstantin Komarov struct MFT_REF *ref = data; 47682cae269SKonstantin Komarov 47782cae269SKonstantin Komarov return ino_get(ref) == inode->i_ino; 47882cae269SKonstantin Komarov } 47982cae269SKonstantin Komarov 48082cae269SKonstantin Komarov static int ntfs_set_inode(struct inode *inode, void *data) 48182cae269SKonstantin Komarov { 48282cae269SKonstantin Komarov const struct MFT_REF *ref = data; 48382cae269SKonstantin Komarov 48482cae269SKonstantin Komarov inode->i_ino = ino_get(ref); 48582cae269SKonstantin Komarov return 0; 48682cae269SKonstantin Komarov } 48782cae269SKonstantin Komarov 48882cae269SKonstantin Komarov struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref, 48982cae269SKonstantin Komarov const struct cpu_str *name) 49082cae269SKonstantin Komarov { 49182cae269SKonstantin Komarov struct inode *inode; 49282cae269SKonstantin Komarov 49382cae269SKonstantin Komarov inode = iget5_locked(sb, ino_get(ref), ntfs_test_inode, ntfs_set_inode, 49482cae269SKonstantin Komarov (void *)ref); 49582cae269SKonstantin Komarov if (unlikely(!inode)) 49682cae269SKonstantin Komarov return ERR_PTR(-ENOMEM); 49782cae269SKonstantin Komarov 49882cae269SKonstantin Komarov /* If this is a freshly allocated inode, need to read it now. */ 49982cae269SKonstantin Komarov if (inode->i_state & I_NEW) 50082cae269SKonstantin Komarov inode = ntfs_read_mft(inode, name, ref); 50182cae269SKonstantin Komarov else if (ref->seq != ntfs_i(inode)->mi.mrec->seq) { 502e8b8e97fSKari Argillander /* Inode overlaps? */ 50382cae269SKonstantin Komarov make_bad_inode(inode); 50482cae269SKonstantin Komarov } 50582cae269SKonstantin Komarov 50682cae269SKonstantin Komarov return inode; 50782cae269SKonstantin Komarov } 50882cae269SKonstantin Komarov 50982cae269SKonstantin Komarov enum get_block_ctx { 51082cae269SKonstantin Komarov GET_BLOCK_GENERAL = 0, 51182cae269SKonstantin Komarov GET_BLOCK_WRITE_BEGIN = 1, 51282cae269SKonstantin Komarov GET_BLOCK_DIRECT_IO_R = 2, 51382cae269SKonstantin Komarov GET_BLOCK_DIRECT_IO_W = 3, 51482cae269SKonstantin Komarov GET_BLOCK_BMAP = 4, 51582cae269SKonstantin Komarov }; 51682cae269SKonstantin Komarov 51782cae269SKonstantin Komarov static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo, 51882cae269SKonstantin Komarov struct buffer_head *bh, int create, 51982cae269SKonstantin Komarov enum get_block_ctx ctx) 52082cae269SKonstantin Komarov { 52182cae269SKonstantin Komarov struct super_block *sb = inode->i_sb; 52282cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 52382cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 52482cae269SKonstantin Komarov struct page *page = bh->b_page; 52582cae269SKonstantin Komarov u8 cluster_bits = sbi->cluster_bits; 52682cae269SKonstantin Komarov u32 block_size = sb->s_blocksize; 52782cae269SKonstantin Komarov u64 bytes, lbo, valid; 52882cae269SKonstantin Komarov u32 off; 52982cae269SKonstantin Komarov int err; 53082cae269SKonstantin Komarov CLST vcn, lcn, len; 53182cae269SKonstantin Komarov bool new; 53282cae269SKonstantin Komarov 533e8b8e97fSKari Argillander /* Clear previous state. */ 53482cae269SKonstantin Komarov clear_buffer_new(bh); 53582cae269SKonstantin Komarov clear_buffer_uptodate(bh); 53682cae269SKonstantin Komarov 537e8b8e97fSKari Argillander /* Direct write uses 'create=0'. */ 53882cae269SKonstantin Komarov if (!create && vbo >= ni->i_valid) { 539e8b8e97fSKari Argillander /* Out of valid. */ 54082cae269SKonstantin Komarov return 0; 54182cae269SKonstantin Komarov } 54282cae269SKonstantin Komarov 54382cae269SKonstantin Komarov if (vbo >= inode->i_size) { 544e8b8e97fSKari Argillander /* Out of size. */ 54582cae269SKonstantin Komarov return 0; 54682cae269SKonstantin Komarov } 54782cae269SKonstantin Komarov 54882cae269SKonstantin Komarov if (is_resident(ni)) { 54982cae269SKonstantin Komarov ni_lock(ni); 55082cae269SKonstantin Komarov err = attr_data_read_resident(ni, page); 55182cae269SKonstantin Komarov ni_unlock(ni); 55282cae269SKonstantin Komarov 55382cae269SKonstantin Komarov if (!err) 55482cae269SKonstantin Komarov set_buffer_uptodate(bh); 55582cae269SKonstantin Komarov bh->b_size = block_size; 55682cae269SKonstantin Komarov return err; 55782cae269SKonstantin Komarov } 55882cae269SKonstantin Komarov 55982cae269SKonstantin Komarov vcn = vbo >> cluster_bits; 56082cae269SKonstantin Komarov off = vbo & sbi->cluster_mask; 56182cae269SKonstantin Komarov new = false; 56282cae269SKonstantin Komarov 56382cae269SKonstantin Komarov err = attr_data_get_block(ni, vcn, 1, &lcn, &len, create ? &new : NULL); 56482cae269SKonstantin Komarov if (err) 56582cae269SKonstantin Komarov goto out; 56682cae269SKonstantin Komarov 56782cae269SKonstantin Komarov if (!len) 56882cae269SKonstantin Komarov return 0; 56982cae269SKonstantin Komarov 57082cae269SKonstantin Komarov bytes = ((u64)len << cluster_bits) - off; 57182cae269SKonstantin Komarov 57282cae269SKonstantin Komarov if (lcn == SPARSE_LCN) { 57382cae269SKonstantin Komarov if (!create) { 57482cae269SKonstantin Komarov if (bh->b_size > bytes) 57582cae269SKonstantin Komarov bh->b_size = bytes; 57682cae269SKonstantin Komarov return 0; 57782cae269SKonstantin Komarov } 57882cae269SKonstantin Komarov WARN_ON(1); 57982cae269SKonstantin Komarov } 58082cae269SKonstantin Komarov 58182cae269SKonstantin Komarov if (new) { 58282cae269SKonstantin Komarov set_buffer_new(bh); 58382cae269SKonstantin Komarov if ((len << cluster_bits) > block_size) 58482cae269SKonstantin Komarov ntfs_sparse_cluster(inode, page, vcn, len); 58582cae269SKonstantin Komarov } 58682cae269SKonstantin Komarov 58782cae269SKonstantin Komarov lbo = ((u64)lcn << cluster_bits) + off; 58882cae269SKonstantin Komarov 58982cae269SKonstantin Komarov set_buffer_mapped(bh); 59082cae269SKonstantin Komarov bh->b_bdev = sb->s_bdev; 59182cae269SKonstantin Komarov bh->b_blocknr = lbo >> sb->s_blocksize_bits; 59282cae269SKonstantin Komarov 59382cae269SKonstantin Komarov valid = ni->i_valid; 59482cae269SKonstantin Komarov 59582cae269SKonstantin Komarov if (ctx == GET_BLOCK_DIRECT_IO_W) { 596e8b8e97fSKari Argillander /* ntfs_direct_IO will update ni->i_valid. */ 59782cae269SKonstantin Komarov if (vbo >= valid) 59882cae269SKonstantin Komarov set_buffer_new(bh); 59982cae269SKonstantin Komarov } else if (create) { 600d3624466SKonstantin Komarov /* Normal write. */ 60182cae269SKonstantin Komarov if (bytes > bh->b_size) 60282cae269SKonstantin Komarov bytes = bh->b_size; 60382cae269SKonstantin Komarov 60482cae269SKonstantin Komarov if (vbo >= valid) 60582cae269SKonstantin Komarov set_buffer_new(bh); 60682cae269SKonstantin Komarov 60782cae269SKonstantin Komarov if (vbo + bytes > valid) { 60882cae269SKonstantin Komarov ni->i_valid = vbo + bytes; 60982cae269SKonstantin Komarov mark_inode_dirty(inode); 61082cae269SKonstantin Komarov } 61182cae269SKonstantin Komarov } else if (vbo >= valid) { 612e8b8e97fSKari Argillander /* Read out of valid data. */ 613e8b8e97fSKari Argillander /* Should never be here 'cause already checked. */ 61482cae269SKonstantin Komarov clear_buffer_mapped(bh); 61582cae269SKonstantin Komarov } else if (vbo + bytes <= valid) { 616e8b8e97fSKari Argillander /* Normal read. */ 61782cae269SKonstantin Komarov } else if (vbo + block_size <= valid) { 618e8b8e97fSKari Argillander /* Normal short read. */ 61982cae269SKonstantin Komarov bytes = block_size; 62082cae269SKonstantin Komarov } else { 62182cae269SKonstantin Komarov /* 622e8b8e97fSKari Argillander * Read across valid size: vbo < valid && valid < vbo + block_size 62382cae269SKonstantin Komarov */ 62482cae269SKonstantin Komarov bytes = block_size; 62582cae269SKonstantin Komarov 62682cae269SKonstantin Komarov if (page) { 62782cae269SKonstantin Komarov u32 voff = valid - vbo; 62882cae269SKonstantin Komarov 62982cae269SKonstantin Komarov bh->b_size = block_size; 63082cae269SKonstantin Komarov off = vbo & (PAGE_SIZE - 1); 63182cae269SKonstantin Komarov set_bh_page(bh, page, off); 63282cae269SKonstantin Komarov ll_rw_block(REQ_OP_READ, 0, 1, &bh); 63382cae269SKonstantin Komarov wait_on_buffer(bh); 63482cae269SKonstantin Komarov if (!buffer_uptodate(bh)) { 63582cae269SKonstantin Komarov err = -EIO; 63682cae269SKonstantin Komarov goto out; 63782cae269SKonstantin Komarov } 63882cae269SKonstantin Komarov zero_user_segment(page, off + voff, off + block_size); 63982cae269SKonstantin Komarov } 64082cae269SKonstantin Komarov } 64182cae269SKonstantin Komarov 64282cae269SKonstantin Komarov if (bh->b_size > bytes) 64382cae269SKonstantin Komarov bh->b_size = bytes; 64482cae269SKonstantin Komarov 64582cae269SKonstantin Komarov #ifndef __LP64__ 64682cae269SKonstantin Komarov if (ctx == GET_BLOCK_DIRECT_IO_W || ctx == GET_BLOCK_DIRECT_IO_R) { 64782cae269SKonstantin Komarov static_assert(sizeof(size_t) < sizeof(loff_t)); 64882cae269SKonstantin Komarov if (bytes > 0x40000000u) 64982cae269SKonstantin Komarov bh->b_size = 0x40000000u; 65082cae269SKonstantin Komarov } 65182cae269SKonstantin Komarov #endif 65282cae269SKonstantin Komarov 65382cae269SKonstantin Komarov return 0; 65482cae269SKonstantin Komarov 65582cae269SKonstantin Komarov out: 65682cae269SKonstantin Komarov return err; 65782cae269SKonstantin Komarov } 65882cae269SKonstantin Komarov 65982cae269SKonstantin Komarov int ntfs_get_block(struct inode *inode, sector_t vbn, 66082cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 66182cae269SKonstantin Komarov { 66282cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, (u64)vbn << inode->i_blkbits, 66382cae269SKonstantin Komarov bh_result, create, GET_BLOCK_GENERAL); 66482cae269SKonstantin Komarov } 66582cae269SKonstantin Komarov 66682cae269SKonstantin Komarov static int ntfs_get_block_bmap(struct inode *inode, sector_t vsn, 66782cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 66882cae269SKonstantin Komarov { 66982cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, 67082cae269SKonstantin Komarov (u64)vsn << inode->i_sb->s_blocksize_bits, 67182cae269SKonstantin Komarov bh_result, create, GET_BLOCK_BMAP); 67282cae269SKonstantin Komarov } 67382cae269SKonstantin Komarov 67482cae269SKonstantin Komarov static sector_t ntfs_bmap(struct address_space *mapping, sector_t block) 67582cae269SKonstantin Komarov { 67682cae269SKonstantin Komarov return generic_block_bmap(mapping, block, ntfs_get_block_bmap); 67782cae269SKonstantin Komarov } 67882cae269SKonstantin Komarov 67982cae269SKonstantin Komarov static int ntfs_readpage(struct file *file, struct page *page) 68082cae269SKonstantin Komarov { 68182cae269SKonstantin Komarov int err; 68282cae269SKonstantin Komarov struct address_space *mapping = page->mapping; 68382cae269SKonstantin Komarov struct inode *inode = mapping->host; 68482cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 68582cae269SKonstantin Komarov 68682cae269SKonstantin Komarov if (is_resident(ni)) { 68782cae269SKonstantin Komarov ni_lock(ni); 68882cae269SKonstantin Komarov err = attr_data_read_resident(ni, page); 68982cae269SKonstantin Komarov ni_unlock(ni); 69082cae269SKonstantin Komarov if (err != E_NTFS_NONRESIDENT) { 69182cae269SKonstantin Komarov unlock_page(page); 69282cae269SKonstantin Komarov return err; 69382cae269SKonstantin Komarov } 69482cae269SKonstantin Komarov } 69582cae269SKonstantin Komarov 69682cae269SKonstantin Komarov if (is_compressed(ni)) { 69782cae269SKonstantin Komarov ni_lock(ni); 69882cae269SKonstantin Komarov err = ni_readpage_cmpr(ni, page); 69982cae269SKonstantin Komarov ni_unlock(ni); 70082cae269SKonstantin Komarov return err; 70182cae269SKonstantin Komarov } 70282cae269SKonstantin Komarov 703e8b8e97fSKari Argillander /* Normal + sparse files. */ 70482cae269SKonstantin Komarov return mpage_readpage(page, ntfs_get_block); 70582cae269SKonstantin Komarov } 70682cae269SKonstantin Komarov 70782cae269SKonstantin Komarov static void ntfs_readahead(struct readahead_control *rac) 70882cae269SKonstantin Komarov { 70982cae269SKonstantin Komarov struct address_space *mapping = rac->mapping; 71082cae269SKonstantin Komarov struct inode *inode = mapping->host; 71182cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 71282cae269SKonstantin Komarov u64 valid; 71382cae269SKonstantin Komarov loff_t pos; 71482cae269SKonstantin Komarov 71582cae269SKonstantin Komarov if (is_resident(ni)) { 716e8b8e97fSKari Argillander /* No readahead for resident. */ 71782cae269SKonstantin Komarov return; 71882cae269SKonstantin Komarov } 71982cae269SKonstantin Komarov 72082cae269SKonstantin Komarov if (is_compressed(ni)) { 721e8b8e97fSKari Argillander /* No readahead for compressed. */ 72282cae269SKonstantin Komarov return; 72382cae269SKonstantin Komarov } 72482cae269SKonstantin Komarov 72582cae269SKonstantin Komarov valid = ni->i_valid; 72682cae269SKonstantin Komarov pos = readahead_pos(rac); 72782cae269SKonstantin Komarov 72882cae269SKonstantin Komarov if (valid < i_size_read(inode) && pos <= valid && 72982cae269SKonstantin Komarov valid < pos + readahead_length(rac)) { 730e8b8e97fSKari Argillander /* Range cross 'valid'. Read it page by page. */ 73182cae269SKonstantin Komarov return; 73282cae269SKonstantin Komarov } 73382cae269SKonstantin Komarov 73482cae269SKonstantin Komarov mpage_readahead(rac, ntfs_get_block); 73582cae269SKonstantin Komarov } 73682cae269SKonstantin Komarov 73782cae269SKonstantin Komarov static int ntfs_get_block_direct_IO_R(struct inode *inode, sector_t iblock, 73882cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 73982cae269SKonstantin Komarov { 74082cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, (u64)iblock << inode->i_blkbits, 74182cae269SKonstantin Komarov bh_result, create, GET_BLOCK_DIRECT_IO_R); 74282cae269SKonstantin Komarov } 74382cae269SKonstantin Komarov 74482cae269SKonstantin Komarov static int ntfs_get_block_direct_IO_W(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_W); 74982cae269SKonstantin Komarov } 75082cae269SKonstantin Komarov 75182cae269SKonstantin Komarov static ssize_t ntfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 75282cae269SKonstantin Komarov { 75382cae269SKonstantin Komarov struct file *file = iocb->ki_filp; 75482cae269SKonstantin Komarov struct address_space *mapping = file->f_mapping; 75582cae269SKonstantin Komarov struct inode *inode = mapping->host; 75682cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 75782cae269SKonstantin Komarov loff_t vbo = iocb->ki_pos; 75882cae269SKonstantin Komarov loff_t end; 75982cae269SKonstantin Komarov int wr = iov_iter_rw(iter) & WRITE; 760*52e00ea6SKonstantin Komarov size_t iter_count = iov_iter_count(iter); 76182cae269SKonstantin Komarov loff_t valid; 76282cae269SKonstantin Komarov ssize_t ret; 76382cae269SKonstantin Komarov 76482cae269SKonstantin Komarov if (is_resident(ni)) { 765e8b8e97fSKari Argillander /* Switch to buffered write. */ 76682cae269SKonstantin Komarov ret = 0; 76782cae269SKonstantin Komarov goto out; 76882cae269SKonstantin Komarov } 76982cae269SKonstantin Komarov 77082cae269SKonstantin Komarov ret = blockdev_direct_IO(iocb, inode, iter, 77182cae269SKonstantin Komarov wr ? ntfs_get_block_direct_IO_W 77282cae269SKonstantin Komarov : ntfs_get_block_direct_IO_R); 77382cae269SKonstantin Komarov 774*52e00ea6SKonstantin Komarov if (ret > 0) 775*52e00ea6SKonstantin Komarov end = vbo + ret; 776*52e00ea6SKonstantin Komarov else if (wr && ret == -EIOCBQUEUED) 777*52e00ea6SKonstantin Komarov end = vbo + iter_count; 778*52e00ea6SKonstantin Komarov else 77982cae269SKonstantin Komarov goto out; 78082cae269SKonstantin Komarov 78182cae269SKonstantin Komarov valid = ni->i_valid; 78282cae269SKonstantin Komarov if (wr) { 78382cae269SKonstantin Komarov if (end > valid && !S_ISBLK(inode->i_mode)) { 78482cae269SKonstantin Komarov ni->i_valid = end; 78582cae269SKonstantin Komarov mark_inode_dirty(inode); 78682cae269SKonstantin Komarov } 78782cae269SKonstantin Komarov } else if (vbo < valid && valid < end) { 788e8b8e97fSKari Argillander /* Fix page. */ 78982cae269SKonstantin Komarov iov_iter_revert(iter, end - valid); 79082cae269SKonstantin Komarov iov_iter_zero(end - valid, iter); 79182cae269SKonstantin Komarov } 79282cae269SKonstantin Komarov 79382cae269SKonstantin Komarov out: 79482cae269SKonstantin Komarov return ret; 79582cae269SKonstantin Komarov } 79682cae269SKonstantin Komarov 79782cae269SKonstantin Komarov int ntfs_set_size(struct inode *inode, u64 new_size) 79882cae269SKonstantin Komarov { 79982cae269SKonstantin Komarov struct super_block *sb = inode->i_sb; 80082cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 80182cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 80282cae269SKonstantin Komarov int err; 80382cae269SKonstantin Komarov 804e8b8e97fSKari Argillander /* Check for maximum file size. */ 80582cae269SKonstantin Komarov if (is_sparsed(ni) || is_compressed(ni)) { 80682cae269SKonstantin Komarov if (new_size > sbi->maxbytes_sparse) { 80782cae269SKonstantin Komarov err = -EFBIG; 80882cae269SKonstantin Komarov goto out; 80982cae269SKonstantin Komarov } 81082cae269SKonstantin Komarov } else if (new_size > sbi->maxbytes) { 81182cae269SKonstantin Komarov err = -EFBIG; 81282cae269SKonstantin Komarov goto out; 81382cae269SKonstantin Komarov } 81482cae269SKonstantin Komarov 81582cae269SKonstantin Komarov ni_lock(ni); 81682cae269SKonstantin Komarov down_write(&ni->file.run_lock); 81782cae269SKonstantin Komarov 81882cae269SKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size, 81982cae269SKonstantin Komarov &ni->i_valid, true, NULL); 82082cae269SKonstantin Komarov 82182cae269SKonstantin Komarov up_write(&ni->file.run_lock); 82282cae269SKonstantin Komarov ni_unlock(ni); 82382cae269SKonstantin Komarov 82482cae269SKonstantin Komarov mark_inode_dirty(inode); 82582cae269SKonstantin Komarov 82682cae269SKonstantin Komarov out: 82782cae269SKonstantin Komarov return err; 82882cae269SKonstantin Komarov } 82982cae269SKonstantin Komarov 83082cae269SKonstantin Komarov static int ntfs_writepage(struct page *page, struct writeback_control *wbc) 83182cae269SKonstantin Komarov { 83282cae269SKonstantin Komarov struct address_space *mapping = page->mapping; 83382cae269SKonstantin Komarov struct inode *inode = mapping->host; 83482cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 83582cae269SKonstantin Komarov int err; 83682cae269SKonstantin Komarov 83782cae269SKonstantin Komarov if (is_resident(ni)) { 83882cae269SKonstantin Komarov ni_lock(ni); 83982cae269SKonstantin Komarov err = attr_data_write_resident(ni, page); 84082cae269SKonstantin Komarov ni_unlock(ni); 84182cae269SKonstantin Komarov if (err != E_NTFS_NONRESIDENT) { 84282cae269SKonstantin Komarov unlock_page(page); 84382cae269SKonstantin Komarov return err; 84482cae269SKonstantin Komarov } 84582cae269SKonstantin Komarov } 84682cae269SKonstantin Komarov 84782cae269SKonstantin Komarov return block_write_full_page(page, ntfs_get_block, wbc); 84882cae269SKonstantin Komarov } 84982cae269SKonstantin Komarov 85082cae269SKonstantin Komarov static int ntfs_writepages(struct address_space *mapping, 85182cae269SKonstantin Komarov struct writeback_control *wbc) 85282cae269SKonstantin Komarov { 85382cae269SKonstantin Komarov struct inode *inode = mapping->host; 85482cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 855e8b8e97fSKari Argillander /* Redirect call to 'ntfs_writepage' for resident files. */ 85682cae269SKonstantin Komarov get_block_t *get_block = is_resident(ni) ? NULL : &ntfs_get_block; 85782cae269SKonstantin Komarov 85882cae269SKonstantin Komarov return mpage_writepages(mapping, wbc, get_block); 85982cae269SKonstantin Komarov } 86082cae269SKonstantin Komarov 86182cae269SKonstantin Komarov static int ntfs_get_block_write_begin(struct inode *inode, sector_t vbn, 86282cae269SKonstantin Komarov struct buffer_head *bh_result, int create) 86382cae269SKonstantin Komarov { 86482cae269SKonstantin Komarov return ntfs_get_block_vbo(inode, (u64)vbn << inode->i_blkbits, 86582cae269SKonstantin Komarov bh_result, create, GET_BLOCK_WRITE_BEGIN); 86682cae269SKonstantin Komarov } 86782cae269SKonstantin Komarov 86882cae269SKonstantin Komarov static int ntfs_write_begin(struct file *file, struct address_space *mapping, 86982cae269SKonstantin Komarov loff_t pos, u32 len, u32 flags, struct page **pagep, 87082cae269SKonstantin Komarov void **fsdata) 87182cae269SKonstantin Komarov { 87282cae269SKonstantin Komarov int err; 87382cae269SKonstantin Komarov struct inode *inode = mapping->host; 87482cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 87582cae269SKonstantin Komarov 87682cae269SKonstantin Komarov *pagep = NULL; 87782cae269SKonstantin Komarov if (is_resident(ni)) { 87882cae269SKonstantin Komarov struct page *page = grab_cache_page_write_begin( 87982cae269SKonstantin Komarov mapping, pos >> PAGE_SHIFT, flags); 88082cae269SKonstantin Komarov 88182cae269SKonstantin Komarov if (!page) { 88282cae269SKonstantin Komarov err = -ENOMEM; 88382cae269SKonstantin Komarov goto out; 88482cae269SKonstantin Komarov } 88582cae269SKonstantin Komarov 88682cae269SKonstantin Komarov ni_lock(ni); 88782cae269SKonstantin Komarov err = attr_data_read_resident(ni, page); 88882cae269SKonstantin Komarov ni_unlock(ni); 88982cae269SKonstantin Komarov 89082cae269SKonstantin Komarov if (!err) { 89182cae269SKonstantin Komarov *pagep = page; 89282cae269SKonstantin Komarov goto out; 89382cae269SKonstantin Komarov } 89482cae269SKonstantin Komarov unlock_page(page); 89582cae269SKonstantin Komarov put_page(page); 89682cae269SKonstantin Komarov 89782cae269SKonstantin Komarov if (err != E_NTFS_NONRESIDENT) 89882cae269SKonstantin Komarov goto out; 89982cae269SKonstantin Komarov } 90082cae269SKonstantin Komarov 90182cae269SKonstantin Komarov err = block_write_begin(mapping, pos, len, flags, pagep, 90282cae269SKonstantin Komarov ntfs_get_block_write_begin); 90382cae269SKonstantin Komarov 90482cae269SKonstantin Komarov out: 90582cae269SKonstantin Komarov return err; 90682cae269SKonstantin Komarov } 90782cae269SKonstantin Komarov 908e8b8e97fSKari Argillander /* 909e8b8e97fSKari Argillander * ntfs_write_end - Address_space_operations::write_end. 910e8b8e97fSKari Argillander */ 91182cae269SKonstantin Komarov static int ntfs_write_end(struct file *file, struct address_space *mapping, 91282cae269SKonstantin Komarov loff_t pos, u32 len, u32 copied, struct page *page, 91382cae269SKonstantin Komarov void *fsdata) 91482cae269SKonstantin Komarov 91582cae269SKonstantin Komarov { 91682cae269SKonstantin Komarov struct inode *inode = mapping->host; 91782cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 91882cae269SKonstantin Komarov u64 valid = ni->i_valid; 91982cae269SKonstantin Komarov bool dirty = false; 92082cae269SKonstantin Komarov int err; 92182cae269SKonstantin Komarov 92282cae269SKonstantin Komarov if (is_resident(ni)) { 92382cae269SKonstantin Komarov ni_lock(ni); 92482cae269SKonstantin Komarov err = attr_data_write_resident(ni, page); 92582cae269SKonstantin Komarov ni_unlock(ni); 92682cae269SKonstantin Komarov if (!err) { 92782cae269SKonstantin Komarov dirty = true; 928e8b8e97fSKari Argillander /* Clear any buffers in page. */ 92982cae269SKonstantin Komarov if (page_has_buffers(page)) { 93082cae269SKonstantin Komarov struct buffer_head *head, *bh; 93182cae269SKonstantin Komarov 93282cae269SKonstantin Komarov bh = head = page_buffers(page); 93382cae269SKonstantin Komarov do { 93482cae269SKonstantin Komarov clear_buffer_dirty(bh); 93582cae269SKonstantin Komarov clear_buffer_mapped(bh); 93682cae269SKonstantin Komarov set_buffer_uptodate(bh); 93782cae269SKonstantin Komarov } while (head != (bh = bh->b_this_page)); 93882cae269SKonstantin Komarov } 93982cae269SKonstantin Komarov SetPageUptodate(page); 94082cae269SKonstantin Komarov err = copied; 94182cae269SKonstantin Komarov } 94282cae269SKonstantin Komarov unlock_page(page); 94382cae269SKonstantin Komarov put_page(page); 94482cae269SKonstantin Komarov } else { 94582cae269SKonstantin Komarov err = generic_write_end(file, mapping, pos, len, copied, page, 94682cae269SKonstantin Komarov fsdata); 94782cae269SKonstantin Komarov } 94882cae269SKonstantin Komarov 94982cae269SKonstantin Komarov if (err >= 0) { 95082cae269SKonstantin Komarov if (!(ni->std_fa & FILE_ATTRIBUTE_ARCHIVE)) { 95182cae269SKonstantin Komarov inode->i_ctime = inode->i_mtime = current_time(inode); 95282cae269SKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE; 95382cae269SKonstantin Komarov dirty = true; 95482cae269SKonstantin Komarov } 95582cae269SKonstantin Komarov 95682cae269SKonstantin Komarov if (valid != ni->i_valid) { 957e8b8e97fSKari Argillander /* ni->i_valid is changed in ntfs_get_block_vbo. */ 95882cae269SKonstantin Komarov dirty = true; 95982cae269SKonstantin Komarov } 96082cae269SKonstantin Komarov 96182cae269SKonstantin Komarov if (dirty) 96282cae269SKonstantin Komarov mark_inode_dirty(inode); 96382cae269SKonstantin Komarov } 96482cae269SKonstantin Komarov 96582cae269SKonstantin Komarov return err; 96682cae269SKonstantin Komarov } 96782cae269SKonstantin Komarov 96882cae269SKonstantin Komarov int reset_log_file(struct inode *inode) 96982cae269SKonstantin Komarov { 97082cae269SKonstantin Komarov int err; 97182cae269SKonstantin Komarov loff_t pos = 0; 97282cae269SKonstantin Komarov u32 log_size = inode->i_size; 97382cae269SKonstantin Komarov struct address_space *mapping = inode->i_mapping; 97482cae269SKonstantin Komarov 97582cae269SKonstantin Komarov for (;;) { 97682cae269SKonstantin Komarov u32 len; 97782cae269SKonstantin Komarov void *kaddr; 97882cae269SKonstantin Komarov struct page *page; 97982cae269SKonstantin Komarov 98082cae269SKonstantin Komarov len = pos + PAGE_SIZE > log_size ? (log_size - pos) : PAGE_SIZE; 98182cae269SKonstantin Komarov 98282cae269SKonstantin Komarov err = block_write_begin(mapping, pos, len, 0, &page, 98382cae269SKonstantin Komarov ntfs_get_block_write_begin); 98482cae269SKonstantin Komarov if (err) 98582cae269SKonstantin Komarov goto out; 98682cae269SKonstantin Komarov 98782cae269SKonstantin Komarov kaddr = kmap_atomic(page); 98882cae269SKonstantin Komarov memset(kaddr, -1, len); 98982cae269SKonstantin Komarov kunmap_atomic(kaddr); 99082cae269SKonstantin Komarov flush_dcache_page(page); 99182cae269SKonstantin Komarov 99282cae269SKonstantin Komarov err = block_write_end(NULL, mapping, pos, len, len, page, NULL); 99382cae269SKonstantin Komarov if (err < 0) 99482cae269SKonstantin Komarov goto out; 99582cae269SKonstantin Komarov pos += len; 99682cae269SKonstantin Komarov 99782cae269SKonstantin Komarov if (pos >= log_size) 99882cae269SKonstantin Komarov break; 99982cae269SKonstantin Komarov balance_dirty_pages_ratelimited(mapping); 100082cae269SKonstantin Komarov } 100182cae269SKonstantin Komarov out: 100282cae269SKonstantin Komarov mark_inode_dirty_sync(inode); 100382cae269SKonstantin Komarov 100482cae269SKonstantin Komarov return err; 100582cae269SKonstantin Komarov } 100682cae269SKonstantin Komarov 100782cae269SKonstantin Komarov int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc) 100882cae269SKonstantin Komarov { 100982cae269SKonstantin Komarov return _ni_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); 101082cae269SKonstantin Komarov } 101182cae269SKonstantin Komarov 101282cae269SKonstantin Komarov int ntfs_sync_inode(struct inode *inode) 101382cae269SKonstantin Komarov { 101482cae269SKonstantin Komarov return _ni_write_inode(inode, 1); 101582cae269SKonstantin Komarov } 101682cae269SKonstantin Komarov 101782cae269SKonstantin Komarov /* 1018e8b8e97fSKari Argillander * writeback_inode - Helper function for ntfs_flush_inodes(). 1019e8b8e97fSKari Argillander * 1020e8b8e97fSKari Argillander * This writes both the inode and the file data blocks, waiting 1021e8b8e97fSKari Argillander * for in flight data blocks before the start of the call. It 1022e8b8e97fSKari Argillander * does not wait for any io started during the call. 102382cae269SKonstantin Komarov */ 102482cae269SKonstantin Komarov static int writeback_inode(struct inode *inode) 102582cae269SKonstantin Komarov { 102682cae269SKonstantin Komarov int ret = sync_inode_metadata(inode, 0); 102782cae269SKonstantin Komarov 102882cae269SKonstantin Komarov if (!ret) 102982cae269SKonstantin Komarov ret = filemap_fdatawrite(inode->i_mapping); 103082cae269SKonstantin Komarov return ret; 103182cae269SKonstantin Komarov } 103282cae269SKonstantin Komarov 103382cae269SKonstantin Komarov /* 1034e8b8e97fSKari Argillander * ntfs_flush_inodes 1035e8b8e97fSKari Argillander * 1036e8b8e97fSKari Argillander * Write data and metadata corresponding to i1 and i2. The io is 103782cae269SKonstantin Komarov * started but we do not wait for any of it to finish. 103882cae269SKonstantin Komarov * 1039e8b8e97fSKari Argillander * filemap_flush() is used for the block device, so if there is a dirty 104082cae269SKonstantin Komarov * page for a block already in flight, we will not wait and start the 1041e8b8e97fSKari Argillander * io over again. 104282cae269SKonstantin Komarov */ 104382cae269SKonstantin Komarov int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, 104482cae269SKonstantin Komarov struct inode *i2) 104582cae269SKonstantin Komarov { 104682cae269SKonstantin Komarov int ret = 0; 104782cae269SKonstantin Komarov 104882cae269SKonstantin Komarov if (i1) 104982cae269SKonstantin Komarov ret = writeback_inode(i1); 105082cae269SKonstantin Komarov if (!ret && i2) 105182cae269SKonstantin Komarov ret = writeback_inode(i2); 105282cae269SKonstantin Komarov if (!ret) 105382cae269SKonstantin Komarov ret = filemap_flush(sb->s_bdev->bd_inode->i_mapping); 105482cae269SKonstantin Komarov return ret; 105582cae269SKonstantin Komarov } 105682cae269SKonstantin Komarov 105782cae269SKonstantin Komarov int inode_write_data(struct inode *inode, const void *data, size_t bytes) 105882cae269SKonstantin Komarov { 105982cae269SKonstantin Komarov pgoff_t idx; 106082cae269SKonstantin Komarov 1061e8b8e97fSKari Argillander /* Write non resident data. */ 106282cae269SKonstantin Komarov for (idx = 0; bytes; idx++) { 106382cae269SKonstantin Komarov size_t op = bytes > PAGE_SIZE ? PAGE_SIZE : bytes; 106482cae269SKonstantin Komarov struct page *page = ntfs_map_page(inode->i_mapping, idx); 106582cae269SKonstantin Komarov 106682cae269SKonstantin Komarov if (IS_ERR(page)) 106782cae269SKonstantin Komarov return PTR_ERR(page); 106882cae269SKonstantin Komarov 106982cae269SKonstantin Komarov lock_page(page); 107082cae269SKonstantin Komarov WARN_ON(!PageUptodate(page)); 107182cae269SKonstantin Komarov ClearPageUptodate(page); 107282cae269SKonstantin Komarov 107382cae269SKonstantin Komarov memcpy(page_address(page), data, op); 107482cae269SKonstantin Komarov 107582cae269SKonstantin Komarov flush_dcache_page(page); 107682cae269SKonstantin Komarov SetPageUptodate(page); 107782cae269SKonstantin Komarov unlock_page(page); 107882cae269SKonstantin Komarov 107982cae269SKonstantin Komarov ntfs_unmap_page(page); 108082cae269SKonstantin Komarov 108182cae269SKonstantin Komarov bytes -= op; 108282cae269SKonstantin Komarov data = Add2Ptr(data, PAGE_SIZE); 108382cae269SKonstantin Komarov } 108482cae269SKonstantin Komarov return 0; 108582cae269SKonstantin Komarov } 108682cae269SKonstantin Komarov 108782cae269SKonstantin Komarov /* 1088e8b8e97fSKari Argillander * ntfs_reparse_bytes 1089e8b8e97fSKari Argillander * 1090d3624466SKonstantin Komarov * Number of bytes for REPARSE_DATA_BUFFER(IO_REPARSE_TAG_SYMLINK) 1091e8b8e97fSKari Argillander * for unicode string of @uni_len length. 109282cae269SKonstantin Komarov */ 109382cae269SKonstantin Komarov static inline u32 ntfs_reparse_bytes(u32 uni_len) 109482cae269SKonstantin Komarov { 1095e8b8e97fSKari Argillander /* Header + unicode string + decorated unicode string. */ 109682cae269SKonstantin Komarov return sizeof(short) * (2 * uni_len + 4) + 109782cae269SKonstantin Komarov offsetof(struct REPARSE_DATA_BUFFER, 109882cae269SKonstantin Komarov SymbolicLinkReparseBuffer.PathBuffer); 109982cae269SKonstantin Komarov } 110082cae269SKonstantin Komarov 110182cae269SKonstantin Komarov static struct REPARSE_DATA_BUFFER * 110282cae269SKonstantin Komarov ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname, 110382cae269SKonstantin Komarov u32 size, u16 *nsize) 110482cae269SKonstantin Komarov { 110582cae269SKonstantin Komarov int i, err; 110682cae269SKonstantin Komarov struct REPARSE_DATA_BUFFER *rp; 110782cae269SKonstantin Komarov __le16 *rp_name; 110882cae269SKonstantin Komarov typeof(rp->SymbolicLinkReparseBuffer) *rs; 110982cae269SKonstantin Komarov 1110195c52bdSKari Argillander rp = kzalloc(ntfs_reparse_bytes(2 * size + 2), GFP_NOFS); 111182cae269SKonstantin Komarov if (!rp) 111282cae269SKonstantin Komarov return ERR_PTR(-ENOMEM); 111382cae269SKonstantin Komarov 111482cae269SKonstantin Komarov rs = &rp->SymbolicLinkReparseBuffer; 111582cae269SKonstantin Komarov rp_name = rs->PathBuffer; 111682cae269SKonstantin Komarov 1117e8b8e97fSKari Argillander /* Convert link name to UTF-16. */ 111882cae269SKonstantin Komarov err = ntfs_nls_to_utf16(sbi, symname, size, 111982cae269SKonstantin Komarov (struct cpu_str *)(rp_name - 1), 2 * size, 112082cae269SKonstantin Komarov UTF16_LITTLE_ENDIAN); 112182cae269SKonstantin Komarov if (err < 0) 112282cae269SKonstantin Komarov goto out; 112382cae269SKonstantin Komarov 1124e8b8e97fSKari Argillander /* err = the length of unicode name of symlink. */ 112582cae269SKonstantin Komarov *nsize = ntfs_reparse_bytes(err); 112682cae269SKonstantin Komarov 112782cae269SKonstantin Komarov if (*nsize > sbi->reparse.max_size) { 112882cae269SKonstantin Komarov err = -EFBIG; 112982cae269SKonstantin Komarov goto out; 113082cae269SKonstantin Komarov } 113182cae269SKonstantin Komarov 1132e8b8e97fSKari Argillander /* Translate Linux '/' into Windows '\'. */ 113382cae269SKonstantin Komarov for (i = 0; i < err; i++) { 113482cae269SKonstantin Komarov if (rp_name[i] == cpu_to_le16('/')) 113582cae269SKonstantin Komarov rp_name[i] = cpu_to_le16('\\'); 113682cae269SKonstantin Komarov } 113782cae269SKonstantin Komarov 113882cae269SKonstantin Komarov rp->ReparseTag = IO_REPARSE_TAG_SYMLINK; 113982cae269SKonstantin Komarov rp->ReparseDataLength = 114082cae269SKonstantin Komarov cpu_to_le16(*nsize - offsetof(struct REPARSE_DATA_BUFFER, 114182cae269SKonstantin Komarov SymbolicLinkReparseBuffer)); 114282cae269SKonstantin Komarov 1143e8b8e97fSKari Argillander /* PrintName + SubstituteName. */ 114482cae269SKonstantin Komarov rs->SubstituteNameOffset = cpu_to_le16(sizeof(short) * err); 114582cae269SKonstantin Komarov rs->SubstituteNameLength = cpu_to_le16(sizeof(short) * err + 8); 114682cae269SKonstantin Komarov rs->PrintNameLength = rs->SubstituteNameOffset; 114782cae269SKonstantin Komarov 114882cae269SKonstantin Komarov /* 1149e8b8e97fSKari Argillander * TODO: Use relative path if possible to allow Windows to 1150e8b8e97fSKari Argillander * parse this path. 1151e8b8e97fSKari Argillander * 0-absolute path 1- relative path (SYMLINK_FLAG_RELATIVE). 115282cae269SKonstantin Komarov */ 115382cae269SKonstantin Komarov rs->Flags = 0; 115482cae269SKonstantin Komarov 115582cae269SKonstantin Komarov memmove(rp_name + err + 4, rp_name, sizeof(short) * err); 115682cae269SKonstantin Komarov 1157e8b8e97fSKari Argillander /* Decorate SubstituteName. */ 115882cae269SKonstantin Komarov rp_name += err; 115982cae269SKonstantin Komarov rp_name[0] = cpu_to_le16('\\'); 116082cae269SKonstantin Komarov rp_name[1] = cpu_to_le16('?'); 116182cae269SKonstantin Komarov rp_name[2] = cpu_to_le16('?'); 116282cae269SKonstantin Komarov rp_name[3] = cpu_to_le16('\\'); 116382cae269SKonstantin Komarov 116482cae269SKonstantin Komarov return rp; 116582cae269SKonstantin Komarov out: 1166195c52bdSKari Argillander kfree(rp); 116782cae269SKonstantin Komarov return ERR_PTR(err); 116882cae269SKonstantin Komarov } 116982cae269SKonstantin Komarov 117082cae269SKonstantin Komarov struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, 117182cae269SKonstantin Komarov struct inode *dir, struct dentry *dentry, 117282cae269SKonstantin Komarov const struct cpu_str *uni, umode_t mode, 117382cae269SKonstantin Komarov dev_t dev, const char *symname, u32 size, 117482cae269SKonstantin Komarov struct ntfs_fnd *fnd) 117582cae269SKonstantin Komarov { 117682cae269SKonstantin Komarov int err; 117782cae269SKonstantin Komarov struct super_block *sb = dir->i_sb; 117882cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 117982cae269SKonstantin Komarov const struct qstr *name = &dentry->d_name; 118082cae269SKonstantin Komarov CLST ino = 0; 118182cae269SKonstantin Komarov struct ntfs_inode *dir_ni = ntfs_i(dir); 118282cae269SKonstantin Komarov struct ntfs_inode *ni = NULL; 118382cae269SKonstantin Komarov struct inode *inode = NULL; 118482cae269SKonstantin Komarov struct ATTRIB *attr; 118582cae269SKonstantin Komarov struct ATTR_STD_INFO5 *std5; 118682cae269SKonstantin Komarov struct ATTR_FILE_NAME *fname; 118782cae269SKonstantin Komarov struct MFT_REC *rec; 118882cae269SKonstantin Komarov u32 asize, dsize, sd_size; 118982cae269SKonstantin Komarov enum FILE_ATTRIBUTE fa; 119082cae269SKonstantin Komarov __le32 security_id = SECURITY_ID_INVALID; 119182cae269SKonstantin Komarov CLST vcn; 119282cae269SKonstantin Komarov const void *sd; 119382cae269SKonstantin Komarov u16 t16, nsize = 0, aid = 0; 119482cae269SKonstantin Komarov struct INDEX_ROOT *root, *dir_root; 119582cae269SKonstantin Komarov struct NTFS_DE *e, *new_de = NULL; 119682cae269SKonstantin Komarov struct REPARSE_DATA_BUFFER *rp = NULL; 119782cae269SKonstantin Komarov bool rp_inserted = false; 119882cae269SKonstantin Komarov 1199d562e901SKonstantin Komarov ni_lock_dir(dir_ni); 1200d562e901SKonstantin Komarov 120182cae269SKonstantin Komarov dir_root = indx_get_root(&dir_ni->dir, dir_ni, NULL, NULL); 1202d562e901SKonstantin Komarov if (!dir_root) { 1203d562e901SKonstantin Komarov err = -EINVAL; 1204d562e901SKonstantin Komarov goto out1; 1205d562e901SKonstantin Komarov } 120682cae269SKonstantin Komarov 120782cae269SKonstantin Komarov if (S_ISDIR(mode)) { 1208d3624466SKonstantin Komarov /* Use parent's directory attributes. */ 120982cae269SKonstantin Komarov fa = dir_ni->std_fa | FILE_ATTRIBUTE_DIRECTORY | 121082cae269SKonstantin Komarov FILE_ATTRIBUTE_ARCHIVE; 121182cae269SKonstantin Komarov /* 1212d3624466SKonstantin Komarov * By default child directory inherits parent attributes. 1213d3624466SKonstantin Komarov * Root directory is hidden + system. 1214d3624466SKonstantin Komarov * Make an exception for children in root. 121582cae269SKonstantin Komarov */ 121682cae269SKonstantin Komarov if (dir->i_ino == MFT_REC_ROOT) 121782cae269SKonstantin Komarov fa &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); 121882cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 121982cae269SKonstantin Komarov /* It is good idea that link should be the same type (file/dir) as target */ 122082cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_REPARSE_POINT; 122182cae269SKonstantin Komarov 122282cae269SKonstantin Komarov /* 1223d3624466SKonstantin Komarov * Linux: there are dir/file/symlink and so on. 1224d3624466SKonstantin Komarov * NTFS: symlinks are "dir + reparse" or "file + reparse" 122582cae269SKonstantin Komarov * It is good idea to create: 122682cae269SKonstantin Komarov * dir + reparse if 'symname' points to directory 122782cae269SKonstantin Komarov * or 122882cae269SKonstantin Komarov * file + reparse if 'symname' points to file 1229e8b8e97fSKari Argillander * Unfortunately kern_path hangs if symname contains 'dir'. 123082cae269SKonstantin Komarov */ 123182cae269SKonstantin Komarov 123282cae269SKonstantin Komarov /* 123382cae269SKonstantin Komarov * struct path path; 123482cae269SKonstantin Komarov * 123582cae269SKonstantin Komarov * if (!kern_path(symname, LOOKUP_FOLLOW, &path)){ 123682cae269SKonstantin Komarov * struct inode *target = d_inode(path.dentry); 123782cae269SKonstantin Komarov * 123882cae269SKonstantin Komarov * if (S_ISDIR(target->i_mode)) 123982cae269SKonstantin Komarov * fa |= FILE_ATTRIBUTE_DIRECTORY; 124082cae269SKonstantin Komarov * // if ( target->i_sb == sb ){ 124182cae269SKonstantin Komarov * // use relative path? 124282cae269SKonstantin Komarov * // } 124382cae269SKonstantin Komarov * path_put(&path); 124482cae269SKonstantin Komarov * } 124582cae269SKonstantin Komarov */ 124682cae269SKonstantin Komarov } else if (S_ISREG(mode)) { 1247564c97bdSKari Argillander if (sbi->options->sparse) { 1248e8b8e97fSKari Argillander /* Sparsed regular file, cause option 'sparse'. */ 124982cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_SPARSE_FILE | 125082cae269SKonstantin Komarov FILE_ATTRIBUTE_ARCHIVE; 125182cae269SKonstantin Komarov } else if (dir_ni->std_fa & FILE_ATTRIBUTE_COMPRESSED) { 1252e8b8e97fSKari Argillander /* Compressed regular file, if parent is compressed. */ 125382cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ARCHIVE; 125482cae269SKonstantin Komarov } else { 1255e8b8e97fSKari Argillander /* Regular file, default attributes. */ 125682cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_ARCHIVE; 125782cae269SKonstantin Komarov } 125882cae269SKonstantin Komarov } else { 125982cae269SKonstantin Komarov fa = FILE_ATTRIBUTE_ARCHIVE; 126082cae269SKonstantin Komarov } 126182cae269SKonstantin Komarov 126282cae269SKonstantin Komarov if (!(mode & 0222)) 126382cae269SKonstantin Komarov fa |= FILE_ATTRIBUTE_READONLY; 126482cae269SKonstantin Komarov 1265e8b8e97fSKari Argillander /* Allocate PATH_MAX bytes. */ 126682cae269SKonstantin Komarov new_de = __getname(); 126782cae269SKonstantin Komarov if (!new_de) { 126882cae269SKonstantin Komarov err = -ENOMEM; 126982cae269SKonstantin Komarov goto out1; 127082cae269SKonstantin Komarov } 127182cae269SKonstantin Komarov 1272e8b8e97fSKari Argillander /* Mark rw ntfs as dirty. it will be cleared at umount. */ 127382cae269SKonstantin Komarov ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); 127482cae269SKonstantin Komarov 1275e8b8e97fSKari Argillander /* Step 1: allocate and fill new mft record. */ 127682cae269SKonstantin Komarov err = ntfs_look_free_mft(sbi, &ino, false, NULL, NULL); 127782cae269SKonstantin Komarov if (err) 127882cae269SKonstantin Komarov goto out2; 127982cae269SKonstantin Komarov 128082cae269SKonstantin Komarov ni = ntfs_new_inode(sbi, ino, fa & FILE_ATTRIBUTE_DIRECTORY); 128182cae269SKonstantin Komarov if (IS_ERR(ni)) { 128282cae269SKonstantin Komarov err = PTR_ERR(ni); 128382cae269SKonstantin Komarov ni = NULL; 128482cae269SKonstantin Komarov goto out3; 128582cae269SKonstantin Komarov } 128682cae269SKonstantin Komarov inode = &ni->vfs_inode; 128782cae269SKonstantin Komarov inode_init_owner(mnt_userns, inode, dir, mode); 128878ab59feSKonstantin Komarov mode = inode->i_mode; 128982cae269SKonstantin Komarov 129082cae269SKonstantin Komarov inode->i_atime = inode->i_mtime = inode->i_ctime = ni->i_crtime = 129182cae269SKonstantin Komarov current_time(inode); 129282cae269SKonstantin Komarov 129382cae269SKonstantin Komarov rec = ni->mi.mrec; 129482cae269SKonstantin Komarov rec->hard_links = cpu_to_le16(1); 129582cae269SKonstantin Komarov attr = Add2Ptr(rec, le16_to_cpu(rec->attr_off)); 129682cae269SKonstantin Komarov 1297e8b8e97fSKari Argillander /* Get default security id. */ 129882cae269SKonstantin Komarov sd = s_default_security; 129982cae269SKonstantin Komarov sd_size = sizeof(s_default_security); 130082cae269SKonstantin Komarov 130182cae269SKonstantin Komarov if (is_ntfs3(sbi)) { 130282cae269SKonstantin Komarov security_id = dir_ni->std_security_id; 130382cae269SKonstantin Komarov if (le32_to_cpu(security_id) < SECURITY_ID_FIRST) { 130482cae269SKonstantin Komarov security_id = sbi->security.def_security_id; 130582cae269SKonstantin Komarov 130682cae269SKonstantin Komarov if (security_id == SECURITY_ID_INVALID && 130782cae269SKonstantin Komarov !ntfs_insert_security(sbi, sd, sd_size, 130882cae269SKonstantin Komarov &security_id, NULL)) 130982cae269SKonstantin Komarov sbi->security.def_security_id = security_id; 131082cae269SKonstantin Komarov } 131182cae269SKonstantin Komarov } 131282cae269SKonstantin Komarov 1313e8b8e97fSKari Argillander /* Insert standard info. */ 131482cae269SKonstantin Komarov std5 = Add2Ptr(attr, SIZEOF_RESIDENT); 131582cae269SKonstantin Komarov 131682cae269SKonstantin Komarov if (security_id == SECURITY_ID_INVALID) { 131782cae269SKonstantin Komarov dsize = sizeof(struct ATTR_STD_INFO); 131882cae269SKonstantin Komarov } else { 131982cae269SKonstantin Komarov dsize = sizeof(struct ATTR_STD_INFO5); 132082cae269SKonstantin Komarov std5->security_id = security_id; 132182cae269SKonstantin Komarov ni->std_security_id = security_id; 132282cae269SKonstantin Komarov } 132382cae269SKonstantin Komarov asize = SIZEOF_RESIDENT + dsize; 132482cae269SKonstantin Komarov 132582cae269SKonstantin Komarov attr->type = ATTR_STD; 132682cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 132782cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 132882cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 132982cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(dsize); 133082cae269SKonstantin Komarov 133182cae269SKonstantin Komarov std5->cr_time = std5->m_time = std5->c_time = std5->a_time = 133282cae269SKonstantin Komarov kernel2nt(&inode->i_atime); 133382cae269SKonstantin Komarov 133482cae269SKonstantin Komarov ni->std_fa = fa; 133582cae269SKonstantin Komarov std5->fa = fa; 133682cae269SKonstantin Komarov 133782cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 133882cae269SKonstantin Komarov 1339e8b8e97fSKari Argillander /* Insert file name. */ 134082cae269SKonstantin Komarov err = fill_name_de(sbi, new_de, name, uni); 134182cae269SKonstantin Komarov if (err) 134282cae269SKonstantin Komarov goto out4; 134382cae269SKonstantin Komarov 134482cae269SKonstantin Komarov mi_get_ref(&ni->mi, &new_de->ref); 134582cae269SKonstantin Komarov 134682cae269SKonstantin Komarov fname = (struct ATTR_FILE_NAME *)(new_de + 1); 134782cae269SKonstantin Komarov mi_get_ref(&dir_ni->mi, &fname->home); 134882cae269SKonstantin Komarov fname->dup.cr_time = fname->dup.m_time = fname->dup.c_time = 134982cae269SKonstantin Komarov fname->dup.a_time = std5->cr_time; 135082cae269SKonstantin Komarov fname->dup.alloc_size = fname->dup.data_size = 0; 135182cae269SKonstantin Komarov fname->dup.fa = std5->fa; 135282cae269SKonstantin Komarov fname->dup.ea_size = fname->dup.reparse = 0; 135382cae269SKonstantin Komarov 135482cae269SKonstantin Komarov dsize = le16_to_cpu(new_de->key_size); 1355fa3cacf5SKari Argillander asize = ALIGN(SIZEOF_RESIDENT + dsize, 8); 135682cae269SKonstantin Komarov 135782cae269SKonstantin Komarov attr->type = ATTR_NAME; 135882cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 135982cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 136082cae269SKonstantin Komarov attr->res.flags = RESIDENT_FLAG_INDEXED; 136182cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 136282cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(dsize); 136382cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), fname, dsize); 136482cae269SKonstantin Komarov 136582cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 136682cae269SKonstantin Komarov 136782cae269SKonstantin Komarov if (security_id == SECURITY_ID_INVALID) { 1368e8b8e97fSKari Argillander /* Insert security attribute. */ 1369fa3cacf5SKari Argillander asize = SIZEOF_RESIDENT + ALIGN(sd_size, 8); 137082cae269SKonstantin Komarov 137182cae269SKonstantin Komarov attr->type = ATTR_SECURE; 137282cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 137382cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 137482cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 137582cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(sd_size); 137682cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), sd, sd_size); 137782cae269SKonstantin Komarov 137882cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 137982cae269SKonstantin Komarov } 138082cae269SKonstantin Komarov 138178ab59feSKonstantin Komarov attr->id = cpu_to_le16(aid++); 138282cae269SKonstantin Komarov if (fa & FILE_ATTRIBUTE_DIRECTORY) { 138382cae269SKonstantin Komarov /* 1384e8b8e97fSKari Argillander * Regular directory or symlink to directory. 1385e8b8e97fSKari Argillander * Create root attribute. 138682cae269SKonstantin Komarov */ 138782cae269SKonstantin Komarov dsize = sizeof(struct INDEX_ROOT) + sizeof(struct NTFS_DE); 138882cae269SKonstantin Komarov asize = sizeof(I30_NAME) + SIZEOF_RESIDENT + dsize; 138982cae269SKonstantin Komarov 139082cae269SKonstantin Komarov attr->type = ATTR_ROOT; 139182cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 139282cae269SKonstantin Komarov 139382cae269SKonstantin Komarov attr->name_len = ARRAY_SIZE(I30_NAME); 139482cae269SKonstantin Komarov attr->name_off = SIZEOF_RESIDENT_LE; 139582cae269SKonstantin Komarov attr->res.data_off = 139682cae269SKonstantin Komarov cpu_to_le16(sizeof(I30_NAME) + SIZEOF_RESIDENT); 139782cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(dsize); 139882cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), I30_NAME, 139982cae269SKonstantin Komarov sizeof(I30_NAME)); 140082cae269SKonstantin Komarov 140182cae269SKonstantin Komarov root = Add2Ptr(attr, sizeof(I30_NAME) + SIZEOF_RESIDENT); 140282cae269SKonstantin Komarov memcpy(root, dir_root, offsetof(struct INDEX_ROOT, ihdr)); 140382cae269SKonstantin Komarov root->ihdr.de_off = 140482cae269SKonstantin Komarov cpu_to_le32(sizeof(struct INDEX_HDR)); // 0x10 140582cae269SKonstantin Komarov root->ihdr.used = cpu_to_le32(sizeof(struct INDEX_HDR) + 140682cae269SKonstantin Komarov sizeof(struct NTFS_DE)); 140782cae269SKonstantin Komarov root->ihdr.total = root->ihdr.used; 140882cae269SKonstantin Komarov 140982cae269SKonstantin Komarov e = Add2Ptr(root, sizeof(struct INDEX_ROOT)); 141082cae269SKonstantin Komarov e->size = cpu_to_le16(sizeof(struct NTFS_DE)); 141182cae269SKonstantin Komarov e->flags = NTFS_IE_LAST; 141282cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 141382cae269SKonstantin Komarov /* 1414e8b8e97fSKari Argillander * Symlink to file. 1415e8b8e97fSKari Argillander * Create empty resident data attribute. 141682cae269SKonstantin Komarov */ 141782cae269SKonstantin Komarov asize = SIZEOF_RESIDENT; 141882cae269SKonstantin Komarov 1419e8b8e97fSKari Argillander /* Insert empty ATTR_DATA */ 142082cae269SKonstantin Komarov attr->type = ATTR_DATA; 142182cae269SKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_RESIDENT); 142282cae269SKonstantin Komarov attr->name_off = SIZEOF_RESIDENT_LE; 142382cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 142478ab59feSKonstantin Komarov } else if (S_ISREG(mode)) { 142582cae269SKonstantin Komarov /* 142678ab59feSKonstantin Komarov * Regular file. Create empty non resident data attribute. 142782cae269SKonstantin Komarov */ 142882cae269SKonstantin Komarov attr->type = ATTR_DATA; 142982cae269SKonstantin Komarov attr->non_res = 1; 143082cae269SKonstantin Komarov attr->nres.evcn = cpu_to_le64(-1ll); 143182cae269SKonstantin Komarov if (fa & FILE_ATTRIBUTE_SPARSE_FILE) { 143278ab59feSKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8); 143382cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_EX_LE; 143482cae269SKonstantin Komarov attr->flags = ATTR_FLAG_SPARSED; 143582cae269SKonstantin Komarov asize = SIZEOF_NONRESIDENT_EX + 8; 143682cae269SKonstantin Komarov } else if (fa & FILE_ATTRIBUTE_COMPRESSED) { 143778ab59feSKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8); 143882cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_EX_LE; 143982cae269SKonstantin Komarov attr->flags = ATTR_FLAG_COMPRESSED; 144082cae269SKonstantin Komarov attr->nres.c_unit = COMPRESSION_UNIT; 144182cae269SKonstantin Komarov asize = SIZEOF_NONRESIDENT_EX + 8; 144282cae269SKonstantin Komarov } else { 144378ab59feSKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_NONRESIDENT + 8); 144482cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_LE; 144582cae269SKonstantin Komarov asize = SIZEOF_NONRESIDENT + 8; 144682cae269SKonstantin Komarov } 144782cae269SKonstantin Komarov attr->nres.run_off = attr->name_off; 144882cae269SKonstantin Komarov } else { 144978ab59feSKonstantin Komarov /* 145078ab59feSKonstantin Komarov * Node. Create empty resident data attribute. 145178ab59feSKonstantin Komarov */ 145278ab59feSKonstantin Komarov attr->type = ATTR_DATA; 145382cae269SKonstantin Komarov attr->size = cpu_to_le32(SIZEOF_RESIDENT); 145482cae269SKonstantin Komarov attr->name_off = SIZEOF_RESIDENT_LE; 145582cae269SKonstantin Komarov if (fa & FILE_ATTRIBUTE_SPARSE_FILE) 145682cae269SKonstantin Komarov attr->flags = ATTR_FLAG_SPARSED; 145782cae269SKonstantin Komarov else if (fa & FILE_ATTRIBUTE_COMPRESSED) 145882cae269SKonstantin Komarov attr->flags = ATTR_FLAG_COMPRESSED; 145982cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 146082cae269SKonstantin Komarov asize = SIZEOF_RESIDENT; 146182cae269SKonstantin Komarov ni->ni_flags |= NI_FLAG_RESIDENT; 146282cae269SKonstantin Komarov } 146382cae269SKonstantin Komarov 146482cae269SKonstantin Komarov if (S_ISDIR(mode)) { 146582cae269SKonstantin Komarov ni->ni_flags |= NI_FLAG_DIR; 146682cae269SKonstantin Komarov err = indx_init(&ni->dir, sbi, attr, INDEX_MUTEX_I30); 146782cae269SKonstantin Komarov if (err) 146882cae269SKonstantin Komarov goto out4; 146982cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 147082cae269SKonstantin Komarov rp = ntfs_create_reparse_buffer(sbi, symname, size, &nsize); 147182cae269SKonstantin Komarov 147282cae269SKonstantin Komarov if (IS_ERR(rp)) { 147382cae269SKonstantin Komarov err = PTR_ERR(rp); 147482cae269SKonstantin Komarov rp = NULL; 147582cae269SKonstantin Komarov goto out4; 147682cae269SKonstantin Komarov } 147782cae269SKonstantin Komarov 147882cae269SKonstantin Komarov /* 1479e8b8e97fSKari Argillander * Insert ATTR_REPARSE. 148082cae269SKonstantin Komarov */ 148182cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 148282cae269SKonstantin Komarov attr->type = ATTR_REPARSE; 148382cae269SKonstantin Komarov attr->id = cpu_to_le16(aid++); 148482cae269SKonstantin Komarov 1485e8b8e97fSKari Argillander /* Resident or non resident? */ 1486fa3cacf5SKari Argillander asize = ALIGN(SIZEOF_RESIDENT + nsize, 8); 148782cae269SKonstantin Komarov t16 = PtrOffset(rec, attr); 148882cae269SKonstantin Komarov 148914a98119SKonstantin Komarov /* 149014a98119SKonstantin Komarov * Below function 'ntfs_save_wsl_perm' requires 0x78 bytes. 149114a98119SKonstantin Komarov * It is good idea to keep extened attributes resident. 149214a98119SKonstantin Komarov */ 149378ab59feSKonstantin Komarov if (asize + t16 + 0x78 + 8 > sbi->record_size) { 149482cae269SKonstantin Komarov CLST alen; 149582cae269SKonstantin Komarov CLST clst = bytes_to_cluster(sbi, nsize); 149682cae269SKonstantin Komarov 1497e8b8e97fSKari Argillander /* Bytes per runs. */ 149882cae269SKonstantin Komarov t16 = sbi->record_size - t16 - SIZEOF_NONRESIDENT; 149982cae269SKonstantin Komarov 150082cae269SKonstantin Komarov attr->non_res = 1; 150182cae269SKonstantin Komarov attr->nres.evcn = cpu_to_le64(clst - 1); 150282cae269SKonstantin Komarov attr->name_off = SIZEOF_NONRESIDENT_LE; 150382cae269SKonstantin Komarov attr->nres.run_off = attr->name_off; 150482cae269SKonstantin Komarov attr->nres.data_size = cpu_to_le64(nsize); 150582cae269SKonstantin Komarov attr->nres.valid_size = attr->nres.data_size; 150682cae269SKonstantin Komarov attr->nres.alloc_size = 150782cae269SKonstantin Komarov cpu_to_le64(ntfs_up_cluster(sbi, nsize)); 150882cae269SKonstantin Komarov 150982cae269SKonstantin Komarov err = attr_allocate_clusters(sbi, &ni->file.run, 0, 0, 151082cae269SKonstantin Komarov clst, NULL, 0, &alen, 0, 151182cae269SKonstantin Komarov NULL); 151282cae269SKonstantin Komarov if (err) 151382cae269SKonstantin Komarov goto out5; 151482cae269SKonstantin Komarov 151582cae269SKonstantin Komarov err = run_pack(&ni->file.run, 0, clst, 151682cae269SKonstantin Komarov Add2Ptr(attr, SIZEOF_NONRESIDENT), t16, 151782cae269SKonstantin Komarov &vcn); 151882cae269SKonstantin Komarov if (err < 0) 151982cae269SKonstantin Komarov goto out5; 152082cae269SKonstantin Komarov 152182cae269SKonstantin Komarov if (vcn != clst) { 152282cae269SKonstantin Komarov err = -EINVAL; 152382cae269SKonstantin Komarov goto out5; 152482cae269SKonstantin Komarov } 152582cae269SKonstantin Komarov 1526fa3cacf5SKari Argillander asize = SIZEOF_NONRESIDENT + ALIGN(err, 8); 152782cae269SKonstantin Komarov } else { 152882cae269SKonstantin Komarov attr->res.data_off = SIZEOF_RESIDENT_LE; 152982cae269SKonstantin Komarov attr->res.data_size = cpu_to_le32(nsize); 153082cae269SKonstantin Komarov memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), rp, nsize); 153182cae269SKonstantin Komarov nsize = 0; 153282cae269SKonstantin Komarov } 153314a98119SKonstantin Komarov /* Size of symlink equals the length of input string. */ 153414a98119SKonstantin Komarov inode->i_size = size; 153582cae269SKonstantin Komarov 153682cae269SKonstantin Komarov attr->size = cpu_to_le32(asize); 153782cae269SKonstantin Komarov 153882cae269SKonstantin Komarov err = ntfs_insert_reparse(sbi, IO_REPARSE_TAG_SYMLINK, 153982cae269SKonstantin Komarov &new_de->ref); 154082cae269SKonstantin Komarov if (err) 154182cae269SKonstantin Komarov goto out5; 154282cae269SKonstantin Komarov 154382cae269SKonstantin Komarov rp_inserted = true; 154482cae269SKonstantin Komarov } 154582cae269SKonstantin Komarov 154682cae269SKonstantin Komarov attr = Add2Ptr(attr, asize); 154782cae269SKonstantin Komarov attr->type = ATTR_END; 154882cae269SKonstantin Komarov 154982cae269SKonstantin Komarov rec->used = cpu_to_le32(PtrOffset(rec, attr) + 8); 155082cae269SKonstantin Komarov rec->next_attr_id = cpu_to_le16(aid); 155182cae269SKonstantin Komarov 1552e8b8e97fSKari Argillander /* Step 2: Add new name in index. */ 155378ab59feSKonstantin Komarov err = indx_insert_entry(&dir_ni->dir, dir_ni, new_de, sbi, fnd, 0); 155482cae269SKonstantin Komarov if (err) 155582cae269SKonstantin Komarov goto out6; 155682cae269SKonstantin Komarov 1557d562e901SKonstantin Komarov /* Unlock parent directory before ntfs_init_acl. */ 1558d562e901SKonstantin Komarov ni_unlock(dir_ni); 1559d562e901SKonstantin Komarov 156082cae269SKonstantin Komarov inode->i_generation = le16_to_cpu(rec->seq); 156182cae269SKonstantin Komarov 156282cae269SKonstantin Komarov dir->i_mtime = dir->i_ctime = inode->i_atime; 156382cae269SKonstantin Komarov 156482cae269SKonstantin Komarov if (S_ISDIR(mode)) { 156582cae269SKonstantin Komarov inode->i_op = &ntfs_dir_inode_operations; 156682cae269SKonstantin Komarov inode->i_fop = &ntfs_dir_operations; 156782cae269SKonstantin Komarov } else if (S_ISLNK(mode)) { 156882cae269SKonstantin Komarov inode->i_op = &ntfs_link_inode_operations; 156982cae269SKonstantin Komarov inode->i_fop = NULL; 157082cae269SKonstantin Komarov inode->i_mapping->a_ops = &ntfs_aops; 157114a98119SKonstantin Komarov inode->i_size = size; 157214a98119SKonstantin Komarov inode_nohighmem(inode); 157382cae269SKonstantin Komarov } else if (S_ISREG(mode)) { 157482cae269SKonstantin Komarov inode->i_op = &ntfs_file_inode_operations; 157582cae269SKonstantin Komarov inode->i_fop = &ntfs_file_operations; 157682cae269SKonstantin Komarov inode->i_mapping->a_ops = 157782cae269SKonstantin Komarov is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops; 157882cae269SKonstantin Komarov init_rwsem(&ni->file.run_lock); 157982cae269SKonstantin Komarov } else { 158082cae269SKonstantin Komarov inode->i_op = &ntfs_special_inode_operations; 158182cae269SKonstantin Komarov init_special_inode(inode, mode, dev); 158282cae269SKonstantin Komarov } 158382cae269SKonstantin Komarov 158482cae269SKonstantin Komarov #ifdef CONFIG_NTFS3_FS_POSIX_ACL 158582cae269SKonstantin Komarov if (!S_ISLNK(mode) && (sb->s_flags & SB_POSIXACL)) { 158682cae269SKonstantin Komarov err = ntfs_init_acl(mnt_userns, inode, dir); 158782cae269SKonstantin Komarov if (err) 15886c1ee4d3SKonstantin Komarov goto out7; 158982cae269SKonstantin Komarov } else 159082cae269SKonstantin Komarov #endif 159182cae269SKonstantin Komarov { 159282cae269SKonstantin Komarov inode->i_flags |= S_NOSEC; 159382cae269SKonstantin Komarov } 159482cae269SKonstantin Komarov 1595e8b8e97fSKari Argillander /* Write non resident data. */ 159682cae269SKonstantin Komarov if (nsize) { 159763544672SKonstantin Komarov err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rp, nsize, 0); 159882cae269SKonstantin Komarov if (err) 159982cae269SKonstantin Komarov goto out7; 160082cae269SKonstantin Komarov } 160182cae269SKonstantin Komarov 1602e8b8e97fSKari Argillander /* 1603e8b8e97fSKari Argillander * Call 'd_instantiate' after inode->i_op is set 1604e8b8e97fSKari Argillander * but before finish_open. 1605e8b8e97fSKari Argillander */ 160682cae269SKonstantin Komarov d_instantiate(dentry, inode); 160782cae269SKonstantin Komarov 160882cae269SKonstantin Komarov ntfs_save_wsl_perm(inode); 160982cae269SKonstantin Komarov mark_inode_dirty(dir); 161078ab59feSKonstantin Komarov mark_inode_dirty(inode); 161182cae269SKonstantin Komarov 1612e8b8e97fSKari Argillander /* Normal exit. */ 161382cae269SKonstantin Komarov goto out2; 161482cae269SKonstantin Komarov 161582cae269SKonstantin Komarov out7: 161682cae269SKonstantin Komarov 1617e8b8e97fSKari Argillander /* Undo 'indx_insert_entry'. */ 1618d562e901SKonstantin Komarov ni_lock_dir(dir_ni); 161982cae269SKonstantin Komarov indx_delete_entry(&dir_ni->dir, dir_ni, new_de + 1, 162082cae269SKonstantin Komarov le16_to_cpu(new_de->key_size), sbi); 1621d562e901SKonstantin Komarov /* ni_unlock(dir_ni); will be called later. */ 162282cae269SKonstantin Komarov out6: 162382cae269SKonstantin Komarov if (rp_inserted) 162482cae269SKonstantin Komarov ntfs_remove_reparse(sbi, IO_REPARSE_TAG_SYMLINK, &new_de->ref); 162582cae269SKonstantin Komarov 162682cae269SKonstantin Komarov out5: 162782cae269SKonstantin Komarov if (S_ISDIR(mode) || run_is_empty(&ni->file.run)) 162882cae269SKonstantin Komarov goto out4; 162982cae269SKonstantin Komarov 163082cae269SKonstantin Komarov run_deallocate(sbi, &ni->file.run, false); 163182cae269SKonstantin Komarov 163282cae269SKonstantin Komarov out4: 163382cae269SKonstantin Komarov clear_rec_inuse(rec); 163482cae269SKonstantin Komarov clear_nlink(inode); 163582cae269SKonstantin Komarov ni->mi.dirty = false; 163682cae269SKonstantin Komarov discard_new_inode(inode); 163782cae269SKonstantin Komarov out3: 163882cae269SKonstantin Komarov ntfs_mark_rec_free(sbi, ino); 163982cae269SKonstantin Komarov 164082cae269SKonstantin Komarov out2: 164182cae269SKonstantin Komarov __putname(new_de); 1642195c52bdSKari Argillander kfree(rp); 164382cae269SKonstantin Komarov 164482cae269SKonstantin Komarov out1: 1645d562e901SKonstantin Komarov if (err) { 1646d562e901SKonstantin Komarov ni_unlock(dir_ni); 164782cae269SKonstantin Komarov return ERR_PTR(err); 1648d562e901SKonstantin Komarov } 164982cae269SKonstantin Komarov 165082cae269SKonstantin Komarov unlock_new_inode(inode); 165182cae269SKonstantin Komarov 165282cae269SKonstantin Komarov return inode; 165382cae269SKonstantin Komarov } 165482cae269SKonstantin Komarov 165582cae269SKonstantin Komarov int ntfs_link_inode(struct inode *inode, struct dentry *dentry) 165682cae269SKonstantin Komarov { 165782cae269SKonstantin Komarov int err; 165882cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 165978ab59feSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 166078ab59feSKonstantin Komarov struct NTFS_DE *de; 166178ab59feSKonstantin Komarov struct ATTR_FILE_NAME *de_name; 166282cae269SKonstantin Komarov 1663e8b8e97fSKari Argillander /* Allocate PATH_MAX bytes. */ 166478ab59feSKonstantin Komarov de = __getname(); 166578ab59feSKonstantin Komarov if (!de) 166682cae269SKonstantin Komarov return -ENOMEM; 166782cae269SKonstantin Komarov 1668e8b8e97fSKari Argillander /* Mark rw ntfs as dirty. It will be cleared at umount. */ 166978ab59feSKonstantin Komarov ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); 167082cae269SKonstantin Komarov 167178ab59feSKonstantin Komarov /* Construct 'de'. */ 167278ab59feSKonstantin Komarov err = fill_name_de(sbi, de, &dentry->d_name, NULL); 167382cae269SKonstantin Komarov if (err) 167482cae269SKonstantin Komarov goto out; 167582cae269SKonstantin Komarov 167678ab59feSKonstantin Komarov de_name = (struct ATTR_FILE_NAME *)(de + 1); 167778ab59feSKonstantin Komarov /* Fill duplicate info. */ 167878ab59feSKonstantin Komarov de_name->dup.cr_time = de_name->dup.m_time = de_name->dup.c_time = 167978ab59feSKonstantin Komarov de_name->dup.a_time = kernel2nt(&inode->i_ctime); 168078ab59feSKonstantin Komarov de_name->dup.alloc_size = de_name->dup.data_size = 168178ab59feSKonstantin Komarov cpu_to_le64(inode->i_size); 168278ab59feSKonstantin Komarov de_name->dup.fa = ni->std_fa; 168378ab59feSKonstantin Komarov de_name->dup.ea_size = de_name->dup.reparse = 0; 168482cae269SKonstantin Komarov 168578ab59feSKonstantin Komarov err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de); 168682cae269SKonstantin Komarov out: 168778ab59feSKonstantin Komarov __putname(de); 168882cae269SKonstantin Komarov return err; 168982cae269SKonstantin Komarov } 169082cae269SKonstantin Komarov 169182cae269SKonstantin Komarov /* 169282cae269SKonstantin Komarov * ntfs_unlink_inode 169382cae269SKonstantin Komarov * 169482cae269SKonstantin Komarov * inode_operations::unlink 169582cae269SKonstantin Komarov * inode_operations::rmdir 169682cae269SKonstantin Komarov */ 169782cae269SKonstantin Komarov int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry) 169882cae269SKonstantin Komarov { 169982cae269SKonstantin Komarov int err; 170078ab59feSKonstantin Komarov struct ntfs_sb_info *sbi = dir->i_sb->s_fs_info; 170182cae269SKonstantin Komarov struct inode *inode = d_inode(dentry); 170282cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 170382cae269SKonstantin Komarov struct ntfs_inode *dir_ni = ntfs_i(dir); 170478ab59feSKonstantin Komarov struct NTFS_DE *de, *de2 = NULL; 170578ab59feSKonstantin Komarov int undo_remove; 170682cae269SKonstantin Komarov 170778ab59feSKonstantin Komarov if (ntfs_is_meta_file(sbi, ni->mi.rno)) 170882cae269SKonstantin Komarov return -EINVAL; 170982cae269SKonstantin Komarov 171078ab59feSKonstantin Komarov /* Allocate PATH_MAX bytes. */ 171178ab59feSKonstantin Komarov de = __getname(); 171278ab59feSKonstantin Komarov if (!de) 171378ab59feSKonstantin Komarov return -ENOMEM; 171478ab59feSKonstantin Komarov 171582cae269SKonstantin Komarov ni_lock(ni); 171682cae269SKonstantin Komarov 171778ab59feSKonstantin Komarov if (S_ISDIR(inode->i_mode) && !dir_is_empty(inode)) { 171882cae269SKonstantin Komarov err = -ENOTEMPTY; 171978ab59feSKonstantin Komarov goto out; 172082cae269SKonstantin Komarov } 172182cae269SKonstantin Komarov 172278ab59feSKonstantin Komarov err = fill_name_de(sbi, de, &dentry->d_name, NULL); 172382cae269SKonstantin Komarov if (err < 0) 172478ab59feSKonstantin Komarov goto out; 172582cae269SKonstantin Komarov 172678ab59feSKonstantin Komarov undo_remove = 0; 172778ab59feSKonstantin Komarov err = ni_remove_name(dir_ni, ni, de, &de2, &undo_remove); 172882cae269SKonstantin Komarov 172978ab59feSKonstantin Komarov if (!err) { 173082cae269SKonstantin Komarov drop_nlink(inode); 173182cae269SKonstantin Komarov dir->i_mtime = dir->i_ctime = current_time(dir); 173282cae269SKonstantin Komarov mark_inode_dirty(dir); 173382cae269SKonstantin Komarov inode->i_ctime = dir->i_ctime; 173482cae269SKonstantin Komarov if (inode->i_nlink) 173582cae269SKonstantin Komarov mark_inode_dirty(inode); 173678ab59feSKonstantin Komarov } else if (!ni_remove_name_undo(dir_ni, ni, de, de2, undo_remove)) { 173778ab59feSKonstantin Komarov make_bad_inode(inode); 173878ab59feSKonstantin Komarov ntfs_inode_err(inode, "failed to undo unlink"); 173978ab59feSKonstantin Komarov ntfs_set_state(sbi, NTFS_DIRTY_ERROR); 174078ab59feSKonstantin Komarov } else { 174178ab59feSKonstantin Komarov if (ni_is_dirty(dir)) 174278ab59feSKonstantin Komarov mark_inode_dirty(dir); 174378ab59feSKonstantin Komarov if (ni_is_dirty(inode)) 174478ab59feSKonstantin Komarov mark_inode_dirty(inode); 174578ab59feSKonstantin Komarov } 174682cae269SKonstantin Komarov 174778ab59feSKonstantin Komarov out: 174882cae269SKonstantin Komarov ni_unlock(ni); 174978ab59feSKonstantin Komarov __putname(de); 175082cae269SKonstantin Komarov return err; 175182cae269SKonstantin Komarov } 175282cae269SKonstantin Komarov 175382cae269SKonstantin Komarov void ntfs_evict_inode(struct inode *inode) 175482cae269SKonstantin Komarov { 175582cae269SKonstantin Komarov truncate_inode_pages_final(&inode->i_data); 175682cae269SKonstantin Komarov 175782cae269SKonstantin Komarov if (inode->i_nlink) 175882cae269SKonstantin Komarov _ni_write_inode(inode, inode_needs_sync(inode)); 175982cae269SKonstantin Komarov 176082cae269SKonstantin Komarov invalidate_inode_buffers(inode); 176182cae269SKonstantin Komarov clear_inode(inode); 176282cae269SKonstantin Komarov 176382cae269SKonstantin Komarov ni_clear(ntfs_i(inode)); 176482cae269SKonstantin Komarov } 176582cae269SKonstantin Komarov 176682cae269SKonstantin Komarov static noinline int ntfs_readlink_hlp(struct inode *inode, char *buffer, 176782cae269SKonstantin Komarov int buflen) 176882cae269SKonstantin Komarov { 17694dbe8e44SKonstantin Komarov int i, err = -EINVAL; 177082cae269SKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 177182cae269SKonstantin Komarov struct super_block *sb = inode->i_sb; 177282cae269SKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 17734dbe8e44SKonstantin Komarov u64 size; 17744dbe8e44SKonstantin Komarov u16 ulen = 0; 177582cae269SKonstantin Komarov void *to_free = NULL; 177682cae269SKonstantin Komarov struct REPARSE_DATA_BUFFER *rp; 17774dbe8e44SKonstantin Komarov const __le16 *uname; 177882cae269SKonstantin Komarov struct ATTRIB *attr; 177982cae269SKonstantin Komarov 1780e8b8e97fSKari Argillander /* Reparse data present. Try to parse it. */ 178182cae269SKonstantin Komarov static_assert(!offsetof(struct REPARSE_DATA_BUFFER, ReparseTag)); 178282cae269SKonstantin Komarov static_assert(sizeof(u32) == sizeof(rp->ReparseTag)); 178382cae269SKonstantin Komarov 178482cae269SKonstantin Komarov *buffer = 0; 178582cae269SKonstantin Komarov 178682cae269SKonstantin Komarov attr = ni_find_attr(ni, NULL, NULL, ATTR_REPARSE, NULL, 0, NULL, NULL); 17874dbe8e44SKonstantin Komarov if (!attr) 178882cae269SKonstantin Komarov goto out; 178982cae269SKonstantin Komarov 179082cae269SKonstantin Komarov if (!attr->non_res) { 17914dbe8e44SKonstantin Komarov rp = resident_data_ex(attr, sizeof(struct REPARSE_DATA_BUFFER)); 17924dbe8e44SKonstantin Komarov if (!rp) 179382cae269SKonstantin Komarov goto out; 17944dbe8e44SKonstantin Komarov size = le32_to_cpu(attr->res.data_size); 179582cae269SKonstantin Komarov } else { 17964dbe8e44SKonstantin Komarov size = le64_to_cpu(attr->nres.data_size); 17974dbe8e44SKonstantin Komarov rp = NULL; 17984dbe8e44SKonstantin Komarov } 17994dbe8e44SKonstantin Komarov 18004dbe8e44SKonstantin Komarov if (size > sbi->reparse.max_size || size <= sizeof(u32)) 18014dbe8e44SKonstantin Komarov goto out; 18024dbe8e44SKonstantin Komarov 18034dbe8e44SKonstantin Komarov if (!rp) { 18044dbe8e44SKonstantin Komarov rp = kmalloc(size, GFP_NOFS); 180582cae269SKonstantin Komarov if (!rp) { 180682cae269SKonstantin Komarov err = -ENOMEM; 180782cae269SKonstantin Komarov goto out; 180882cae269SKonstantin Komarov } 180982cae269SKonstantin Komarov to_free = rp; 18104dbe8e44SKonstantin Komarov /* Read into temporal buffer. */ 18114dbe8e44SKonstantin Komarov err = ntfs_read_run_nb(sbi, &ni->file.run, 0, rp, size, NULL); 181282cae269SKonstantin Komarov if (err) 181382cae269SKonstantin Komarov goto out; 181482cae269SKonstantin Komarov } 181582cae269SKonstantin Komarov 1816e8b8e97fSKari Argillander /* Microsoft Tag. */ 181782cae269SKonstantin Komarov switch (rp->ReparseTag) { 181882cae269SKonstantin Komarov case IO_REPARSE_TAG_MOUNT_POINT: 1819e8b8e97fSKari Argillander /* Mount points and junctions. */ 182082cae269SKonstantin Komarov /* Can we use 'Rp->MountPointReparseBuffer.PrintNameLength'? */ 18214dbe8e44SKonstantin Komarov if (size <= offsetof(struct REPARSE_DATA_BUFFER, 182282cae269SKonstantin Komarov MountPointReparseBuffer.PathBuffer)) 182382cae269SKonstantin Komarov goto out; 18244dbe8e44SKonstantin Komarov uname = Add2Ptr(rp, 182582cae269SKonstantin Komarov offsetof(struct REPARSE_DATA_BUFFER, 182682cae269SKonstantin Komarov MountPointReparseBuffer.PathBuffer) + 182782cae269SKonstantin Komarov le16_to_cpu(rp->MountPointReparseBuffer 18284dbe8e44SKonstantin Komarov .PrintNameOffset)); 18294dbe8e44SKonstantin Komarov ulen = le16_to_cpu(rp->MountPointReparseBuffer.PrintNameLength); 183082cae269SKonstantin Komarov break; 183182cae269SKonstantin Komarov 183282cae269SKonstantin Komarov case IO_REPARSE_TAG_SYMLINK: 183382cae269SKonstantin Komarov /* FolderSymbolicLink */ 183482cae269SKonstantin Komarov /* Can we use 'Rp->SymbolicLinkReparseBuffer.PrintNameLength'? */ 18354dbe8e44SKonstantin Komarov if (size <= offsetof(struct REPARSE_DATA_BUFFER, 183682cae269SKonstantin Komarov SymbolicLinkReparseBuffer.PathBuffer)) 183782cae269SKonstantin Komarov goto out; 18384dbe8e44SKonstantin Komarov uname = Add2Ptr( 18394dbe8e44SKonstantin Komarov rp, offsetof(struct REPARSE_DATA_BUFFER, 184082cae269SKonstantin Komarov SymbolicLinkReparseBuffer.PathBuffer) + 184182cae269SKonstantin Komarov le16_to_cpu(rp->SymbolicLinkReparseBuffer 18424dbe8e44SKonstantin Komarov .PrintNameOffset)); 18434dbe8e44SKonstantin Komarov ulen = le16_to_cpu( 184482cae269SKonstantin Komarov rp->SymbolicLinkReparseBuffer.PrintNameLength); 184582cae269SKonstantin Komarov break; 184682cae269SKonstantin Komarov 184782cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD: 184882cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_1: 184982cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_2: 185082cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_3: 185182cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_4: 185282cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_5: 185382cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_6: 185482cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_7: 185582cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_8: 185682cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_9: 185782cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_A: 185882cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_B: 185982cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_C: 186082cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_D: 186182cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_E: 186282cae269SKonstantin Komarov case IO_REPARSE_TAG_CLOUD_F: 186382cae269SKonstantin Komarov err = sizeof("OneDrive") - 1; 186482cae269SKonstantin Komarov if (err > buflen) 186582cae269SKonstantin Komarov err = buflen; 186682cae269SKonstantin Komarov memcpy(buffer, "OneDrive", err); 186782cae269SKonstantin Komarov goto out; 186882cae269SKonstantin Komarov 186982cae269SKonstantin Komarov default: 187082cae269SKonstantin Komarov if (IsReparseTagMicrosoft(rp->ReparseTag)) { 1871d3624466SKonstantin Komarov /* Unknown Microsoft Tag. */ 187282cae269SKonstantin Komarov goto out; 187382cae269SKonstantin Komarov } 187482cae269SKonstantin Komarov if (!IsReparseTagNameSurrogate(rp->ReparseTag) || 18754dbe8e44SKonstantin Komarov size <= sizeof(struct REPARSE_POINT)) { 187682cae269SKonstantin Komarov goto out; 187782cae269SKonstantin Komarov } 187882cae269SKonstantin Komarov 1879e8b8e97fSKari Argillander /* Users tag. */ 18804dbe8e44SKonstantin Komarov uname = Add2Ptr(rp, sizeof(struct REPARSE_POINT)); 18814dbe8e44SKonstantin Komarov ulen = le16_to_cpu(rp->ReparseDataLength) - 188282cae269SKonstantin Komarov sizeof(struct REPARSE_POINT); 188382cae269SKonstantin Komarov } 188482cae269SKonstantin Komarov 1885e8b8e97fSKari Argillander /* Convert nlen from bytes to UNICODE chars. */ 18864dbe8e44SKonstantin Komarov ulen >>= 1; 188782cae269SKonstantin Komarov 1888e8b8e97fSKari Argillander /* Check that name is available. */ 18894dbe8e44SKonstantin Komarov if (!ulen || uname + ulen > (__le16 *)Add2Ptr(rp, size)) 189082cae269SKonstantin Komarov goto out; 189182cae269SKonstantin Komarov 1892e8b8e97fSKari Argillander /* If name is already zero terminated then truncate it now. */ 18934dbe8e44SKonstantin Komarov if (!uname[ulen - 1]) 18944dbe8e44SKonstantin Komarov ulen -= 1; 189582cae269SKonstantin Komarov 18964dbe8e44SKonstantin Komarov err = ntfs_utf16_to_nls(sbi, uname, ulen, buffer, buflen); 189782cae269SKonstantin Komarov 189882cae269SKonstantin Komarov if (err < 0) 189982cae269SKonstantin Komarov goto out; 190082cae269SKonstantin Komarov 1901e8b8e97fSKari Argillander /* Translate Windows '\' into Linux '/'. */ 190282cae269SKonstantin Komarov for (i = 0; i < err; i++) { 190382cae269SKonstantin Komarov if (buffer[i] == '\\') 190482cae269SKonstantin Komarov buffer[i] = '/'; 190582cae269SKonstantin Komarov } 190682cae269SKonstantin Komarov 1907e8b8e97fSKari Argillander /* Always set last zero. */ 190882cae269SKonstantin Komarov buffer[err] = 0; 190982cae269SKonstantin Komarov out: 1910195c52bdSKari Argillander kfree(to_free); 191182cae269SKonstantin Komarov return err; 191282cae269SKonstantin Komarov } 191382cae269SKonstantin Komarov 191482cae269SKonstantin Komarov static const char *ntfs_get_link(struct dentry *de, struct inode *inode, 191582cae269SKonstantin Komarov struct delayed_call *done) 191682cae269SKonstantin Komarov { 191782cae269SKonstantin Komarov int err; 191882cae269SKonstantin Komarov char *ret; 191982cae269SKonstantin Komarov 192082cae269SKonstantin Komarov if (!de) 192182cae269SKonstantin Komarov return ERR_PTR(-ECHILD); 192282cae269SKonstantin Komarov 192382cae269SKonstantin Komarov ret = kmalloc(PAGE_SIZE, GFP_NOFS); 192482cae269SKonstantin Komarov if (!ret) 192582cae269SKonstantin Komarov return ERR_PTR(-ENOMEM); 192682cae269SKonstantin Komarov 192782cae269SKonstantin Komarov err = ntfs_readlink_hlp(inode, ret, PAGE_SIZE); 192882cae269SKonstantin Komarov if (err < 0) { 192982cae269SKonstantin Komarov kfree(ret); 193082cae269SKonstantin Komarov return ERR_PTR(err); 193182cae269SKonstantin Komarov } 193282cae269SKonstantin Komarov 193382cae269SKonstantin Komarov set_delayed_call(done, kfree_link, ret); 193482cae269SKonstantin Komarov 193582cae269SKonstantin Komarov return ret; 193682cae269SKonstantin Komarov } 193782cae269SKonstantin Komarov 193882cae269SKonstantin Komarov // clang-format off 193982cae269SKonstantin Komarov const struct inode_operations ntfs_link_inode_operations = { 194082cae269SKonstantin Komarov .get_link = ntfs_get_link, 194182cae269SKonstantin Komarov .setattr = ntfs3_setattr, 194282cae269SKonstantin Komarov .listxattr = ntfs_listxattr, 194382cae269SKonstantin Komarov .permission = ntfs_permission, 194482cae269SKonstantin Komarov .get_acl = ntfs_get_acl, 194582cae269SKonstantin Komarov .set_acl = ntfs_set_acl, 194682cae269SKonstantin Komarov }; 194782cae269SKonstantin Komarov 194882cae269SKonstantin Komarov const struct address_space_operations ntfs_aops = { 194982cae269SKonstantin Komarov .readpage = ntfs_readpage, 195082cae269SKonstantin Komarov .readahead = ntfs_readahead, 195182cae269SKonstantin Komarov .writepage = ntfs_writepage, 195282cae269SKonstantin Komarov .writepages = ntfs_writepages, 195382cae269SKonstantin Komarov .write_begin = ntfs_write_begin, 195482cae269SKonstantin Komarov .write_end = ntfs_write_end, 195582cae269SKonstantin Komarov .direct_IO = ntfs_direct_IO, 195682cae269SKonstantin Komarov .bmap = ntfs_bmap, 195782cae269SKonstantin Komarov .set_page_dirty = __set_page_dirty_buffers, 195882cae269SKonstantin Komarov }; 195982cae269SKonstantin Komarov 196082cae269SKonstantin Komarov const struct address_space_operations ntfs_aops_cmpr = { 196182cae269SKonstantin Komarov .readpage = ntfs_readpage, 196282cae269SKonstantin Komarov .readahead = ntfs_readahead, 196382cae269SKonstantin Komarov }; 196482cae269SKonstantin Komarov // clang-format on 1965