Message ID | 162995209561.7591.4202079352301963089@noble.neil.brown.name (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | NFSD: drop support for ancient file-handles | expand |
> On Aug 26, 2021, at 12:28 AM, NeilBrown <neilb@suse.de> wrote: > > > File-handles not in the "new" or "version 1" format have not been handed > out for new mounts since Linux 2.4 which was released 20 years ago. > I think it is safe to say that no such file handles are still in use, > and that we can drop support for them. > > This patch also moves the nfsfh.h from the include/uapi directory into > fs/nfsd. I can find no evidence of it being used anywhere outside the > kernel. Certainly nfs-utils and wireshark do not use it. > > fh_base and fh_pad are occasionally used to refer to the whole > filehandle. These are replaced with "fh_raw" which is hopefully more > meaningful. > > Signed-off-by: NeilBrown <neilb@suse.de> > --- > > I found > https://www.spinics.net/lists/linux-nfs/msg43280.html > "Re: [PATCH] nfsd: clean up fh_auth usage" > from 2014 where moving nfsfh.h out of uapi was considered but not > actioned. Christoph said he would "do some research if the > uapi <linux/nfsd/*.h> headers are used anywhere at all". I can find no > report on the result of that research. My own research turned up > nothing. > > Thanks, > NeilBrown Hi Neil- I have no philosophical objection to this clean up, but I'm concerned a bit about timing. It's a large patch, and 5.15 should be opening on Sunday. I would prefer this to go into 5.16, if that's OK with you? > fs/nfsd/lockd.c | 2 +- > fs/nfsd/nfs3xdr.c | 4 +- > fs/nfsd/nfs4callback.c | 2 +- > fs/nfsd/nfs4proc.c | 2 +- > fs/nfsd/nfs4state.c | 4 +- > fs/nfsd/nfs4xdr.c | 4 +- > fs/nfsd/nfsctl.c | 6 +- > fs/nfsd/nfsfh.c | 177 +++++++++++--------------------- > fs/nfsd/nfsfh.h | 55 +++++++++- > fs/nfsd/nfsxdr.c | 4 +- > include/uapi/linux/nfsd/nfsfh.h | 116 --------------------- > 11 files changed, 126 insertions(+), 250 deletions(-) > delete mode 100644 include/uapi/linux/nfsd/nfsfh.h > > diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c > index 3f5b3d7b62b7..74d1630e7994 100644 > --- a/fs/nfsd/lockd.c > +++ b/fs/nfsd/lockd.c > @@ -33,7 +33,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) > /* must initialize before using! but maxsize doesn't matter */ > fh_init(&fh,0); > fh.fh_handle.fh_size = f->size; > - memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size); > + memcpy((char*)&fh.fh_handle.fh_raw, f->data, f->size); > fh.fh_export = NULL; > > nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp); > diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c > index 0a5ebc52e6a9..3d37923afb06 100644 > --- a/fs/nfsd/nfs3xdr.c > +++ b/fs/nfsd/nfs3xdr.c > @@ -92,7 +92,7 @@ svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp) > return false; > fh_init(fhp, NFS3_FHSIZE); > fhp->fh_handle.fh_size = size; > - memcpy(&fhp->fh_handle.fh_base, p, size); > + memcpy(&fhp->fh_handle.fh_raw, p, size); > > return true; > } > @@ -131,7 +131,7 @@ svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp) > *p++ = cpu_to_be32(size); > if (size) > p[XDR_QUADLEN(size) - 1] = 0; > - memcpy(p, &fhp->fh_handle.fh_base, size); > + memcpy(p, &fhp->fh_handle.fh_raw, size); > > return true; > } > diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c > index 0f8b10f363e7..11f8715d92d6 100644 > --- a/fs/nfsd/nfs4callback.c > +++ b/fs/nfsd/nfs4callback.c > @@ -121,7 +121,7 @@ static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh) > > BUG_ON(length > NFS4_FHSIZE); > p = xdr_reserve_space(xdr, 4 + length); > - xdr_encode_opaque(p, &fh->fh_base, length); > + xdr_encode_opaque(p, &fh->fh_raw, length); > } > > /* > diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c > index 486c5dba4b65..4872b9519a72 100644 > --- a/fs/nfsd/nfs4proc.c > +++ b/fs/nfsd/nfs4proc.c > @@ -519,7 +519,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, > > fh_put(&cstate->current_fh); > cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; > - memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, > + memcpy(&cstate->current_fh.fh_handle.fh_raw, putfh->pf_fhval, > putfh->pf_fhlen); > ret = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS); > #ifdef CONFIG_NFSD_V4_2_INTER_SSC > diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c > index fa67ecd5fe63..d66b4be99063 100644 > --- a/fs/nfsd/nfs4state.c > +++ b/fs/nfsd/nfs4state.c > @@ -1010,7 +1010,7 @@ static int delegation_blocked(struct knfsd_fh *fh) > } > spin_unlock(&blocked_delegations_lock); > } > - hash = jhash(&fh->fh_base, fh->fh_size, 0); > + hash = jhash(&fh->fh_raw, fh->fh_size, 0); > if (test_bit(hash&255, bd->set[0]) && > test_bit((hash>>8)&255, bd->set[0]) && > test_bit((hash>>16)&255, bd->set[0])) > @@ -1029,7 +1029,7 @@ static void block_delegations(struct knfsd_fh *fh) > u32 hash; > struct bloom_pair *bd = &blocked_delegations; > > - hash = jhash(&fh->fh_base, fh->fh_size, 0); > + hash = jhash(&fh->fh_raw, fh->fh_size, 0); > > spin_lock(&blocked_delegations_lock); > __set_bit(hash&255, bd->set[bd->new]); > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c > index 7abeccb975b2..a54b2845473b 100644 > --- a/fs/nfsd/nfs4xdr.c > +++ b/fs/nfsd/nfs4xdr.c > @@ -3110,7 +3110,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4); > if (!p) > goto out_resource; > - p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, > + p = xdr_encode_opaque(p, &fhp->fh_handle.fh_raw, > fhp->fh_handle.fh_size); > } > if (bmval0 & FATTR4_WORD0_FILEID) { > @@ -3667,7 +3667,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh > p = xdr_reserve_space(xdr, len + 4); > if (!p) > return nfserr_resource; > - p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len); > + p = xdr_encode_opaque(p, &fhp->fh_handle.fh_raw, len); > return 0; > } > > diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c > index c2c3d9077dc5..449b57e5e328 100644 > --- a/fs/nfsd/nfsctl.c > +++ b/fs/nfsd/nfsctl.c > @@ -395,12 +395,12 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) > auth_domain_put(dom); > if (len) > return len; > - > + > mesg = buf; > len = SIMPLE_TRANSACTION_LIMIT; > - qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size); > + qword_addhex(&mesg, &len, (char*)&fh.fh_raw, fh.fh_size); > mesg[-1] = '\n'; > - return mesg - buf; > + return mesg - buf; > } > > /* > diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c > index c475d2271f9c..7695c0f1eefe 100644 > --- a/fs/nfsd/nfsfh.c > +++ b/fs/nfsd/nfsfh.c > @@ -154,11 +154,12 @@ static inline __be32 check_pseudo_root(struct svc_rqst *rqstp, > static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) > { > struct knfsd_fh *fh = &fhp->fh_handle; > - struct fid *fid = NULL, sfid; > + struct fid *fid = NULL; > struct svc_export *exp; > struct dentry *dentry; > int fileid_type; > int data_left = fh->fh_size/4; > + int len; > __be32 error; > > error = nfserr_stale; > @@ -167,48 +168,35 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) > if (rqstp->rq_vers == 4 && fh->fh_size == 0) > return nfserr_nofilehandle; > > - if (fh->fh_version == 1) { > - int len; > - > - if (--data_left < 0) > - return error; > - if (fh->fh_auth_type != 0) > - return error; > - len = key_len(fh->fh_fsid_type) / 4; > - if (len == 0) > - return error; > - if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { > - /* deprecated, convert to type 3 */ > - len = key_len(FSID_ENCODE_DEV)/4; > - fh->fh_fsid_type = FSID_ENCODE_DEV; > - /* > - * struct knfsd_fh uses host-endian fields, which are > - * sometimes used to hold net-endian values. This > - * confuses sparse, so we must use __force here to > - * keep it from complaining. > - */ > - fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]), > - ntohl((__force __be32)fh->fh_fsid[1]))); > - fh->fh_fsid[1] = fh->fh_fsid[2]; > - } > - data_left -= len; > - if (data_left < 0) > - return error; > - exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid); > - fid = (struct fid *)(fh->fh_fsid + len); > - } else { > - __u32 tfh[2]; > - dev_t xdev; > - ino_t xino; > - > - if (fh->fh_size != NFS_FHSIZE) > - return error; > - /* assume old filehandle format */ > - xdev = old_decode_dev(fh->ofh_xdev); > - xino = u32_to_ino_t(fh->ofh_xino); > - mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL); > - exp = rqst_exp_find(rqstp, FSID_DEV, tfh); > + if (fh->fh_version != 1) > + return error; > + > + if (--data_left < 0) > + return error; > + if (fh->fh_auth_type != 0) > + return error; > + len = key_len(fh->fh_fsid_type) / 4; > + if (len == 0) > + return error; > + if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { > + /* deprecated, convert to type 3 */ > + len = key_len(FSID_ENCODE_DEV)/4; > + fh->fh_fsid_type = FSID_ENCODE_DEV; > + /* > + * struct knfsd_fh uses host-endian fields, which are > + * sometimes used to hold net-endian values. This > + * confuses sparse, so we must use __force here to > + * keep it from complaining. > + */ > + fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]), > + ntohl((__force __be32)fh->fh_fsid[1]))); > + fh->fh_fsid[1] = fh->fh_fsid[2]; > } > + data_left -= len; > + if (data_left < 0) > + return error; > + exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid); > + fid = (struct fid *)(fh->fh_fsid + len); > > error = nfserr_stale; > if (IS_ERR(exp)) { > @@ -253,18 +241,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) > if (rqstp->rq_vers > 2) > error = nfserr_badhandle; > > - if (fh->fh_version != 1) { > - sfid.i32.ino = fh->ofh_ino; > - sfid.i32.gen = fh->ofh_generation; > - sfid.i32.parent_ino = fh->ofh_dirino; > - fid = &sfid; > - data_left = 3; > - if (fh->ofh_dirino == 0) > - fileid_type = FILEID_INO32_GEN; > - else > - fileid_type = FILEID_INO32_GEN_PARENT; > - } else > - fileid_type = fh->fh_fileid_type; > + fileid_type = fh->fh_fileid_type; > > if (fileid_type == FILEID_ROOT) > dentry = dget(exp->ex_path.dentry); > @@ -452,20 +429,6 @@ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, > } > } > > -/* > - * for composing old style file handles > - */ > -static inline void _fh_update_old(struct dentry *dentry, > - struct svc_export *exp, > - struct knfsd_fh *fh) > -{ > - fh->ofh_ino = ino_t_to_u32(d_inode(dentry)->i_ino); > - fh->ofh_generation = d_inode(dentry)->i_generation; > - if (d_is_dir(dentry) || > - (exp->ex_flags & NFSEXP_NOSUBTREECHECK)) > - fh->ofh_dirino = 0; > -} > - > static bool is_root_export(struct svc_export *exp) > { > return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root; > @@ -600,35 +563,21 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, > fhp->fh_dentry = dget(dentry); /* our internal copy */ > fhp->fh_export = exp_get(exp); > > - if (fhp->fh_handle.fh_version == 0xca) { > - /* old style filehandle please */ > - memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); > - fhp->fh_handle.fh_size = NFS_FHSIZE; > - fhp->fh_handle.ofh_dcookie = 0xfeebbaca; > - fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); > - fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; > - fhp->fh_handle.ofh_xino = > - ino_t_to_u32(d_inode(exp->ex_path.dentry)->i_ino); > - fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); > - if (inode) > - _fh_update_old(dentry, exp, &fhp->fh_handle); > - } else { > - fhp->fh_handle.fh_size = > - key_len(fhp->fh_handle.fh_fsid_type) + 4; > - fhp->fh_handle.fh_auth_type = 0; > - > - mk_fsid(fhp->fh_handle.fh_fsid_type, > - fhp->fh_handle.fh_fsid, > - ex_dev, > - d_inode(exp->ex_path.dentry)->i_ino, > - exp->ex_fsid, exp->ex_uuid); > - > - if (inode) > - _fh_update(fhp, exp, dentry); > - if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) { > - fh_put(fhp); > - return nfserr_opnotsupp; > - } > + fhp->fh_handle.fh_size = > + key_len(fhp->fh_handle.fh_fsid_type) + 4; > + fhp->fh_handle.fh_auth_type = 0; > + > + mk_fsid(fhp->fh_handle.fh_fsid_type, > + fhp->fh_handle.fh_fsid, > + ex_dev, > + d_inode(exp->ex_path.dentry)->i_ino, > + exp->ex_fsid, exp->ex_uuid); > + > + if (inode) > + _fh_update(fhp, exp, dentry); > + if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) { > + fh_put(fhp); > + return nfserr_opnotsupp; > } > > return 0; > @@ -649,23 +598,19 @@ fh_update(struct svc_fh *fhp) > dentry = fhp->fh_dentry; > if (d_really_is_negative(dentry)) > goto out_negative; > - if (fhp->fh_handle.fh_version != 1) { > - _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); > - } else { > - if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) > - return 0; > + if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) > + return 0; > > - _fh_update(fhp, fhp->fh_export, dentry); > - if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) > - return nfserr_opnotsupp; > - } > + _fh_update(fhp, fhp->fh_export, dentry); > + if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) > + return nfserr_opnotsupp; > return 0; > out_bad: > printk(KERN_ERR "fh_update: fh not verified!\n"); > return nfserr_serverfault; > out_negative: > printk(KERN_ERR "fh_update: %pd2 still negative!\n", > - dentry); > + dentry); > return nfserr_serverfault; > } > > @@ -702,12 +647,12 @@ char * SVCFH_fmt(struct svc_fh *fhp) > static char buf[80]; > sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x", > fh->fh_size, > - fh->fh_base.fh_pad[0], > - fh->fh_base.fh_pad[1], > - fh->fh_base.fh_pad[2], > - fh->fh_base.fh_pad[3], > - fh->fh_base.fh_pad[4], > - fh->fh_base.fh_pad[5]); > + fh->fh_raw[0], > + fh->fh_raw[1], > + fh->fh_raw[2], > + fh->fh_raw[3], > + fh->fh_raw[4], > + fh->fh_raw[5]); > return buf; > } > > diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h > index 6106697adc04..f36234c474dc 100644 > --- a/fs/nfsd/nfsfh.h > +++ b/fs/nfsd/nfsfh.h > @@ -10,9 +10,56 @@ > > #include <linux/crc32.h> > #include <linux/sunrpc/svc.h> > -#include <uapi/linux/nfsd/nfsfh.h> > #include <linux/iversion.h> > #include <linux/exportfs.h> > +#include <linux/nfs4.h> > + > +/* > + * The file handle starts with a sequence of four-byte words. > + * The first word contains a version number (1) and three descriptor bytes > + * that tell how the remaining 3 variable length fields should be handled. > + * These three bytes are auth_type, fsid_type and fileid_type. > + * > + * All four-byte values are in host-byte-order. > + * > + * The auth_type field is deprecated and must be set to 0. > + * > + * The fsid_type identifies how the filesystem (or export point) is > + * encoded. > + * Current values: > + * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number > + * NOTE: we cannot use the kdev_t device id value, because kdev_t.h > + * says we mustn't. We must break it up and reassemble. > + * 1 - 4 byte user specified identifier > + * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED > + * 3 - 4 byte device id, encoded for user-space, 4 byte inode number > + * 4 - 4 byte inode number and 4 byte uuid > + * 5 - 8 byte uuid > + * 6 - 16 byte uuid > + * 7 - 8 byte inode number and 16 byte uuid > + * > + * The fileid_type identified how the file within the filesystem is encoded. > + * The values for this field are filesystem specific, exccept that > + * filesystems must not use the values '0' or '0xff'. 'See enum fid_type' > + * in include/linux/exportfs.h for currently registered values. > + */ > + > +struct knfsd_fh { > + unsigned int fh_size; /* > + * Points to the current size while > + * building a new file handle. > + */ > + union { > + __u32 fh_raw[NFS4_FHSIZE/4]; > + struct { > + __u8 fh_version; /* == 1 */ > + __u8 fh_auth_type; /* deprecated */ > + __u8 fh_fsid_type; > + __u8 fh_fileid_type; > + __u32 fh_fsid[]; /* flexible-array member */ > + }; > + }; > +}; > > static inline __u32 ino_t_to_u32(ino_t ino) > { > @@ -188,7 +235,7 @@ static inline void > fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src) > { > dst->fh_size = src->fh_size; > - memcpy(&dst->fh_base, &src->fh_base, src->fh_size); > + memcpy(&dst->fh_raw, &src->fh_raw, src->fh_size); > } > > static __inline__ struct svc_fh * > @@ -203,7 +250,7 @@ static inline bool fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) > { > if (fh1->fh_size != fh2->fh_size) > return false; > - if (memcmp(fh1->fh_base.fh_pad, fh2->fh_base.fh_pad, fh1->fh_size) != 0) > + if (memcmp(fh1->fh_raw, fh2->fh_raw, fh1->fh_size) != 0) > return false; > return true; > } > @@ -227,7 +274,7 @@ static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) > */ > static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) > { > - return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size); > + return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_raw, fh->fh_size); > } > #else > static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) > diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c > index a06c05fe3b42..082449c7d0db 100644 > --- a/fs/nfsd/nfsxdr.c > +++ b/fs/nfsd/nfsxdr.c > @@ -64,7 +64,7 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp) > if (!p) > return false; > fh_init(fhp, NFS_FHSIZE); > - memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE); > + memcpy(&fhp->fh_handle.fh_raw, p, NFS_FHSIZE); > fhp->fh_handle.fh_size = NFS_FHSIZE; > > return true; > @@ -78,7 +78,7 @@ svcxdr_encode_fhandle(struct xdr_stream *xdr, const struct svc_fh *fhp) > p = xdr_reserve_space(xdr, NFS_FHSIZE); > if (!p) > return false; > - memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE); > + memcpy(p, &fhp->fh_handle.fh_raw, NFS_FHSIZE); > > return true; > } > diff --git a/include/uapi/linux/nfsd/nfsfh.h b/include/uapi/linux/nfsd/nfsfh.h > deleted file mode 100644 > index 427294dd56a1..000000000000 > --- a/include/uapi/linux/nfsd/nfsfh.h > +++ /dev/null > @@ -1,116 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > -/* > - * This file describes the layout of the file handles as passed > - * over the wire. > - * > - * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> > - */ > - > -#ifndef _UAPI_LINUX_NFSD_FH_H > -#define _UAPI_LINUX_NFSD_FH_H > - > -#include <linux/types.h> > -#include <linux/nfs.h> > -#include <linux/nfs2.h> > -#include <linux/nfs3.h> > -#include <linux/nfs4.h> > - > -/* > - * This is the old "dentry style" Linux NFSv2 file handle. > - * > - * The xino and xdev fields are currently used to transport the > - * ino/dev of the exported inode. > - */ > -struct nfs_fhbase_old { > - __u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */ > - __u32 fb_ino; /* our inode number */ > - __u32 fb_dirino; /* dir inode number, 0 for directories */ > - __u32 fb_dev; /* our device */ > - __u32 fb_xdev; > - __u32 fb_xino; > - __u32 fb_generation; > -}; > - > -/* > - * This is the new flexible, extensible style NFSv2/v3/v4 file handle. > - * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000 > - * > - * The file handle starts with a sequence of four-byte words. > - * The first word contains a version number (1) and three descriptor bytes > - * that tell how the remaining 3 variable length fields should be handled. > - * These three bytes are auth_type, fsid_type and fileid_type. > - * > - * All four-byte values are in host-byte-order. > - * > - * The auth_type field is deprecated and must be set to 0. > - * > - * The fsid_type identifies how the filesystem (or export point) is > - * encoded. > - * Current values: > - * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number > - * NOTE: we cannot use the kdev_t device id value, because kdev_t.h > - * says we mustn't. We must break it up and reassemble. > - * 1 - 4 byte user specified identifier > - * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED > - * 3 - 4 byte device id, encoded for user-space, 4 byte inode number > - * 4 - 4 byte inode number and 4 byte uuid > - * 5 - 8 byte uuid > - * 6 - 16 byte uuid > - * 7 - 8 byte inode number and 16 byte uuid > - * > - * The fileid_type identified how the file within the filesystem is encoded. > - * The values for this field are filesystem specific, exccept that > - * filesystems must not use the values '0' or '0xff'. 'See enum fid_type' > - * in include/linux/exportfs.h for currently registered values. > - */ > -struct nfs_fhbase_new { > - union { > - struct { > - __u8 fb_version_aux; /* == 1, even => nfs_fhbase_old */ > - __u8 fb_auth_type_aux; > - __u8 fb_fsid_type_aux; > - __u8 fb_fileid_type_aux; > - __u32 fb_auth[1]; > - /* __u32 fb_fsid[0]; floating */ > - /* __u32 fb_fileid[0]; floating */ > - }; > - struct { > - __u8 fb_version; /* == 1, even => nfs_fhbase_old */ > - __u8 fb_auth_type; > - __u8 fb_fsid_type; > - __u8 fb_fileid_type; > - __u32 fb_auth_flex[]; /* flexible-array member */ > - }; > - }; > -}; > - > -struct knfsd_fh { > - unsigned int fh_size; /* significant for NFSv3. > - * Points to the current size while building > - * a new file handle > - */ > - union { > - struct nfs_fhbase_old fh_old; > - __u32 fh_pad[NFS4_FHSIZE/4]; > - struct nfs_fhbase_new fh_new; > - } fh_base; > -}; > - > -#define ofh_dcookie fh_base.fh_old.fb_dcookie > -#define ofh_ino fh_base.fh_old.fb_ino > -#define ofh_dirino fh_base.fh_old.fb_dirino > -#define ofh_dev fh_base.fh_old.fb_dev > -#define ofh_xdev fh_base.fh_old.fb_xdev > -#define ofh_xino fh_base.fh_old.fb_xino > -#define ofh_generation fh_base.fh_old.fb_generation > - > -#define fh_version fh_base.fh_new.fb_version > -#define fh_fsid_type fh_base.fh_new.fb_fsid_type > -#define fh_auth_type fh_base.fh_new.fb_auth_type > -#define fh_fileid_type fh_base.fh_new.fb_fileid_type > -#define fh_fsid fh_base.fh_new.fb_auth_flex > - > -/* Do not use, provided for userspace compatiblity. */ > -#define fh_auth fh_base.fh_new.fb_auth > - > -#endif /* _UAPI_LINUX_NFSD_FH_H */ > -- > 2.32.0 > > -- Chuck Lever
On Thu, Aug 26, 2021 at 02:28:15PM +1000, NeilBrown wrote: > > File-handles not in the "new" or "version 1" format have not been handed > out for new mounts since Linux 2.4 which was released 20 years ago. > I think it is safe to say that no such file handles are still in use, > and that we can drop support for them. > > This patch also moves the nfsfh.h from the include/uapi directory into > fs/nfsd. I can find no evidence of it being used anywhere outside the > kernel. Certainly nfs-utils and wireshark do not use it. > > fh_base and fh_pad are occasionally used to refer to the whole > filehandle. These are replaced with "fh_raw" which is hopefully more > meaningful. Oh boy, I will not miss those (fh_version == 1) cases in nfsfh.c. Excellent. Looks like it just needs the following folded in. --b. diff --git a/fs/nfsd/flexfilelayout.c b/fs/nfsd/flexfilelayout.c index db7ef07ae50c..2e2f1d5e9f62 100644 --- a/fs/nfsd/flexfilelayout.c +++ b/fs/nfsd/flexfilelayout.c @@ -61,7 +61,7 @@ nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, goto out_error; fl->fh.size = fhp->fh_handle.fh_size; - memcpy(fl->fh.data, &fhp->fh_handle.fh_base, fl->fh.size); + memcpy(fl->fh.data, &fhp->fh_handle.fh_raw, fl->fh.size); /* Give whole file layout segments */ seg->offset = 0; diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 4872b9519a72..3f7e59ec4e32 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1383,7 +1383,7 @@ nfsd4_setup_inter_ssc(struct svc_rqst *rqstp, s_fh = &cstate->save_fh; copy->c_fh.size = s_fh->fh_handle.fh_size; - memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_base, copy->c_fh.size); + memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_raw, copy->c_fh.size); copy->stateid.seqid = cpu_to_be32(s_stid->si_generation); memcpy(copy->stateid.other, (void *)&s_stid->si_opaque, sizeof(stateid_opaque_t));
On Fri, 27 Aug 2021, Chuck Lever III wrote: > > > On Aug 26, 2021, at 12:28 AM, NeilBrown <neilb@suse.de> wrote: > > > > > > File-handles not in the "new" or "version 1" format have not been handed > > out for new mounts since Linux 2.4 which was released 20 years ago. > > I think it is safe to say that no such file handles are still in use, > > and that we can drop support for them. > > > > This patch also moves the nfsfh.h from the include/uapi directory into > > fs/nfsd. I can find no evidence of it being used anywhere outside the > > kernel. Certainly nfs-utils and wireshark do not use it. > > > > fh_base and fh_pad are occasionally used to refer to the whole > > filehandle. These are replaced with "fh_raw" which is hopefully more > > meaningful. > > > > Signed-off-by: NeilBrown <neilb@suse.de> > > --- > > > > I found > > https://www.spinics.net/lists/linux-nfs/msg43280.html > > "Re: [PATCH] nfsd: clean up fh_auth usage" > > from 2014 where moving nfsfh.h out of uapi was considered but not > > actioned. Christoph said he would "do some research if the > > uapi <linux/nfsd/*.h> headers are used anywhere at all". I can find no > > report on the result of that research. My own research turned up > > nothing. > > > > Thanks, > > NeilBrown > > Hi Neil- > > I have no philosophical objection to this clean up, but I'm > concerned a bit about timing. It's a large patch, and 5.15 > should be opening on Sunday. I would prefer this to go into > 5.16, if that's OK with you? No problem at all. I enjoy the luxury of send patches whenever I'm ready, and assume you will process them only when you are ready. I do, of course, appreciate knowing what you plan. Thanks, NeilBrown
On Fri, 27 Aug 2021, J. Bruce Fields wrote: > On Thu, Aug 26, 2021 at 02:28:15PM +1000, NeilBrown wrote: > > > > File-handles not in the "new" or "version 1" format have not been handed > > out for new mounts since Linux 2.4 which was released 20 years ago. > > I think it is safe to say that no such file handles are still in use, > > and that we can drop support for them. > > > > This patch also moves the nfsfh.h from the include/uapi directory into > > fs/nfsd. I can find no evidence of it being used anywhere outside the > > kernel. Certainly nfs-utils and wireshark do not use it. > > > > fh_base and fh_pad are occasionally used to refer to the whole > > filehandle. These are replaced with "fh_raw" which is hopefully more > > meaningful. > > Oh boy, I will not miss those (fh_version == 1) cases in nfsfh.c. > Excellent. :-) > > Looks like it just needs the following folded in. Don't know how I missed those - so happy to have reliable reviewers! Thanks, NeilBrown
On Thu, Aug 26, 2021 at 02:28:15PM +1000, NeilBrown wrote: > This patch also moves the nfsfh.h from the include/uapi directory into > fs/nfsd. I can find no evidence of it being used anywhere outside the > kernel. Certainly nfs-utils and wireshark do not use it. That sounds fine, but I'd split this into a separate patch. > fh_base and fh_pad are occasionally used to refer to the whole > filehandle. These are replaced with "fh_raw" which is hopefully more > meaningful. I think that kind of cleanup should also be a separate patch. That being said as far as I can tell fh_raw is only ever used in context where we can just pass a void pointer. So just giving the struct for the "new" file handle after fh_size a name and passing that would be much cleaner than a union with a char array. > I found > https://www.spinics.net/lists/linux-nfs/msg43280.html > "Re: [PATCH] nfsd: clean up fh_auth usage" > from 2014 where moving nfsfh.h out of uapi was considered but not > actioned. Christoph said he would "do some research if the > uapi <linux/nfsd/*.h> headers are used anywhere at all". I can find no > report on the result of that research. My own research turned up > nothing. I can't remember doing much of research, and certainly not of finding anything. > - memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size); > + memcpy((char*)&fh.fh_handle.fh_raw, f->data, f->size); Indedpendnt on what we're going to pass here, I don't think we should need cast like this one (there are a few more).
On Sat, 28 Aug 2021, Christoph Hellwig wrote: > On Thu, Aug 26, 2021 at 02:28:15PM +1000, NeilBrown wrote: > > This patch also moves the nfsfh.h from the include/uapi directory into > > fs/nfsd. I can find no evidence of it being used anywhere outside the > > kernel. Certainly nfs-utils and wireshark do not use it. > > That sounds fine, but I'd split this into a separate patch. Thanks for your review. Your suggestions seem appropriate. I'll send out revised patches in a couple of days. NeilBrown > > > fh_base and fh_pad are occasionally used to refer to the whole > > filehandle. These are replaced with "fh_raw" which is hopefully more > > meaningful. > > I think that kind of cleanup should also be a separate patch. That > being said as far as I can tell fh_raw is only ever used in context > where we can just pass a void pointer. So just giving the struct > for the "new" file handle after fh_size a name and passing that > would be much cleaner than a union with a char array. > > > > I found > > https://www.spinics.net/lists/linux-nfs/msg43280.html > > "Re: [PATCH] nfsd: clean up fh_auth usage" > > from 2014 where moving nfsfh.h out of uapi was considered but not > > actioned. Christoph said he would "do some research if the > > uapi <linux/nfsd/*.h> headers are used anywhere at all". I can find no > > report on the result of that research. My own research turned up > > nothing. > > I can't remember doing much of research, and certainly not of finding > anything. > > > - memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size); > > + memcpy((char*)&fh.fh_handle.fh_raw, f->data, f->size); > > Indedpendnt on what we're going to pass here, I don't think we > should need cast like this one (there are a few more). > >
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 3f5b3d7b62b7..74d1630e7994 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -33,7 +33,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) /* must initialize before using! but maxsize doesn't matter */ fh_init(&fh,0); fh.fh_handle.fh_size = f->size; - memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size); + memcpy((char*)&fh.fh_handle.fh_raw, f->data, f->size); fh.fh_export = NULL; nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp); diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 0a5ebc52e6a9..3d37923afb06 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -92,7 +92,7 @@ svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp) return false; fh_init(fhp, NFS3_FHSIZE); fhp->fh_handle.fh_size = size; - memcpy(&fhp->fh_handle.fh_base, p, size); + memcpy(&fhp->fh_handle.fh_raw, p, size); return true; } @@ -131,7 +131,7 @@ svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp) *p++ = cpu_to_be32(size); if (size) p[XDR_QUADLEN(size) - 1] = 0; - memcpy(p, &fhp->fh_handle.fh_base, size); + memcpy(p, &fhp->fh_handle.fh_raw, size); return true; } diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 0f8b10f363e7..11f8715d92d6 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -121,7 +121,7 @@ static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh) BUG_ON(length > NFS4_FHSIZE); p = xdr_reserve_space(xdr, 4 + length); - xdr_encode_opaque(p, &fh->fh_base, length); + xdr_encode_opaque(p, &fh->fh_raw, length); } /* diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 486c5dba4b65..4872b9519a72 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -519,7 +519,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, fh_put(&cstate->current_fh); cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; - memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, + memcpy(&cstate->current_fh.fh_handle.fh_raw, putfh->pf_fhval, putfh->pf_fhlen); ret = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS); #ifdef CONFIG_NFSD_V4_2_INTER_SSC diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fa67ecd5fe63..d66b4be99063 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1010,7 +1010,7 @@ static int delegation_blocked(struct knfsd_fh *fh) } spin_unlock(&blocked_delegations_lock); } - hash = jhash(&fh->fh_base, fh->fh_size, 0); + hash = jhash(&fh->fh_raw, fh->fh_size, 0); if (test_bit(hash&255, bd->set[0]) && test_bit((hash>>8)&255, bd->set[0]) && test_bit((hash>>16)&255, bd->set[0])) @@ -1029,7 +1029,7 @@ static void block_delegations(struct knfsd_fh *fh) u32 hash; struct bloom_pair *bd = &blocked_delegations; - hash = jhash(&fh->fh_base, fh->fh_size, 0); + hash = jhash(&fh->fh_raw, fh->fh_size, 0); spin_lock(&blocked_delegations_lock); __set_bit(hash&255, bd->set[bd->new]); diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 7abeccb975b2..a54b2845473b 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3110,7 +3110,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4); if (!p) goto out_resource; - p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, + p = xdr_encode_opaque(p, &fhp->fh_handle.fh_raw, fhp->fh_handle.fh_size); } if (bmval0 & FATTR4_WORD0_FILEID) { @@ -3667,7 +3667,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh p = xdr_reserve_space(xdr, len + 4); if (!p) return nfserr_resource; - p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len); + p = xdr_encode_opaque(p, &fhp->fh_handle.fh_raw, len); return 0; } diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index c2c3d9077dc5..449b57e5e328 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -395,12 +395,12 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) auth_domain_put(dom); if (len) return len; - + mesg = buf; len = SIMPLE_TRANSACTION_LIMIT; - qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size); + qword_addhex(&mesg, &len, (char*)&fh.fh_raw, fh.fh_size); mesg[-1] = '\n'; - return mesg - buf; + return mesg - buf; } /* diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index c475d2271f9c..7695c0f1eefe 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -154,11 +154,12 @@ static inline __be32 check_pseudo_root(struct svc_rqst *rqstp, static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) { struct knfsd_fh *fh = &fhp->fh_handle; - struct fid *fid = NULL, sfid; + struct fid *fid = NULL; struct svc_export *exp; struct dentry *dentry; int fileid_type; int data_left = fh->fh_size/4; + int len; __be32 error; error = nfserr_stale; @@ -167,48 +168,35 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) if (rqstp->rq_vers == 4 && fh->fh_size == 0) return nfserr_nofilehandle; - if (fh->fh_version == 1) { - int len; - - if (--data_left < 0) - return error; - if (fh->fh_auth_type != 0) - return error; - len = key_len(fh->fh_fsid_type) / 4; - if (len == 0) - return error; - if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { - /* deprecated, convert to type 3 */ - len = key_len(FSID_ENCODE_DEV)/4; - fh->fh_fsid_type = FSID_ENCODE_DEV; - /* - * struct knfsd_fh uses host-endian fields, which are - * sometimes used to hold net-endian values. This - * confuses sparse, so we must use __force here to - * keep it from complaining. - */ - fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]), - ntohl((__force __be32)fh->fh_fsid[1]))); - fh->fh_fsid[1] = fh->fh_fsid[2]; - } - data_left -= len; - if (data_left < 0) - return error; - exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid); - fid = (struct fid *)(fh->fh_fsid + len); - } else { - __u32 tfh[2]; - dev_t xdev; - ino_t xino; - - if (fh->fh_size != NFS_FHSIZE) - return error; - /* assume old filehandle format */ - xdev = old_decode_dev(fh->ofh_xdev); - xino = u32_to_ino_t(fh->ofh_xino); - mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL); - exp = rqst_exp_find(rqstp, FSID_DEV, tfh); + if (fh->fh_version != 1) + return error; + + if (--data_left < 0) + return error; + if (fh->fh_auth_type != 0) + return error; + len = key_len(fh->fh_fsid_type) / 4; + if (len == 0) + return error; + if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { + /* deprecated, convert to type 3 */ + len = key_len(FSID_ENCODE_DEV)/4; + fh->fh_fsid_type = FSID_ENCODE_DEV; + /* + * struct knfsd_fh uses host-endian fields, which are + * sometimes used to hold net-endian values. This + * confuses sparse, so we must use __force here to + * keep it from complaining. + */ + fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]), + ntohl((__force __be32)fh->fh_fsid[1]))); + fh->fh_fsid[1] = fh->fh_fsid[2]; } + data_left -= len; + if (data_left < 0) + return error; + exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid); + fid = (struct fid *)(fh->fh_fsid + len); error = nfserr_stale; if (IS_ERR(exp)) { @@ -253,18 +241,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) if (rqstp->rq_vers > 2) error = nfserr_badhandle; - if (fh->fh_version != 1) { - sfid.i32.ino = fh->ofh_ino; - sfid.i32.gen = fh->ofh_generation; - sfid.i32.parent_ino = fh->ofh_dirino; - fid = &sfid; - data_left = 3; - if (fh->ofh_dirino == 0) - fileid_type = FILEID_INO32_GEN; - else - fileid_type = FILEID_INO32_GEN_PARENT; - } else - fileid_type = fh->fh_fileid_type; + fileid_type = fh->fh_fileid_type; if (fileid_type == FILEID_ROOT) dentry = dget(exp->ex_path.dentry); @@ -452,20 +429,6 @@ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, } } -/* - * for composing old style file handles - */ -static inline void _fh_update_old(struct dentry *dentry, - struct svc_export *exp, - struct knfsd_fh *fh) -{ - fh->ofh_ino = ino_t_to_u32(d_inode(dentry)->i_ino); - fh->ofh_generation = d_inode(dentry)->i_generation; - if (d_is_dir(dentry) || - (exp->ex_flags & NFSEXP_NOSUBTREECHECK)) - fh->ofh_dirino = 0; -} - static bool is_root_export(struct svc_export *exp) { return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root; @@ -600,35 +563,21 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, fhp->fh_dentry = dget(dentry); /* our internal copy */ fhp->fh_export = exp_get(exp); - if (fhp->fh_handle.fh_version == 0xca) { - /* old style filehandle please */ - memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); - fhp->fh_handle.fh_size = NFS_FHSIZE; - fhp->fh_handle.ofh_dcookie = 0xfeebbaca; - fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); - fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; - fhp->fh_handle.ofh_xino = - ino_t_to_u32(d_inode(exp->ex_path.dentry)->i_ino); - fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); - if (inode) - _fh_update_old(dentry, exp, &fhp->fh_handle); - } else { - fhp->fh_handle.fh_size = - key_len(fhp->fh_handle.fh_fsid_type) + 4; - fhp->fh_handle.fh_auth_type = 0; - - mk_fsid(fhp->fh_handle.fh_fsid_type, - fhp->fh_handle.fh_fsid, - ex_dev, - d_inode(exp->ex_path.dentry)->i_ino, - exp->ex_fsid, exp->ex_uuid); - - if (inode) - _fh_update(fhp, exp, dentry); - if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) { - fh_put(fhp); - return nfserr_opnotsupp; - } + fhp->fh_handle.fh_size = + key_len(fhp->fh_handle.fh_fsid_type) + 4; + fhp->fh_handle.fh_auth_type = 0; + + mk_fsid(fhp->fh_handle.fh_fsid_type, + fhp->fh_handle.fh_fsid, + ex_dev, + d_inode(exp->ex_path.dentry)->i_ino, + exp->ex_fsid, exp->ex_uuid); + + if (inode) + _fh_update(fhp, exp, dentry); + if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) { + fh_put(fhp); + return nfserr_opnotsupp; } return 0; @@ -649,23 +598,19 @@ fh_update(struct svc_fh *fhp) dentry = fhp->fh_dentry; if (d_really_is_negative(dentry)) goto out_negative; - if (fhp->fh_handle.fh_version != 1) { - _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); - } else { - if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) - return 0; + if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) + return 0; - _fh_update(fhp, fhp->fh_export, dentry); - if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) - return nfserr_opnotsupp; - } + _fh_update(fhp, fhp->fh_export, dentry); + if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) + return nfserr_opnotsupp; return 0; out_bad: printk(KERN_ERR "fh_update: fh not verified!\n"); return nfserr_serverfault; out_negative: printk(KERN_ERR "fh_update: %pd2 still negative!\n", - dentry); + dentry); return nfserr_serverfault; } @@ -702,12 +647,12 @@ char * SVCFH_fmt(struct svc_fh *fhp) static char buf[80]; sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x", fh->fh_size, - fh->fh_base.fh_pad[0], - fh->fh_base.fh_pad[1], - fh->fh_base.fh_pad[2], - fh->fh_base.fh_pad[3], - fh->fh_base.fh_pad[4], - fh->fh_base.fh_pad[5]); + fh->fh_raw[0], + fh->fh_raw[1], + fh->fh_raw[2], + fh->fh_raw[3], + fh->fh_raw[4], + fh->fh_raw[5]); return buf; } diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h index 6106697adc04..f36234c474dc 100644 --- a/fs/nfsd/nfsfh.h +++ b/fs/nfsd/nfsfh.h @@ -10,9 +10,56 @@ #include <linux/crc32.h> #include <linux/sunrpc/svc.h> -#include <uapi/linux/nfsd/nfsfh.h> #include <linux/iversion.h> #include <linux/exportfs.h> +#include <linux/nfs4.h> + +/* + * The file handle starts with a sequence of four-byte words. + * The first word contains a version number (1) and three descriptor bytes + * that tell how the remaining 3 variable length fields should be handled. + * These three bytes are auth_type, fsid_type and fileid_type. + * + * All four-byte values are in host-byte-order. + * + * The auth_type field is deprecated and must be set to 0. + * + * The fsid_type identifies how the filesystem (or export point) is + * encoded. + * Current values: + * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number + * NOTE: we cannot use the kdev_t device id value, because kdev_t.h + * says we mustn't. We must break it up and reassemble. + * 1 - 4 byte user specified identifier + * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED + * 3 - 4 byte device id, encoded for user-space, 4 byte inode number + * 4 - 4 byte inode number and 4 byte uuid + * 5 - 8 byte uuid + * 6 - 16 byte uuid + * 7 - 8 byte inode number and 16 byte uuid + * + * The fileid_type identified how the file within the filesystem is encoded. + * The values for this field are filesystem specific, exccept that + * filesystems must not use the values '0' or '0xff'. 'See enum fid_type' + * in include/linux/exportfs.h for currently registered values. + */ + +struct knfsd_fh { + unsigned int fh_size; /* + * Points to the current size while + * building a new file handle. + */ + union { + __u32 fh_raw[NFS4_FHSIZE/4]; + struct { + __u8 fh_version; /* == 1 */ + __u8 fh_auth_type; /* deprecated */ + __u8 fh_fsid_type; + __u8 fh_fileid_type; + __u32 fh_fsid[]; /* flexible-array member */ + }; + }; +}; static inline __u32 ino_t_to_u32(ino_t ino) { @@ -188,7 +235,7 @@ static inline void fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src) { dst->fh_size = src->fh_size; - memcpy(&dst->fh_base, &src->fh_base, src->fh_size); + memcpy(&dst->fh_raw, &src->fh_raw, src->fh_size); } static __inline__ struct svc_fh * @@ -203,7 +250,7 @@ static inline bool fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) { if (fh1->fh_size != fh2->fh_size) return false; - if (memcmp(fh1->fh_base.fh_pad, fh2->fh_base.fh_pad, fh1->fh_size) != 0) + if (memcmp(fh1->fh_raw, fh2->fh_raw, fh1->fh_size) != 0) return false; return true; } @@ -227,7 +274,7 @@ static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2) */ static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) { - return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size); + return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_raw, fh->fh_size); } #else static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index a06c05fe3b42..082449c7d0db 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -64,7 +64,7 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp) if (!p) return false; fh_init(fhp, NFS_FHSIZE); - memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE); + memcpy(&fhp->fh_handle.fh_raw, p, NFS_FHSIZE); fhp->fh_handle.fh_size = NFS_FHSIZE; return true; @@ -78,7 +78,7 @@ svcxdr_encode_fhandle(struct xdr_stream *xdr, const struct svc_fh *fhp) p = xdr_reserve_space(xdr, NFS_FHSIZE); if (!p) return false; - memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE); + memcpy(p, &fhp->fh_handle.fh_raw, NFS_FHSIZE); return true; } diff --git a/include/uapi/linux/nfsd/nfsfh.h b/include/uapi/linux/nfsd/nfsfh.h deleted file mode 100644 index 427294dd56a1..000000000000 --- a/include/uapi/linux/nfsd/nfsfh.h +++ /dev/null @@ -1,116 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * This file describes the layout of the file handles as passed - * over the wire. - * - * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> - */ - -#ifndef _UAPI_LINUX_NFSD_FH_H -#define _UAPI_LINUX_NFSD_FH_H - -#include <linux/types.h> -#include <linux/nfs.h> -#include <linux/nfs2.h> -#include <linux/nfs3.h> -#include <linux/nfs4.h> - -/* - * This is the old "dentry style" Linux NFSv2 file handle. - * - * The xino and xdev fields are currently used to transport the - * ino/dev of the exported inode. - */ -struct nfs_fhbase_old { - __u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */ - __u32 fb_ino; /* our inode number */ - __u32 fb_dirino; /* dir inode number, 0 for directories */ - __u32 fb_dev; /* our device */ - __u32 fb_xdev; - __u32 fb_xino; - __u32 fb_generation; -}; - -/* - * This is the new flexible, extensible style NFSv2/v3/v4 file handle. - * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000 - * - * The file handle starts with a sequence of four-byte words. - * The first word contains a version number (1) and three descriptor bytes - * that tell how the remaining 3 variable length fields should be handled. - * These three bytes are auth_type, fsid_type and fileid_type. - * - * All four-byte values are in host-byte-order. - * - * The auth_type field is deprecated and must be set to 0. - * - * The fsid_type identifies how the filesystem (or export point) is - * encoded. - * Current values: - * 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number - * NOTE: we cannot use the kdev_t device id value, because kdev_t.h - * says we mustn't. We must break it up and reassemble. - * 1 - 4 byte user specified identifier - * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED - * 3 - 4 byte device id, encoded for user-space, 4 byte inode number - * 4 - 4 byte inode number and 4 byte uuid - * 5 - 8 byte uuid - * 6 - 16 byte uuid - * 7 - 8 byte inode number and 16 byte uuid - * - * The fileid_type identified how the file within the filesystem is encoded. - * The values for this field are filesystem specific, exccept that - * filesystems must not use the values '0' or '0xff'. 'See enum fid_type' - * in include/linux/exportfs.h for currently registered values. - */ -struct nfs_fhbase_new { - union { - struct { - __u8 fb_version_aux; /* == 1, even => nfs_fhbase_old */ - __u8 fb_auth_type_aux; - __u8 fb_fsid_type_aux; - __u8 fb_fileid_type_aux; - __u32 fb_auth[1]; - /* __u32 fb_fsid[0]; floating */ - /* __u32 fb_fileid[0]; floating */ - }; - struct { - __u8 fb_version; /* == 1, even => nfs_fhbase_old */ - __u8 fb_auth_type; - __u8 fb_fsid_type; - __u8 fb_fileid_type; - __u32 fb_auth_flex[]; /* flexible-array member */ - }; - }; -}; - -struct knfsd_fh { - unsigned int fh_size; /* significant for NFSv3. - * Points to the current size while building - * a new file handle - */ - union { - struct nfs_fhbase_old fh_old; - __u32 fh_pad[NFS4_FHSIZE/4]; - struct nfs_fhbase_new fh_new; - } fh_base; -}; - -#define ofh_dcookie fh_base.fh_old.fb_dcookie -#define ofh_ino fh_base.fh_old.fb_ino -#define ofh_dirino fh_base.fh_old.fb_dirino -#define ofh_dev fh_base.fh_old.fb_dev -#define ofh_xdev fh_base.fh_old.fb_xdev -#define ofh_xino fh_base.fh_old.fb_xino -#define ofh_generation fh_base.fh_old.fb_generation - -#define fh_version fh_base.fh_new.fb_version -#define fh_fsid_type fh_base.fh_new.fb_fsid_type -#define fh_auth_type fh_base.fh_new.fb_auth_type -#define fh_fileid_type fh_base.fh_new.fb_fileid_type -#define fh_fsid fh_base.fh_new.fb_auth_flex - -/* Do not use, provided for userspace compatiblity. */ -#define fh_auth fh_base.fh_new.fb_auth - -#endif /* _UAPI_LINUX_NFSD_FH_H */
File-handles not in the "new" or "version 1" format have not been handed out for new mounts since Linux 2.4 which was released 20 years ago. I think it is safe to say that no such file handles are still in use, and that we can drop support for them. This patch also moves the nfsfh.h from the include/uapi directory into fs/nfsd. I can find no evidence of it being used anywhere outside the kernel. Certainly nfs-utils and wireshark do not use it. fh_base and fh_pad are occasionally used to refer to the whole filehandle. These are replaced with "fh_raw" which is hopefully more meaningful. Signed-off-by: NeilBrown <neilb@suse.de> --- I found https://www.spinics.net/lists/linux-nfs/msg43280.html "Re: [PATCH] nfsd: clean up fh_auth usage" from 2014 where moving nfsfh.h out of uapi was considered but not actioned. Christoph said he would "do some research if the uapi <linux/nfsd/*.h> headers are used anywhere at all". I can find no report on the result of that research. My own research turned up nothing. Thanks, NeilBrown fs/nfsd/lockd.c | 2 +- fs/nfsd/nfs3xdr.c | 4 +- fs/nfsd/nfs4callback.c | 2 +- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4state.c | 4 +- fs/nfsd/nfs4xdr.c | 4 +- fs/nfsd/nfsctl.c | 6 +- fs/nfsd/nfsfh.c | 177 +++++++++++--------------------- fs/nfsd/nfsfh.h | 55 +++++++++- fs/nfsd/nfsxdr.c | 4 +- include/uapi/linux/nfsd/nfsfh.h | 116 --------------------- 11 files changed, 126 insertions(+), 250 deletions(-) delete mode 100644 include/uapi/linux/nfsd/nfsfh.h