static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
-struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
+struct nfs_write_data *nfs_commit_alloc(void)
{
struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
- if (pagecount <= ARRAY_SIZE(p->page_array))
- p->pagevec = p->page_array;
- else {
- p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS);
- if (!p->pagevec) {
- mempool_free(p, nfs_commit_mempool);
- p = NULL;
- }
- }
}
return p;
}
mempool_free(p, nfs_commit_mempool);
}
-struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
+struct nfs_write_data *nfs_writedata_alloc(size_t len)
{
+ unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS);
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
+ p->npages = pagecount;
if (pagecount <= ARRAY_SIZE(p->page_array))
p->pagevec = p->page_array;
else {
return p;
}
-void nfs_writedata_free(struct nfs_write_data *p)
+static void nfs_writedata_free(struct nfs_write_data *p)
{
if (p && (p->pagevec != &p->page_array[0]))
kfree(p->pagevec);
int result, written = 0;
struct nfs_write_data *wdata;
- wdata = nfs_writedata_alloc(1);
+ wdata = nfs_writedata_alloc(wsize);
if (!wdata)
return -ENOMEM;
out:
clear_bit(BDI_write_congested, &bdi->state);
wake_up_all(&nfs_write_congestion);
+ writeback_congestion_end();
return err;
}
return ret;
}
-static void nfs_cancel_requests(struct list_head *head)
+static void nfs_cancel_dirty_list(struct list_head *head)
{
struct nfs_page *req;
while(!list_empty(head)) {
}
}
+static void nfs_cancel_commit_list(struct list_head *head)
+{
+ struct nfs_page *req;
+
+ while(!list_empty(head)) {
+ req = nfs_list_entry(head->next);
+ nfs_list_remove_request(req);
+ nfs_inode_remove_request(req);
+ dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+ nfs_clear_page_writeback(req);
+ }
+}
+
/*
* nfs_scan_dirty - Scan an inode for dirty requests
* @inode: NFS inode to scan
struct nfs_page *req = nfs_list_entry(head->next);
struct page *page = req->wb_page;
struct nfs_write_data *data;
- unsigned int wsize = NFS_SERVER(inode)->wsize;
- unsigned int nbytes, offset;
+ size_t wsize = NFS_SERVER(inode)->wsize, nbytes;
+ unsigned int offset;
int requests = 0;
LIST_HEAD(list);
nfs_list_remove_request(req);
nbytes = req->wb_bytes;
- for (;;) {
- data = nfs_writedata_alloc(1);
+ do {
+ size_t len = min(nbytes, wsize);
+
+ data = nfs_writedata_alloc(len);
if (!data)
goto out_bad;
list_add(&data->pages, &list);
requests++;
- if (nbytes <= wsize)
- break;
- nbytes -= wsize;
- }
+ nbytes -= len;
+ } while (nbytes != 0);
atomic_set(&req->wb_complete, requests);
ClearPageError(page);
struct nfs_write_data *data;
unsigned int count;
- data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
+ data = nfs_writedata_alloc(NFS_SERVER(inode)->wsize);
if (!data)
goto out_bad;
if (time_before(complain, jiffies)) {
dprintk("NFS: faulty NFS server %s:"
" (committed = %d) != (stable = %d)\n",
- NFS_SERVER(data->inode)->hostname,
+ NFS_SERVER(data->inode)->nfs_client->cl_hostname,
resp->verf->committed, argp->stable);
complain = jiffies + 300 * HZ;
}
struct nfs_write_data *data;
struct nfs_page *req;
- data = nfs_commit_alloc(NFS_SERVER(inode)->wpages);
+ data = nfs_commit_alloc();
if (!data)
goto out_bad;
req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
nfs_mark_request_commit(req);
+ dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
nfs_clear_page_writeback(req);
}
return -ENOMEM;
if (pages != 0) {
spin_unlock(&nfsi->req_lock);
if (how & FLUSH_INVALIDATE)
- nfs_cancel_requests(&head);
+ nfs_cancel_dirty_list(&head);
else
ret = nfs_flush_list(inode, &head, pages, how);
spin_lock(&nfsi->req_lock);
break;
if (how & FLUSH_INVALIDATE) {
spin_unlock(&nfsi->req_lock);
- nfs_cancel_requests(&head);
+ nfs_cancel_commit_list(&head);
spin_lock(&nfsi->req_lock);
continue;
}