Patch "NFSD: da_addr_body field missing in some GETDEVICEINFO replies" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    NFSD: da_addr_body field missing in some GETDEVICEINFO replies

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     nfsd-da_addr_body-field-missing-in-some-getdeviceinf.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit fd227c599828289044079c14dc53a7ad286e0975
Author: Chuck Lever <chuck.lever@xxxxxxxxxx>
Date:   Wed Aug 16 10:20:52 2023 -0400

    NFSD: da_addr_body field missing in some GETDEVICEINFO replies
    
    [ Upstream commit 6372e2ee629894433fe6107d7048536a3280a284 ]
    
    The XDR specification in RFC 8881 looks like this:
    
    struct device_addr4 {
            layouttype4     da_layout_type;
            opaque          da_addr_body<>;
    };
    
    struct GETDEVICEINFO4resok {
            device_addr4    gdir_device_addr;
            bitmap4         gdir_notification;
    };
    
    union GETDEVICEINFO4res switch (nfsstat4 gdir_status) {
    case NFS4_OK:
            GETDEVICEINFO4resok gdir_resok4;
    case NFS4ERR_TOOSMALL:
            count4          gdir_mincount;
    default:
            void;
    };
    
    Looking at nfsd4_encode_getdeviceinfo() ....
    
    When the client provides a zero gd_maxcount, then the Linux NFS
    server implementation encodes the da_layout_type field and then
    skips the da_addr_body field completely, proceeding directly to
    encode gdir_notification field.
    
    There does not appear to be an option in the specification to skip
    encoding da_addr_body. Moreover, Section 18.40.3 says:
    
    > If the client wants to just update or turn off notifications, it
    > MAY send a GETDEVICEINFO operation with gdia_maxcount set to zero.
    > In that event, if the device ID is valid, the reply's da_addr_body
    > field of the gdir_device_addr field will be of zero length.
    
    Since the layout drivers are responsible for encoding the
    da_addr_body field, put this fix inside the ->encode_getdeviceinfo
    methods.
    
    Fixes: 9cf514ccfacb ("nfsd: implement pNFS operations")
    Reviewed-by: Christoph Hellwig <hch@xxxxxx>
    Cc: Tom Haynes <loghyr@xxxxxxxxx>
    Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/nfsd/blocklayoutxdr.c b/fs/nfsd/blocklayoutxdr.c
index 442543304930b..2455dc8be18a8 100644
--- a/fs/nfsd/blocklayoutxdr.c
+++ b/fs/nfsd/blocklayoutxdr.c
@@ -82,6 +82,15 @@ nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
 	int len = sizeof(__be32), ret, i;
 	__be32 *p;
 
+	/*
+	 * See paragraph 5 of RFC 8881 S18.40.3.
+	 */
+	if (!gdp->gd_maxcount) {
+		if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
+			return nfserr_resource;
+		return nfs_ok;
+	}
+
 	p = xdr_reserve_space(xdr, len + sizeof(__be32));
 	if (!p)
 		return nfserr_resource;
diff --git a/fs/nfsd/flexfilelayoutxdr.c b/fs/nfsd/flexfilelayoutxdr.c
index e81d2a5cf381e..bb205328e043d 100644
--- a/fs/nfsd/flexfilelayoutxdr.c
+++ b/fs/nfsd/flexfilelayoutxdr.c
@@ -85,6 +85,15 @@ nfsd4_ff_encode_getdeviceinfo(struct xdr_stream *xdr,
 	int addr_len;
 	__be32 *p;
 
+	/*
+	 * See paragraph 5 of RFC 8881 S18.40.3.
+	 */
+	if (!gdp->gd_maxcount) {
+		if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
+			return nfserr_resource;
+		return nfs_ok;
+	}
+
 	/* len + padding for two strings */
 	addr_len = 16 + da->netaddr.netid_len + da->netaddr.addr_len;
 	ver_len = 20;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 3d7b0ad4157df..1d24fff2709c5 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -4126,20 +4126,17 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
 
 	*p++ = cpu_to_be32(gdev->gd_layout_type);
 
-	/* If maxcount is 0 then just update notifications */
-	if (gdev->gd_maxcount != 0) {
-		ops = nfsd4_layout_ops[gdev->gd_layout_type];
-		nfserr = ops->encode_getdeviceinfo(xdr, gdev);
-		if (nfserr) {
-			/*
-			 * We don't bother to burden the layout drivers with
-			 * enforcing gd_maxcount, just tell the client to
-			 * come back with a bigger buffer if it's not enough.
-			 */
-			if (xdr->buf->len + 4 > gdev->gd_maxcount)
-				goto toosmall;
-			return nfserr;
-		}
+	ops = nfsd4_layout_ops[gdev->gd_layout_type];
+	nfserr = ops->encode_getdeviceinfo(xdr, gdev);
+	if (nfserr) {
+		/*
+		 * We don't bother to burden the layout drivers with
+		 * enforcing gd_maxcount, just tell the client to
+		 * come back with a bigger buffer if it's not enough.
+		 */
+		if (xdr->buf->len + 4 > gdev->gd_maxcount)
+			goto toosmall;
+		return nfserr;
 	}
 
 	if (gdev->gd_notify_types) {



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux