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