The branch stable/13 has been updated by rmacklem:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=6e8e261f0d4e8b71e2a7ab74a05e0ed7cae5704a

commit 6e8e261f0d4e8b71e2a7ab74a05e0ed7cae5704a
Author:     Rick Macklem <rmack...@freebsd.org>
AuthorDate: 2021-11-11 23:43:58 +0000
Commit:     Rick Macklem <rmack...@freebsd.org>
CommitDate: 2021-11-25 00:32:09 +0000

    nfscl: Add a LayoutError RPC for NFSv4.2 pNFS mounts
    
    If a pNFS server's DS runs out of disk space, it replies
    NFSERR_NOSPC to the client doing writing.  For the Linux
    client, it then sends a LayoutError RPC to the MDS server to
    tell it about the error.  This patch adds the same to the
    FreeBSD NFSv4.2 pNFS client, to maintain Linux compatible
    behaviour, particlularily for non-FreeBSD pNFS servers.
    
    (cherry picked from commit 44744f75386e2102584acbca24fbe67de16051ca)
---
 sys/fs/nfs/nfs_commonsubs.c     |  8 ++++--
 sys/fs/nfs/nfsport.h            | 15 ++++++++---
 sys/fs/nfs/nfsproto.h           | 11 +++++++-
 sys/fs/nfsclient/nfs_clrpcops.c | 56 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 144b2e215496..58d517b0b13d 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -215,7 +215,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,
-    1, 0, 0, 1, 0 };
+    1, 0, 0, 1, 0, 0, 0, 0 };
 
 /* local functions */
 static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
@@ -299,6 +299,9 @@ static struct {
        { NFSV4OP_REMOVEXATTR, 2, "Rmxattr", 7, },
        { NFSV4OP_LISTXATTRS, 2, "Listxattr", 9, },
        { NFSV4OP_BINDCONNTOSESS, 1, "BindConSess", 11, },
+       { NFSV4OP_LOOKUP, 5, "LookupOpen", 10, },
+       { NFSV4OP_DEALLOCATE, 2, "Deallocate", 10, },
+       { NFSV4OP_LAYOUTERROR, 1, "LayoutError", 11, },
 };
 
 /*
@@ -307,7 +310,8 @@ 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, 1, 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
 };
 
 /*
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
index cb82666ab397..5dcce15f7f64 100644
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -415,10 +415,19 @@
 /* BindConnectionToSession, done by the krpc for a new connection. */
 #define        NFSPROC_BINDCONNTOSESS  65
 
+/* Do a Lookup+Open for "oneopenown". */
+#define        NFSPROC_LOOKUPOPEN      66
+
+/* Do an NFSv4.2 Deallocate. */
+#define        NFSPROC_DEALLOCATE      67
+
+/* Do an NFSv4.2 LayoutError. */
+#define        NFSPROC_LAYOUTERROR     68
+
 /*
  * Must be defined as one higher than the last NFSv4.2 Proc# above.
  */
-#define        NFSV42_NPROCS           66
+#define        NFSV42_NPROCS           69
 
 #endif /* NFS_V3NPROCS */
 
@@ -447,7 +456,7 @@ struct nfsstatsv1 {
        uint64_t        readlink_bios;
        uint64_t        biocache_readdirs;
        uint64_t        readdir_bios;
-       uint64_t        rpccnt[NFSV42_NPROCS + 14];
+       uint64_t        rpccnt[NFSV42_NPROCS + 11];
        uint64_t        rpcretries;
        uint64_t        srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15];
        uint64_t        reserved_0;
@@ -512,7 +521,7 @@ struct nfsstatsov1 {
        uint64_t        readlink_bios;
        uint64_t        biocache_readdirs;
        uint64_t        readdir_bios;
-       uint64_t        rpccnt[NFSV42_NPROCS + 3];
+       uint64_t        rpccnt[NFSV42_NPROCS];
        uint64_t        rpcretries;
        uint64_t        srvrpccnt[NFSV42_PURENOPS + NFSV4OP_FAKENOPS];
        uint64_t        reserved_0;
diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h
index 13e146154805..968cc6a41cc3 100644
--- a/sys/fs/nfs/nfsproto.h
+++ b/sys/fs/nfs/nfsproto.h
@@ -396,10 +396,19 @@
 /* BindConnectionToSession, done by the krpc for a new connection. */
 #define        NFSPROC_BINDCONNTOSESS  65
 
+/* Do a Lookup+Open for "oneopenown". */
+#define        NFSPROC_LOOKUPOPEN      66
+
+/* Do an NFSv4.2 Deallocate. */
+#define        NFSPROC_DEALLOCATE      67
+
+/* Do an NFSv4.2 LayoutError. */
+#define        NFSPROC_LAYOUTERROR     68
+
 /*
  * Must be defined as one higher than the last NFSv4.2 Proc# above.
  */
-#define        NFSV42_NPROCS           66
+#define        NFSV42_NPROCS           69
 
 #endif /* NFS_V3NPROCS */
 
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 6489569f8acf..b616cd729ab1 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -147,6 +147,9 @@ static int nfsrpc_locku(struct nfsrv_descript *, struct 
nfsmount *,
     u_int32_t, struct ucred *, NFSPROC_T *, int);
 static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *,
     struct acl *, nfsv4stateid_t *, void *);
+static int nfsrpc_layouterror(struct nfsmount *, uint8_t *, int, uint64_t,
+    uint64_t, nfsv4stateid_t *, struct ucred *, NFSPROC_T *, uint32_t,
+    uint32_t, char *);
 static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int,
     uint32_t, uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
     struct ucred *, NFSPROC_T *);
@@ -5459,6 +5462,44 @@ nfsmout:
        return (error);
 }
 
+/*
+ * Do the NFSv4.2 LayoutError.
+ */
+static int
+nfsrpc_layouterror(struct nfsmount *nmp, uint8_t *fh, int fhlen, uint64_t 
offset,
+    uint64_t len, nfsv4stateid_t *stateidp, struct ucred *cred, NFSPROC_T *p,
+    uint32_t stat, uint32_t op, char *devid)
+{
+       uint32_t *tl;
+       struct nfsrv_descript nfsd, *nd = &nfsd;
+       int error;
+
+       nfscl_reqstart(nd, NFSPROC_LAYOUTERROR, nmp, fh, fhlen, NULL, NULL,
+           0, 0);
+       NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
+           NFSX_V4DEVICEID + 3 * NFSX_UNSIGNED);
+       txdr_hyper(offset, tl); tl += 2;
+       txdr_hyper(len, tl); tl += 2;
+       *tl++ = txdr_unsigned(stateidp->seqid);
+       *tl++ = stateidp->other[0];
+       *tl++ = stateidp->other[1];
+       *tl++ = stateidp->other[2];
+       *tl++ = txdr_unsigned(1);
+       NFSBCOPY(devid, tl, NFSX_V4DEVICEID);
+       tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
+       *tl++ = txdr_unsigned(stat);
+       *tl = txdr_unsigned(op);
+       nd->nd_flag |= ND_USEGSSNAME;
+       error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
+           NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
+       if (error != 0)
+               return (error);
+       if (nd->nd_repstat != 0)
+               error = nd->nd_repstat;
+       m_freem(nd->nd_mrep);
+       return (error);
+}
+
 /*
  * Acquire a layout and devinfo, if possible. The caller must have acquired
  * a reference count on the nfsclclient structure before calling this.
@@ -5798,6 +5839,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, 
int *must_commit,
        size_t iovlen = 0;
        off_t offs = 0;
        ssize_t resid = 0;
+       uint32_t op;
 
        if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 || nfs_numnfscbd == 0 ||
            (np->n_flag & NNOLAYOUT) != 0)
@@ -5977,6 +6019,20 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, 
int *must_commit,
                                NFSLOCKMNT(nmp);
                                nmp->nm_state |= NFSSTA_OPENMODE;
                                NFSUNLOCKMNT(nmp);
+                       } else if ((error == NFSERR_NOSPC ||
+                           error == NFSERR_IO || error == NFSERR_NXIO) &&
+                           nmp->nm_minorvers == NFSV42_MINORVERSION) {
+                               if (docommit != 0)
+                                       op = NFSV4OP_COMMIT;
+                               else if (rwaccess == NFSV4OPEN_ACCESSREAD)
+                                       op = NFSV4OP_READ;
+                               else
+                                       op = NFSV4OP_WRITE;
+                               nfsrpc_layouterror(nmp, np->n_fhp->nfh_fh,
+                                   np->n_fhp->nfh_len, off, xfer,
+                                   &layp->nfsly_stateid, newcred, p, error, op,
+                                   dip->nfsdi_deviceid);
+                               error = EIO;
                        } else
                                error = EIO;
                        if (error == 0)

Reply via email to