Patch "nfsd_splice_actor(): handle compound pages" has been added to the 5.10-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_splice_actor(): handle compound pages

to the 5.10-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_splice_actor-handle-compound-pages.patch
and it can be found in the queue-5.10 subdirectory.

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



commit c34305b052c2bb7a246929aaeed1eb3a1392fb53
Author: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
Date:   Sat Sep 10 22:14:02 2022 +0100

    nfsd_splice_actor(): handle compound pages
    
    [ Upstream commit bfbfb6182ad1d7d184b16f25165faad879147f79 ]
    
    pipe_buffer might refer to a compound page (and contain more than a PAGE_SIZE
    worth of data).  Theoretically it had been possible since way back, but
    nfsd_splice_actor() hadn't run into that until copy_page_to_iter() change.
    Fortunately, the only thing that changes for compound pages is that we
    need to stuff each relevant subpage in and convert the offset into offset
    in the first subpage.
    
    Acked-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
    Tested-by: Benjamin Coddington <bcodding@xxxxxxxxxx>
    Fixes: f0f6b614f83d "copy_page_to_iter(): don't split high-order page in case of ITER_PIPE"
    Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
    [ cel: "‘for’ loop initial declarations are only allowed in C99 or C11 mode" ]
    Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 95f2e4549c034..bc377ee177171 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -862,10 +862,15 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 		  struct splice_desc *sd)
 {
 	struct svc_rqst *rqstp = sd->u.data;
-
-	svc_rqst_replace_page(rqstp, buf->page);
-	if (rqstp->rq_res.page_len == 0)
-		rqstp->rq_res.page_base = buf->offset;
+	struct page *page = buf->page;	// may be a compound one
+	unsigned offset = buf->offset;
+	int i;
+
+	page += offset / PAGE_SIZE;
+	for (i = sd->len; i > 0; i -= PAGE_SIZE)
+		svc_rqst_replace_page(rqstp, page++);
+	if (rqstp->rq_res.page_len == 0)	// first call
+		rqstp->rq_res.page_base = offset % PAGE_SIZE;
 	rqstp->rq_res.page_len += sd->len;
 	return sd->len;
 }




[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