- struct nfs_open_context *ctx = dreq->ctx;
- struct inode *inode = ctx->dentry->d_inode;
- struct list_head *list = &dreq->list;
- struct page **pages = dreq->pages;
- size_t count = dreq->user_count;
- loff_t pos = dreq->pos;
- size_t wsize = NFS_SERVER(inode)->wsize;
- unsigned int curpage, pgbase;
-
- curpage = 0;
- pgbase = dreq->user_addr & ~PAGE_MASK;
- do {
- struct nfs_write_data *data;
- size_t bytes;
-
- bytes = wsize;
- if (count < wsize)
- bytes = count;
-
- BUG_ON(list_empty(list));
- data = list_entry(list->next, struct nfs_write_data, pages);
- list_move_tail(&data->pages, &dreq->rewrite_list);
-
- data->inode = inode;
- data->cred = ctx->cred;
- data->args.fh = NFS_FH(inode);
- data->args.context = ctx;
- data->args.offset = pos;
- data->args.pgbase = pgbase;
- data->args.pages = &pages[curpage];
- data->args.count = bytes;
- data->res.fattr = &data->fattr;
- data->res.count = bytes;
- data->res.verf = &data->verf;
-
- rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
- &nfs_write_direct_ops, data);
- NFS_PROTO(inode)->write_setup(data, sync);
-
- data->task.tk_priority = RPC_PRIORITY_NORMAL;
- data->task.tk_cookie = (unsigned long) inode;
-
- lock_kernel();
- rpc_execute(&data->task);
- unlock_kernel();
-
- dfprintk(VFS, "NFS: %5u initiated direct write call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
- data->task.tk_pid,
- inode->i_sb->s_id,
- (long long)NFS_FILEID(inode),
- bytes,
- (unsigned long long)data->args.offset);
-
- pos += bytes;
- pgbase += bytes;
- curpage += pgbase >> PAGE_SHIFT;
- pgbase &= ~PAGE_MASK;
-
- count -= bytes;
- } while (count != 0);
- BUG_ON(!list_empty(list));
-}
-
-static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos, struct page **pages, int nr_pages)
-{
- ssize_t result;
- sigset_t oldset;
- struct inode *inode = iocb->ki_filp->f_mapping->host;
- struct rpc_clnt *clnt = NFS_CLIENT(inode);
- struct nfs_direct_req *dreq;
- size_t wsize = NFS_SERVER(inode)->wsize;
- int sync = 0;
-
- dreq = nfs_direct_write_alloc(count, wsize);
- if (!dreq)
- return -ENOMEM;
- if (dreq->commit_data == NULL || count < wsize)
- sync = FLUSH_STABLE;