patch-2.1.80 linux/fs/nfs/write.c
Next file: linux/fs/proc/array.c
Previous file: linux/fs/nfs/read.c
Back to the patch index
Back to the overall index
- Lines: 204
- Date:
Tue Jan 20 12:11:58 1998
- Orig file:
v2.1.79/linux/fs/nfs/write.c
- Orig date:
Mon Jan 12 22:09:18 1998
diff -u --recursive --new-file v2.1.79/linux/fs/nfs/write.c linux/fs/nfs/write.c
@@ -128,7 +128,7 @@
req->wb_flags |= NFS_WRITE_LOCKED;
rpc_wake_up_task(&req->wb_task);
- dprintk("nfs: wake up task %d (flags %x)\n",
+ dprintk("NFS: wake up task %d (flags %x)\n",
req->wb_task.tk_pid, req->wb_flags);
}
@@ -182,8 +182,8 @@
} while (count);
io_error:
- /* N.B. do we want to refresh if there was an error?? (fattr valid?) */
- if (refresh) {
+ /* Note: we don't refresh if the call failed (fattr invalid) */
+ if (refresh && result >= 0) {
/* See comments in nfs_wback_result */
/* N.B. I don't think this is right -- sync writes in order */
if (fattr.size < inode->i_size)
@@ -509,25 +509,16 @@
nfs_updatepage(struct dentry *dentry, struct page *page, const char *buffer,
unsigned long offset, unsigned int count, int sync)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = dentry->d_inode;
+ u8 *page_addr = (u8 *) page_address(page);
struct nfs_wreq *req;
int status = 0, page_locked = 1;
- u8 *page_addr;
dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
count, page->offset+offset, sync);
set_bit(PG_locked, &page->flags);
- page_addr = (u8 *) page_address(page);
-
- /* If wsize is smaller than page size, update and write
- * page synchronously.
- */
- if (NFS_SERVER(inode)->wsize < PAGE_SIZE) {
- copy_from_user(page_addr + offset, buffer, count);
- return nfs_writepage_sync(dentry, inode, page, offset, count);
- }
/*
* Try to find a corresponding request on the writeback queue.
@@ -541,6 +532,7 @@
*/
if ((req = find_write_request(inode, page)) != NULL) {
if (update_write_request(req, offset, count)) {
+ /* N.B. check for a fault here and cancel the req */
copy_from_user(page_addr + offset, buffer, count);
goto updated;
}
@@ -549,16 +541,23 @@
return 0;
}
+ /* Copy data to page buffer. */
+ status = -EFAULT;
+ if (copy_from_user(page_addr + offset, buffer, count))
+ goto done;
+
+ /* If wsize is smaller than page size, update and write
+ * page synchronously.
+ */
+ if (NFS_SERVER(inode)->wsize < PAGE_SIZE)
+ return nfs_writepage_sync(dentry, inode, page, offset, count);
+
/* Create the write request. */
status = -ENOBUFS;
req = create_write_request(dentry, inode, page, offset, count);
if (!req)
goto done;
- /* Copy data to page buffer. */
- /* N.B. should check for fault here ... */
- copy_from_user(page_addr + offset, buffer, count);
-
/* Schedule request */
page_locked = schedule_write_request(req, sync);
@@ -588,8 +587,14 @@
if ((count = nfs_write_error(inode)) < 0)
status = count;
}
- } else
+ } else {
+ if (status < 0) {
+printk("NFS: %s/%s write failed, clearing bit\n",
+dentry->d_parent->d_name.name, dentry->d_name.name);
+ clear_bit(PG_uptodate, &page->flags);
+ }
nfs_unlock_page(page);
+ }
}
dprintk("NFS: nfs_updatepage returns %d (isize %ld)\n",
@@ -641,21 +646,19 @@
req->wb_task.tk_pid,
req->wb_inode->i_dev, req->wb_inode->i_ino,
req->wb_page->offset, req->wb_flags);
- if (!WB_INPROGRESS(req)) {
- rqoffset = req->wb_page->offset + req->wb_offset;
- rqend = rqoffset + req->wb_bytes;
-
- if (rqoffset < end && offset < rqend
+ 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 (!WB_HAVELOCK(req)) {
+ if (!WB_INPROGRESS(req) && !WB_HAVELOCK(req)) {
#ifdef NFS_DEBUG_VERBOSE
printk("nfs_flush: flushing inode=%ld, %d @ %lu\n",
req->wb_inode->i_ino, req->wb_bytes, rqoffset);
#endif
- nfs_flush_request(req);
- }
- last = req;
+ nfs_flush_request(req);
}
+ last = req;
}
if (invalidate)
req->wb_flags |= NFS_WRITE_INVALIDATE;
@@ -815,32 +818,26 @@
struct page *page = req->wb_page;
struct dentry *dentry = req->wb_dentry;
- dprintk("NFS: %4d nfs_wback_lock (status %d flags %x)\n",
- task->tk_pid, task->tk_status, req->wb_flags);
+ dprintk("NFS: %4d nfs_wback_lock (%s/%s, status=%d flags=%x)\n",
+ task->tk_pid, dentry->d_parent->d_name.name,
+ dentry->d_name.name, task->tk_status, req->wb_flags);
if (!WB_HAVELOCK(req))
req->wb_flags |= NFS_WRITE_WANTLOCK;
- if (WB_WANTLOCK(req) && test_and_set_bit(PG_locked, &page->flags)) {
- printk("NFS: page already locked in writeback_lock!\n");
- task->tk_timeout = 2 * HZ;
- rpc_sleep_on(&write_queue, task, NULL, NULL);
- return;
- }
- task->tk_status = 0;
+ if (WB_WANTLOCK(req) && test_and_set_bit(PG_locked, &page->flags))
+ goto out_locked;
req->wb_flags &= ~NFS_WRITE_WANTLOCK;
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))) {
- task->tk_timeout = HZ;
- rpc_sleep_on(&write_queue, task, NULL, NULL);
- return;
- }
+ 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);
}
@@ -854,6 +851,18 @@
rpc_call_setup(task, NFSPROC_WRITE, req->wb_args, req->wb_fattr, 0);
req->wb_flags |= NFS_WRITE_INPROGRESS;
+ return;
+
+out_locked:
+ printk("NFS: page already locked in writeback_lock!\n");
+ 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;
}
/*
@@ -867,9 +876,12 @@
struct page *page = req->wb_page;
int status = task->tk_status;
- dprintk("NFS: %4d nfs_wback_result (status %d)\n",
- task->tk_pid, status);
+ dprintk("NFS: %4d nfs_wback_result (%s/%s, status=%d, flags=%x)\n",
+ 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 */
+ req->wb_flags |= NFS_WRITE_COMPLETE;
if (status < 0) {
/*
* An error occurred. Report the error back to the
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov