From owner-svn-src-all@freebsd.org Thu Dec 12 23:22:57 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 53ADE1DCFF2; Thu, 12 Dec 2019 23:22:57 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47YqbP2Fxdz4F6B; Thu, 12 Dec 2019 23:22:57 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 47D82332D; Thu, 12 Dec 2019 23:22:57 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xBCNMv1D040927; Thu, 12 Dec 2019 23:22:57 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xBCNMt80040917; Thu, 12 Dec 2019 23:22:55 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201912122322.xBCNMt80040917@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Thu, 12 Dec 2019 23:22:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r355677 - in head/sys/fs: nfs nfsclient nfsserver X-SVN-Group: head X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in head/sys/fs: nfs nfsclient nfsserver X-SVN-Commit-Revision: 355677 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Dec 2019 23:22:57 -0000 Author: rmacklem Date: Thu Dec 12 23:22:55 2019 New Revision: 355677 URL: https://svnweb.freebsd.org/changeset/base/355677 Log: Add support for NFSv4.2 to the NFS client and server. This patch adds support for NFSv4.2 (RFC-7862) and Extended Attributes (RFC-8276) to the NFS client and server. NFSv4.2 is comprised of several optional features that can be supported in addition to NFSv4.1. This patch adds the following optional features: - posix_fadvise(POSIX_FADV_WILLNEED/POSIX_FADV_DONTNEED) - posix_fallocate() - intra server file range copying via the copy_file_range(2) syscall --> Avoiding data tranfer over the wire to/from the NFS client. - lseek(SEEK_DATA/SEEK_HOLE) - Extended attribute syscalls for "user" namespace attributes as defined by RFC-8276. Although this patch is fairly large, it should not affect support for the other versions of NFS. However it does add two new sysctls that allow a sysadmin to limit which minor versions of NFSv4 a server supports, allowing a sysadmin to disable NFSv4.2. Unfortunately, when the NFS stats structure was last revised, it was assumed that there would be no additional operations added beyond what was specified in RFC-7862. However RFC-8276 did add additional operations, forcing the NFS stats structure to revised again. It now has extra unused entries in all arrays, so that future extensions to NFSv4.2 can be accomodated without revising this structure again. A future commit will update nfsstat(1) to report counts for the new NFSv4.2 specific operations/procedures. This patch affects the internal interface between the nfscommon, nfscl and nfsd modules and, as such, they all must be upgraded simultaneously. I will do a version bump (although arguably not needed), due to this. This code has survived a "make universe" but has not been built with a recent GCC. If you encounter build problems, please email me. Relnotes: yes Modified: head/sys/fs/nfs/nfs.h head/sys/fs/nfs/nfs_commonport.c head/sys/fs/nfs/nfs_commonsubs.c head/sys/fs/nfs/nfs_var.h head/sys/fs/nfs/nfsclstate.h head/sys/fs/nfs/nfsport.h head/sys/fs/nfs/nfsproto.h head/sys/fs/nfsclient/nfs_clrpcops.c head/sys/fs/nfsclient/nfs_clstate.c head/sys/fs/nfsclient/nfs_clvfsops.c head/sys/fs/nfsclient/nfs_clvnops.c head/sys/fs/nfsclient/nfsmount.h head/sys/fs/nfsserver/nfs_nfsdkrpc.c head/sys/fs/nfsserver/nfs_nfsdport.c head/sys/fs/nfsserver/nfs_nfsdserv.c head/sys/fs/nfsserver/nfs_nfsdsocket.c head/sys/fs/nfsserver/nfs_nfsdstate.c head/sys/fs/nfsserver/nfs_nfsdsubs.c Modified: head/sys/fs/nfs/nfs.h ============================================================================== --- head/sys/fs/nfs/nfs.h Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfs/nfs.h Thu Dec 12 23:22:55 2019 (r355677) @@ -668,6 +668,8 @@ struct nfsrv_descript { uint32_t *nd_sequence; /* Sequence Op. ptr */ nfsv4stateid_t nd_curstateid; /* Current StateID */ nfsv4stateid_t nd_savedcurstateid; /* Saved Current StateID */ + uint32_t nd_maxreq; /* Max. request (session). */ + uint32_t nd_maxresp; /* Max. reply (session). */ }; #define nd_princlen nd_gssnamelen Modified: head/sys/fs/nfs/nfs_commonport.c ============================================================================== --- head/sys/fs/nfs/nfs_commonport.c Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfs/nfs_commonport.c Thu Dec 12 23:22:55 2019 (r355677) @@ -80,6 +80,7 @@ int nfs_pnfsio(task_fn_t *, void *); static int nfs_realign_test; static int nfs_realign_count; static struct ext_nfsstats oldnfsstats; +static struct nfsstatsov1 nfsstatsov1; SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem"); SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, @@ -580,11 +581,143 @@ nfssvc_call(struct thread *p, struct nfssvc_args *uap, } else { error = copyin(uap->argp, &nfsstatver, sizeof(nfsstatver)); - if (error == 0 && nfsstatver.vers != NFSSTATS_V1) - error = EPERM; - if (error == 0) - error = copyout(&nfsstatsv1, uap->argp, - sizeof (nfsstatsv1)); + if (error == 0) { + if (nfsstatver.vers == NFSSTATS_OV1) { + /* Copy nfsstatsv1 to nfsstatsov1. */ + nfsstatsov1.attrcache_hits = + nfsstatsv1.attrcache_hits; + nfsstatsov1.attrcache_misses = + nfsstatsv1.attrcache_misses; + nfsstatsov1.lookupcache_hits = + nfsstatsv1.lookupcache_hits; + nfsstatsov1.lookupcache_misses = + nfsstatsv1.lookupcache_misses; + nfsstatsov1.direofcache_hits = + nfsstatsv1.direofcache_hits; + nfsstatsov1.direofcache_misses = + nfsstatsv1.direofcache_misses; + nfsstatsov1.accesscache_hits = + nfsstatsv1.accesscache_hits; + nfsstatsov1.accesscache_misses = + nfsstatsv1.accesscache_misses; + nfsstatsov1.biocache_reads = + nfsstatsv1.biocache_reads; + nfsstatsov1.read_bios = + nfsstatsv1.read_bios; + nfsstatsov1.read_physios = + nfsstatsv1.read_physios; + nfsstatsov1.biocache_writes = + nfsstatsv1.biocache_writes; + nfsstatsov1.write_bios = + nfsstatsv1.write_bios; + nfsstatsov1.write_physios = + nfsstatsv1.write_physios; + nfsstatsov1.biocache_readlinks = + nfsstatsv1.biocache_readlinks; + nfsstatsov1.readlink_bios = + nfsstatsv1.readlink_bios; + nfsstatsov1.biocache_readdirs = + nfsstatsv1.biocache_readdirs; + nfsstatsov1.readdir_bios = + nfsstatsv1.readdir_bios; + for (i = 0; i < NFSV42_NPROCS; i++) + nfsstatsov1.rpccnt[i] = + nfsstatsv1.rpccnt[i]; + nfsstatsov1.rpcretries = + nfsstatsv1.rpcretries; + for (i = 0; i < NFSV42_PURENOPS; i++) + nfsstatsov1.srvrpccnt[i] = + nfsstatsv1.srvrpccnt[i]; + for (i = NFSV42_NOPS, + j = NFSV42_PURENOPS; + i < NFSV42_NOPS + NFSV4OP_FAKENOPS; + i++, j++) + nfsstatsov1.srvrpccnt[j] = + nfsstatsv1.srvrpccnt[i]; + nfsstatsov1.srvrpc_errs = + nfsstatsv1.srvrpc_errs; + nfsstatsov1.srv_errs = + nfsstatsv1.srv_errs; + nfsstatsov1.rpcrequests = + nfsstatsv1.rpcrequests; + nfsstatsov1.rpctimeouts = + nfsstatsv1.rpctimeouts; + nfsstatsov1.rpcunexpected = + nfsstatsv1.rpcunexpected; + nfsstatsov1.rpcinvalid = + nfsstatsv1.rpcinvalid; + nfsstatsov1.srvcache_inproghits = + nfsstatsv1.srvcache_inproghits; + nfsstatsov1.srvcache_idemdonehits = + nfsstatsv1.srvcache_idemdonehits; + nfsstatsov1.srvcache_nonidemdonehits = + nfsstatsv1.srvcache_nonidemdonehits; + nfsstatsov1.srvcache_misses = + nfsstatsv1.srvcache_misses; + nfsstatsov1.srvcache_tcppeak = + nfsstatsv1.srvcache_tcppeak; + nfsstatsov1.srvcache_size = + nfsstatsv1.srvcache_size; + nfsstatsov1.srvclients = + nfsstatsv1.srvclients; + nfsstatsov1.srvopenowners = + nfsstatsv1.srvopenowners; + nfsstatsov1.srvopens = + nfsstatsv1.srvopens; + nfsstatsov1.srvlockowners = + nfsstatsv1.srvlockowners; + nfsstatsov1.srvlocks = + nfsstatsv1.srvlocks; + nfsstatsov1.srvdelegates = + nfsstatsv1.srvdelegates; + for (i = 0; i < NFSV42_CBNOPS; i++) + nfsstatsov1.cbrpccnt[i] = + nfsstatsv1.cbrpccnt[i]; + nfsstatsov1.clopenowners = + nfsstatsv1.clopenowners; + nfsstatsov1.clopens = + nfsstatsv1.clopens; + nfsstatsov1.cllockowners = + nfsstatsv1.cllockowners; + nfsstatsov1.cllocks = + nfsstatsv1.cllocks; + nfsstatsov1.cldelegates = + nfsstatsv1.cldelegates; + nfsstatsov1.cllocalopenowners = + nfsstatsv1.cllocalopenowners; + nfsstatsov1.cllocalopens = + nfsstatsv1.cllocalopens; + nfsstatsov1.cllocallockowners = + nfsstatsv1.cllocallockowners; + nfsstatsov1.cllocallocks = + nfsstatsv1.cllocallocks; + nfsstatsov1.srvstartcnt = + nfsstatsv1.srvstartcnt; + nfsstatsov1.srvdonecnt = + nfsstatsv1.srvdonecnt; + for (i = NFSV42_NOPS, + j = NFSV42_PURENOPS; + i < NFSV42_NOPS + NFSV4OP_FAKENOPS; + i++, j++) { + nfsstatsov1.srvbytes[j] = + nfsstatsv1.srvbytes[i]; + nfsstatsov1.srvops[j] = + nfsstatsv1.srvops[i]; + nfsstatsov1.srvduration[j] = + nfsstatsv1.srvduration[i]; + } + nfsstatsov1.busyfrom = + nfsstatsv1.busyfrom; + nfsstatsov1.busyfrom = + nfsstatsv1.busyfrom; + error = copyout(&nfsstatsov1, uap->argp, + sizeof(nfsstatsov1)); + } else if (nfsstatver.vers != NFSSTATS_V1) + error = EPERM; + else + error = copyout(&nfsstatsv1, uap->argp, + sizeof(nfsstatsv1)); + } } if (error == 0) { if ((uap->flag & NFSSVC_ZEROCLTSTATS) != 0) { Modified: head/sys/fs/nfs/nfs_commonsubs.c ============================================================================== --- head/sys/fs/nfs/nfs_commonsubs.c Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfs/nfs_commonsubs.c Thu Dec 12 23:22:55 2019 (r355677) @@ -47,6 +47,8 @@ __FBSDID("$FreeBSD$"); #include +#include + #include /* @@ -91,6 +93,10 @@ int nfsrv_maxpnfsmirror = 1; SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsmirror, CTLFLAG_RD, &nfsrv_maxpnfsmirror, 0, "Mirror level for pNFS service"); +int nfs_maxcopyrange = 10 * 1024 * 1024; +SYSCTL_INT(_vfs_nfs, OID_AUTO, maxcopyrange, CTLFLAG_RW, + &nfs_maxcopyrange, 0, "Max size of a Copy so RPC times reasonable"); + /* * This array of structures indicates, for V4: * retfh - which of 3 types of calling args are used @@ -108,7 +114,7 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsmirror, CTLFLAG_RD, * non-idempotent Ops. * Define it here, since it is used by both the client and server. */ -struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS] = { +struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = { { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* undef */ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* undef */ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* undef */ @@ -168,6 +174,23 @@ struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS] = { { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Want Delegation */ { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Destroy ClientID */ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Reclaim Complete */ + { 0, 1, 1, 1, LK_EXCLUSIVE, 1, 0 }, /* Allocate */ + { 2, 1, 1, 0, LK_SHARED, 1, 0 }, /* Copy */ + { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Copy Notify */ + { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Deallocate */ + { 0, 1, 0, 0, LK_SHARED, 1, 0 }, /* IO Advise */ + { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Layout Error */ + { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Layout Stats */ + { 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, 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 */ + { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Getxattr */ + { 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Setxattr */ + { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Listxattrs */ + { 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Removexattr */ }; #endif /* !APPLEKEXT */ @@ -192,9 +215,10 @@ static struct nfsrv_lughash *nfsgroupnamehash; * marked 0 in this array, the code will still work, just not quite as * efficiently.) */ -static int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, +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, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 1 }; /* local functions */ static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep); @@ -211,7 +235,7 @@ static struct { int opcnt; const u_char *tag; int taglen; -} nfsv4_opmap[NFSV41_NPROCS] = { +} nfsv4_opmap[NFSV42_NPROCS] = { { 0, 1, "Null", 4 }, { NFSV4OP_GETATTR, 1, "Getattr", 7, }, { NFSV4OP_SETATTR, 2, "Setattr", 7, }, @@ -268,15 +292,24 @@ static struct { { NFSV4OP_COMMIT, 1, "CommitDS", 8, }, { NFSV4OP_OPEN, 3, "OpenLayoutGet", 13, }, { NFSV4OP_OPEN, 8, "CreateLayGet", 12, }, + { NFSV4OP_IOADVISE, 1, "Advise", 6, }, + { NFSV4OP_ALLOCATE, 2, "Allocate", 8, }, + { NFSV4OP_SAVEFH, 5, "Copy", 4, }, + { NFSV4OP_SEEK, 2, "Seek", 4, }, + { NFSV4OP_SEEK, 1, "SeekDS", 6, }, + { NFSV4OP_GETXATTR, 2, "Getxattr", 8, }, + { NFSV4OP_SETXATTR, 2, "Setxattr", 8, }, + { NFSV4OP_REMOVEXATTR, 2, "Rmxattr", 7, }, + { NFSV4OP_LISTXATTRS, 2, "Listxattr", 9, }, }; /* * NFS RPCS that have large request message size. */ -static int nfs_bigrequest[NFSV41_NPROCS] = { +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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; /* @@ -301,13 +334,17 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, nd->nd_flag = ND_NFSV4 | ND_NFSCL; if (minorvers == NFSV41_MINORVERSION) nd->nd_flag |= ND_NFSV41; + else if (minorvers == NFSV42_MINORVERSION) + nd->nd_flag |= (ND_NFSV41 | ND_NFSV42); } else if (vers == NFS_VER3) nd->nd_flag = ND_NFSV3 | ND_NFSCL; else { if (NFSHASNFSV4(nmp)) { nd->nd_flag = ND_NFSV4 | ND_NFSCL; - if (NFSHASNFSV4N(nmp)) + if (nmp->nm_minorvers == 1) nd->nd_flag |= ND_NFSV41; + else if (nmp->nm_minorvers == 2) + nd->nd_flag |= (ND_NFSV41 | ND_NFSV42); } else if (NFSHASNFSV3(nmp)) nd->nd_flag = ND_NFSV3 | ND_NFSCL; else @@ -356,7 +393,9 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag, nfsv4_opmap[procnum].taglen); NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); - if ((nd->nd_flag & ND_NFSV41) != 0) + if ((nd->nd_flag & ND_NFSV42) != 0) + *tl++ = txdr_unsigned(NFSV42_MINORVERSION); + else if ((nd->nd_flag & ND_NFSV41) != 0) *tl++ = txdr_unsigned(NFSV41_MINORVERSION); else *tl++ = txdr_unsigned(NFSV4_MINORVERSION); @@ -409,7 +448,7 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, } else { (void) nfsm_fhtom(nd, nfhp, fhlen, 0); } - if (procnum < NFSV41_NPROCS) + if (procnum < NFSV42_NPROCS) NFSINCRGLOBAL(nfsstatsv1.rpccnt[procnum]); } @@ -2449,6 +2488,8 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount struct nfsfsinfo fsinf; struct timespec temptime; NFSACL_T *aclp, *naclp = NULL; + size_t atsiz; + bool xattrsupp; #ifdef QUOTA struct dqblk dqb; uid_t savuid; @@ -2523,6 +2564,18 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount } } + /* Check to see if Extended Attributes are supported. */ + xattrsupp = false; + if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_XATTRSUPPORT)) { + if (NFSVOPLOCK(vp, LK_SHARED) == 0) { + error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, + "xxx", NULL, &atsiz, cred, p); + NFSVOPUNLOCK(vp, 0); + if (error != EOPNOTSUPP) + xattrsupp = true; + } + } + /* * Put out the attribute bitmap for the ones being filled in * and get the field for the number of attributes returned. @@ -2972,6 +3025,14 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *tl = txdr_unsigned(NFS_SRVMAXIO); retnum += NFSX_UNSIGNED; break; + case NFSATTRBIT_XATTRSUPPORT: + NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); + if (xattrsupp) + *tl = newnfs_true; + else + *tl = newnfs_false; + retnum += NFSX_UNSIGNED; + break; default: printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos); } @@ -4629,6 +4690,8 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_d error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq, sessionid); + nd->nd_maxreq = sep->nfsess_maxreq; + nd->nd_maxresp = sep->nfsess_maxresp; /* Build the Sequence arguments. */ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED); Modified: head/sys/fs/nfs/nfs_var.h ============================================================================== --- head/sys/fs/nfs/nfs_var.h Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfs/nfs_var.h Thu Dec 12 23:22:55 2019 (r355677) @@ -128,7 +128,8 @@ void nfsrv_setupstable(NFSPROC_T *); void nfsrv_updatestable(NFSPROC_T *); void nfsrv_writestable(u_char *, int, int, NFSPROC_T *); void nfsrv_throwawayopens(NFSPROC_T *); -int nfsrv_checkremove(vnode_t, int, NFSPROC_T *); +int nfsrv_checkremove(vnode_t, int, struct nfsrv_descript *, nfsquad_t, + NFSPROC_T *); void nfsd_recalldelegation(vnode_t, NFSPROC_T *); void nfsd_disabledelegation(vnode_t, NFSPROC_T *); int nfsrv_checksetattr(vnode_t, struct nfsrv_descript *, @@ -161,6 +162,7 @@ void nfsrv_freealllayoutsanddevids(void); void nfsrv_freefilelayouts(fhandle_t *); int nfsrv_deldsserver(int, char *, NFSPROC_T *); struct nfsdevice *nfsrv_deldsnmp(int, struct nfsmount *, NFSPROC_T *); +int nfsrv_delds(char *, NFSPROC_T *); int nfsrv_createdevids(struct nfsd_nfsd_args *, NFSPROC_T *); int nfsrv_checkdsattr(vnode_t, NFSPROC_T *); int nfsrv_copymr(vnode_t, vnode_t, vnode_t, struct nfsdevice *, @@ -268,8 +270,28 @@ int nfsrvd_layoutcommit(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); int nfsrvd_layoutreturn(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); +int nfsrvd_ioadvise(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); +int nfsrvd_layouterror(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); +int nfsrvd_layoutstats(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); int nfsrvd_teststateid(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); +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_getxattr(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); +int nfsrvd_setxattr(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); +int nfsrvd_rmxattr(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); +int nfsrvd_listxattr(struct nfsrv_descript *, int, + vnode_t, struct nfsexstuff *); int nfsrvd_notsupp(struct nfsrv_descript *, int, vnode_t, struct nfsexstuff *); @@ -501,10 +523,11 @@ int nfsrpc_delegreturn(struct nfscldeleg *, struct ucr int nfsrpc_getacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *, void *); int nfsrpc_setacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *, void *); int nfsrpc_exchangeid(struct nfsmount *, struct nfsclclient *, - struct nfssockreq *, uint32_t, struct nfsclds **, struct ucred *, + struct nfssockreq *, int, uint32_t, struct nfsclds **, struct ucred *, NFSPROC_T *); int nfsrpc_createsession(struct nfsmount *, struct nfsclsession *, - struct nfssockreq *, uint32_t, int, struct ucred *, NFSPROC_T *); + struct nfssockreq *, struct nfsclds *, uint32_t, int, struct ucred *, + NFSPROC_T *); int nfsrpc_destroysession(struct nfsmount *, struct nfsclclient *, struct ucred *, NFSPROC_T *); int nfsrpc_destroyclient(struct nfsmount *, struct nfsclclient *, @@ -518,11 +541,27 @@ int nfsrpc_layoutreturn(struct nfsmount *, uint8_t *, int, uint64_t, uint64_t, nfsv4stateid_t *, struct ucred *, NFSPROC_T *, uint32_t, uint32_t, char *); int nfsrpc_reclaimcomplete(struct nfsmount *, struct ucred *, NFSPROC_T *); +int nfsrpc_advise(vnode_t, off_t, uint64_t, int, struct ucred *, NFSPROC_T *); int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t, int, struct ucred *, NFSPROC_T *); int nfscl_findlayoutforio(struct nfscllayout *, uint64_t, uint32_t, struct nfsclflayout **); void nfscl_freenfsclds(struct nfsclds *); +int nfsrpc_allocate(vnode_t, off_t, off_t, struct nfsvattr *, int *, + struct ucred *, NFSPROC_T *, void *); +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 *); +int nfsrpc_getextattr(vnode_t, const char *, struct uio *, ssize_t *, + struct nfsvattr *, int *, struct ucred *, NFSPROC_T *); +int nfsrpc_setextattr(vnode_t, const char *, struct uio *, struct nfsvattr *, + int *, struct ucred *, NFSPROC_T *); +int nfsrpc_listextattr(vnode_t, uint64_t *, struct uio *, size_t *, bool *, + struct nfsvattr *, int *, struct ucred *, NFSPROC_T *); +int nfsrpc_rmextattr(vnode_t, const char *, struct nfsvattr *, int *, + struct ucred *, NFSPROC_T *); /* nfs_clstate.c */ int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int, @@ -644,8 +683,8 @@ int nfsvno_readlink(vnode_t, struct ucred *, NFSPROC_T mbuf_t *, int *); int nfsvno_read(vnode_t, off_t, int, struct ucred *, NFSPROC_T *, mbuf_t *, mbuf_t *); -int nfsvno_write(vnode_t, off_t, int, int, int *, mbuf_t, - char *, struct ucred *, NFSPROC_T *); +int nfsvno_write(vnode_t, off_t, int, int *, mbuf_t, char *, struct ucred *, + NFSPROC_T *); int nfsvno_createsub(struct nfsrv_descript *, struct nameidata *, vnode_t *, struct nfsvattr *, int *, int32_t *, NFSDEV_T, struct nfsexstuff *); @@ -704,6 +743,17 @@ int nfsrv_dscreate(struct vnode *, struct vattr *, str int nfsrv_updatemdsattr(struct vnode *, struct nfsvattr *, NFSPROC_T *); void nfsrv_killrpcs(struct nfsmount *); int nfsrv_setacl(struct vnode *, NFSACL_T *, struct ucred *, NFSPROC_T *); +int nfsvno_seek(struct nfsrv_descript *, struct vnode *, u_long, off_t *, int, + bool *, struct ucred *, NFSPROC_T *); +int nfsvno_allocate(struct vnode *, off_t, off_t, struct ucred *, NFSPROC_T *); +int nfsvno_getxattr(struct vnode *, char *, uint32_t, struct ucred *, + struct thread *, struct mbuf **, struct mbuf **, int *); +int nfsvno_setxattr(struct vnode *, char *, int, struct mbuf *, char *, + struct ucred *, struct thread *); +int nfsvno_rmxattr(struct nfsrv_descript *, struct vnode *, char *, + struct ucred *, struct thread *); +int nfsvno_listxattr(struct vnode *, uint64_t, struct ucred *, struct thread *, + u_char **, uint32_t *, bool *); /* nfs_commonkrpc.c */ int newnfs_nmcancelreqs(struct nfsmount *); Modified: head/sys/fs/nfs/nfsclstate.h ============================================================================== --- head/sys/fs/nfs/nfsclstate.h Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfs/nfsclstate.h Thu Dec 12 23:22:55 2019 (r355677) @@ -64,6 +64,8 @@ struct nfsclsession { uint64_t nfsess_slots; uint32_t nfsess_sequenceid; uint32_t nfsess_maxcache; /* Max size for cached reply. */ + uint32_t nfsess_maxreq; /* Max request size. */ + uint32_t nfsess_maxresp; /* Max reply size. */ uint16_t nfsess_foreslots; uint16_t nfsess_backslots; uint8_t nfsess_sessionid[NFSX_V4SESSIONID]; @@ -72,7 +74,7 @@ struct nfsclsession { /* * This structure holds the session, clientid and related information - * needed for an NFSv4.1 Meta Data Server (MDS) or Data Server (DS). + * needed for an NFSv4.1 or NFSv4.2 Meta Data Server (MDS) or Data Server (DS). * It is malloc'd to the correct length. */ struct nfsclds { @@ -95,6 +97,7 @@ struct nfsclds { #define NFSCLDS_DS 0x0004 #define NFSCLDS_CLOSED 0x0008 #define NFSCLDS_SAMECONN 0x0010 +#define NFSCLDS_MINORV2 0x0020 struct nfsclclient { LIST_ENTRY(nfsclclient) nfsc_list; Modified: head/sys/fs/nfs/nfsport.h ============================================================================== --- head/sys/fs/nfs/nfsport.h Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfs/nfsport.h Thu Dec 12 23:22:55 2019 (r355677) @@ -289,7 +289,7 @@ /* * Must be one more than the last NFSv4.2 op#. */ -#define NFSV42_NOPS 72 +#define NFSV42_NOPS 76 /* Quirky case if the illegal op code */ #define NFSV4OP_OPILLEGAL 10044 @@ -423,10 +423,10 @@ #endif /* NFS_V3NPROCS */ /* - * New stats structure. + * Newest stats structure. * The vers field will be set to NFSSTATS_V1 by the caller. */ -#define NFSSTATS_V1 1 +#define NFSSTATS_V1 2 struct nfsstatsv1 { int vers; /* Set to version requested by caller. */ uint64_t attrcache_hits; @@ -447,9 +447,9 @@ struct nfsstatsv1 { uint64_t readlink_bios; uint64_t biocache_readdirs; uint64_t readdir_bios; - uint64_t rpccnt[NFSV41_NPROCS + 13]; + uint64_t rpccnt[NFSV42_NPROCS + 15]; uint64_t rpcretries; - uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS]; + uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; uint64_t srvrpc_errs; uint64_t srv_errs; uint64_t rpcrequests; @@ -468,6 +468,71 @@ struct nfsstatsv1 { uint64_t srvlockowners; uint64_t srvlocks; uint64_t srvdelegates; + uint64_t cbrpccnt[NFSV42_CBNOPS + 10]; + uint64_t clopenowners; + uint64_t clopens; + uint64_t cllockowners; + uint64_t cllocks; + uint64_t cldelegates; + uint64_t cllocalopenowners; + uint64_t cllocalopens; + uint64_t cllocallockowners; + uint64_t cllocallocks; + uint64_t srvstartcnt; + uint64_t srvdonecnt; + uint64_t srvbytes[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; + uint64_t srvops[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; + struct bintime srvduration[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; + struct bintime busyfrom; + struct bintime busytime; +}; + +/* + * Newer stats structure. + * The vers field will be set to NFSSTATS_OV1 by the caller. + */ +#define NFSSTATS_OV1 1 +struct nfsstatsov1 { + int vers; /* Set to version requested by caller. */ + uint64_t attrcache_hits; + uint64_t attrcache_misses; + uint64_t lookupcache_hits; + uint64_t lookupcache_misses; + uint64_t direofcache_hits; + uint64_t direofcache_misses; + uint64_t accesscache_hits; + uint64_t accesscache_misses; + uint64_t biocache_reads; + uint64_t read_bios; + uint64_t read_physios; + uint64_t biocache_writes; + uint64_t write_bios; + uint64_t write_physios; + uint64_t biocache_readlinks; + uint64_t readlink_bios; + uint64_t biocache_readdirs; + uint64_t readdir_bios; + uint64_t rpccnt[NFSV42_NPROCS + 4]; + uint64_t rpcretries; + uint64_t srvrpccnt[NFSV42_PURENOPS + NFSV4OP_FAKENOPS]; + uint64_t srvrpc_errs; + uint64_t srv_errs; + uint64_t rpcrequests; + uint64_t rpctimeouts; + uint64_t rpcunexpected; + uint64_t rpcinvalid; + uint64_t srvcache_inproghits; + uint64_t srvcache_idemdonehits; + uint64_t srvcache_nonidemdonehits; + uint64_t srvcache_misses; + uint64_t srvcache_tcppeak; + int srvcache_size; /* Updated by atomic_xx_int(). */ + uint64_t srvclients; + uint64_t srvopenowners; + uint64_t srvopens; + uint64_t srvlockowners; + uint64_t srvlocks; + uint64_t srvdelegates; uint64_t cbrpccnt[NFSV42_CBNOPS]; uint64_t clopenowners; uint64_t clopens; @@ -480,9 +545,9 @@ struct nfsstatsv1 { uint64_t cllocallocks; uint64_t srvstartcnt; uint64_t srvdonecnt; - uint64_t srvbytes[NFSV42_NOPS + NFSV4OP_FAKENOPS]; - uint64_t srvops[NFSV42_NOPS + NFSV4OP_FAKENOPS]; - struct bintime srvduration[NFSV42_NOPS + NFSV4OP_FAKENOPS]; + uint64_t srvbytes[NFSV42_PURENOPS + NFSV4OP_FAKENOPS]; + uint64_t srvops[NFSV42_PURENOPS + NFSV4OP_FAKENOPS]; + struct bintime srvduration[NFSV42_PURENOPS + NFSV4OP_FAKENOPS]; struct bintime busyfrom; struct bintime busytime; }; Modified: head/sys/fs/nfs/nfsproto.h ============================================================================== --- head/sys/fs/nfs/nfsproto.h Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfs/nfsproto.h Thu Dec 12 23:22:55 2019 (r355677) @@ -1070,7 +1070,7 @@ struct nfsv3_sattr { /* Not sure what attribute bit#81/0x00020000 is? */ #define NFSATTRBM_XATTRSUPPORT 0x00040000 -#define NFSATTRBIT_MAX 77 +#define NFSATTRBIT_MAX 83 /* * Sets of attributes that are supported, by words in the bitmap. Modified: head/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- head/sys/fs/nfsclient/nfs_clrpcops.c Thu Dec 12 22:59:22 2019 (r355676) +++ head/sys/fs/nfsclient/nfs_clrpcops.c Thu Dec 12 23:22:55 2019 (r355677) @@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$"); #include "opt_inet6.h" #include +#include +#include #include #include @@ -72,6 +74,8 @@ extern int nfsrv_useacl; extern char nfsv4_callbackaddr[INET6_ADDRSTRLEN]; extern int nfscl_debuglevel; extern int nfs_pnfsiothreads; +extern u_long sb_max_adj; +extern int nfs_maxcopyrange; NFSCLSTATEMUTEX; int nfstest_outofseq = 0; int nfscl_assumeposixlocks = 1; @@ -110,6 +114,9 @@ struct nfsclwritedsdorpc { struct nfsclds *dsp; uint64_t off; int len; +#ifdef notyet + int advise; +#endif struct nfsfh *fhp; struct mbuf *m; int vers; @@ -142,7 +149,8 @@ static int nfsrpc_getlayout(struct nfsmount *, vnode_t uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **, struct ucred *, NFSPROC_T *); static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *, - struct sockaddr_in6 *, sa_family_t, int, struct nfsclds **, NFSPROC_T *); + struct sockaddr_in6 *, sa_family_t, int, int, struct nfsclds **, + NFSPROC_T *); static void nfscl_initsessionslots(struct nfsclsession *); static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *, nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *, @@ -172,12 +180,21 @@ static int nfsio_commitds(vnode_t, uint64_t, int, stru NFSPROC_T *); static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *, struct nfsfh *, int, int, struct ucred *, NFSPROC_T *); +#ifdef notyet +static int nfsio_adviseds(vnode_t, uint64_t, int, int, struct nfsclds *, + struct nfsfh *, int, int, struct nfsclwritedsdorpc *, struct ucred *, + NFSPROC_T *); +static int nfsrpc_adviseds(vnode_t, uint64_t, int, int, struct nfsclds *, + struct nfsfh *, int, int, struct ucred *, NFSPROC_T *); +#endif +static int nfsrpc_allocaterpc(vnode_t, off_t, off_t, nfsv4stateid_t *, + struct nfsvattr *, int *, struct ucred *, NFSPROC_T *, void *); static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t, uint64_t, uint64_t, nfsv4stateid_t *, int, int, int); static int nfsrv_parseug(struct nfsrv_descript *, int, uid_t *, gid_t *, NFSPROC_T *); -static int nfsrv_parselayoutget(struct nfsrv_descript *, nfsv4stateid_t *, - int *, struct nfsclflayouthead *); +static int nfsrv_parselayoutget(struct nfsmount *, struct nfsrv_descript *, + nfsv4stateid_t *, int *, struct nfsclflayouthead *); static int nfsrpc_getopenlayout(struct nfsmount *, vnode_t, u_int8_t *, int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int, struct nfscldeleg **, struct ucred *, NFSPROC_T *); @@ -200,6 +217,11 @@ static int nfsrpc_layoutget(struct nfsmount *, uint8_t static int nfsrpc_layoutgetres(struct nfsmount *, vnode_t, uint8_t *, int, nfsv4stateid_t *, int, uint32_t *, struct nfscllayout **, struct nfsclflayouthead *, int, int, int *, struct ucred *, NFSPROC_T *); +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 *); @@ -935,12 +957,12 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclcli * previous session has failed, so... * do an ExchangeID followed by the CreateSession. */ - error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sockreq, + error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sockreq, 0, NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, &dsp, cred, p); NFSCL_DEBUG(1, "aft exch=%d\n", error); if (error == 0) error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess, - &nmp->nm_sockreq, + &nmp->nm_sockreq, NULL, dsp->nfsclds_sess.nfsess_sequenceid, 1, cred, p); if (error == 0) { NFSLOCKMNT(nmp); @@ -4647,8 +4669,8 @@ nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPR */ int nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclclient *clp, - struct nfssockreq *nrp, uint32_t exchflags, struct nfsclds **dspp, - struct ucred *cred, NFSPROC_T *p) + struct nfssockreq *nrp, int minorvers, uint32_t exchflags, + struct nfsclds **dspp, struct ucred *cred, NFSPROC_T *p) { uint32_t *tl, v41flags; struct nfsrv_descript nfsd; @@ -4658,7 +4680,10 @@ nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclcl int error, len; *dspp = NULL; - nfscl_reqstart(nd, NFSPROC_EXCHANGEID, nmp, NULL, 0, NULL, NULL, 0, 0); + if (minorvers == 0) + minorvers = nmp->nm_minorvers; + nfscl_reqstart(nd, NFSPROC_EXCHANGEID, nmp, NULL, 0, NULL, NULL, + NFS_VER4, minorvers); NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); *tl++ = txdr_unsigned(nfsboottime.tv_sec); /* Client owner */ *tl = txdr_unsigned(clp->nfsc_rev); @@ -4709,6 +4734,8 @@ nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclcl } if ((v41flags & NFSV4EXCH_USEPNFSDS) != 0) dsp->nfsclds_flags |= NFSCLDS_DS; + if (minorvers == NFSV42_MINORVERSION) + dsp->nfsclds_flags |= NFSCLDS_MINORV2; if (len > 0) nd->nd_repstat = nfsrv_mtostr(nd, dsp->nfsclds_serverown, len); @@ -4732,21 +4759,27 @@ nfsmout: */ int nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep, - struct nfssockreq *nrp, uint32_t sequenceid, int mds, struct ucred *cred, - NFSPROC_T *p) + struct nfssockreq *nrp, struct nfsclds *dsp, uint32_t sequenceid, int mds, + struct ucred *cred, NFSPROC_T *p) { uint32_t crflags, maxval, *tl; struct nfsrv_descript nfsd; struct nfsrv_descript *nd = &nfsd; - int error, irdcnt; + int error, irdcnt, minorvers; /* Make sure nm_rsize, nm_wsize is set. */ if (nmp->nm_rsize > NFS_MAXBSIZE || nmp->nm_rsize == 0) nmp->nm_rsize = NFS_MAXBSIZE; if (nmp->nm_wsize > NFS_MAXBSIZE || nmp->nm_wsize == 0) nmp->nm_wsize = NFS_MAXBSIZE; - nfscl_reqstart(nd, NFSPROC_CREATESESSION, nmp, NULL, 0, NULL, NULL, 0, - 0); + if (dsp == NULL) + minorvers = nmp->nm_minorvers; + else if ((dsp->nfsclds_flags & NFSCLDS_MINORV2) != 0) + minorvers = NFSV42_MINORVERSION; + else + minorvers = NFSV41_MINORVERSION; + nfscl_reqstart(nd, NFSPROC_CREATESESSION, nmp, NULL, 0, NULL, NULL, + NFS_VER4, minorvers); NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED); *tl++ = sep->nfsess_clientid.lval[0]; *tl++ = sep->nfsess_clientid.lval[1]; @@ -4759,8 +4792,18 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsc /* Fill in fore channel attributes. */ NFSM_BUILD(tl, uint32_t *, 7 * NFSX_UNSIGNED); *tl++ = 0; /* Header pad size */ - *tl++ = txdr_unsigned(nmp->nm_wsize + NFS_MAXXDR);/* Max request size */ - *tl++ = txdr_unsigned(nmp->nm_rsize + NFS_MAXXDR);/* Max reply size */ + if ((nd->nd_flag & ND_NFSV42) != 0 && mds != 0 && sb_max_adj >= + nmp->nm_wsize && sb_max_adj >= nmp->nm_rsize) { + /* + * NFSv4.2 Extended Attribute operations may want to do + * requests/replies that are larger than nm_rsize/nm_wsize. + */ + *tl++ = txdr_unsigned(sb_max_adj - NFS_MAXXDR); + *tl++ = txdr_unsigned(sb_max_adj - NFS_MAXXDR); + } else { + *tl++ = txdr_unsigned(nmp->nm_wsize + NFS_MAXXDR); + *tl++ = txdr_unsigned(nmp->nm_rsize + NFS_MAXXDR); + } *tl++ = txdr_unsigned(4096); /* Max response size cached */ *tl++ = txdr_unsigned(20); /* Max operations */ *tl++ = txdr_unsigned(64); /* Max slots */ @@ -4817,6 +4860,7 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsc else break; } + sep->nfsess_maxreq = maxval; /* Make sure nm_rsize is small enough. */ maxval = fxdr_unsigned(uint32_t, *tl++); @@ -4826,6 +4870,7 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsc else break; } + sep->nfsess_maxresp = maxval; sep->nfsess_maxcache = fxdr_unsigned(int, *tl++); tl++; @@ -4928,7 +4973,8 @@ nfsrpc_layoutget(struct nfsmount *nmp, uint8_t *fhp, i if (error != 0) return (error); if (nd->nd_repstat == 0) - error = nfsrv_parselayoutget(nd, stateidp, retonclosep, flhp); + error = nfsrv_parselayoutget(nmp, nd, stateidp, retonclosep, + flhp); if (error == 0 && nd->nd_repstat != 0) error = nd->nd_repstat; mbuf_freem(nd->nd_mrep); @@ -4950,7 +4996,8 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de struct sockaddr_in6 sin6, ssin6; struct nfsclds *dsp = NULL, **dspp, **gotdspp; struct nfscldevinfo *ndi; - int addrcnt = 0, bitcnt, error, gotvers, i, isudp, j, stripecnt; + int addrcnt = 0, bitcnt, error, gotminor, gotvers, i, isudp, j; + int stripecnt; uint8_t stripeindex; sa_family_t af, safilled; @@ -5082,7 +5129,8 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de } } - gotvers = NFS_VER4; /* Always NFSv4 for File Layout. */ + gotvers = NFS_VER4; /* Default NFSv4.1 for File Layout. */ + gotminor = NFSV41_MINORVERSION; /* For Flex File, we will take one of the versions to use. */ if (layouttype == NFSLAYOUT_FLEXFILE) { NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); @@ -5093,14 +5141,19 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de goto nfsmout; } gotvers = 0; + gotminor = 0; for (i = 0; i < j; i++) { NFSM_DISSECT(tl, uint32_t *, 5 * NFSX_UNSIGNED); vers = fxdr_unsigned(uint32_t, *tl++); minorvers = fxdr_unsigned(uint32_t, *tl++); - if ((vers == NFS_VER4 && minorvers == - NFSV41_MINORVERSION) || (vers == NFS_VER3 && - gotvers == 0)) { + if (vers == NFS_VER3) + minorvers = 0; + if ((vers == NFS_VER4 && ((minorvers == + NFSV41_MINORVERSION && gotminor == 0) || + minorvers == NFSV42_MINORVERSION)) || + (vers == NFS_VER3 && gotvers == 0)) { gotvers = vers; + gotminor = minorvers; /* We'll take this one. */ ndi->nfsdi_versindex = i; ndi->nfsdi_vers = vers; @@ -5118,7 +5171,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de } } if (gotvers == 0) { - printf("pNFS: no NFSv3 or NFSv4.1\n"); + printf("pNFS: no NFSv3, NFSv4.1 or NFSv4.2\n"); error = NFSERR_BADXDR; goto nfsmout; } @@ -5144,7 +5197,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de * NFS version and IP address. */ error = nfsrpc_fillsa(nmp, &ssin, &ssin6, safilled, - gotvers, &dsp, p); + gotvers, gotminor, &dsp, p); } if (error == 0) { KASSERT(gotdspp != NULL, ("gotdspp is NULL")); @@ -5373,15 +5426,15 @@ nfsrpc_getlayout(struct nfsmount *nmp, vnode_t vp, str */ static int nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in *sin, - struct sockaddr_in6 *sin6, sa_family_t af, int vers, struct nfsclds **dspp, - NFSPROC_T *p) + struct sockaddr_in6 *sin6, sa_family_t af, int vers, int minorvers, + struct nfsclds **dspp, NFSPROC_T *p) { struct sockaddr_in *msad, *sad; struct sockaddr_in6 *msad6, *sad6; struct nfsclclient *clp; struct nfssockreq *nrp; struct nfsclds *dsp, *tdsp; - int error; + int error, firsttry; enum nfsclds_state retv; uint32_t sequenceid; @@ -5492,9 +5545,16 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in /* Now, do the exchangeid and create session. */ if (error == 0) { if (vers == NFS_VER4) { - error = nfsrpc_exchangeid(nmp, clp, nrp, - NFSV4EXCH_USEPNFSDS, &dsp, nrp->nr_cred, p); - NFSCL_DEBUG(3, "DS exchangeid=%d\n", error); + firsttry = 0; + do { + error = nfsrpc_exchangeid(nmp, clp, nrp, + minorvers, NFSV4EXCH_USEPNFSDS, &dsp, + nrp->nr_cred, p); + NFSCL_DEBUG(3, "DS exchangeid=%d\n", error); + if (error == NFSERR_MINORVERMISMATCH) + minorvers = NFSV42_MINORVERSION; + } while (error == NFSERR_MINORVERMISMATCH && + firsttry++ == 0); if (error != 0) newnfs_disconnect(nrp); } else { @@ -5534,7 +5594,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in dsp->nfsclds_sess.nfsess_sequenceid; NFSUNLOCKMNT(nmp); error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess, - nrp, sequenceid, 0, nrp->nr_cred, p); + nrp, dsp, sequenceid, 0, nrp->nr_cred, p); NFSCL_DEBUG(3, "DS createsess=%d\n", error); } } else { @@ -5896,7 +5956,7 @@ nfscl_findlayoutforio(struct nfscllayout *lyp, uint64_ } /* - * Do I/O using an NFSv4.1 file layout. + * Do I/O using an NFSv4.1 or NFSv4.2 file layout. */ static int nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, @@ -5905,7 +5965,7 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *i uint64_t len, int docommit, struct ucred *cred, NFSPROC_T *p) { uint64_t io_off, rel_off, stripe_unit_size, transfer, xfer; - int commit_thru_mds, error, stripe_index, stripe_pos; + int commit_thru_mds, error, stripe_index, stripe_pos, minorvers; struct nfsnode *np; struct nfsfh *fhp; struct nfsclds **dspp; @@ -5922,6 +5982,10 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *i while (len > 0 && error == 0) { stripe_index = nfsfldi_stripeindex(dp, stripe_pos); dspp = nfsfldi_addr(dp, stripe_index); + if (((*dspp)->nfsclds_flags & NFSCLDS_MINORV2) != 0) + minorvers = NFSV42_MINORVERSION; + else + minorvers = NFSV41_MINORVERSION; if (len > transfer && docommit == 0) xfer = transfer; else @@ -5959,7 +6023,7 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *i if (docommit != 0) { if (error == 0) error = nfsrpc_commitds(vp, io_off, xfer, - *dspp, fhp, 0, 0, cred, p); + *dspp, fhp, NFS_VER4, minorvers, cred, p); if (error == 0) { /* * Set both eof and uio_resid = 0 to end any @@ -5974,11 +6038,11 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *i } } else if (rwflag == NFSV4OPEN_ACCESSREAD) error = nfsrpc_readds(vp, uiop, stateidp, eofp, *dspp, - io_off, xfer, fhp, 0, 0, 0, cred, p); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***