1 /* SPDX-License-Identifier: GPL-2.0 */ 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 11 #include <linux/crc32.h> 12 #include <linux/sunrpc/svc.h> 13 #include <uapi/linux/nfsd/nfsfh.h> 14 #include <linux/iversion.h> 15 16 static inline __u32 ino_t_to_u32(ino_t ino) 17 { 18 return (__u32) ino; 19 } 20 21 static inline ino_t u32_to_ino_t(__u32 uino) 22 { 23 return (ino_t) uino; 24 } 25 26 /* 27 * This is the internal representation of an NFS handle used in knfsd. 28 * pre_mtime/post_version will be used to support wcc_attr's in NFSv3. 29 */ 30 typedef struct svc_fh { 31 struct knfsd_fh fh_handle; /* FH data */ 32 int fh_maxsize; /* max size for fh_handle */ 33 struct dentry * fh_dentry; /* validated dentry */ 34 struct svc_export * fh_export; /* export pointer */ 35 36 bool fh_locked; /* inode locked by us */ 37 bool fh_want_write; /* remount protection taken */ 38 int fh_flags; /* FH flags */ 39 #ifdef CONFIG_NFSD_V3 40 bool fh_post_saved; /* post-op attrs saved */ 41 bool fh_pre_saved; /* pre-op attrs saved */ 42 43 /* Pre-op attributes saved during fh_lock */ 44 __u64 fh_pre_size; /* size before operation */ 45 struct timespec64 fh_pre_mtime; /* mtime before oper */ 46 struct timespec64 fh_pre_ctime; /* ctime before oper */ 47 /* 48 * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode) 49 * to find out if it is valid. 50 */ 51 u64 fh_pre_change; 52 53 /* Post-op attributes saved in fh_unlock */ 54 struct kstat fh_post_attr; /* full attrs after operation */ 55 u64 fh_post_change; /* nfsv4 change; see above */ 56 #endif /* CONFIG_NFSD_V3 */ 57 58 } svc_fh; 59 #define NFSD4_FH_FOREIGN (1<<0) 60 #define SET_FH_FLAG(c, f) ((c)->fh_flags |= (f)) 61 #define HAS_FH_FLAG(c, f) ((c)->fh_flags & (f)) 62 63 enum nfsd_fsid { 64 FSID_DEV = 0, 65 FSID_NUM, 66 FSID_MAJOR_MINOR, 67 FSID_ENCODE_DEV, 68 FSID_UUID4_INUM, 69 FSID_UUID8, 70 FSID_UUID16, 71 FSID_UUID16_INUM, 72 }; 73 74 enum fsid_source { 75 FSIDSOURCE_DEV, 76 FSIDSOURCE_FSID, 77 FSIDSOURCE_UUID, 78 }; 79 extern enum fsid_source fsid_source(struct svc_fh *fhp); 80 81 82 /* 83 * This might look a little large to "inline" but in all calls except 84 * one, 'vers' is constant so moste of the function disappears. 85 * 86 * In some cases the values are considered to be host endian and in 87 * others, net endian. fsidv is always considered to be u32 as the 88 * callers don't know which it will be. So we must use __force to keep 89 * sparse from complaining. Since these values are opaque to the 90 * client, that shouldn't be a problem. 91 */ 92 static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino, 93 u32 fsid, unsigned char *uuid) 94 { 95 u32 *up; 96 switch(vers) { 97 case FSID_DEV: 98 fsidv[0] = (__force __u32)htonl((MAJOR(dev)<<16) | 99 MINOR(dev)); 100 fsidv[1] = ino_t_to_u32(ino); 101 break; 102 case FSID_NUM: 103 fsidv[0] = fsid; 104 break; 105 case FSID_MAJOR_MINOR: 106 fsidv[0] = (__force __u32)htonl(MAJOR(dev)); 107 fsidv[1] = (__force __u32)htonl(MINOR(dev)); 108 fsidv[2] = ino_t_to_u32(ino); 109 break; 110 111 case FSID_ENCODE_DEV: 112 fsidv[0] = new_encode_dev(dev); 113 fsidv[1] = ino_t_to_u32(ino); 114 break; 115 116 case FSID_UUID4_INUM: 117 /* 4 byte fsid and inode number */ 118 up = (u32*)uuid; 119 fsidv[0] = ino_t_to_u32(ino); 120 fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3]; 121 break; 122 123 case FSID_UUID8: 124 /* 8 byte fsid */ 125 up = (u32*)uuid; 126 fsidv[0] = up[0] ^ up[2]; 127 fsidv[1] = up[1] ^ up[3]; 128 break; 129 130 case FSID_UUID16: 131 /* 16 byte fsid - NFSv3+ only */ 132 memcpy(fsidv, uuid, 16); 133 break; 134 135 case FSID_UUID16_INUM: 136 /* 8 byte inode and 16 byte fsid */ 137 *(u64*)fsidv = (u64)ino; 138 memcpy(fsidv+2, uuid, 16); 139 break; 140 default: BUG(); 141 } 142 } 143 144 static inline int key_len(int type) 145 { 146 switch(type) { 147 case FSID_DEV: return 8; 148 case FSID_NUM: return 4; 149 case FSID_MAJOR_MINOR: return 12; 150 case FSID_ENCODE_DEV: return 8; 151 case FSID_UUID4_INUM: return 8; 152 case FSID_UUID8: return 8; 153 case FSID_UUID16: return 16; 154 case FSID_UUID16_INUM: return 24; 155 default: return 0; 156 } 157 } 158 159 /* 160 * Shorthand for dprintk()'s 161 */ 162 extern char * SVCFH_fmt(struct svc_fh *fhp); 163 164 /* 165 * Function prototypes 166 */ 167 __be32 fh_verify(struct svc_rqst *, struct svc_fh *, umode_t, int); 168 __be32 fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *); 169 __be32 fh_update(struct svc_fh *); 170 void fh_put(struct svc_fh *); 171 172 static __inline__ struct svc_fh * 173 fh_copy(struct svc_fh *dst, struct svc_fh *src) 174 { 175 WARN_ON(src->fh_dentry || src->fh_locked); 176 177 *dst = *src; 178 return dst; 179 } 180 181 static inline void 182 fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src) 183 { 184 dst->fh_size = src->fh_size; 185 memcpy(&dst->fh_base, &src->fh_base, src->fh_size); 186 } 187 188 static __inline__ struct svc_fh * 189 fh_init(struct svc_fh *fhp, int maxsize) 190 { 191 memset(fhp, 0, sizeof(*fhp)); 192 fhp->fh_maxsize = maxsize; 193 return fhp; 194 } 195 196 static inline bool fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) 197 { 198 if (fh1->fh_size != fh2->fh_size) 199 return false; 200 if (memcmp(fh1->fh_base.fh_pad, fh2->fh_base.fh_pad, fh1->fh_size) != 0) 201 return false; 202 return true; 203 } 204 205 static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) 206 { 207 if (fh1->fh_fsid_type != fh2->fh_fsid_type) 208 return false; 209 if (memcmp(fh1->fh_fsid, fh2->fh_fsid, key_len(fh1->fh_fsid_type)) != 0) 210 return false; 211 return true; 212 } 213 214 #ifdef CONFIG_CRC32 215 /** 216 * knfsd_fh_hash - calculate the crc32 hash for the filehandle 217 * @fh - pointer to filehandle 218 * 219 * returns a crc32 hash for the filehandle that is compatible with 220 * the one displayed by "wireshark". 221 */ 222 223 static inline u32 224 knfsd_fh_hash(struct knfsd_fh *fh) 225 { 226 return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size); 227 } 228 #else 229 static inline u32 230 knfsd_fh_hash(struct knfsd_fh *fh) 231 { 232 return 0; 233 } 234 #endif 235 236 #ifdef CONFIG_NFSD_V3 237 /* 238 * The wcc data stored in current_fh should be cleared 239 * between compound ops. 240 */ 241 static inline void 242 fh_clear_wcc(struct svc_fh *fhp) 243 { 244 fhp->fh_post_saved = false; 245 fhp->fh_pre_saved = false; 246 } 247 248 /* 249 * We could use i_version alone as the change attribute. However, 250 * i_version can go backwards after a reboot. On its own that doesn't 251 * necessarily cause a problem, but if i_version goes backwards and then 252 * is incremented again it could reuse a value that was previously used 253 * before boot, and a client who queried the two values might 254 * incorrectly assume nothing changed. 255 * 256 * By using both ctime and the i_version counter we guarantee that as 257 * long as time doesn't go backwards we never reuse an old value. 258 */ 259 static inline u64 nfsd4_change_attribute(struct kstat *stat, 260 struct inode *inode) 261 { 262 u64 chattr; 263 264 chattr = stat->ctime.tv_sec; 265 chattr <<= 30; 266 chattr += stat->ctime.tv_nsec; 267 chattr += inode_query_iversion(inode); 268 return chattr; 269 } 270 271 extern void fill_pre_wcc(struct svc_fh *fhp); 272 extern void fill_post_wcc(struct svc_fh *fhp); 273 #else 274 #define fh_clear_wcc(ignored) 275 #define fill_pre_wcc(ignored) 276 #define fill_post_wcc(notused) 277 #endif /* CONFIG_NFSD_V3 */ 278 279 280 /* 281 * Lock a file handle/inode 282 * NOTE: both fh_lock and fh_unlock are done "by hand" in 283 * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once 284 * so, any changes here should be reflected there. 285 */ 286 287 static inline void 288 fh_lock_nested(struct svc_fh *fhp, unsigned int subclass) 289 { 290 struct dentry *dentry = fhp->fh_dentry; 291 struct inode *inode; 292 293 BUG_ON(!dentry); 294 295 if (fhp->fh_locked) { 296 printk(KERN_WARNING "fh_lock: %pd2 already locked!\n", 297 dentry); 298 return; 299 } 300 301 inode = d_inode(dentry); 302 inode_lock_nested(inode, subclass); 303 fill_pre_wcc(fhp); 304 fhp->fh_locked = true; 305 } 306 307 static inline void 308 fh_lock(struct svc_fh *fhp) 309 { 310 fh_lock_nested(fhp, I_MUTEX_NORMAL); 311 } 312 313 /* 314 * Unlock a file handle/inode 315 */ 316 static inline void 317 fh_unlock(struct svc_fh *fhp) 318 { 319 if (fhp->fh_locked) { 320 fill_post_wcc(fhp); 321 inode_unlock(d_inode(fhp->fh_dentry)); 322 fhp->fh_locked = false; 323 } 324 } 325 326 #endif /* _LINUX_NFSD_NFSFH_H */ 327