aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-05 13:17:12 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-05 13:17:12 -0400
commit83715ad54fad5a7ed330110f83e31ae92630e9d9 (patch)
tree3e8717ef9d168cbefd950bac544cb38542e6ee90
parent5e66dd6d66ffe758b39b6dcadf2330753ee1159b (diff)
NFS: Fix NFS page_state usage
The introduction of the FLUSH_INVALIDATE argument to nfs_sync_inode_wait() does not clear the nr_unstable page state counter for pages that are being released. Also fix a longstanding similar bug when nfs_commit_list() fails. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/write.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index bca5734ca9fb..86bac6a5008e 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -578,7 +578,7 @@ static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, un
578 return ret; 578 return ret;
579} 579}
580 580
581static void nfs_cancel_requests(struct list_head *head) 581static void nfs_cancel_dirty_list(struct list_head *head)
582{ 582{
583 struct nfs_page *req; 583 struct nfs_page *req;
584 while(!list_empty(head)) { 584 while(!list_empty(head)) {
@@ -589,6 +589,19 @@ static void nfs_cancel_requests(struct list_head *head)
589 } 589 }
590} 590}
591 591
592static void nfs_cancel_commit_list(struct list_head *head)
593{
594 struct nfs_page *req;
595
596 while(!list_empty(head)) {
597 req = nfs_list_entry(head->next);
598 nfs_list_remove_request(req);
599 nfs_inode_remove_request(req);
600 nfs_clear_page_writeback(req);
601 dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
602 }
603}
604
592/* 605/*
593 * nfs_scan_dirty - Scan an inode for dirty requests 606 * nfs_scan_dirty - Scan an inode for dirty requests
594 * @inode: NFS inode to scan 607 * @inode: NFS inode to scan
@@ -1381,6 +1394,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1381 nfs_list_remove_request(req); 1394 nfs_list_remove_request(req);
1382 nfs_mark_request_commit(req); 1395 nfs_mark_request_commit(req);
1383 nfs_clear_page_writeback(req); 1396 nfs_clear_page_writeback(req);
1397 dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
1384 } 1398 }
1385 return -ENOMEM; 1399 return -ENOMEM;
1386} 1400}
@@ -1499,7 +1513,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
1499 if (pages != 0) { 1513 if (pages != 0) {
1500 spin_unlock(&nfsi->req_lock); 1514 spin_unlock(&nfsi->req_lock);
1501 if (how & FLUSH_INVALIDATE) 1515 if (how & FLUSH_INVALIDATE)
1502 nfs_cancel_requests(&head); 1516 nfs_cancel_dirty_list(&head);
1503 else 1517 else
1504 ret = nfs_flush_list(inode, &head, pages, how); 1518 ret = nfs_flush_list(inode, &head, pages, how);
1505 spin_lock(&nfsi->req_lock); 1519 spin_lock(&nfsi->req_lock);
@@ -1512,7 +1526,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
1512 break; 1526 break;
1513 if (how & FLUSH_INVALIDATE) { 1527 if (how & FLUSH_INVALIDATE) {
1514 spin_unlock(&nfsi->req_lock); 1528 spin_unlock(&nfsi->req_lock);
1515 nfs_cancel_requests(&head); 1529 nfs_cancel_commit_list(&head);
1516 spin_lock(&nfsi->req_lock); 1530 spin_lock(&nfsi->req_lock);
1517 continue; 1531 continue;
1518 } 1532 }