.. | .. |
---|
509 | 509 | return result; |
---|
510 | 510 | } |
---|
511 | 511 | |
---|
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) |
---|
514 | 514 | { |
---|
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; |
---|
516 | 533 | |
---|
517 | 534 | 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); |
---|
519 | 537 | 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); |
---|
525 | 538 | } |
---|
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); |
---|
527 | 553 | } |
---|
528 | 554 | } |
---|
529 | 555 | |
---|
.. | .. |
---|
549 | 575 | nfs_init_cinfo_from_dreq(&cinfo, dreq); |
---|
550 | 576 | nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo); |
---|
551 | 577 | |
---|
552 | | - nfs_direct_join_group(&reqs, dreq->inode); |
---|
| 578 | + nfs_direct_join_group(&reqs, &cinfo, dreq->inode); |
---|
553 | 579 | |
---|
554 | 580 | dreq->count = 0; |
---|
555 | 581 | dreq->max_count = 0; |
---|