NFSD: move filehandle format declarations out of "uapi".
[linux-2.6-block.git] / fs / nfsd / nfsfh.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
9c69de4c
CH
2/*
3 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
4 *
5 * This file describes the layout of the file handles as passed
6 * over the wire.
7 */
8#ifndef _LINUX_NFSD_NFSFH_H
9#define _LINUX_NFSD_NFSFH_H
10
6e8b50d1 11#include <linux/crc32.h>
9c69de4c 12#include <linux/sunrpc/svc.h>
1f15a550 13#include <linux/iversion.h>
3cc55f44 14#include <linux/exportfs.h>
ef5825e3
N
15#include <linux/nfs4.h>
16
17
18/*
19 * This is the old "dentry style" Linux NFSv2 file handle.
20 *
21 * The xino and xdev fields are currently used to transport the
22 * ino/dev of the exported inode.
23 */
24struct nfs_fhbase_old {
25 u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */
26 u32 fb_ino; /* our inode number */
27 u32 fb_dirino; /* dir inode number, 0 for directories */
28 u32 fb_dev; /* our device */
29 u32 fb_xdev;
30 u32 fb_xino;
31 u32 fb_generation;
32};
33
34/*
35 * This is the new flexible, extensible style NFSv2/v3/v4 file handle.
36 *
37 * The file handle starts with a sequence of four-byte words.
38 * The first word contains a version number (1) and three descriptor bytes
39 * that tell how the remaining 3 variable length fields should be handled.
40 * These three bytes are auth_type, fsid_type and fileid_type.
41 *
42 * All four-byte values are in host-byte-order.
43 *
44 * The auth_type field is deprecated and must be set to 0.
45 *
46 * The fsid_type identifies how the filesystem (or export point) is
47 * encoded.
48 * Current values:
49 * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
50 * NOTE: we cannot use the kdev_t device id value, because kdev_t.h
51 * says we mustn't. We must break it up and reassemble.
52 * 1 - 4 byte user specified identifier
53 * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
54 * 3 - 4 byte device id, encoded for user-space, 4 byte inode number
55 * 4 - 4 byte inode number and 4 byte uuid
56 * 5 - 8 byte uuid
57 * 6 - 16 byte uuid
58 * 7 - 8 byte inode number and 16 byte uuid
59 *
60 * The fileid_type identified how the file within the filesystem is encoded.
61 * The values for this field are filesystem specific, exccept that
62 * filesystems must not use the values '0' or '0xff'. 'See enum fid_type'
63 * in include/linux/exportfs.h for currently registered values.
64 */
65struct nfs_fhbase_new {
66 union {
67 struct {
68 u8 fb_version_aux; /* == 1, even => nfs_fhbase_old */
69 u8 fb_auth_type_aux;
70 u8 fb_fsid_type_aux;
71 u8 fb_fileid_type_aux;
72 u32 fb_auth[1];
73 /* u32 fb_fsid[0]; floating */
74 /* u32 fb_fileid[0]; floating */
75 };
76 struct {
77 u8 fb_version; /* == 1, even => nfs_fhbase_old */
78 u8 fb_auth_type;
79 u8 fb_fsid_type;
80 u8 fb_fileid_type;
81 u32 fb_auth_flex[]; /* flexible-array member */
82 };
83 };
84};
85
86struct knfsd_fh {
87 unsigned int fh_size; /* significant for NFSv3.
88 * Points to the current size while building
89 * a new file handle
90 */
91 union {
92 struct nfs_fhbase_old fh_old;
93 u32 fh_pad[NFS4_FHSIZE/4];
94 struct nfs_fhbase_new fh_new;
95 } fh_base;
96};
97
98#define ofh_dcookie fh_base.fh_old.fb_dcookie
99#define ofh_ino fh_base.fh_old.fb_ino
100#define ofh_dirino fh_base.fh_old.fb_dirino
101#define ofh_dev fh_base.fh_old.fb_dev
102#define ofh_xdev fh_base.fh_old.fb_xdev
103#define ofh_xino fh_base.fh_old.fb_xino
104#define ofh_generation fh_base.fh_old.fb_generation
105
106#define fh_version fh_base.fh_new.fb_version
107#define fh_fsid_type fh_base.fh_new.fb_fsid_type
108#define fh_auth_type fh_base.fh_new.fb_auth_type
109#define fh_fileid_type fh_base.fh_new.fb_fileid_type
110#define fh_fsid fh_base.fh_new.fb_auth_flex
9c69de4c
CH
111
112static inline __u32 ino_t_to_u32(ino_t ino)
113{
114 return (__u32) ino;
115}
116
117static inline ino_t u32_to_ino_t(__u32 uino)
118{
119 return (ino_t) uino;
120}
1557aca7 121
9c69de4c
CH
122/*
123 * This is the internal representation of an NFS handle used in knfsd.
124 * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
125 */
126typedef struct svc_fh {
127 struct knfsd_fh fh_handle; /* FH data */
fcaba026 128 int fh_maxsize; /* max size for fh_handle */
9c69de4c
CH
129 struct dentry * fh_dentry; /* validated dentry */
130 struct svc_export * fh_export; /* export pointer */
9c69de4c 131
aaf91ec1
JL
132 bool fh_locked; /* inode locked by us */
133 bool fh_want_write; /* remount protection taken */
daab110e 134 bool fh_no_wcc; /* no wcc data needed */
716a8bc7
TM
135 bool fh_no_atomic_attr;
136 /*
137 * wcc data is not atomic with
138 * operation
139 */
b9e8638e 140 int fh_flags; /* FH flags */
9c69de4c 141#ifdef CONFIG_NFSD_V3
aaf91ec1
JL
142 bool fh_post_saved; /* post-op attrs saved */
143 bool fh_pre_saved; /* pre-op attrs saved */
9c69de4c
CH
144
145 /* Pre-op attributes saved during fh_lock */
146 __u64 fh_pre_size; /* size before operation */
92c5e469
AB
147 struct timespec64 fh_pre_mtime; /* mtime before oper */
148 struct timespec64 fh_pre_ctime; /* ctime before oper */
9c69de4c
CH
149 /*
150 * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
151 * to find out if it is valid.
152 */
153 u64 fh_pre_change;
154
155 /* Post-op attributes saved in fh_unlock */
156 struct kstat fh_post_attr; /* full attrs after operation */
157 u64 fh_post_change; /* nfsv4 change; see above */
158#endif /* CONFIG_NFSD_V3 */
9c69de4c 159} svc_fh;
b9e8638e
OK
160#define NFSD4_FH_FOREIGN (1<<0)
161#define SET_FH_FLAG(c, f) ((c)->fh_flags |= (f))
162#define HAS_FH_FLAG(c, f) ((c)->fh_flags & (f))
1557aca7
BF
163
164enum nfsd_fsid {
165 FSID_DEV = 0,
166 FSID_NUM,
167 FSID_MAJOR_MINOR,
168 FSID_ENCODE_DEV,
169 FSID_UUID4_INUM,
170 FSID_UUID8,
171 FSID_UUID16,
172 FSID_UUID16_INUM,
173};
174
175enum fsid_source {
176 FSIDSOURCE_DEV,
177 FSIDSOURCE_FSID,
178 FSIDSOURCE_UUID,
179};
2c42f804 180extern enum fsid_source fsid_source(const struct svc_fh *fhp);
1557aca7
BF
181
182
94ec938b
JL
183/*
184 * This might look a little large to "inline" but in all calls except
1557aca7 185 * one, 'vers' is constant so moste of the function disappears.
94ec938b
JL
186 *
187 * In some cases the values are considered to be host endian and in
188 * others, net endian. fsidv is always considered to be u32 as the
189 * callers don't know which it will be. So we must use __force to keep
190 * sparse from complaining. Since these values are opaque to the
191 * client, that shouldn't be a problem.
1557aca7
BF
192 */
193static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
194 u32 fsid, unsigned char *uuid)
195{
196 u32 *up;
197 switch(vers) {
198 case FSID_DEV:
94ec938b 199 fsidv[0] = (__force __u32)htonl((MAJOR(dev)<<16) |
1557aca7
BF
200 MINOR(dev));
201 fsidv[1] = ino_t_to_u32(ino);
202 break;
203 case FSID_NUM:
204 fsidv[0] = fsid;
205 break;
206 case FSID_MAJOR_MINOR:
94ec938b
JL
207 fsidv[0] = (__force __u32)htonl(MAJOR(dev));
208 fsidv[1] = (__force __u32)htonl(MINOR(dev));
1557aca7
BF
209 fsidv[2] = ino_t_to_u32(ino);
210 break;
211
212 case FSID_ENCODE_DEV:
213 fsidv[0] = new_encode_dev(dev);
214 fsidv[1] = ino_t_to_u32(ino);
215 break;
216
217 case FSID_UUID4_INUM:
218 /* 4 byte fsid and inode number */
219 up = (u32*)uuid;
220 fsidv[0] = ino_t_to_u32(ino);
221 fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
222 break;
223
224 case FSID_UUID8:
225 /* 8 byte fsid */
226 up = (u32*)uuid;
227 fsidv[0] = up[0] ^ up[2];
228 fsidv[1] = up[1] ^ up[3];
229 break;
230
231 case FSID_UUID16:
232 /* 16 byte fsid - NFSv3+ only */
233 memcpy(fsidv, uuid, 16);
234 break;
235
236 case FSID_UUID16_INUM:
237 /* 8 byte inode and 16 byte fsid */
238 *(u64*)fsidv = (u64)ino;
239 memcpy(fsidv+2, uuid, 16);
240 break;
241 default: BUG();
242 }
243}
244
245static inline int key_len(int type)
246{
247 switch(type) {
248 case FSID_DEV: return 8;
249 case FSID_NUM: return 4;
250 case FSID_MAJOR_MINOR: return 12;
251 case FSID_ENCODE_DEV: return 8;
252 case FSID_UUID4_INUM: return 8;
253 case FSID_UUID8: return 8;
254 case FSID_UUID16: return 16;
255 case FSID_UUID16_INUM: return 24;
256 default: return 0;
257 }
258}
259
260/*
261 * Shorthand for dprintk()'s
262 */
263extern char * SVCFH_fmt(struct svc_fh *fhp);
264
265/*
266 * Function prototypes
267 */
175a4eb7 268__be32 fh_verify(struct svc_rqst *, struct svc_fh *, umode_t, int);
1557aca7
BF
269__be32 fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
270__be32 fh_update(struct svc_fh *);
271void fh_put(struct svc_fh *);
272
273static __inline__ struct svc_fh *
274fh_copy(struct svc_fh *dst, struct svc_fh *src)
275{
276 WARN_ON(src->fh_dentry || src->fh_locked);
277
278 *dst = *src;
279 return dst;
280}
281
282static inline void
283fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
284{
285 dst->fh_size = src->fh_size;
286 memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
287}
288
289static __inline__ struct svc_fh *
290fh_init(struct svc_fh *fhp, int maxsize)
291{
292 memset(fhp, 0, sizeof(*fhp));
293 fhp->fh_maxsize = maxsize;
294 return fhp;
295}
296
4d94c2ef
CH
297static inline bool fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
298{
299 if (fh1->fh_size != fh2->fh_size)
300 return false;
301 if (memcmp(fh1->fh_base.fh_pad, fh2->fh_base.fh_pad, fh1->fh_size) != 0)
302 return false;
303 return true;
304}
305
9558f250
CH
306static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
307{
308 if (fh1->fh_fsid_type != fh2->fh_fsid_type)
309 return false;
0ab39de6 310 if (memcmp(fh1->fh_fsid, fh2->fh_fsid, key_len(fh1->fh_fsid_type)) != 0)
9558f250
CH
311 return false;
312 return true;
313}
314
6e8b50d1
JL
315#ifdef CONFIG_CRC32
316/**
317 * knfsd_fh_hash - calculate the crc32 hash for the filehandle
318 * @fh - pointer to filehandle
319 *
320 * returns a crc32 hash for the filehandle that is compatible with
321 * the one displayed by "wireshark".
322 */
1736aec8 323static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh)
6e8b50d1
JL
324{
325 return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size);
326}
327#else
1736aec8 328static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh)
6e8b50d1
JL
329{
330 return 0;
331}
332#endif
333
1557aca7 334#ifdef CONFIG_NFSD_V3
2336745e
KM
335/*
336 * The wcc data stored in current_fh should be cleared
337 * between compound ops.
338 */
339static inline void
340fh_clear_wcc(struct svc_fh *fhp)
341{
aaf91ec1
JL
342 fhp->fh_post_saved = false;
343 fhp->fh_pre_saved = false;
2336745e
KM
344}
345
630458e7
BF
346/*
347 * We could use i_version alone as the change attribute. However,
348 * i_version can go backwards after a reboot. On its own that doesn't
349 * necessarily cause a problem, but if i_version goes backwards and then
350 * is incremented again it could reuse a value that was previously used
351 * before boot, and a client who queried the two values might
352 * incorrectly assume nothing changed.
353 *
354 * By using both ctime and the i_version counter we guarantee that as
355 * long as time doesn't go backwards we never reuse an old value.
356 */
39ca1bf6
AG
357static inline u64 nfsd4_change_attribute(struct kstat *stat,
358 struct inode *inode)
630458e7 359{
3cc55f44
BF
360 if (inode->i_sb->s_export_op->fetch_iversion)
361 return inode->i_sb->s_export_op->fetch_iversion(inode);
362 else if (IS_I_VERSION(inode)) {
4b03d997
BF
363 u64 chattr;
364
70b87f77
BF
365 chattr = stat->ctime.tv_sec;
366 chattr <<= 30;
367 chattr += stat->ctime.tv_nsec;
368 chattr += inode_query_iversion(inode);
4b03d997
BF
369 return chattr;
370 } else
371 return time_to_chattr(&stat->ctime);
630458e7
BF
372}
373
39ca1bf6
AG
374extern void fill_pre_wcc(struct svc_fh *fhp);
375extern void fill_post_wcc(struct svc_fh *fhp);
1557aca7 376#else
2336745e
KM
377#define fh_clear_wcc(ignored)
378#define fill_pre_wcc(ignored)
1557aca7
BF
379#define fill_post_wcc(notused)
380#endif /* CONFIG_NFSD_V3 */
381
382
383/*
384 * Lock a file handle/inode
385 * NOTE: both fh_lock and fh_unlock are done "by hand" in
386 * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
387 * so, any changes here should be reflected there.
388 */
389
390static inline void
391fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
392{
393 struct dentry *dentry = fhp->fh_dentry;
394 struct inode *inode;
395
396 BUG_ON(!dentry);
397
398 if (fhp->fh_locked) {
a6a9f18f
AV
399 printk(KERN_WARNING "fh_lock: %pd2 already locked!\n",
400 dentry);
1557aca7
BF
401 return;
402 }
403
2b0143b5 404 inode = d_inode(dentry);
5955102c 405 inode_lock_nested(inode, subclass);
1557aca7 406 fill_pre_wcc(fhp);
aaf91ec1 407 fhp->fh_locked = true;
1557aca7
BF
408}
409
410static inline void
411fh_lock(struct svc_fh *fhp)
412{
413 fh_lock_nested(fhp, I_MUTEX_NORMAL);
414}
415
416/*
417 * Unlock a file handle/inode
418 */
419static inline void
420fh_unlock(struct svc_fh *fhp)
421{
1557aca7
BF
422 if (fhp->fh_locked) {
423 fill_post_wcc(fhp);
5955102c 424 inode_unlock(d_inode(fhp->fh_dentry));
aaf91ec1 425 fhp->fh_locked = false;
1557aca7
BF
426 }
427}
428
9c69de4c 429#endif /* _LINUX_NFSD_NFSFH_H */