162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS 462306a36Sopenharmony_ci * project. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 2001-2006 Anton Altaparmakov 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/dcache.h> 1062306a36Sopenharmony_ci#include <linux/exportfs.h> 1162306a36Sopenharmony_ci#include <linux/security.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "attrib.h" 1562306a36Sopenharmony_ci#include "debug.h" 1662306a36Sopenharmony_ci#include "dir.h" 1762306a36Sopenharmony_ci#include "mft.h" 1862306a36Sopenharmony_ci#include "ntfs.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/** 2162306a36Sopenharmony_ci * ntfs_lookup - find the inode represented by a dentry in a directory inode 2262306a36Sopenharmony_ci * @dir_ino: directory inode in which to look for the inode 2362306a36Sopenharmony_ci * @dent: dentry representing the inode to look for 2462306a36Sopenharmony_ci * @flags: lookup flags 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * In short, ntfs_lookup() looks for the inode represented by the dentry @dent 2762306a36Sopenharmony_ci * in the directory inode @dir_ino and if found attaches the inode to the 2862306a36Sopenharmony_ci * dentry @dent. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * In more detail, the dentry @dent specifies which inode to look for by 3162306a36Sopenharmony_ci * supplying the name of the inode in @dent->d_name.name. ntfs_lookup() 3262306a36Sopenharmony_ci * converts the name to Unicode and walks the contents of the directory inode 3362306a36Sopenharmony_ci * @dir_ino looking for the converted Unicode name. If the name is found in the 3462306a36Sopenharmony_ci * directory, the corresponding inode is loaded by calling ntfs_iget() on its 3562306a36Sopenharmony_ci * inode number and the inode is associated with the dentry @dent via a call to 3662306a36Sopenharmony_ci * d_splice_alias(). 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * If the name is not found in the directory, a NULL inode is inserted into the 3962306a36Sopenharmony_ci * dentry @dent via a call to d_add(). The dentry is then termed a negative 4062306a36Sopenharmony_ci * dentry. 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * Only if an actual error occurs, do we return an error via ERR_PTR(). 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * In order to handle the case insensitivity issues of NTFS with regards to the 4562306a36Sopenharmony_ci * dcache and the dcache requiring only one dentry per directory, we deal with 4662306a36Sopenharmony_ci * dentry aliases that only differ in case in ->ntfs_lookup() while maintaining 4762306a36Sopenharmony_ci * a case sensitive dcache. This means that we get the full benefit of dcache 4862306a36Sopenharmony_ci * speed when the file/directory is looked up with the same case as returned by 4962306a36Sopenharmony_ci * ->ntfs_readdir() but that a lookup for any other case (or for the short file 5062306a36Sopenharmony_ci * name) will not find anything in dcache and will enter ->ntfs_lookup() 5162306a36Sopenharmony_ci * instead, where we search the directory for a fully matching file name 5262306a36Sopenharmony_ci * (including case) and if that is not found, we search for a file name that 5362306a36Sopenharmony_ci * matches with different case and if that has non-POSIX semantics we return 5462306a36Sopenharmony_ci * that. We actually do only one search (case sensitive) and keep tabs on 5562306a36Sopenharmony_ci * whether we have found a case insensitive match in the process. 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * To simplify matters for us, we do not treat the short vs long filenames as 5862306a36Sopenharmony_ci * two hard links but instead if the lookup matches a short filename, we 5962306a36Sopenharmony_ci * return the dentry for the corresponding long filename instead. 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * There are three cases we need to distinguish here: 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * 1) @dent perfectly matches (i.e. including case) a directory entry with a 6462306a36Sopenharmony_ci * file name in the WIN32 or POSIX namespaces. In this case 6562306a36Sopenharmony_ci * ntfs_lookup_inode_by_name() will return with name set to NULL and we 6662306a36Sopenharmony_ci * just d_splice_alias() @dent. 6762306a36Sopenharmony_ci * 2) @dent matches (not including case) a directory entry with a file name in 6862306a36Sopenharmony_ci * the WIN32 namespace. In this case ntfs_lookup_inode_by_name() will return 6962306a36Sopenharmony_ci * with name set to point to a kmalloc()ed ntfs_name structure containing 7062306a36Sopenharmony_ci * the properly cased little endian Unicode name. We convert the name to the 7162306a36Sopenharmony_ci * current NLS code page, search if a dentry with this name already exists 7262306a36Sopenharmony_ci * and if so return that instead of @dent. At this point things are 7362306a36Sopenharmony_ci * complicated by the possibility of 'disconnected' dentries due to NFS 7462306a36Sopenharmony_ci * which we deal with appropriately (see the code comments). The VFS will 7562306a36Sopenharmony_ci * then destroy the old @dent and use the one we returned. If a dentry is 7662306a36Sopenharmony_ci * not found, we allocate a new one, d_splice_alias() it, and return it as 7762306a36Sopenharmony_ci * above. 7862306a36Sopenharmony_ci * 3) @dent matches either perfectly or not (i.e. we don't care about case) a 7962306a36Sopenharmony_ci * directory entry with a file name in the DOS namespace. In this case 8062306a36Sopenharmony_ci * ntfs_lookup_inode_by_name() will return with name set to point to a 8162306a36Sopenharmony_ci * kmalloc()ed ntfs_name structure containing the mft reference (cpu endian) 8262306a36Sopenharmony_ci * of the inode. We use the mft reference to read the inode and to find the 8362306a36Sopenharmony_ci * file name in the WIN32 namespace corresponding to the matched short file 8462306a36Sopenharmony_ci * name. We then convert the name to the current NLS code page, and proceed 8562306a36Sopenharmony_ci * searching for a dentry with this name, etc, as in case 2), above. 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * Locking: Caller must hold i_mutex on the directory. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_cistatic struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, 9062306a36Sopenharmony_ci unsigned int flags) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci ntfs_volume *vol = NTFS_SB(dir_ino->i_sb); 9362306a36Sopenharmony_ci struct inode *dent_inode; 9462306a36Sopenharmony_ci ntfschar *uname; 9562306a36Sopenharmony_ci ntfs_name *name = NULL; 9662306a36Sopenharmony_ci MFT_REF mref; 9762306a36Sopenharmony_ci unsigned long dent_ino; 9862306a36Sopenharmony_ci int uname_len; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci ntfs_debug("Looking up %pd in directory inode 0x%lx.", 10162306a36Sopenharmony_ci dent, dir_ino->i_ino); 10262306a36Sopenharmony_ci /* Convert the name of the dentry to Unicode. */ 10362306a36Sopenharmony_ci uname_len = ntfs_nlstoucs(vol, dent->d_name.name, dent->d_name.len, 10462306a36Sopenharmony_ci &uname); 10562306a36Sopenharmony_ci if (uname_len < 0) { 10662306a36Sopenharmony_ci if (uname_len != -ENAMETOOLONG) 10762306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to convert name to " 10862306a36Sopenharmony_ci "Unicode."); 10962306a36Sopenharmony_ci return ERR_PTR(uname_len); 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci mref = ntfs_lookup_inode_by_name(NTFS_I(dir_ino), uname, uname_len, 11262306a36Sopenharmony_ci &name); 11362306a36Sopenharmony_ci kmem_cache_free(ntfs_name_cache, uname); 11462306a36Sopenharmony_ci if (!IS_ERR_MREF(mref)) { 11562306a36Sopenharmony_ci dent_ino = MREF(mref); 11662306a36Sopenharmony_ci ntfs_debug("Found inode 0x%lx. Calling ntfs_iget.", dent_ino); 11762306a36Sopenharmony_ci dent_inode = ntfs_iget(vol->sb, dent_ino); 11862306a36Sopenharmony_ci if (!IS_ERR(dent_inode)) { 11962306a36Sopenharmony_ci /* Consistency check. */ 12062306a36Sopenharmony_ci if (is_bad_inode(dent_inode) || MSEQNO(mref) == 12162306a36Sopenharmony_ci NTFS_I(dent_inode)->seq_no || 12262306a36Sopenharmony_ci dent_ino == FILE_MFT) { 12362306a36Sopenharmony_ci /* Perfect WIN32/POSIX match. -- Case 1. */ 12462306a36Sopenharmony_ci if (!name) { 12562306a36Sopenharmony_ci ntfs_debug("Done. (Case 1.)"); 12662306a36Sopenharmony_ci return d_splice_alias(dent_inode, dent); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci /* 12962306a36Sopenharmony_ci * We are too indented. Handle imperfect 13062306a36Sopenharmony_ci * matches and short file names further below. 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci goto handle_name; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci ntfs_error(vol->sb, "Found stale reference to inode " 13562306a36Sopenharmony_ci "0x%lx (reference sequence number = " 13662306a36Sopenharmony_ci "0x%x, inode sequence number = 0x%x), " 13762306a36Sopenharmony_ci "returning -EIO. Run chkdsk.", 13862306a36Sopenharmony_ci dent_ino, MSEQNO(mref), 13962306a36Sopenharmony_ci NTFS_I(dent_inode)->seq_no); 14062306a36Sopenharmony_ci iput(dent_inode); 14162306a36Sopenharmony_ci dent_inode = ERR_PTR(-EIO); 14262306a36Sopenharmony_ci } else 14362306a36Sopenharmony_ci ntfs_error(vol->sb, "ntfs_iget(0x%lx) failed with " 14462306a36Sopenharmony_ci "error code %li.", dent_ino, 14562306a36Sopenharmony_ci PTR_ERR(dent_inode)); 14662306a36Sopenharmony_ci kfree(name); 14762306a36Sopenharmony_ci /* Return the error code. */ 14862306a36Sopenharmony_ci return ERR_CAST(dent_inode); 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci /* It is guaranteed that @name is no longer allocated at this point. */ 15162306a36Sopenharmony_ci if (MREF_ERR(mref) == -ENOENT) { 15262306a36Sopenharmony_ci ntfs_debug("Entry was not found, adding negative dentry."); 15362306a36Sopenharmony_ci /* The dcache will handle negative entries. */ 15462306a36Sopenharmony_ci d_add(dent, NULL); 15562306a36Sopenharmony_ci ntfs_debug("Done."); 15662306a36Sopenharmony_ci return NULL; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error " 15962306a36Sopenharmony_ci "code %i.", -MREF_ERR(mref)); 16062306a36Sopenharmony_ci return ERR_PTR(MREF_ERR(mref)); 16162306a36Sopenharmony_ci // TODO: Consider moving this lot to a separate function! (AIA) 16262306a36Sopenharmony_cihandle_name: 16362306a36Sopenharmony_ci { 16462306a36Sopenharmony_ci MFT_RECORD *m; 16562306a36Sopenharmony_ci ntfs_attr_search_ctx *ctx; 16662306a36Sopenharmony_ci ntfs_inode *ni = NTFS_I(dent_inode); 16762306a36Sopenharmony_ci int err; 16862306a36Sopenharmony_ci struct qstr nls_name; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci nls_name.name = NULL; 17162306a36Sopenharmony_ci if (name->type != FILE_NAME_DOS) { /* Case 2. */ 17262306a36Sopenharmony_ci ntfs_debug("Case 2."); 17362306a36Sopenharmony_ci nls_name.len = (unsigned)ntfs_ucstonls(vol, 17462306a36Sopenharmony_ci (ntfschar*)&name->name, name->len, 17562306a36Sopenharmony_ci (unsigned char**)&nls_name.name, 0); 17662306a36Sopenharmony_ci kfree(name); 17762306a36Sopenharmony_ci } else /* if (name->type == FILE_NAME_DOS) */ { /* Case 3. */ 17862306a36Sopenharmony_ci FILE_NAME_ATTR *fn; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci ntfs_debug("Case 3."); 18162306a36Sopenharmony_ci kfree(name); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* Find the WIN32 name corresponding to the matched DOS name. */ 18462306a36Sopenharmony_ci ni = NTFS_I(dent_inode); 18562306a36Sopenharmony_ci m = map_mft_record(ni); 18662306a36Sopenharmony_ci if (IS_ERR(m)) { 18762306a36Sopenharmony_ci err = PTR_ERR(m); 18862306a36Sopenharmony_ci m = NULL; 18962306a36Sopenharmony_ci ctx = NULL; 19062306a36Sopenharmony_ci goto err_out; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(ni, m); 19362306a36Sopenharmony_ci if (unlikely(!ctx)) { 19462306a36Sopenharmony_ci err = -ENOMEM; 19562306a36Sopenharmony_ci goto err_out; 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci do { 19862306a36Sopenharmony_ci ATTR_RECORD *a; 19962306a36Sopenharmony_ci u32 val_len; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, 20262306a36Sopenharmony_ci NULL, 0, ctx); 20362306a36Sopenharmony_ci if (unlikely(err)) { 20462306a36Sopenharmony_ci ntfs_error(vol->sb, "Inode corrupt: No WIN32 " 20562306a36Sopenharmony_ci "namespace counterpart to DOS " 20662306a36Sopenharmony_ci "file name. Run chkdsk."); 20762306a36Sopenharmony_ci if (err == -ENOENT) 20862306a36Sopenharmony_ci err = -EIO; 20962306a36Sopenharmony_ci goto err_out; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci /* Consistency checks. */ 21262306a36Sopenharmony_ci a = ctx->attr; 21362306a36Sopenharmony_ci if (a->non_resident || a->flags) 21462306a36Sopenharmony_ci goto eio_err_out; 21562306a36Sopenharmony_ci val_len = le32_to_cpu(a->data.resident.value_length); 21662306a36Sopenharmony_ci if (le16_to_cpu(a->data.resident.value_offset) + 21762306a36Sopenharmony_ci val_len > le32_to_cpu(a->length)) 21862306a36Sopenharmony_ci goto eio_err_out; 21962306a36Sopenharmony_ci fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + le16_to_cpu( 22062306a36Sopenharmony_ci ctx->attr->data.resident.value_offset)); 22162306a36Sopenharmony_ci if ((u32)(fn->file_name_length * sizeof(ntfschar) + 22262306a36Sopenharmony_ci sizeof(FILE_NAME_ATTR)) > val_len) 22362306a36Sopenharmony_ci goto eio_err_out; 22462306a36Sopenharmony_ci } while (fn->file_name_type != FILE_NAME_WIN32); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* Convert the found WIN32 name to current NLS code page. */ 22762306a36Sopenharmony_ci nls_name.len = (unsigned)ntfs_ucstonls(vol, 22862306a36Sopenharmony_ci (ntfschar*)&fn->file_name, fn->file_name_length, 22962306a36Sopenharmony_ci (unsigned char**)&nls_name.name, 0); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 23262306a36Sopenharmony_ci unmap_mft_record(ni); 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci m = NULL; 23562306a36Sopenharmony_ci ctx = NULL; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* Check if a conversion error occurred. */ 23862306a36Sopenharmony_ci if ((signed)nls_name.len < 0) { 23962306a36Sopenharmony_ci err = (signed)nls_name.len; 24062306a36Sopenharmony_ci goto err_out; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci nls_name.hash = full_name_hash(dent, nls_name.name, nls_name.len); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci dent = d_add_ci(dent, dent_inode, &nls_name); 24562306a36Sopenharmony_ci kfree(nls_name.name); 24662306a36Sopenharmony_ci return dent; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cieio_err_out: 24962306a36Sopenharmony_ci ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk."); 25062306a36Sopenharmony_ci err = -EIO; 25162306a36Sopenharmony_cierr_out: 25262306a36Sopenharmony_ci if (ctx) 25362306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 25462306a36Sopenharmony_ci if (m) 25562306a36Sopenharmony_ci unmap_mft_record(ni); 25662306a36Sopenharmony_ci iput(dent_inode); 25762306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed, returning error code %i.", err); 25862306a36Sopenharmony_ci return ERR_PTR(err); 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci/* 26362306a36Sopenharmony_ci * Inode operations for directories. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ciconst struct inode_operations ntfs_dir_inode_ops = { 26662306a36Sopenharmony_ci .lookup = ntfs_lookup, /* VFS: Lookup directory. */ 26762306a36Sopenharmony_ci}; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci/** 27062306a36Sopenharmony_ci * ntfs_get_parent - find the dentry of the parent of a given directory dentry 27162306a36Sopenharmony_ci * @child_dent: dentry of the directory whose parent directory to find 27262306a36Sopenharmony_ci * 27362306a36Sopenharmony_ci * Find the dentry for the parent directory of the directory specified by the 27462306a36Sopenharmony_ci * dentry @child_dent. This function is called from 27562306a36Sopenharmony_ci * fs/exportfs/expfs.c::find_exported_dentry() which in turn is called from the 27662306a36Sopenharmony_ci * default ->decode_fh() which is export_decode_fh() in the same file. 27762306a36Sopenharmony_ci * 27862306a36Sopenharmony_ci * The code is based on the ext3 ->get_parent() implementation found in 27962306a36Sopenharmony_ci * fs/ext3/namei.c::ext3_get_parent(). 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * Note: ntfs_get_parent() is called with @d_inode(child_dent)->i_mutex down. 28262306a36Sopenharmony_ci * 28362306a36Sopenharmony_ci * Return the dentry of the parent directory on success or the error code on 28462306a36Sopenharmony_ci * error (IS_ERR() is true). 28562306a36Sopenharmony_ci */ 28662306a36Sopenharmony_cistatic struct dentry *ntfs_get_parent(struct dentry *child_dent) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct inode *vi = d_inode(child_dent); 28962306a36Sopenharmony_ci ntfs_inode *ni = NTFS_I(vi); 29062306a36Sopenharmony_ci MFT_RECORD *mrec; 29162306a36Sopenharmony_ci ntfs_attr_search_ctx *ctx; 29262306a36Sopenharmony_ci ATTR_RECORD *attr; 29362306a36Sopenharmony_ci FILE_NAME_ATTR *fn; 29462306a36Sopenharmony_ci unsigned long parent_ino; 29562306a36Sopenharmony_ci int err; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); 29862306a36Sopenharmony_ci /* Get the mft record of the inode belonging to the child dentry. */ 29962306a36Sopenharmony_ci mrec = map_mft_record(ni); 30062306a36Sopenharmony_ci if (IS_ERR(mrec)) 30162306a36Sopenharmony_ci return ERR_CAST(mrec); 30262306a36Sopenharmony_ci /* Find the first file name attribute in the mft record. */ 30362306a36Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(ni, mrec); 30462306a36Sopenharmony_ci if (unlikely(!ctx)) { 30562306a36Sopenharmony_ci unmap_mft_record(ni); 30662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_citry_next: 30962306a36Sopenharmony_ci err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL, 31062306a36Sopenharmony_ci 0, ctx); 31162306a36Sopenharmony_ci if (unlikely(err)) { 31262306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 31362306a36Sopenharmony_ci unmap_mft_record(ni); 31462306a36Sopenharmony_ci if (err == -ENOENT) 31562306a36Sopenharmony_ci ntfs_error(vi->i_sb, "Inode 0x%lx does not have a " 31662306a36Sopenharmony_ci "file name attribute. Run chkdsk.", 31762306a36Sopenharmony_ci vi->i_ino); 31862306a36Sopenharmony_ci return ERR_PTR(err); 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci attr = ctx->attr; 32162306a36Sopenharmony_ci if (unlikely(attr->non_resident)) 32262306a36Sopenharmony_ci goto try_next; 32362306a36Sopenharmony_ci fn = (FILE_NAME_ATTR *)((u8 *)attr + 32462306a36Sopenharmony_ci le16_to_cpu(attr->data.resident.value_offset)); 32562306a36Sopenharmony_ci if (unlikely((u8 *)fn + le32_to_cpu(attr->data.resident.value_length) > 32662306a36Sopenharmony_ci (u8*)attr + le32_to_cpu(attr->length))) 32762306a36Sopenharmony_ci goto try_next; 32862306a36Sopenharmony_ci /* Get the inode number of the parent directory. */ 32962306a36Sopenharmony_ci parent_ino = MREF_LE(fn->parent_directory); 33062306a36Sopenharmony_ci /* Release the search context and the mft record of the child. */ 33162306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 33262306a36Sopenharmony_ci unmap_mft_record(ni); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return d_obtain_alias(ntfs_iget(vi->i_sb, parent_ino)); 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic struct inode *ntfs_nfs_get_inode(struct super_block *sb, 33862306a36Sopenharmony_ci u64 ino, u32 generation) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci struct inode *inode; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci inode = ntfs_iget(sb, ino); 34362306a36Sopenharmony_ci if (!IS_ERR(inode)) { 34462306a36Sopenharmony_ci if (is_bad_inode(inode) || inode->i_generation != generation) { 34562306a36Sopenharmony_ci iput(inode); 34662306a36Sopenharmony_ci inode = ERR_PTR(-ESTALE); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci return inode; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid, 35462306a36Sopenharmony_ci int fh_len, int fh_type) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 35762306a36Sopenharmony_ci ntfs_nfs_get_inode); 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid, 36162306a36Sopenharmony_ci int fh_len, int fh_type) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci return generic_fh_to_parent(sb, fid, fh_len, fh_type, 36462306a36Sopenharmony_ci ntfs_nfs_get_inode); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* 36862306a36Sopenharmony_ci * Export operations allowing NFS exporting of mounted NTFS partitions. 36962306a36Sopenharmony_ci * 37062306a36Sopenharmony_ci * We use the default ->encode_fh() for now. Note that they 37162306a36Sopenharmony_ci * use 32 bits to store the inode number which is an unsigned long so on 64-bit 37262306a36Sopenharmony_ci * architectures is usually 64 bits so it would all fail horribly on huge 37362306a36Sopenharmony_ci * volumes. I guess we need to define our own encode and decode fh functions 37462306a36Sopenharmony_ci * that store 64-bit inode numbers at some point but for now we will ignore the 37562306a36Sopenharmony_ci * problem... 37662306a36Sopenharmony_ci * 37762306a36Sopenharmony_ci * We also use the default ->get_name() helper (used by ->decode_fh() via 37862306a36Sopenharmony_ci * fs/exportfs/expfs.c::find_exported_dentry()) as that is completely fs 37962306a36Sopenharmony_ci * independent. 38062306a36Sopenharmony_ci * 38162306a36Sopenharmony_ci * The default ->get_parent() just returns -EACCES so we have to provide our 38262306a36Sopenharmony_ci * own and the default ->get_dentry() is incompatible with NTFS due to not 38362306a36Sopenharmony_ci * allowing the inode number 0 which is used in NTFS for the system file $MFT 38462306a36Sopenharmony_ci * and due to using iget() whereas NTFS needs ntfs_iget(). 38562306a36Sopenharmony_ci */ 38662306a36Sopenharmony_ciconst struct export_operations ntfs_export_ops = { 38762306a36Sopenharmony_ci .get_parent = ntfs_get_parent, /* Find the parent of a given 38862306a36Sopenharmony_ci directory. */ 38962306a36Sopenharmony_ci .fh_to_dentry = ntfs_fh_to_dentry, 39062306a36Sopenharmony_ci .fh_to_parent = ntfs_fh_to_parent, 39162306a36Sopenharmony_ci}; 392