patch-2.1.59 linux/fs/nfs/write.c
Next file: linux/fs/super.c
Previous file: linux/fs/nfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 126
- Date:
Wed Oct 15 21:08:46 1997
- Orig file:
v2.1.58/linux/fs/nfs/write.c
- Orig date:
Tue Sep 23 16:48:49 1997
diff -u --recursive --new-file v2.1.58/linux/fs/nfs/write.c linux/fs/nfs/write.c
@@ -196,22 +196,44 @@
clear_bit(PG_uptodate, &page->flags);
goto io_error;
}
+ if (result != wsize)
+ printk("NFS: short write, wsize=%u, result=%d\n",
+ wsize, result);
refresh = 1;
buffer += wsize;
offset += wsize;
written += wsize;
count -= wsize;
+ /*
+ * If we've extended the file, update the inode
+ * now so we don't invalidate the cache.
+ */
+ if (offset > inode->i_size)
+ inode->i_size = offset;
} while (count);
io_error:
+ /* N.B. do we want to refresh if there was an error?? (fattr valid?) */
if (refresh) {
/* 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)
fattr.size = inode->i_size;
+ if (fattr.mtime.seconds < inode->i_mtime)
+ printk("nfs_writepage_sync: prior time??\n");
/* Solaris 2.5 server seems to send garbled
* fattrs occasionally */
- if (inode->i_ino == fattr.fileid)
+ if (inode->i_ino == fattr.fileid) {
+ /*
+ * We expect the mtime value to change, and
+ * don't want to invalidate the caches.
+ */
+ inode->i_mtime = fattr.mtime.seconds;
nfs_refresh_inode(inode, &fattr);
+ }
+ else
+ printk("nfs_writepage_sync: inode %ld, got %u?\n",
+ inode->i_ino, fattr.fileid);
}
nfs_unlock_page(page);
@@ -327,7 +349,7 @@
wreq = (struct nfs_wreq *) kmalloc(sizeof(*wreq), GFP_USER);
if (!wreq)
- return NULL;
+ goto out_fail;
memset(wreq, 0, sizeof(*wreq));
task = &wreq->wb_task;
@@ -336,11 +358,8 @@
task->tk_action = nfs_wback_lock;
rpcauth_lookupcred(task); /* Obtain user creds */
- if (task->tk_status < 0) {
- rpc_release_task(task);
- kfree(wreq);
- return NULL;
- }
+ if (task->tk_status < 0)
+ goto out_req;
/* Put the task on inode's writeback request list. */
wreq->wb_inode = inode;
@@ -357,6 +376,12 @@
rpc_wake_up_next(&write_queue);
return wreq;
+
+out_req:
+ rpc_release_task(task);
+ kfree(wreq);
+out_fail:
+ return NULL;
}
/*
@@ -423,6 +448,8 @@
}
remove_wait_queue(&page->wait, &wait);
current->state = TASK_RUNNING;
+if (atomic_read(&page->count) == 1)
+printk("NFS: lost a page\n");
atomic_dec(&page->count);
return retval;
}
@@ -808,15 +835,29 @@
}
clear_bit(PG_uptodate, &page->flags);
} else if (!WB_CANCELLED(req)) {
+ 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.
*/
- if (req->wb_fattr->size < inode->i_size)
- req->wb_fattr->size = inode->i_size;
- /* possible Solaris 2.5 server bug workaround */
- if (inode->i_ino == req->wb_fattr->fileid)
- nfs_refresh_inode(inode, req->wb_fattr);
+ if (fattr->mtime.seconds >= inode->i_mtime) {
+ if (fattr->size < inode->i_size)
+ fattr->size = inode->i_size;
+
+ /* possible Solaris 2.5 server bug workaround */
+ if (inode->i_ino == fattr->fileid) {
+ /*
+ * We expect these values to change, and
+ * don't want to invalidate the caches.
+ */
+ inode->i_size = fattr->size;
+ inode->i_mtime = fattr->mtime.seconds;
+ nfs_refresh_inode(inode, fattr);
+ }
+ else
+ printk("nfs_wback_result: inode %ld, got %u?\n",
+ inode->i_ino, fattr->fileid);
+ }
}
rpc_release_task(task);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov