svn commit: r350884 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Mon Aug 12 05:25:42 UTC 2019
Author: rmacklem
Date: Mon Aug 12 05:25:40 2019
New Revision: 350884
URL: https://svnweb.freebsd.org/changeset/base/350884
Log:
Add support for the Seek operation to the NFSv4.2 client and server.
Modified:
projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c
projects/nfsv42/sys/fs/nfs/nfs_var.h
projects/nfsv42/sys/fs/nfs/nfsport.h
projects/nfsv42/sys/fs/nfs/nfsproto.h
projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c
projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c
projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c
projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c
Modified: projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Mon Aug 12 05:25:40 2019 (r350884)
@@ -177,7 +177,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Offload Cancel */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Offload Status */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Read Plus */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Seek */
+ { 0, 1, 0, 0, LK_SHARED, 1, 0 }, /* Seek */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Write Same */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Clone */
};
@@ -206,7 +206,7 @@ static struct nfsrv_lughash *nfsgroupnamehash;
*/
static int nfs_bigreply[NFSV42_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
/* local functions */
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
@@ -283,6 +283,7 @@ static struct {
{ NFSV4OP_IOADVISE, 1, "Advise", 6, },
{ NFSV4OP_ALLOCATE, 2, "Allocate", 8, },
{ NFSV4OP_SAVEFH, 5, "Copy", 4, },
+ { NFSV4OP_SEEK, 2, "Seek", 4, },
};
/*
@@ -291,7 +292,7 @@ static struct {
static int nfs_bigrequest[NFSV42_NPROCS] = {
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
Modified: projects/nfsv42/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_var.h Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfs/nfs_var.h Mon Aug 12 05:25:40 2019 (r350884)
@@ -281,6 +281,8 @@ int nfsrvd_allocate(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
int nfsrvd_copy_file_range(struct nfsrv_descript *, int,
vnode_t, vnode_t, struct nfsexstuff *, struct nfsexstuff *);
+int nfsrvd_seek(struct nfsrv_descript *, int,
+ vnode_t, struct nfsexstuff *);
int nfsrvd_notsupp(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
@@ -540,6 +542,8 @@ int nfsrpc_allocate(vnode_t, off_t, off_t, struct nfsv
int nfsrpc_copy_file_range(vnode_t, off_t *, vnode_t, off_t *, size_t *,
unsigned int, int *, struct nfsvattr *, int *, struct nfsvattr *,
struct ucred *, bool, bool *);
+int nfsrpc_seek(vnode_t, off_t *, bool *, int, struct ucred *,
+ struct nfsvattr *, int *);
/* nfs_clstate.c */
int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int,
Modified: projects/nfsv42/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsport.h Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfs/nfsport.h Mon Aug 12 05:25:40 2019 (r350884)
@@ -397,11 +397,12 @@
#define NFSPROC_IOADVISE 56
#define NFSPROC_ALLOCATE 57
#define NFSPROC_COPY 58
+#define NFSPROC_SEEK 59
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 59
+#define NFSV42_NPROCS 60
#endif /* NFS_V3NPROCS */
@@ -430,7 +431,7 @@ struct nfsstatsv1 {
uint64_t readlink_bios;
uint64_t biocache_readdirs;
uint64_t readdir_bios;
- uint64_t rpccnt[NFSV42_NPROCS + 10];
+ uint64_t rpccnt[NFSV42_NPROCS + 9];
uint64_t rpcretries;
uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS];
uint64_t srvrpc_errs;
Modified: projects/nfsv42/sys/fs/nfs/nfsproto.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsproto.h Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfs/nfsproto.h Mon Aug 12 05:25:40 2019 (r350884)
@@ -381,11 +381,12 @@
#define NFSPROC_IOADVISE 56
#define NFSPROC_ALLOCATE 57
#define NFSPROC_COPY 58
+#define NFSPROC_SEEK 59
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 59
+#define NFSV42_NPROCS 60
#endif /* NFS_V3NPROCS */
@@ -1477,5 +1478,9 @@ typedef struct nfsv4stateid nfsv4stateid_t;
#define NFSV4LAYOUTRET_FILE 1
#define NFSV4LAYOUTRET_FSID 2
#define NFSV4LAYOUTRET_ALL 3
+
+/* Seek Contents. */
+#define NFSV4CONTENT_DATA 0
+#define NFSV4CONTENT_HOLE 1
#endif /* _NFS_NFSPROTO_H_ */
Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Mon Aug 12 05:25:40 2019 (r350884)
@@ -216,6 +216,8 @@ static int nfsrpc_layoutgetres(struct nfsmount *, vnod
static int nfsrpc_copyrpc(vnode_t, off_t, vnode_t, off_t, size_t *,
nfsv4stateid_t *, nfsv4stateid_t *, struct nfsvattr *, int *,
struct nfsvattr *, int *, bool, int *, struct ucred *, NFSPROC_T *);
+static int nfsrpc_seekrpc(vnode_t, off_t *, nfsv4stateid_t *, bool *,
+ int, struct nfsvattr *, int *, struct ucred *);
int nfs_pnfsio(task_fn_t *, void *);
@@ -8139,6 +8141,100 @@ nfsrpc_copyrpc(vnode_t invp, off_t inoff, vnode_t outv
}
if (error == 0)
error = nd->nd_repstat;
+nfsmout:
+ mbuf_freem(nd->nd_mrep);
+ return (error);
+}
+
+/*
+ * Seek operation.
+ */
+APPLESTATIC int
+nfsrpc_seek(vnode_t vp, off_t *offp, bool *eofp, int content,
+ struct ucred *cred, struct nfsvattr *nap, int *attrflagp)
+{
+ int error, expireret = 0, retrycnt;
+ u_int32_t clidrev = 0;
+ struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
+ struct nfsnode *np = VTONFS(vp);
+ struct nfsfh *nfhp = NULL;
+ nfsv4stateid_t stateid;
+ void *lckp;
+
+ if (nmp->nm_clp != NULL)
+ clidrev = nmp->nm_clp->nfsc_clientidrev;
+ nfhp = np->n_fhp;
+ retrycnt = 0;
+ do {
+ lckp = NULL;
+ nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
+ NFSV4OPEN_ACCESSREAD, 0, cred, curthread, &stateid, &lckp);
+ error = nfsrpc_seekrpc(vp, offp, &stateid, eofp, content,
+ nap, attrflagp, cred);
+ if (error == NFSERR_STALESTATEID)
+ nfscl_initiate_recovery(nmp->nm_clp);
+ if (lckp != NULL)
+ nfscl_lockderef(lckp);
+ if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
+ error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+ error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
+ (void) nfs_catnap(PZERO, error, "nfs_seek");
+ } else if ((error == NFSERR_EXPIRED ||
+ error == NFSERR_BADSTATEID) && clidrev != 0) {
+ expireret = nfscl_hasexpired(nmp->nm_clp, clidrev,
+ curthread);
+ }
+ retrycnt++;
+ } while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
+ error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+ error == NFSERR_BADSESSION ||
+ (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
+ ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
+ expireret == 0 && clidrev != 0 && retrycnt < 4) ||
+ (error == NFSERR_OPENMODE && retrycnt < 4));
+ if (error && retrycnt >= 4)
+ error = EIO;
+ return (error);
+}
+
+/*
+ * The seek RPC.
+ */
+static int
+nfsrpc_seekrpc(vnode_t vp, off_t *offp, nfsv4stateid_t *stateidp, bool *eofp,
+ int content, struct nfsvattr *nap, int *attrflagp, struct ucred *cred)
+{
+ uint32_t *tl;
+ int error;
+ struct nfsrv_descript nfsd;
+ struct nfsrv_descript *nd = &nfsd;
+ nfsattrbit_t attrbits;
+
+ *attrflagp = 0;
+ NFSCL_REQSTART(nd, NFSPROC_SEEK, vp);
+ nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
+ NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
+ txdr_hyper(*offp, tl); tl += 2;
+ *tl++ = txdr_unsigned(content);
+ *tl = txdr_unsigned(NFSV4OP_GETATTR);
+ NFSGETATTR_ATTRBIT(&attrbits);
+ nfsrv_putattrbit(nd, &attrbits);
+ error = nfscl_request(nd, vp, curthread, cred, NULL);
+ if (error != 0)
+ return (error);
+ if (nd->nd_repstat == 0) {
+ NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED + NFSX_HYPER);
+ if (*tl++ == newnfs_true)
+ *eofp = true;
+ else
+ *eofp = false;
+ *offp = fxdr_hyper(tl);
+ /* Just skip over Getattr op status. */
+ error = nfsm_loadattr(nd, nap);
+ if (error == 0)
+ *attrflagp = 1;
+ }
+ error = nd->nd_repstat;
nfsmout:
mbuf_freem(nd->nd_mrep);
return (error);
Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Mon Aug 12 05:25:40 2019 (r350884)
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/bio.h>
#include <sys/buf.h>
+#include <sys/filio.h>
#include <sys/jail.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -145,6 +146,7 @@ static vop_setacl_t nfs_setacl;
static vop_advise_t nfs_advise;
static vop_allocate_t nfs_allocate;
static vop_copy_file_range_t nfs_copy_file_range;
+static vop_ioctl_t nfs_ioctl;
/*
* Global vfs data structures for nfs
@@ -185,6 +187,7 @@ static struct vop_vector newnfs_vnodeops_nosig = {
.vop_advise = nfs_advise,
.vop_allocate = nfs_allocate,
.vop_copy_file_range = nfs_copy_file_range,
+ .vop_ioctl = nfs_ioctl,
};
static int
@@ -3678,6 +3681,67 @@ nfs_copy_file_range(struct vop_copy_file_range_args *a
if (error != 0)
error = nfscl_maperr(curthread, error, (uid_t)0, (gid_t)0);
+ return (error);
+}
+
+/*
+ * nfs ioctl call
+ */
+static int
+nfs_ioctl(struct vop_ioctl_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nfsvattr nfsva;
+ struct nfsmount *nmp;
+ int attrflag, content, error, ret;
+ bool eof;
+
+ if (vp->v_type != VREG)
+ return (ENOTTY);
+ nmp = VFSTONFS(vp->v_mount);
+ if (!NFSHASNFSV4(nmp) || nmp->nm_minorvers < NFSV42_MINORVERSION) {
+#ifdef notyet
+ error = vop_stdioctl(ap);
+#else
+ error = ENOTTY;
+#endif
+ return (error);
+ }
+
+ error = vn_lock(vp, LK_SHARED);
+ if (error != 0)
+ return (EBADF);
+
+ /* Do the actual NFSv4.2 RPC. */
+ switch (ap->a_command) {
+ case FIOSEEKDATA:
+ content = NFSV4CONTENT_DATA;
+ break;
+ case FIOSEEKHOLE:
+ content = NFSV4CONTENT_HOLE;
+ break;
+ default:
+ return (ENOTTY);
+ }
+ attrflag = 0;
+ if (*((off_t *)ap->a_data) >= VTONFS(vp)->n_size)
+ error = ENXIO;
+ else {
+ error = nfsrpc_seek(vp, (off_t *)ap->a_data, &eof, content,
+ ap->a_cred, &nfsva, &attrflag);
+ /* If at eof for FIOSEEKDATA, return ENXIO. */
+ if (eof && error == 0 && content == NFSV4CONTENT_DATA)
+ error = ENXIO;
+ }
+ if (attrflag != 0) {
+ ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
+ if (error == 0 && ret != 0)
+ error = ret;
+ }
+ NFSVOPUNLOCK(vp, 0);
+
+ if (error != 0)
+ error = ENXIO;
return (error);
}
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Mon Aug 12 05:25:40 2019 (r350884)
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#ifndef APPLEKEXT
#include <fs/nfs/nfsport.h>
+#include <sys/filio.h>
/* Global vars */
extern u_int32_t newnfs_false, newnfs_true;
@@ -5190,7 +5191,7 @@ nfsmout:
* nfs copy service
*/
APPLESTATIC int
-nfsrvd_copy_file_range(struct nfsrv_descript *nd, int isdgram,
+nfsrvd_copy_file_range(struct nfsrv_descript *nd, __unused int isdgram,
vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
{
uint32_t *tl;
@@ -5226,7 +5227,7 @@ nfsrvd_copy_file_range(struct nfsrv_descript *nd, int
instp->ls_ownerlen = 0;
instp->ls_op = NULL;
instp->ls_uid = nd->nd_cred->cr_uid;
- instp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
+ instp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
clientid.lval[0] = instp->ls_stateid.other[0] = *tl++;
clientid.lval[1] = instp->ls_stateid.other[1] = *tl++;
if ((nd->nd_flag & ND_IMPLIEDCLID) != 0)
@@ -5237,7 +5238,7 @@ nfsrvd_copy_file_range(struct nfsrv_descript *nd, int
outstp->ls_ownerlen = 0;
outstp->ls_op = NULL;
outstp->ls_uid = nd->nd_cred->cr_uid;
- outstp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
+ outstp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
outstp->ls_stateid.other[0] = *tl++;
outstp->ls_stateid.other[1] = *tl++;
outstp->ls_stateid.other[2] = *tl++;
@@ -5398,6 +5399,98 @@ out:
nfsmout:
vput(vp);
vrele(tovp);
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfs seek service
+ */
+APPLESTATIC int
+nfsrvd_seek(struct nfsrv_descript *nd, __unused int isdgram,
+ vnode_t vp, struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ struct nfsvattr at;
+ int content, error = 0;
+ off_t off;
+ u_long cmd;
+ nfsattrbit_t attrbits;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ if (nfsrv_devidcnt > 0) {
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + NFSX_HYPER + NFSX_UNSIGNED);
+ /* Ignore the stateid for now. */
+ tl += (NFSX_STATEID / NFSX_UNSIGNED);
+ off = fxdr_hyper(tl); tl += 2;
+ content = fxdr_unsigned(int, *tl);
+ if (content == NFSV4CONTENT_DATA)
+ cmd = FIOSEEKDATA;
+ else if (content == NFSV4CONTENT_HOLE)
+ cmd = FIOSEEKHOLE;
+ else
+ nd->nd_repstat = NFSERR_BADXDR;
+ if (nd->nd_repstat == 0 && (nd->nd_flag & ND_DSSERVER) != 0)
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ if (nd->nd_repstat == 0 && vnode_vtype(vp) == VDIR)
+ nd->nd_repstat = NFSERR_ISDIR;
+ if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
+ nd->nd_repstat = NFSERR_WRONGTYPE;
+ if (nd->nd_repstat == 0 && off < 0)
+ nd->nd_repstat = NFSERR_NXIO;
+ if (nd->nd_repstat == 0) {
+ /* Check permissions for the input file. */
+ NFSZERO_ATTRBIT(&attrbits);
+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
+ nd->nd_repstat = nfsvno_getattr(vp, &at, nd, curthread, 1,
+ &attrbits);
+ }
+ if (nd->nd_repstat == 0 && off > at.na_size)
+ nd->nd_repstat = NFSERR_NXIO;
+ if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
+ NFSVNO_EXSTRICTACCESS(exp)))
+ nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp,
+ curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
+ NULL);
+ if (nd->nd_repstat != 0)
+ goto nfsmout;
+
+ if (off < at.na_size) {
+ NFSVOPUNLOCK(vp, 0);
+ nd->nd_repstat = VOP_IOCTL(vp, cmd, &off, 0, nd->nd_cred,
+ curthread);
+ vrele(vp);
+ if (nd->nd_repstat == ENOTTY || nd->nd_repstat == ENXIO) {
+ /*
+ * For FIOSEEKHOLE, find the "virtual hole" at EOF.
+ * For FIOSEEKDATA, just return the offset in the
+ * request unless the error is ENXIO.
+ */
+ if (cmd == FIOSEEKHOLE || error == ENXIO)
+ off = at.na_size;
+ nd->nd_repstat = 0;
+ }
+ } else
+ vput(vp);
+ if (nd->nd_repstat == 0) {
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
+ if (off == at.na_size)
+ *tl++ = newnfs_true;
+ else
+ *tl++ = newnfs_false;
+ txdr_hyper(off, tl);
+ }
+ NFSEXITCODE2(error, nd);
+ return (error);
+nfsmout:
+ vput(vp);
NFSEXITCODE2(error, nd);
return (error);
}
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Mon Aug 12 03:03:56 2019 (r350883)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Mon Aug 12 05:25:40 2019 (r350884)
@@ -206,7 +206,7 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript
nfsrvd_notsupp,
nfsrvd_notsupp,
nfsrvd_notsupp,
- nfsrvd_notsupp,
+ nfsrvd_seek,
nfsrvd_notsupp,
nfsrvd_notsupp,
};
More information about the svn-src-projects
mailing list