]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/nfs/write.c
NFS: Remove bogus nfs_mark_for_revalidate() in nfs_lookup
[karo-tx-linux.git] / fs / nfs / write.c
index 0c346d79fb34acd38124c9988301251ffd2a1ce6..3e9e268b887ee904d7b46547bb3b60b1df99b1c5 100644 (file)
@@ -110,6 +110,13 @@ void nfs_writedata_release(void *wdata)
        nfs_writedata_free(wdata);
 }
 
+static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
+{
+       ctx->error = error;
+       smp_wmb();
+       set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
+}
+
 static struct nfs_page *nfs_page_find_request_locked(struct page *page)
 {
        struct nfs_page *req = NULL;
@@ -292,41 +299,51 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        return 0;
 }
 
-/*
- * Write an mmapped page to the server.
- */
-static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc)
+static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio)
 {
-       struct nfs_pageio_descriptor mypgio, *pgio;
        struct inode *inode = page->mapping->host;
-       int err;
 
        nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
        nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
 
-       if (wbc->for_writepages)
-               pgio = wbc->fs_private;
-       else {
-               nfs_pageio_init_write(&mypgio, inode, wb_priority(wbc));
-               pgio = &mypgio;
-       }
-
        nfs_pageio_cond_complete(pgio, page->index);
+       return nfs_page_async_flush(pgio, page);
+}
 
-       err = nfs_page_async_flush(pgio, page);
+/*
+ * Write an mmapped page to the server.
+ */
+static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc)
+{
+       struct nfs_pageio_descriptor pgio;
+       int err;
 
-       if (!wbc->for_writepages)
-               nfs_pageio_complete(pgio);
-       return err;
+       nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc));
+       err = nfs_do_writepage(page, wbc, &pgio);
+       nfs_pageio_complete(&pgio);
+       if (err < 0)
+               return err;
+       if (pgio.pg_error < 0)
+               return pgio.pg_error;
+       return 0;
 }
 
 int nfs_writepage(struct page *page, struct writeback_control *wbc)
 {
-       int err;
+       int ret;
 
-       err = nfs_writepage_locked(page, wbc);
+       ret = nfs_writepage_locked(page, wbc);
        unlock_page(page);
-       return err; 
+       return ret;
+}
+
+static int nfs_writepages_callback(struct page *page, struct writeback_control *wbc, void *data)
+{
+       int ret;
+
+       ret = nfs_do_writepage(page, wbc, data);
+       unlock_page(page);
+       return ret;
 }
 
 int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
@@ -338,12 +355,11 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
        nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES);
 
        nfs_pageio_init_write(&pgio, inode, wb_priority(wbc));
-       wbc->fs_private = &pgio;
-       err = generic_writepages(mapping, wbc);
+       err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
        nfs_pageio_complete(&pgio);
-       if (err)
+       if (err < 0)
                return err;
-       if (pgio.pg_error)
+       if (pgio.pg_error < 0)
                return pgio.pg_error;
        return 0;
 }
@@ -651,7 +667,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
 
 int nfs_flush_incompatible(struct file *file, struct page *page)
 {
-       struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
+       struct nfs_open_context *ctx = nfs_file_open_context(file);
        struct nfs_page *req;
        int do_flush, status;
        /*
@@ -685,7 +701,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
 int nfs_updatepage(struct file *file, struct page *page,
                unsigned int offset, unsigned int count)
 {
-       struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
+       struct nfs_open_context *ctx = nfs_file_open_context(file);
        struct inode    *inode = page->mapping->host;
        int             status = 0;
 
@@ -936,7 +952,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
 
        if (task->tk_status < 0) {
                nfs_set_pageerror(page);
-               req->wb_context->error = task->tk_status;
+               nfs_context_set_write_error(req->wb_context, task->tk_status);
                dprintk(", error = %d\n", task->tk_status);
                goto out;
        }
@@ -999,7 +1015,7 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
 
                if (task->tk_status < 0) {
                        nfs_set_pageerror(page);
-                       req->wb_context->error = task->tk_status;
+                       nfs_context_set_write_error(req->wb_context, task->tk_status);
                        dprintk(", error = %d\n", task->tk_status);
                        goto remove_request;
                }
@@ -1213,7 +1229,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                        req->wb_bytes,
                        (long long)req_offset(req));
                if (task->tk_status < 0) {
-                       req->wb_context->error = task->tk_status;
+                       nfs_context_set_write_error(req->wb_context, task->tk_status);
                        nfs_inode_remove_request(req);
                        dprintk(", error = %d\n", task->tk_status);
                        goto next;
@@ -1316,53 +1332,52 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr
        return ret;
 }
 
-/*
- * flush the inode to disk.
- */
-int nfs_wb_all(struct inode *inode)
+static int __nfs_write_mapping(struct address_space *mapping, struct writeback_control *wbc, int how)
 {
-       struct address_space *mapping = inode->i_mapping;
-       struct writeback_control wbc = {
-               .bdi = mapping->backing_dev_info,
-               .sync_mode = WB_SYNC_ALL,
-               .nr_to_write = LONG_MAX,
-               .for_writepages = 1,
-               .range_cyclic = 1,
-       };
        int ret;
 
-       ret = nfs_writepages(mapping, &wbc);
+       ret = nfs_writepages(mapping, wbc);
        if (ret < 0)
                goto out;
-       ret = nfs_sync_mapping_wait(mapping, &wbc, 0);
-       if (ret >= 0)
-               return 0;
+       ret = nfs_sync_mapping_wait(mapping, wbc, how);
+       if (ret < 0)
+               goto out;
+       return 0;
 out:
        __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
        return ret;
 }
 
-int nfs_sync_mapping_range(struct address_space *mapping, loff_t range_start, loff_t range_end, int how)
+/* Two pass sync: first using WB_SYNC_NONE, then WB_SYNC_ALL */
+static int nfs_write_mapping(struct address_space *mapping, int how)
 {
        struct writeback_control wbc = {
                .bdi = mapping->backing_dev_info,
-               .sync_mode = WB_SYNC_ALL,
+               .sync_mode = WB_SYNC_NONE,
                .nr_to_write = LONG_MAX,
-               .range_start = range_start,
-               .range_end = range_end,
                .for_writepages = 1,
+               .range_cyclic = 1,
        };
        int ret;
 
-       ret = nfs_writepages(mapping, &wbc);
+       ret = __nfs_write_mapping(mapping, &wbc, how);
        if (ret < 0)
-               goto out;
-       ret = nfs_sync_mapping_wait(mapping, &wbc, how);
-       if (ret >= 0)
-               return 0;
-out:
-       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
-       return ret;
+               return ret;
+       wbc.sync_mode = WB_SYNC_ALL;
+       return __nfs_write_mapping(mapping, &wbc, how);
+}
+
+/*
+ * flush the inode to disk.
+ */
+int nfs_wb_all(struct inode *inode)
+{
+       return nfs_write_mapping(inode->i_mapping, 0);
+}
+
+int nfs_wb_nocommit(struct inode *inode)
+{
+       return nfs_write_mapping(inode->i_mapping, FLUSH_NOCOMMIT);
 }
 
 int nfs_wb_page_cancel(struct inode *inode, struct page *page)