| .. | .. |
|---|
| 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; |
|---|