patch-2.1.82 linux/fs/nfs/write.c
Next file: linux/fs/nfsd/nfsproc.c
Previous file: linux/fs/nfs/nfs2xdr.c
Back to the patch index
Back to the overall index
- Lines: 195
- Date:
Sat Jan 24 10:53:00 1998
- Orig file:
v2.1.81/linux/fs/nfs/write.c
- Orig date:
Tue Jan 20 12:11:58 1998
diff -u --recursive --new-file v2.1.81/linux/fs/nfs/write.c linux/fs/nfs/write.c
@@ -46,7 +46,6 @@
* Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
*/
-#define NFS_NEED_XDR_TYPES
#include <linux/config.h>
#include <linux/types.h>
#include <linux/malloc.h>
@@ -372,8 +371,8 @@
create_write_request(struct dentry *dentry, struct inode *inode,
struct page *page, unsigned int offset, unsigned int bytes)
{
- struct nfs_wreq *wreq;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
+ struct nfs_wreq *wreq;
struct rpc_task *task;
dprintk("NFS: create_write_request(%s/%s, %ld+%d)\n",
@@ -424,7 +423,7 @@
* Schedule a writeback RPC call.
* If the server is congested, don't add to our backlog of queued
* requests but call it synchronously.
- * The function returns true if the page has been unlocked as the
+ * The function returns false if the page has been unlocked as the
* consequence of a synchronous write call.
*
* FIXME: Here we could walk the inode's lock list to see whether the
@@ -642,15 +641,16 @@
req = head = NFS_WRITEBACK(inode);
while (req != NULL) {
- dprintk("NFS: %4d nfs_flush inspect %x/%ld @%ld fl %x\n",
- req->wb_task.tk_pid,
- req->wb_inode->i_dev, req->wb_inode->i_ino,
- req->wb_page->offset, req->wb_flags);
+ dprintk("NFS: %4d nfs_flush inspect %s/%s @%ld fl %x\n",
+ req->wb_task.tk_pid,
+ req->wb_dentry->d_parent->d_name.name,
+ req->wb_dentry->d_name.name,
+ req->wb_page->offset, req->wb_flags);
+
rqoffset = req->wb_page->offset + req->wb_offset;
rqend = rqoffset + req->wb_bytes;
-
- if (rqoffset < end && offset < rqend
- && (pid == 0 || req->wb_pid == pid)) {
+ if (rqoffset < end && offset < rqend &&
+ (pid == 0 || req->wb_pid == pid)) {
if (!WB_INPROGRESS(req) && !WB_HAVELOCK(req)) {
#ifdef NFS_DEBUG_VERBOSE
printk("nfs_flush: flushing inode=%ld, %d @ %lu\n",
@@ -670,11 +670,23 @@
}
/*
+ * Cancel a write request. We always mark it cancelled,
+ * but if it's already in progress there's no point in
+ * calling rpc_exit, and we don't want to overwrite the
+ * tk_status field.
+ */
+static void
+nfs_cancel_request(struct nfs_wreq *req)
+{
+ req->wb_flags |= NFS_WRITE_CANCELLED;
+ if (!WB_INPROGRESS(req)) {
+ rpc_exit(&req->wb_task, 0);
+ rpc_wake_up_task(&req->wb_task);
+ }
+}
+
+/*
* Cancel all writeback requests, both pending and in progress.
- *
- * N.B. This doesn't seem to wake up the tasks -- are we sure
- * they will eventually complete? Also, this could overwrite a
- * failed status code from an already-completed task.
*/
static void
nfs_cancel_dirty(struct inode *inode, pid_t pid)
@@ -683,11 +695,8 @@
req = head = NFS_WRITEBACK(inode);
while (req != NULL) {
- /* N.B. check for task already finished? */
- if (pid == 0 || req->wb_pid == pid) {
- req->wb_flags |= NFS_WRITE_CANCELLED;
- rpc_exit(&req->wb_task, 0);
- }
+ if (pid == 0 || req->wb_pid == pid)
+ nfs_cancel_request(req);
if ((req = WB_NEXT(req)) == head)
break;
}
@@ -708,8 +717,7 @@
int result = 0, cancel = 0;
dprintk("NFS: flush_dirty_pages(%x/%ld for pid %d %ld/%ld)\n",
- inode->i_dev, inode->i_ino, current->pid,
- offset, len);
+ inode->i_dev, inode->i_ino, current->pid, offset, len);
if (IS_SOFT && signalled()) {
nfs_cancel_dirty(inode, pid);
@@ -762,16 +770,15 @@
struct nfs_wreq *req, *head;
unsigned long rqoffset;
- dprintk("NFS: truncate_dirty_pages(%x/%ld, %ld)\n",
- inode->i_dev, inode->i_ino, offset);
+ dprintk("NFS: truncate_dirty_pages(%d/%ld, %ld)\n",
+ inode->i_dev, inode->i_ino, offset);
req = head = NFS_WRITEBACK(inode);
while (req != NULL) {
rqoffset = req->wb_page->offset + req->wb_offset;
if (rqoffset >= offset) {
- req->wb_flags |= NFS_WRITE_CANCELLED;
- rpc_exit(&req->wb_task, 0);
+ nfs_cancel_request(req);
} else if (rqoffset + req->wb_bytes >= offset) {
req->wb_bytes = offset - rqoffset;
}
@@ -831,24 +838,13 @@
req->wb_flags |= NFS_WRITE_LOCKED;
task->tk_status = 0;
- if (req->wb_args == 0) {
- size_t size = sizeof(struct nfs_writeargs)
- + sizeof(struct nfs_fattr);
- void *ptr;
-
- if (!(ptr = kmalloc(size, GFP_KERNEL)))
- goto out_no_args;
- req->wb_args = (struct nfs_writeargs *) ptr;
- req->wb_fattr = (struct nfs_fattr *) (req->wb_args + 1);
- }
-
/* Setup the task struct for a writeback call */
- req->wb_args->fh = NFS_FH(dentry);
- req->wb_args->offset = page->offset + req->wb_offset;
- req->wb_args->count = req->wb_bytes;
- req->wb_args->buffer = (void *) (page_address(page) + req->wb_offset);
+ req->wb_args.fh = NFS_FH(dentry);
+ req->wb_args.offset = page->offset + req->wb_offset;
+ req->wb_args.count = req->wb_bytes;
+ req->wb_args.buffer = (void *) (page_address(page) + req->wb_offset);
- rpc_call_setup(task, NFSPROC_WRITE, req->wb_args, req->wb_fattr, 0);
+ rpc_call_setup(task, NFSPROC_WRITE, &req->wb_args, &req->wb_fattr, 0);
req->wb_flags |= NFS_WRITE_INPROGRESS;
return;
@@ -858,11 +854,6 @@
task->tk_timeout = 2 * HZ;
rpc_sleep_on(&write_queue, task, NULL, NULL);
return;
-out_no_args:
- printk("NFS: can't alloc args, sleeping\n");
- task->tk_timeout = HZ;
- rpc_sleep_on(&write_queue, task, NULL, NULL);
- return;
}
/*
@@ -880,7 +871,7 @@
task->tk_pid, req->wb_dentry->d_parent->d_name.name,
req->wb_dentry->d_name.name, status, req->wb_flags);
- /* Set the WRITE_COMPLETE flag, but leave INPROGRESS set */
+ /* Set the WRITE_COMPLETE flag, but leave WRITE_INPROGRESS set */
req->wb_flags |= NFS_WRITE_COMPLETE;
if (status < 0) {
/*
@@ -892,7 +883,7 @@
status = 0;
clear_bit(PG_uptodate, &page->flags);
} else if (!WB_CANCELLED(req)) {
- struct nfs_fattr *fattr = req->wb_fattr;
+ struct nfs_fattr *fattr = &req->wb_fattr;
/* Update attributes as result of writeback.
* Beware: when UDP replies arrive out of order, we
* may end up overwriting a previous, bigger file size.
@@ -927,11 +918,6 @@
clear_bit(PG_uptodate, &page->flags);
if (WB_HAVELOCK(req))
nfs_unlock_page(page);
-
- if (req->wb_args) {
- kfree(req->wb_args);
- req->wb_args = 0;
- }
/*
* Now it's safe to remove the request from the inode's
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov