Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFS: Use the correct commit info in nfs_join_page_group()

Ensure that nfs_clear_request_commit() updates the correct counters when
it removes them from the commit list.

Fixes: ed5d588fe47f ("NFS: Try to join page groups before an O_DIRECT retransmission")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Trond Myklebust and committed by
Anna Schumaker
b193a78d 8982f7af

+20 -15
+5 -3
fs/nfs/direct.c
··· 498 498 kref_get(&head->wb_kref); 499 499 } 500 500 501 - static void nfs_direct_join_group(struct list_head *list, struct inode *inode) 501 + static void nfs_direct_join_group(struct list_head *list, 502 + struct nfs_commit_info *cinfo, 503 + struct inode *inode) 502 504 { 503 505 struct nfs_page *req, *subreq; 504 506 ··· 522 520 nfs_release_request(subreq); 523 521 } 524 522 } while ((subreq = subreq->wb_this_page) != req); 525 - nfs_join_page_group(req, inode); 523 + nfs_join_page_group(req, cinfo, inode); 526 524 } 527 525 } 528 526 ··· 547 545 nfs_init_cinfo_from_dreq(&cinfo, dreq); 548 546 nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo); 549 547 550 - nfs_direct_join_group(&reqs, dreq->inode); 548 + nfs_direct_join_group(&reqs, &cinfo, dreq->inode); 551 549 552 550 nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo); 553 551 get_dreq(dreq);
+12 -11
fs/nfs/write.c
··· 59 59 static const struct nfs_commit_completion_ops nfs_commit_completion_ops; 60 60 static const struct nfs_rw_ops nfs_rw_write_ops; 61 61 static void nfs_inode_remove_request(struct nfs_page *req); 62 - static void nfs_clear_request_commit(struct nfs_page *req); 62 + static void nfs_clear_request_commit(struct nfs_commit_info *cinfo, 63 + struct nfs_page *req); 63 64 static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo, 64 65 struct inode *inode); 65 66 static struct nfs_page * ··· 503 502 * the (former) group. All subrequests are removed from any write or commit 504 503 * lists, unlinked from the group and destroyed. 505 504 */ 506 - void 507 - nfs_join_page_group(struct nfs_page *head, struct inode *inode) 505 + void nfs_join_page_group(struct nfs_page *head, struct nfs_commit_info *cinfo, 506 + struct inode *inode) 508 507 { 509 508 struct nfs_page *subreq; 510 509 struct nfs_page *destroy_list = NULL; ··· 534 533 * Commit list removal accounting is done after locks are dropped */ 535 534 subreq = head; 536 535 do { 537 - nfs_clear_request_commit(subreq); 536 + nfs_clear_request_commit(cinfo, subreq); 538 537 subreq = subreq->wb_this_page; 539 538 } while (subreq != head); 540 539 ··· 567 566 { 568 567 struct inode *inode = folio_file_mapping(folio)->host; 569 568 struct nfs_page *head; 569 + struct nfs_commit_info cinfo; 570 570 int ret; 571 571 572 + nfs_init_cinfo_from_inode(&cinfo, inode); 572 573 /* 573 574 * A reference is taken only on the head request which acts as a 574 575 * reference to the whole page group - the group will not be destroyed ··· 587 584 return ERR_PTR(ret); 588 585 } 589 586 590 - nfs_join_page_group(head, inode); 587 + nfs_join_page_group(head, &cinfo, inode); 591 588 592 589 return head; 593 590 } ··· 958 955 } 959 956 960 957 /* Called holding the request lock on @req */ 961 - static void 962 - nfs_clear_request_commit(struct nfs_page *req) 958 + static void nfs_clear_request_commit(struct nfs_commit_info *cinfo, 959 + struct nfs_page *req) 963 960 { 964 961 if (test_bit(PG_CLEAN, &req->wb_flags)) { 965 962 struct nfs_open_context *ctx = nfs_req_openctx(req); 966 963 struct inode *inode = d_inode(ctx->dentry); 967 - struct nfs_commit_info cinfo; 968 964 969 - nfs_init_cinfo_from_inode(&cinfo, inode); 970 965 mutex_lock(&NFS_I(inode)->commit_mutex); 971 - if (!pnfs_clear_request_commit(req, &cinfo)) { 972 - nfs_request_remove_commit_list(req, &cinfo); 966 + if (!pnfs_clear_request_commit(req, cinfo)) { 967 + nfs_request_remove_commit_list(req, cinfo); 973 968 } 974 969 mutex_unlock(&NFS_I(inode)->commit_mutex); 975 970 nfs_folio_clear_commit(nfs_page_to_folio(req));
+3 -1
include/linux/nfs_page.h
··· 157 157 extern void nfs_unlock_and_release_request(struct nfs_page *); 158 158 extern struct nfs_page *nfs_page_group_lock_head(struct nfs_page *req); 159 159 extern int nfs_page_group_lock_subrequests(struct nfs_page *head); 160 - extern void nfs_join_page_group(struct nfs_page *head, struct inode *inode); 160 + extern void nfs_join_page_group(struct nfs_page *head, 161 + struct nfs_commit_info *cinfo, 162 + struct inode *inode); 161 163 extern int nfs_page_group_lock(struct nfs_page *); 162 164 extern void nfs_page_group_unlock(struct nfs_page *); 163 165 extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);