unsigned int, unsigned int);
static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc,
struct inode *inode, int ioflags);
+static void nfs_redirty_request(struct nfs_page *req);
static const struct rpc_call_ops nfs_write_partial_ops;
static const struct rpc_call_ops nfs_write_full_ops;
static const struct rpc_call_ops nfs_commit_ops;
BUG();
}
spin_unlock(&inode->i_lock);
- nfs_pageio_add_request(pgio, req);
+ if (!nfs_pageio_add_request(pgio, req)) {
+ nfs_redirty_request(req);
+ nfs_end_page_writeback(page);
+ nfs_clear_page_tag_locked(req);
+ return pgio->pg_error;
+ }
return 0;
}
/*
* Wait for a request to complete.
*
- * Interruptible by signals only if mounted with intr flag.
+ * Interruptible by fatal signals only.
*/
static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, unsigned int npages)
{
* then we need to zero any uninitalised data. */
if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE
&& !PageUptodate(req->wb_page))
- zero_user_page(req->wb_page, req->wb_bytes,
- PAGE_CACHE_SIZE - req->wb_bytes,
- KM_USER0);
+ zero_user_segment(req->wb_page, req->wb_bytes, PAGE_CACHE_SIZE);
return req;
}
return status;
}
+/*
+ * If the page cache is marked as unsafe or invalid, then we can't rely on
+ * the PageUptodate() flag. In this case, we will need to turn off
+ * write optimisations that depend on the page contents being correct.
+ */
+static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
+{
+ return PageUptodate(page) &&
+ !(NFS_I(inode)->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA));
+}
+
/*
* Update and possibly write a cached page of an NFS file.
*
(long long)(page_offset(page) +offset));
/* If we're not using byte range locks, and we know the page
- * is entirely in cache, it may be more efficient to avoid
- * fragmenting write requests.
+ * is up to date, it may be more efficient to extend the write
+ * to cover the entire page in order to avoid fragmentation
+ * inefficiencies.
*/
- if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
+ if (nfs_write_pageuptodate(page, inode) &&
+ inode->i_flock == NULL &&
+ !(file->f_flags & O_SYNC)) {
count = max(count + offset, nfs_page_length(page));
offset = 0;
}
return RPC_PRIORITY_NORMAL;
}
-static void nfs_execute_write(struct nfs_write_data *data)
-{
- struct rpc_clnt *clnt = NFS_CLIENT(data->inode);
- sigset_t oldset;
-
- rpc_clnt_sigmask(clnt, &oldset);
- rpc_execute(&data->task);
- rpc_clnt_sigunmask(clnt, &oldset);
-}
-
/*
* Set up the argument/result storage required for the RPC call.
*/
struct inode *inode = req->wb_context->path.dentry->d_inode;
int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
int priority = flush_task_priority(how);
+ struct rpc_task *task;
struct rpc_message msg = {
.rpc_argp = &data->args,
.rpc_resp = &data->res,
};
struct rpc_task_setup task_setup_data = {
.rpc_client = NFS_CLIENT(inode),
+ .task = &data->task,
.rpc_message = &msg,
.callback_ops = call_ops,
.callback_data = data,
/* Set up the initial task struct. */
NFS_PROTO(inode)->write_setup(data, &msg);
- rpc_init_task(&data->task, &task_setup_data);
dprintk("NFS: %5u initiated write call "
"(req %s/%Ld, %u bytes @ offset %Lu)\n",
count,
(unsigned long long)data->args.offset);
- nfs_execute_write(data);
+ task = rpc_run_task(&task_setup_data);
+ if (!IS_ERR(task))
+ rpc_put_task(task);
}
/*
static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags)
{
- int wsize = NFS_SERVER(inode)->wsize;
+ size_t wsize = NFS_SERVER(inode)->wsize;
if (wsize < PAGE_CACHE_SIZE)
nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
struct inode *inode = first->wb_context->path.dentry->d_inode;
int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
int priority = flush_task_priority(how);
+ struct rpc_task *task;
struct rpc_message msg = {
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = first->wb_context->cred,
};
struct rpc_task_setup task_setup_data = {
+ .task = &data->task,
.rpc_client = NFS_CLIENT(inode),
.rpc_message = &msg,
.callback_ops = &nfs_commit_ops,
/* Set up the initial task struct. */
NFS_PROTO(inode)->commit_setup(data, &msg);
- rpc_init_task(&data->task, &task_setup_data);
dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
- nfs_execute_write(data);
+ task = rpc_run_task(&task_setup_data);
+ if (!IS_ERR(task))
+ rpc_put_task(task);
}
/*