aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 4cfada2cc09f..b383fdd3a15c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -98,11 +98,10 @@ struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
98 if (p) { 98 if (p) {
99 memset(p, 0, sizeof(*p)); 99 memset(p, 0, sizeof(*p));
100 INIT_LIST_HEAD(&p->pages); 100 INIT_LIST_HEAD(&p->pages);
101 if (pagecount < NFS_PAGEVEC_SIZE) 101 if (pagecount <= ARRAY_SIZE(p->page_array))
102 p->pagevec = &p->page_array[0]; 102 p->pagevec = p->page_array;
103 else { 103 else {
104 size_t size = ++pagecount * sizeof(struct page *); 104 p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS);
105 p->pagevec = kzalloc(size, GFP_NOFS);
106 if (!p->pagevec) { 105 if (!p->pagevec) {
107 mempool_free(p, nfs_commit_mempool); 106 mempool_free(p, nfs_commit_mempool);
108 p = NULL; 107 p = NULL;
@@ -126,14 +125,11 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
126 if (p) { 125 if (p) {
127 memset(p, 0, sizeof(*p)); 126 memset(p, 0, sizeof(*p));
128 INIT_LIST_HEAD(&p->pages); 127 INIT_LIST_HEAD(&p->pages);
129 if (pagecount < NFS_PAGEVEC_SIZE) 128 if (pagecount <= ARRAY_SIZE(p->page_array))
130 p->pagevec = &p->page_array[0]; 129 p->pagevec = p->page_array;
131 else { 130 else {
132 size_t size = ++pagecount * sizeof(struct page *); 131 p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS);
133 p->pagevec = kmalloc(size, GFP_NOFS); 132 if (!p->pagevec) {
134 if (p->pagevec) {
135 memset(p->pagevec, 0, size);
136 } else {
137 mempool_free(p, nfs_wdata_mempool); 133 mempool_free(p, nfs_wdata_mempool);
138 p = NULL; 134 p = NULL;
139 } 135 }
@@ -583,6 +579,17 @@ static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, un
583 return ret; 579 return ret;
584} 580}
585 581
582static void nfs_cancel_requests(struct list_head *head)
583{
584 struct nfs_page *req;
585 while(!list_empty(head)) {
586 req = nfs_list_entry(head->next);
587 nfs_list_remove_request(req);
588 nfs_inode_remove_request(req);
589 nfs_clear_page_writeback(req);
590 }
591}
592
586/* 593/*
587 * nfs_scan_dirty - Scan an inode for dirty requests 594 * nfs_scan_dirty - Scan an inode for dirty requests
588 * @inode: NFS inode to scan 595 * @inode: NFS inode to scan
@@ -627,7 +634,7 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_st
627 int res = 0; 634 int res = 0;
628 635
629 if (nfsi->ncommit != 0) { 636 if (nfsi->ncommit != 0) {
630 res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages); 637 res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);
631 nfsi->ncommit -= res; 638 nfsi->ncommit -= res;
632 if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) 639 if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
633 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); 640 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
@@ -1495,15 +1502,25 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
1495 pages = nfs_scan_dirty(inode, &head, idx_start, npages); 1502 pages = nfs_scan_dirty(inode, &head, idx_start, npages);
1496 if (pages != 0) { 1503 if (pages != 0) {
1497 spin_unlock(&nfsi->req_lock); 1504 spin_unlock(&nfsi->req_lock);
1498 ret = nfs_flush_list(inode, &head, pages, how); 1505 if (how & FLUSH_INVALIDATE)
1506 nfs_cancel_requests(&head);
1507 else
1508 ret = nfs_flush_list(inode, &head, pages, how);
1499 spin_lock(&nfsi->req_lock); 1509 spin_lock(&nfsi->req_lock);
1500 continue; 1510 continue;
1501 } 1511 }
1502 if (nocommit) 1512 if (nocommit)
1503 break; 1513 break;
1504 pages = nfs_scan_commit(inode, &head, 0, 0); 1514 pages = nfs_scan_commit(inode, &head, idx_start, npages);
1505 if (pages == 0) 1515 if (pages == 0)
1506 break; 1516 break;
1517 if (how & FLUSH_INVALIDATE) {
1518 spin_unlock(&nfsi->req_lock);
1519 nfs_cancel_requests(&head);
1520 spin_lock(&nfsi->req_lock);
1521 continue;
1522 }
1523 pages += nfs_scan_commit(inode, &head, 0, 0);
1507 spin_unlock(&nfsi->req_lock); 1524 spin_unlock(&nfsi->req_lock);
1508 ret = nfs_commit_list(inode, &head, how); 1525 ret = nfs_commit_list(inode, &head, how);
1509 spin_lock(&nfsi->req_lock); 1526 spin_lock(&nfsi->req_lock);
@@ -1512,7 +1529,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
1512 return ret; 1529 return ret;
1513} 1530}
1514 1531
1515int nfs_init_writepagecache(void) 1532int __init nfs_init_writepagecache(void)
1516{ 1533{
1517 nfs_wdata_cachep = kmem_cache_create("nfs_write_data", 1534 nfs_wdata_cachep = kmem_cache_create("nfs_write_data",
1518 sizeof(struct nfs_write_data), 1535 sizeof(struct nfs_write_data),
@@ -1534,7 +1551,7 @@ int nfs_init_writepagecache(void)
1534 return 0; 1551 return 0;
1535} 1552}
1536 1553
1537void nfs_destroy_writepagecache(void) 1554void __exit nfs_destroy_writepagecache(void)
1538{ 1555{
1539 mempool_destroy(nfs_commit_mempool); 1556 mempool_destroy(nfs_commit_mempool);
1540 mempool_destroy(nfs_wdata_mempool); 1557 mempool_destroy(nfs_wdata_mempool);