Skip to content

Commit 88975a5

Browse files
Trond Myklebustamschuma-ntap
authored andcommitted
NFS: Fix a potential data corruption
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: [email protected] Signed-off-by: Trond Myklebust <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 14e7316 commit 88975a5

File tree

1 file changed

+19
-1
lines changed

1 file changed

+19
-1
lines changed

fs/nfs/direct.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,13 +472,31 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
472472
return result;
473473
}
474474

475+
static void nfs_direct_add_page_head(struct list_head *list,
476+
struct nfs_page *req)
477+
{
478+
struct nfs_page *head = req->wb_head;
479+
480+
if (!list_empty(&head->wb_list) || !nfs_lock_request(head))
481+
return;
482+
if (!list_empty(&head->wb_list)) {
483+
nfs_unlock_request(head);
484+
return;
485+
}
486+
list_add(&head->wb_list, list);
487+
kref_get(&head->wb_kref);
488+
kref_get(&head->wb_kref);
489+
}
490+
475491
static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
476492
{
477493
struct nfs_page *req, *subreq;
478494

479495
list_for_each_entry(req, list, wb_list) {
480-
if (req->wb_head != req)
496+
if (req->wb_head != req) {
497+
nfs_direct_add_page_head(&req->wb_list, req);
481498
continue;
499+
}
482500
subreq = req->wb_this_page;
483501
if (subreq == req)
484502
continue;

0 commit comments

Comments
 (0)