NFSD: drop support for ancient filehandles

[ Upstream commit c645a883df ]

Filehandles 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.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
NeilBrown 2021-09-02 11:15:29 +10:00 коммит произвёл Greg Kroah-Hartman
Родитель f829bb3a06
Коммит ed0815c8b7
2 изменённых файлов: 51 добавлений и 137 удалений

Просмотреть файл

@ -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) static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
{ {
struct knfsd_fh *fh = &fhp->fh_handle; struct knfsd_fh *fh = &fhp->fh_handle;
struct fid *fid = NULL, sfid; struct fid *fid = NULL;
struct svc_export *exp; struct svc_export *exp;
struct dentry *dentry; struct dentry *dentry;
int fileid_type; int fileid_type;
int data_left = fh->fh_size/4; int data_left = fh->fh_size/4;
int len;
__be32 error; __be32 error;
error = nfserr_stale; 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) if (rqstp->rq_vers == 4 && fh->fh_size == 0)
return nfserr_nofilehandle; return nfserr_nofilehandle;
if (fh->fh_version == 1) { if (fh->fh_version != 1)
int len; return error;
if (--data_left < 0) if (--data_left < 0)
return error; return error;
if (fh->fh_auth_type != 0) if (fh->fh_auth_type != 0)
return error; return error;
len = key_len(fh->fh_fsid_type) / 4; len = key_len(fh->fh_fsid_type) / 4;
if (len == 0) if (len == 0)
return error; return error;
if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
/* deprecated, convert to type 3 */ /* deprecated, convert to type 3 */
len = key_len(FSID_ENCODE_DEV)/4; len = key_len(FSID_ENCODE_DEV)/4;
fh->fh_fsid_type = FSID_ENCODE_DEV; fh->fh_fsid_type = FSID_ENCODE_DEV;
/* /*
* struct knfsd_fh uses host-endian fields, which are * struct knfsd_fh uses host-endian fields, which are
* sometimes used to hold net-endian values. This * sometimes used to hold net-endian values. This
* confuses sparse, so we must use __force here to * confuses sparse, so we must use __force here to
* keep it from complaining. * keep it from complaining.
*/ */
fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]), fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]),
ntohl((__force __be32)fh->fh_fsid[1]))); ntohl((__force __be32)fh->fh_fsid[1])));
fh->fh_fsid[1] = fh->fh_fsid[2]; 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);
} }
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; error = nfserr_stale;
if (IS_ERR(exp)) { 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) if (rqstp->rq_vers > 2)
error = nfserr_badhandle; error = nfserr_badhandle;
if (fh->fh_version != 1) { fileid_type = fh->fh_fileid_type;
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;
if (fileid_type == FILEID_ROOT) if (fileid_type == FILEID_ROOT)
dentry = dget(exp->ex_path.dentry); 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) static bool is_root_export(struct svc_export *exp)
{ {
return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root; return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root;
@ -562,9 +525,6 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
/* ref_fh is a reference file handle. /* ref_fh is a reference file handle.
* if it is non-null and for the same filesystem, then we should compose * if it is non-null and for the same filesystem, then we should compose
* a filehandle which is of the same version, where possible. * a filehandle which is of the same version, where possible.
* Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
* Then create a 32byte filehandle using nfs_fhbase_old
*
*/ */
struct inode * inode = d_inode(dentry); struct inode * inode = d_inode(dentry);
@ -600,35 +560,21 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
fhp->fh_dentry = dget(dentry); /* our internal copy */ fhp->fh_dentry = dget(dentry); /* our internal copy */
fhp->fh_export = exp_get(exp); fhp->fh_export = exp_get(exp);
if (fhp->fh_handle.fh_version == 0xca) { fhp->fh_handle.fh_size =
/* old style filehandle please */ key_len(fhp->fh_handle.fh_fsid_type) + 4;
memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); fhp->fh_handle.fh_auth_type = 0;
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, mk_fsid(fhp->fh_handle.fh_fsid_type,
fhp->fh_handle.fh_fsid, fhp->fh_handle.fh_fsid,
ex_dev, ex_dev,
d_inode(exp->ex_path.dentry)->i_ino, d_inode(exp->ex_path.dentry)->i_ino,
exp->ex_fsid, exp->ex_uuid); exp->ex_fsid, exp->ex_uuid);
if (inode) if (inode)
_fh_update(fhp, exp, dentry); _fh_update(fhp, exp, dentry);
if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) { if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) {
fh_put(fhp); fh_put(fhp);
return nfserr_opnotsupp; return nfserr_opnotsupp;
}
} }
return 0; return 0;
@ -649,16 +595,12 @@ fh_update(struct svc_fh *fhp)
dentry = fhp->fh_dentry; dentry = fhp->fh_dentry;
if (d_really_is_negative(dentry)) if (d_really_is_negative(dentry))
goto out_negative; goto out_negative;
if (fhp->fh_handle.fh_version != 1) { if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); return 0;
} else {
if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
return 0;
_fh_update(fhp, fhp->fh_export, dentry); _fh_update(fhp, fhp->fh_export, dentry);
if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
return nfserr_opnotsupp; return nfserr_opnotsupp;
}
return 0; return 0;
out_bad: out_bad:
printk(KERN_ERR "fh_update: fh not verified!\n"); printk(KERN_ERR "fh_update: fh not verified!\n");

Просмотреть файл

@ -14,26 +14,7 @@
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include <linux/nfs4.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.
*
* The file handle starts with a sequence of four-byte words. * The file handle starts with a sequence of four-byte words.
* The first word contains a version number (1) and three descriptor bytes * The first word contains a version number (1) and three descriptor bytes
* that tell how the remaining 3 variable length fields should be handled. * that tell how the remaining 3 variable length fields should be handled.
@ -57,7 +38,7 @@ struct nfs_fhbase_old {
* 6 - 16 byte uuid * 6 - 16 byte uuid
* 7 - 8 byte inode number and 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 fileid_type identifies how the file within the filesystem is encoded.
* The values for this field are filesystem specific, exccept that * The values for this field are filesystem specific, exccept that
* filesystems must not use the values '0' or '0xff'. 'See enum fid_type' * filesystems must not use the values '0' or '0xff'. 'See enum fid_type'
* in include/linux/exportfs.h for currently registered values. * in include/linux/exportfs.h for currently registered values.
@ -65,7 +46,7 @@ struct nfs_fhbase_old {
struct nfs_fhbase_new { struct nfs_fhbase_new {
union { union {
struct { struct {
u8 fb_version_aux; /* == 1, even => nfs_fhbase_old */ u8 fb_version_aux; /* == 1 */
u8 fb_auth_type_aux; u8 fb_auth_type_aux;
u8 fb_fsid_type_aux; u8 fb_fsid_type_aux;
u8 fb_fileid_type_aux; u8 fb_fileid_type_aux;
@ -74,7 +55,7 @@ struct nfs_fhbase_new {
/* u32 fb_fileid[0]; floating */ /* u32 fb_fileid[0]; floating */
}; };
struct { struct {
u8 fb_version; /* == 1, even => nfs_fhbase_old */ u8 fb_version; /* == 1 */
u8 fb_auth_type; u8 fb_auth_type;
u8 fb_fsid_type; u8 fb_fsid_type;
u8 fb_fileid_type; u8 fb_fileid_type;
@ -89,20 +70,11 @@ struct knfsd_fh {
* a new file handle * a new file handle
*/ */
union { union {
struct nfs_fhbase_old fh_old;
u32 fh_pad[NFS4_FHSIZE/4]; u32 fh_pad[NFS4_FHSIZE/4];
struct nfs_fhbase_new fh_new; struct nfs_fhbase_new fh_new;
} fh_base; } 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_version fh_base.fh_new.fb_version
#define fh_fsid_type fh_base.fh_new.fb_fsid_type #define fh_fsid_type fh_base.fh_new.fb_fsid_type
#define fh_auth_type fh_base.fh_new.fb_auth_type #define fh_auth_type fh_base.fh_new.fb_auth_type