hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/nfs/direct.c
....@@ -509,21 +509,47 @@
509509 return result;
510510 }
511511
512
-static void
513
-nfs_direct_join_group(struct list_head *list, struct inode *inode)
512
+static void nfs_direct_add_page_head(struct list_head *list,
513
+ struct nfs_page *req)
514514 {
515
- struct nfs_page *req, *next;
515
+ struct nfs_page *head = req->wb_head;
516
+
517
+ if (!list_empty(&head->wb_list) || !nfs_lock_request(head))
518
+ return;
519
+ if (!list_empty(&head->wb_list)) {
520
+ nfs_unlock_request(head);
521
+ return;
522
+ }
523
+ list_add(&head->wb_list, list);
524
+ kref_get(&head->wb_kref);
525
+ kref_get(&head->wb_kref);
526
+}
527
+
528
+static void nfs_direct_join_group(struct list_head *list,
529
+ struct nfs_commit_info *cinfo,
530
+ struct inode *inode)
531
+{
532
+ struct nfs_page *req, *subreq;
516533
517534 list_for_each_entry(req, list, wb_list) {
518
- if (req->wb_head != req || req->wb_this_page == req)
535
+ if (req->wb_head != req) {
536
+ nfs_direct_add_page_head(&req->wb_list, req);
519537 continue;
520
- for (next = req->wb_this_page;
521
- next != req->wb_head;
522
- next = next->wb_this_page) {
523
- nfs_list_remove_request(next);
524
- nfs_release_request(next);
525538 }
526
- nfs_join_page_group(req, inode);
539
+ subreq = req->wb_this_page;
540
+ if (subreq == req)
541
+ continue;
542
+ do {
543
+ /*
544
+ * Remove subrequests from this list before freeing
545
+ * them in the call to nfs_join_page_group().
546
+ */
547
+ if (!list_empty(&subreq->wb_list)) {
548
+ nfs_list_remove_request(subreq);
549
+ nfs_release_request(subreq);
550
+ }
551
+ } while ((subreq = subreq->wb_this_page) != req);
552
+ nfs_join_page_group(req, cinfo, inode);
527553 }
528554 }
529555
....@@ -549,7 +575,7 @@
549575 nfs_init_cinfo_from_dreq(&cinfo, dreq);
550576 nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
551577
552
- nfs_direct_join_group(&reqs, dreq->inode);
578
+ nfs_direct_join_group(&reqs, &cinfo, dreq->inode);
553579
554580 dreq->count = 0;
555581 dreq->max_count = 0;