xref: /openbmc/linux/fs/nfsd/nfsfh.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
29c69de4cSChristoph Hellwig /*
39c69de4cSChristoph Hellwig  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
49c69de4cSChristoph Hellwig  *
59c69de4cSChristoph Hellwig  * This file describes the layout of the file handles as passed
69c69de4cSChristoph Hellwig  * over the wire.
79c69de4cSChristoph Hellwig  */
89c69de4cSChristoph Hellwig #ifndef _LINUX_NFSD_NFSFH_H
99c69de4cSChristoph Hellwig #define _LINUX_NFSD_NFSFH_H
101557aca7SJ. Bruce Fields 
116e8b50d1SJeff Layton #include <linux/crc32.h>
129c69de4cSChristoph Hellwig #include <linux/sunrpc/svc.h>
131f15a550SJeff Layton #include <linux/iversion.h>
143cc55f44SJ. Bruce Fields #include <linux/exportfs.h>
15ef5825e3SNeilBrown #include <linux/nfs4.h>
16ef5825e3SNeilBrown 
17ef5825e3SNeilBrown /*
18ef5825e3SNeilBrown  * The file handle starts with a sequence of four-byte words.
19ef5825e3SNeilBrown  * The first word contains a version number (1) and three descriptor bytes
20ef5825e3SNeilBrown  * that tell how the remaining 3 variable length fields should be handled.
21ef5825e3SNeilBrown  * These three bytes are auth_type, fsid_type and fileid_type.
22ef5825e3SNeilBrown  *
23ef5825e3SNeilBrown  * All four-byte values are in host-byte-order.
24ef5825e3SNeilBrown  *
25ef5825e3SNeilBrown  * The auth_type field is deprecated and must be set to 0.
26ef5825e3SNeilBrown  *
27ef5825e3SNeilBrown  * The fsid_type identifies how the filesystem (or export point) is
28ef5825e3SNeilBrown  *    encoded.
29ef5825e3SNeilBrown  *  Current values:
30ef5825e3SNeilBrown  *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
31ef5825e3SNeilBrown  *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
32ef5825e3SNeilBrown  *              says we mustn't.  We must break it up and reassemble.
33ef5825e3SNeilBrown  *     1  - 4 byte user specified identifier
34ef5825e3SNeilBrown  *     2  - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
35ef5825e3SNeilBrown  *     3  - 4 byte device id, encoded for user-space, 4 byte inode number
36ef5825e3SNeilBrown  *     4  - 4 byte inode number and 4 byte uuid
37ef5825e3SNeilBrown  *     5  - 8 byte uuid
38ef5825e3SNeilBrown  *     6  - 16 byte uuid
39ef5825e3SNeilBrown  *     7  - 8 byte inode number and 16 byte uuid
40ef5825e3SNeilBrown  *
41c645a883SNeilBrown  * The fileid_type identifies how the file within the filesystem is encoded.
42ef5825e3SNeilBrown  *   The values for this field are filesystem specific, exccept that
43ef5825e3SNeilBrown  *   filesystems must not use the values '0' or '0xff'. 'See enum fid_type'
44ef5825e3SNeilBrown  *   in include/linux/exportfs.h for currently registered values.
45ef5825e3SNeilBrown  */
46ef5825e3SNeilBrown 
47ef5825e3SNeilBrown struct knfsd_fh {
48d8b26071SNeilBrown 	unsigned int	fh_size;	/*
49d8b26071SNeilBrown 					 * Points to the current size while
50d8b26071SNeilBrown 					 * building a new file handle.
51ef5825e3SNeilBrown 					 */
52ef5825e3SNeilBrown 	union {
53d8b26071SNeilBrown 		char			fh_raw[NFS4_FHSIZE];
54d8b26071SNeilBrown 		struct {
55d8b26071SNeilBrown 			u8		fh_version;	/* == 1 */
56d8b26071SNeilBrown 			u8		fh_auth_type;	/* deprecated */
57d8b26071SNeilBrown 			u8		fh_fsid_type;
58d8b26071SNeilBrown 			u8		fh_fileid_type;
59d8b26071SNeilBrown 			u32		fh_fsid[]; /* flexible-array member */
60ef5825e3SNeilBrown 		};
61d8b26071SNeilBrown 	};
62d8b26071SNeilBrown };
631557aca7SJ. Bruce Fields 
ino_t_to_u32(ino_t ino)649c69de4cSChristoph Hellwig static inline __u32 ino_t_to_u32(ino_t ino)
659c69de4cSChristoph Hellwig {
669c69de4cSChristoph Hellwig 	return (__u32) ino;
679c69de4cSChristoph Hellwig }
689c69de4cSChristoph Hellwig 
u32_to_ino_t(__u32 uino)699c69de4cSChristoph Hellwig static inline ino_t u32_to_ino_t(__u32 uino)
709c69de4cSChristoph Hellwig {
719c69de4cSChristoph Hellwig 	return (ino_t) uino;
729c69de4cSChristoph Hellwig }
739c69de4cSChristoph Hellwig 
749c69de4cSChristoph Hellwig /*
759c69de4cSChristoph Hellwig  * This is the internal representation of an NFS handle used in knfsd.
769c69de4cSChristoph Hellwig  * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
779c69de4cSChristoph Hellwig  */
789c69de4cSChristoph Hellwig typedef struct svc_fh {
799c69de4cSChristoph Hellwig 	struct knfsd_fh		fh_handle;	/* FH data */
80fcaba026SJeff Layton 	int			fh_maxsize;	/* max size for fh_handle */
819c69de4cSChristoph Hellwig 	struct dentry *		fh_dentry;	/* validated dentry */
829c69de4cSChristoph Hellwig 	struct svc_export *	fh_export;	/* export pointer */
839c69de4cSChristoph Hellwig 
84aaf91ec1SJeff Layton 	bool			fh_want_write;	/* remount protection taken */
85daab110eSJeff Layton 	bool			fh_no_wcc;	/* no wcc data needed */
86716a8bc7STrond Myklebust 	bool			fh_no_atomic_attr;
87716a8bc7STrond Myklebust 						/*
88716a8bc7STrond Myklebust 						 * wcc data is not atomic with
89716a8bc7STrond Myklebust 						 * operation
90716a8bc7STrond Myklebust 						 */
91b9e8638eSOlga Kornievskaia 	int			fh_flags;	/* FH flags */
92aaf91ec1SJeff Layton 	bool			fh_post_saved;	/* post-op attrs saved */
93aaf91ec1SJeff Layton 	bool			fh_pre_saved;	/* pre-op attrs saved */
949c69de4cSChristoph Hellwig 
95dd8dd403SNeilBrown 	/* Pre-op attributes saved when inode is locked */
969c69de4cSChristoph Hellwig 	__u64			fh_pre_size;	/* size before operation */
9792c5e469SArnd Bergmann 	struct timespec64	fh_pre_mtime;	/* mtime before oper */
9892c5e469SArnd Bergmann 	struct timespec64	fh_pre_ctime;	/* ctime before oper */
999c69de4cSChristoph Hellwig 	/*
1009c69de4cSChristoph Hellwig 	 * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
1019c69de4cSChristoph Hellwig 	 *  to find out if it is valid.
1029c69de4cSChristoph Hellwig 	 */
1039c69de4cSChristoph Hellwig 	u64			fh_pre_change;
1049c69de4cSChristoph Hellwig 
105dd8dd403SNeilBrown 	/* Post-op attributes saved in fh_fill_post_attrs() */
1069c69de4cSChristoph Hellwig 	struct kstat		fh_post_attr;	/* full attrs after operation */
1079c69de4cSChristoph Hellwig 	u64			fh_post_change; /* nfsv4 change; see above */
1089c69de4cSChristoph Hellwig } svc_fh;
109b9e8638eSOlga Kornievskaia #define NFSD4_FH_FOREIGN (1<<0)
110b9e8638eSOlga Kornievskaia #define SET_FH_FLAG(c, f) ((c)->fh_flags |= (f))
111b9e8638eSOlga Kornievskaia #define HAS_FH_FLAG(c, f) ((c)->fh_flags & (f))
1121557aca7SJ. Bruce Fields 
1131557aca7SJ. Bruce Fields enum nfsd_fsid {
1141557aca7SJ. Bruce Fields 	FSID_DEV = 0,
1151557aca7SJ. Bruce Fields 	FSID_NUM,
1161557aca7SJ. Bruce Fields 	FSID_MAJOR_MINOR,
1171557aca7SJ. Bruce Fields 	FSID_ENCODE_DEV,
1181557aca7SJ. Bruce Fields 	FSID_UUID4_INUM,
1191557aca7SJ. Bruce Fields 	FSID_UUID8,
1201557aca7SJ. Bruce Fields 	FSID_UUID16,
1211557aca7SJ. Bruce Fields 	FSID_UUID16_INUM,
1221557aca7SJ. Bruce Fields };
1231557aca7SJ. Bruce Fields 
1241557aca7SJ. Bruce Fields enum fsid_source {
1251557aca7SJ. Bruce Fields 	FSIDSOURCE_DEV,
1261557aca7SJ. Bruce Fields 	FSIDSOURCE_FSID,
1271557aca7SJ. Bruce Fields 	FSIDSOURCE_UUID,
1281557aca7SJ. Bruce Fields };
1292c42f804SChuck Lever extern enum fsid_source fsid_source(const struct svc_fh *fhp);
1301557aca7SJ. Bruce Fields 
1311557aca7SJ. Bruce Fields 
13294ec938bSJeff Layton /*
13394ec938bSJeff Layton  * This might look a little large to "inline" but in all calls except
1341557aca7SJ. Bruce Fields  * one, 'vers' is constant so moste of the function disappears.
13594ec938bSJeff Layton  *
13694ec938bSJeff Layton  * In some cases the values are considered to be host endian and in
13794ec938bSJeff Layton  * others, net endian. fsidv is always considered to be u32 as the
13894ec938bSJeff Layton  * callers don't know which it will be. So we must use __force to keep
13994ec938bSJeff Layton  * sparse from complaining. Since these values are opaque to the
14094ec938bSJeff Layton  * client, that shouldn't be a problem.
1411557aca7SJ. Bruce Fields  */
mk_fsid(int vers,u32 * fsidv,dev_t dev,ino_t ino,u32 fsid,unsigned char * uuid)1421557aca7SJ. Bruce Fields static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
1431557aca7SJ. Bruce Fields 			   u32 fsid, unsigned char *uuid)
1441557aca7SJ. Bruce Fields {
1451557aca7SJ. Bruce Fields 	u32 *up;
1461557aca7SJ. Bruce Fields 	switch(vers) {
1471557aca7SJ. Bruce Fields 	case FSID_DEV:
14894ec938bSJeff Layton 		fsidv[0] = (__force __u32)htonl((MAJOR(dev)<<16) |
1491557aca7SJ. Bruce Fields 				 MINOR(dev));
1501557aca7SJ. Bruce Fields 		fsidv[1] = ino_t_to_u32(ino);
1511557aca7SJ. Bruce Fields 		break;
1521557aca7SJ. Bruce Fields 	case FSID_NUM:
1531557aca7SJ. Bruce Fields 		fsidv[0] = fsid;
1541557aca7SJ. Bruce Fields 		break;
1551557aca7SJ. Bruce Fields 	case FSID_MAJOR_MINOR:
15694ec938bSJeff Layton 		fsidv[0] = (__force __u32)htonl(MAJOR(dev));
15794ec938bSJeff Layton 		fsidv[1] = (__force __u32)htonl(MINOR(dev));
1581557aca7SJ. Bruce Fields 		fsidv[2] = ino_t_to_u32(ino);
1591557aca7SJ. Bruce Fields 		break;
1601557aca7SJ. Bruce Fields 
1611557aca7SJ. Bruce Fields 	case FSID_ENCODE_DEV:
1621557aca7SJ. Bruce Fields 		fsidv[0] = new_encode_dev(dev);
1631557aca7SJ. Bruce Fields 		fsidv[1] = ino_t_to_u32(ino);
1641557aca7SJ. Bruce Fields 		break;
1651557aca7SJ. Bruce Fields 
1661557aca7SJ. Bruce Fields 	case FSID_UUID4_INUM:
1671557aca7SJ. Bruce Fields 		/* 4 byte fsid and inode number */
1681557aca7SJ. Bruce Fields 		up = (u32*)uuid;
1691557aca7SJ. Bruce Fields 		fsidv[0] = ino_t_to_u32(ino);
1701557aca7SJ. Bruce Fields 		fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
1711557aca7SJ. Bruce Fields 		break;
1721557aca7SJ. Bruce Fields 
1731557aca7SJ. Bruce Fields 	case FSID_UUID8:
1741557aca7SJ. Bruce Fields 		/* 8 byte fsid  */
1751557aca7SJ. Bruce Fields 		up = (u32*)uuid;
1761557aca7SJ. Bruce Fields 		fsidv[0] = up[0] ^ up[2];
1771557aca7SJ. Bruce Fields 		fsidv[1] = up[1] ^ up[3];
1781557aca7SJ. Bruce Fields 		break;
1791557aca7SJ. Bruce Fields 
1801557aca7SJ. Bruce Fields 	case FSID_UUID16:
1811557aca7SJ. Bruce Fields 		/* 16 byte fsid - NFSv3+ only */
1821557aca7SJ. Bruce Fields 		memcpy(fsidv, uuid, 16);
1831557aca7SJ. Bruce Fields 		break;
1841557aca7SJ. Bruce Fields 
1851557aca7SJ. Bruce Fields 	case FSID_UUID16_INUM:
1861557aca7SJ. Bruce Fields 		/* 8 byte inode and 16 byte fsid */
1871557aca7SJ. Bruce Fields 		*(u64*)fsidv = (u64)ino;
1881557aca7SJ. Bruce Fields 		memcpy(fsidv+2, uuid, 16);
1891557aca7SJ. Bruce Fields 		break;
1901557aca7SJ. Bruce Fields 	default: BUG();
1911557aca7SJ. Bruce Fields 	}
1921557aca7SJ. Bruce Fields }
1931557aca7SJ. Bruce Fields 
key_len(int type)1941557aca7SJ. Bruce Fields static inline int key_len(int type)
1951557aca7SJ. Bruce Fields {
1961557aca7SJ. Bruce Fields 	switch(type) {
1971557aca7SJ. Bruce Fields 	case FSID_DEV:		return 8;
1981557aca7SJ. Bruce Fields 	case FSID_NUM: 		return 4;
1991557aca7SJ. Bruce Fields 	case FSID_MAJOR_MINOR:	return 12;
2001557aca7SJ. Bruce Fields 	case FSID_ENCODE_DEV:	return 8;
2011557aca7SJ. Bruce Fields 	case FSID_UUID4_INUM:	return 8;
2021557aca7SJ. Bruce Fields 	case FSID_UUID8:	return 8;
2031557aca7SJ. Bruce Fields 	case FSID_UUID16:	return 16;
2041557aca7SJ. Bruce Fields 	case FSID_UUID16_INUM:	return 24;
2051557aca7SJ. Bruce Fields 	default: return 0;
2061557aca7SJ. Bruce Fields 	}
2071557aca7SJ. Bruce Fields }
2081557aca7SJ. Bruce Fields 
2091557aca7SJ. Bruce Fields /*
2101557aca7SJ. Bruce Fields  * Shorthand for dprintk()'s
2111557aca7SJ. Bruce Fields  */
2121557aca7SJ. Bruce Fields extern char * SVCFH_fmt(struct svc_fh *fhp);
2131557aca7SJ. Bruce Fields 
2141557aca7SJ. Bruce Fields /*
2151557aca7SJ. Bruce Fields  * Function prototypes
2161557aca7SJ. Bruce Fields  */
217175a4eb7SAl Viro __be32	fh_verify(struct svc_rqst *, struct svc_fh *, umode_t, int);
2181557aca7SJ. Bruce Fields __be32	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
2191557aca7SJ. Bruce Fields __be32	fh_update(struct svc_fh *);
2201557aca7SJ. Bruce Fields void	fh_put(struct svc_fh *);
2211557aca7SJ. Bruce Fields 
2221557aca7SJ. Bruce Fields static __inline__ struct svc_fh *
fh_copy(struct svc_fh * dst,const struct svc_fh * src)223b48f8056SChuck Lever fh_copy(struct svc_fh *dst, const struct svc_fh *src)
2241557aca7SJ. Bruce Fields {
225dd8dd403SNeilBrown 	WARN_ON(src->fh_dentry);
2261557aca7SJ. Bruce Fields 
2271557aca7SJ. Bruce Fields 	*dst = *src;
2281557aca7SJ. Bruce Fields 	return dst;
2291557aca7SJ. Bruce Fields }
2301557aca7SJ. Bruce Fields 
2311557aca7SJ. Bruce Fields static inline void
fh_copy_shallow(struct knfsd_fh * dst,const struct knfsd_fh * src)232b48f8056SChuck Lever fh_copy_shallow(struct knfsd_fh *dst, const struct knfsd_fh *src)
2331557aca7SJ. Bruce Fields {
2341557aca7SJ. Bruce Fields 	dst->fh_size = src->fh_size;
235d8b26071SNeilBrown 	memcpy(&dst->fh_raw, &src->fh_raw, src->fh_size);
2361557aca7SJ. Bruce Fields }
2371557aca7SJ. Bruce Fields 
2381557aca7SJ. Bruce Fields static __inline__ struct svc_fh *
fh_init(struct svc_fh * fhp,int maxsize)2391557aca7SJ. Bruce Fields fh_init(struct svc_fh *fhp, int maxsize)
2401557aca7SJ. Bruce Fields {
2411557aca7SJ. Bruce Fields 	memset(fhp, 0, sizeof(*fhp));
2421557aca7SJ. Bruce Fields 	fhp->fh_maxsize = maxsize;
2431557aca7SJ. Bruce Fields 	return fhp;
2441557aca7SJ. Bruce Fields }
2451557aca7SJ. Bruce Fields 
fh_match(const struct knfsd_fh * fh1,const struct knfsd_fh * fh2)246b48f8056SChuck Lever static inline bool fh_match(const struct knfsd_fh *fh1,
247b48f8056SChuck Lever 			    const struct knfsd_fh *fh2)
2484d94c2efSChristoph Hellwig {
2494d94c2efSChristoph Hellwig 	if (fh1->fh_size != fh2->fh_size)
2504d94c2efSChristoph Hellwig 		return false;
251d8b26071SNeilBrown 	if (memcmp(fh1->fh_raw, fh2->fh_raw, fh1->fh_size) != 0)
2524d94c2efSChristoph Hellwig 		return false;
2534d94c2efSChristoph Hellwig 	return true;
2544d94c2efSChristoph Hellwig }
2554d94c2efSChristoph Hellwig 
fh_fsid_match(const struct knfsd_fh * fh1,const struct knfsd_fh * fh2)256b48f8056SChuck Lever static inline bool fh_fsid_match(const struct knfsd_fh *fh1,
257b48f8056SChuck Lever 				 const struct knfsd_fh *fh2)
2589558f250SChristoph Hellwig {
2599558f250SChristoph Hellwig 	if (fh1->fh_fsid_type != fh2->fh_fsid_type)
2609558f250SChristoph Hellwig 		return false;
2610ab39de6SDan Carpenter 	if (memcmp(fh1->fh_fsid, fh2->fh_fsid, key_len(fh1->fh_fsid_type)) != 0)
2629558f250SChristoph Hellwig 		return false;
2639558f250SChristoph Hellwig 	return true;
2649558f250SChristoph Hellwig }
2659558f250SChristoph Hellwig 
2666e8b50d1SJeff Layton #ifdef CONFIG_CRC32
2676e8b50d1SJeff Layton /**
2686e8b50d1SJeff Layton  * knfsd_fh_hash - calculate the crc32 hash for the filehandle
2696e8b50d1SJeff Layton  * @fh - pointer to filehandle
2706e8b50d1SJeff Layton  *
2716e8b50d1SJeff Layton  * returns a crc32 hash for the filehandle that is compatible with
2726e8b50d1SJeff Layton  * the one displayed by "wireshark".
2736e8b50d1SJeff Layton  */
knfsd_fh_hash(const struct knfsd_fh * fh)2741736aec8SChuck Lever static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh)
2756e8b50d1SJeff Layton {
276d8b26071SNeilBrown 	return ~crc32_le(0xFFFFFFFF, fh->fh_raw, fh->fh_size);
2776e8b50d1SJeff Layton }
2786e8b50d1SJeff Layton #else
knfsd_fh_hash(const struct knfsd_fh * fh)2791736aec8SChuck Lever static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh)
2806e8b50d1SJeff Layton {
2816e8b50d1SJeff Layton 	return 0;
2826e8b50d1SJeff Layton }
2836e8b50d1SJeff Layton #endif
2846e8b50d1SJeff Layton 
285fcb5e3faSChuck Lever /**
286fcb5e3faSChuck Lever  * fh_clear_pre_post_attrs - Reset pre/post attributes
287fcb5e3faSChuck Lever  * @fhp: file handle to be updated
288fcb5e3faSChuck Lever  *
2892336745eSKinglong Mee  */
fh_clear_pre_post_attrs(struct svc_fh * fhp)290fcb5e3faSChuck Lever static inline void fh_clear_pre_post_attrs(struct svc_fh *fhp)
2912336745eSKinglong Mee {
292aaf91ec1SJeff Layton 	fhp->fh_post_saved = false;
293aaf91ec1SJeff Layton 	fhp->fh_pre_saved = false;
2942336745eSKinglong Mee }
2952336745eSKinglong Mee 
2963139b1d7SJeff Layton u64 nfsd4_change_attribute(struct kstat *stat, struct inode *inode);
297*a332018aSJeff Layton __be32 __must_check fh_fill_pre_attrs(struct svc_fh *fhp);
298*a332018aSJeff Layton __be32 fh_fill_post_attrs(struct svc_fh *fhp);
299*a332018aSJeff Layton __be32 __must_check fh_fill_both_attrs(struct svc_fh *fhp);
3009c69de4cSChristoph Hellwig #endif /* _LINUX_NFSD_NFSFH_H */
301