Skip to content

Commit

Permalink
NFS: Fix a potential data corruption
Browse files Browse the repository at this point in the history
commit 88975a5 upstream.

We must ensure that the subrequests are joined back into the head before
we can retransmit a request. If the head was not on the commit lists,
because the server wrote it synchronously, we still need to add it back
to the retransmission list.
Add a call that mirrors the effect of nfs_cancel_remove_inode() for
O_DIRECT.

Fixes: ed5d588 ("NFS: Try to join page groups before an O_DIRECT retransmission")
Cc: stable@vger.kernel.org
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Trond Myklebust authored and gregkh committed Sep 19, 2023
1 parent de830dc commit 0ec2671
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion fs/nfs/direct.c
Expand Up @@ -472,13 +472,31 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
return result;
}

static void nfs_direct_add_page_head(struct list_head *list,
struct nfs_page *req)
{
struct nfs_page *head = req->wb_head;

if (!list_empty(&head->wb_list) || !nfs_lock_request(head))
return;
if (!list_empty(&head->wb_list)) {
nfs_unlock_request(head);
return;
}
list_add(&head->wb_list, list);
kref_get(&head->wb_kref);
kref_get(&head->wb_kref);
}

static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
{
struct nfs_page *req, *subreq;

list_for_each_entry(req, list, wb_list) {
if (req->wb_head != req)
if (req->wb_head != req) {
nfs_direct_add_page_head(&req->wb_list, req);
continue;
}
subreq = req->wb_this_page;
if (subreq == req)
continue;
Expand Down

0 comments on commit 0ec2671

Please sign in to comment.