1193326Sed// SPDX-License-Identifier: GPL-2.0 2193326Sed/* 3193326Sed * Copyright (c) 2004-2005 Silicon Graphics, Inc. 4193326Sed * All Rights Reserved. 5193326Sed */ 6193326Sed#include "xfs.h" 7193326Sed#include "xfs_shared.h" 8193326Sed#include "xfs_format.h" 9193326Sed#include "xfs_log_format.h" 10193326Sed#include "xfs_trans_resv.h" 11193326Sed#include "xfs_mount.h" 12193326Sed#include "xfs_dir2.h" 13193326Sed#include "xfs_export.h" 14221345Sdim#include "xfs_inode.h" 15193326Sed#include "xfs_trans.h" 16199482Srdivacky#include "xfs_inode_item.h" 17193326Sed#include "xfs_icache.h" 18193326Sed#include "xfs_pnfs.h" 19218893Sdim 20193326Sed/* 21193326Sed * Note that we only accept fileids which are long enough rather than allow 22193326Sed * the parent generation number to default to zero. XFS considers zero a 23221345Sdim * valid generation number not an invalid/wildcard value. 24221345Sdim */ 25193326Sedstatic int xfs_fileid_length(int fileid_type) 26193326Sed{ 27207619Srdivacky switch (fileid_type) { 28207619Srdivacky case FILEID_INO32_GEN: 29193326Sed return 2; 30207619Srdivacky case FILEID_INO32_GEN_PARENT: 31193326Sed return 4; 32218893Sdim case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: 33193326Sed return 3; 34193326Sed case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: 35193326Sed return 6; 36193326Sed } 37193326Sed return FILEID_INVALID; 38193326Sed} 39193326Sed 40193326SedSTATIC int 41193326Sedxfs_fs_encode_fh( 42210299Sed struct inode *inode, 43210299Sed __u32 *fh, 44193326Sed int *max_len, 45193326Sed struct inode *parent) 46193326Sed{ 47193326Sed struct xfs_mount *mp = XFS_M(inode->i_sb); 48193326Sed struct fid *fid = (struct fid *)fh; 49193326Sed struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh; 50198398Srdivacky int fileid_type; 51198092Srdivacky int len; 52198092Srdivacky 53195341Sed /* Directories don't need their parent encoded, they have ".." */ 54199990Srdivacky if (!parent) 55207619Srdivacky fileid_type = FILEID_INO32_GEN; 56193326Sed else 57193326Sed fileid_type = FILEID_INO32_GEN_PARENT; 58193326Sed 59193326Sed /* 60199482Srdivacky * If the filesystem may contain 64bit inode numbers, we need 61193326Sed * to use larger file handles that can represent them. 62218893Sdim * 63208600Srdivacky * While we only allocate inodes that do not fit into 32 bits any 64210299Sed * large enough filesystem may contain them, thus the slightly 65210299Sed * confusing looking conditional below. 66210299Sed */ 67212904Sdim if (!xfs_has_small_inums(mp) || xfs_is_inode32(mp)) 68212904Sdim fileid_type |= XFS_FILEID_TYPE_64FLAG; 69212904Sdim 70221345Sdim /* 71221345Sdim * Only encode if there is enough space given. In practice 72221345Sdim * this means we can't export a filesystem with 64bit inodes 73221345Sdim * over NFSv2 with the subtree_check export option; the other 74221345Sdim * seven combinations work. The real answer is "don't use v2". 75221345Sdim */ 76221345Sdim len = xfs_fileid_length(fileid_type); 77193326Sed if (*max_len < len) { 78193326Sed *max_len = len; 79193326Sed return FILEID_INVALID; 80193326Sed } 81193326Sed *max_len = len; 82193326Sed 83193326Sed switch (fileid_type) { 84193326Sed case FILEID_INO32_GEN_PARENT: 85193326Sed fid->i32.parent_ino = XFS_I(parent)->i_ino; 86193326Sed fid->i32.parent_gen = parent->i_generation; 87193326Sed fallthrough; 88193326Sed case FILEID_INO32_GEN: 89193326Sed fid->i32.ino = XFS_I(inode)->i_ino; 90193326Sed fid->i32.gen = inode->i_generation; 91193326Sed break; 92193326Sed case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: 93193326Sed fid64->parent_ino = XFS_I(parent)->i_ino; 94193326Sed fid64->parent_gen = parent->i_generation; 95193326Sed fallthrough; 96193326Sed case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: 97193326Sed fid64->ino = XFS_I(inode)->i_ino; 98198398Srdivacky fid64->gen = inode->i_generation; 99198398Srdivacky break; 100198398Srdivacky } 101198398Srdivacky 102198398Srdivacky return fileid_type; 103198398Srdivacky} 104198398Srdivacky 105198398Srdivackystruct inode * 106198398Srdivackyxfs_nfs_get_inode( 107198398Srdivacky struct super_block *sb, 108198398Srdivacky u64 ino, 109198398Srdivacky u32 generation) 110198398Srdivacky{ 111198398Srdivacky xfs_mount_t *mp = XFS_M(sb); 112198398Srdivacky xfs_inode_t *ip; 113198398Srdivacky int error; 114218893Sdim 115198398Srdivacky /* 116198398Srdivacky * NFS can sometimes send requests for ino 0. Fail them gracefully. 117198398Srdivacky */ 118198398Srdivacky if (ino == 0) 119199482Srdivacky return ERR_PTR(-ESTALE); 120198398Srdivacky 121199482Srdivacky /* 122198398Srdivacky * The XFS_IGET_UNTRUSTED means that an invalid inode number is just 123199482Srdivacky * fine and not an indication of a corrupted filesystem as clients can 124198398Srdivacky * send invalid file handles and we have to handle it gracefully.. 125199482Srdivacky */ 126198398Srdivacky error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED, 0, &ip); 127198398Srdivacky if (error) { 128198398Srdivacky 129198398Srdivacky /* 130218893Sdim * EINVAL means the inode cluster doesn't exist anymore. 131199482Srdivacky * EFSCORRUPTED means the metadata pointing to the inode cluster 132199482Srdivacky * or the inode cluster itself is corrupt. This implies the 133199482Srdivacky * filehandle is stale, so we should translate it here. 134199482Srdivacky * We don't use ESTALE directly down the chain to not 135199482Srdivacky * confuse applications using bulkstat that expect EINVAL. 136199482Srdivacky */ 137199482Srdivacky switch (error) { 138199482Srdivacky case -EINVAL: 139199482Srdivacky case -ENOENT: 140199482Srdivacky case -EFSCORRUPTED: 141199482Srdivacky error = -ESTALE; 142199482Srdivacky break; 143199482Srdivacky default: 144199482Srdivacky break; 145199482Srdivacky } 146198893Srdivacky return ERR_PTR(error); 147198398Srdivacky } 148218893Sdim 149198398Srdivacky /* 150198398Srdivacky * Reload the incore unlinked list to avoid failure in inodegc. 151198398Srdivacky * Use an unlocked check here because unrecovered unlinked inodes 152198398Srdivacky * should be somewhat rare. 153198398Srdivacky */ 154218893Sdim if (xfs_inode_unlinked_incomplete(ip)) { 155198398Srdivacky error = xfs_inode_reload_unlinked(ip); 156198398Srdivacky if (error) { 157198398Srdivacky xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 158198398Srdivacky xfs_irele(ip); 159218893Sdim return ERR_PTR(error); 160198398Srdivacky } 161198398Srdivacky } 162198398Srdivacky 163198398Srdivacky if (VFS_I(ip)->i_generation != generation || IS_PRIVATE(VFS_I(ip))) { 164199482Srdivacky xfs_irele(ip); 165199482Srdivacky return ERR_PTR(-ESTALE); 166199482Srdivacky } 167199482Srdivacky 168207619Srdivacky return VFS_I(ip); 169207619Srdivacky} 170207619Srdivacky 171199482SrdivackySTATIC struct dentry * 172199482Srdivackyxfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, 173198398Srdivacky int fh_len, int fileid_type) 174193326Sed{ 175193326Sed struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; 176193326Sed struct inode *inode = NULL; 177203955Srdivacky 178193326Sed if (fh_len < xfs_fileid_length(fileid_type)) 179203955Srdivacky return NULL; 180218893Sdim 181203955Srdivacky switch (fileid_type) { 182193326Sed case FILEID_INO32_GEN_PARENT: 183193326Sed case FILEID_INO32_GEN: 184193326Sed inode = xfs_nfs_get_inode(sb, fid->i32.ino, fid->i32.gen); 185193326Sed break; 186193326Sed case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: 187203955Srdivacky case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: 188203955Srdivacky inode = xfs_nfs_get_inode(sb, fid64->ino, fid64->gen); 189203955Srdivacky break; 190218893Sdim } 191193326Sed 192193326Sed return d_obtain_alias(inode); 193198092Srdivacky} 194193326Sed 195203955SrdivackySTATIC struct dentry * 196193326Sedxfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, 197203955Srdivacky int fh_len, int fileid_type) 198193326Sed{ 199198092Srdivacky struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; 200193326Sed struct inode *inode = NULL; 201198092Srdivacky 202193326Sed if (fh_len < xfs_fileid_length(fileid_type)) 203193326Sed return NULL; 204203955Srdivacky 205203955Srdivacky switch (fileid_type) { 206193326Sed case FILEID_INO32_GEN_PARENT: 207193326Sed inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, 208193326Sed fid->i32.parent_gen); 209193326Sed break; 210193326Sed case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: 211203955Srdivacky inode = xfs_nfs_get_inode(sb, fid64->parent_ino, 212193326Sed fid64->parent_gen); 213193326Sed break; 214198092Srdivacky } 215193326Sed 216193326Sed return d_obtain_alias(inode); 217193326Sed} 218198092Srdivacky 219193326SedSTATIC struct dentry * 220193326Sedxfs_fs_get_parent( 221193326Sed struct dentry *child) 222193326Sed{ 223193326Sed int error; 224203955Srdivacky struct xfs_inode *cip; 225193326Sed 226193326Sed error = xfs_lookup(XFS_I(d_inode(child)), &xfs_name_dotdot, &cip, NULL); 227193326Sed if (unlikely(error)) 228198092Srdivacky return ERR_PTR(error); 229193326Sed 230193326Sed return d_obtain_alias(VFS_I(cip)); 231193326Sed} 232218893Sdim 233203955SrdivackySTATIC int 234193326Sedxfs_fs_nfs_commit_metadata( 235198092Srdivacky struct inode *inode) 236203955Srdivacky{ 237203955Srdivacky return xfs_log_force_inode(XFS_I(inode)); 238198092Srdivacky} 239193326Sed 240193326Sedconst struct export_operations xfs_export_operations = { 241193326Sed .encode_fh = xfs_fs_encode_fh, 242193326Sed .fh_to_dentry = xfs_fs_fh_to_dentry, 243193326Sed .fh_to_parent = xfs_fs_fh_to_parent, 244193326Sed .get_parent = xfs_fs_get_parent, 245193326Sed .commit_metadata = xfs_fs_nfs_commit_metadata, 246203955Srdivacky#ifdef CONFIG_EXPORTFS_BLOCK_OPS 247203955Srdivacky .get_uuid = xfs_fs_get_uuid, 248198092Srdivacky .map_blocks = xfs_fs_map_blocks, 249193326Sed .commit_blocks = xfs_fs_commit_blocks, 250193326Sed#endif 251193326Sed}; 252193326Sed