From: Trond Myklebust <trond.myklebust@fys.uio.no>

--=-FFtuzYZJrfmt3IifntWE
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

NFSv2/v3/v4: Deal with the case where the server reads/writes fewer
bytes than we originally requested due to resource limitations etc.

Cheers,
 Trond

--=-FFtuzYZJrfmt3IifntWE
Content-Disposition: attachment; filename=linux-2.6.4-08-short_rw.dif
Content-Transfer-Encoding: base64
Content-Type: text/plain; name=linux-2.6.4-08-short_rw.dif; charset=ISO-8859-1

IHJlYWQuYyAgfCAgIDE5ICsrKysrKysrKysrKysrKy0tLS0NCiB3cml0ZS5jIHwgICA0NSArKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLS0NCiAyIGZpbGVzIGNoYW5n
ZWQsIDQ2IGluc2VydGlvbnMoKyksIDE4IGRlbGV0aW9ucygtKQ0KDQpkaWZmIC11IC0tcmVjdXJz
aXZlIC0tbmV3LWZpbGUgLS1zaG93LWMtZnVuY3Rpb24gbGludXgtMi42LjQtMjUtcnBjX2ZpeGVz
Mi9mcy9uZnMvcmVhZC5jIGxpbnV4LTIuNi40LTI2LXNob3J0X3J3L2ZzL25mcy9yZWFkLmMNCi0t
LSBsaW51eC0yLjYuNC0yNS1ycGNfZml4ZXMyL2ZzL25mcy9yZWFkLmMJMjAwNC0wMy0wNiAwMjoy
NTo1MS4wMDAwMDAwMDAgLTA1MDANCisrKyBsaW51eC0yLjYuNC0yNi1zaG9ydF9ydy9mcy9uZnMv
cmVhZC5jCTIwMDQtMDMtMDYgMDI6NDY6MjIuMDAwMDAwMDAwIC0wNTAwDQpAQCAtNDIxLDggKzQy
MSw2IEBAIHN0YXRpYyB2b2lkIG5mc19yZWFkcGFnZV9yZXN1bHRfcGFydGlhbCgNCiAJCQltZW1j
bGVhcl9oaWdocGFnZV9mbHVzaChwYWdlLA0KIAkJCQkJCWRhdGEtPmFyZ3MucGdiYXNlICsgcmVz
dWx0LA0KIAkJCQkJCXJlcXVlc3QgLSByZXN1bHQpOw0KLQkJCWlmICghZGF0YS0+cmVzLmVvZikN
Ci0JCQkJU2V0UGFnZUVycm9yKHBhZ2UpOw0KIAkJfQ0KIAl9IGVsc2UNCiAJCVNldFBhZ2VFcnJv
cihwYWdlKTsNCkBAIC00NTMsOCArNDUxLDYgQEAgc3RhdGljIHZvaWQgbmZzX3JlYWRwYWdlX3Jl
c3VsdF9mdWxsKHN0cg0KIAkJCQkJbWVtY2xlYXJfaGlnaHBhZ2VfZmx1c2gocGFnZSwNCiAJCQkJ
CQkJcmVxLT53Yl9wZ2Jhc2UgKyBjb3VudCwNCiAJCQkJCQkJcmVxLT53Yl9ieXRlcyAtIGNvdW50
KTsNCi0JCQkJaWYgKCFkYXRhLT5yZXMuZW9mKQ0KLQkJCQkJU2V0UGFnZUVycm9yKHBhZ2UpOw0K
IAkJCQljb3VudCA9IDA7DQogCQkJfSBlbHNlDQogCQkJCWNvdW50IC09IFBBR0VfQ0FDSEVfU0la
RTsNCkBAIC00NzIsMTEgKzQ2OCwyNiBAQCBzdGF0aWMgdm9pZCBuZnNfcmVhZHBhZ2VfcmVzdWx0
X2Z1bGwoc3RyDQogdm9pZCBuZnNfcmVhZHBhZ2VfcmVzdWx0KHN0cnVjdCBycGNfdGFzayAqdGFz
aykNCiB7DQogCXN0cnVjdCBuZnNfcmVhZF9kYXRhICpkYXRhID0gKHN0cnVjdCBuZnNfcmVhZF9k
YXRhICopdGFzay0+dGtfY2FsbGRhdGE7DQorCXN0cnVjdCBuZnNfcmVhZGFyZ3MgKmFyZ3AgPSAm
ZGF0YS0+YXJnczsNCisJc3RydWN0IG5mc19yZWFkcmVzICpyZXNwID0gJmRhdGEtPnJlczsNCiAJ
aW50IHN0YXR1cyA9IHRhc2stPnRrX3N0YXR1czsNCiANCiAJZHByaW50aygiTkZTOiAlNGQgbmZz
X3JlYWRwYWdlX3Jlc3VsdCwgKHN0YXR1cyAlZClcbiIsDQogCQl0YXNrLT50a19waWQsIHN0YXR1
cyk7DQogDQorCS8qIElzIHRoaXMgYSBzaG9ydCByZWFkPyAqLw0KKwlpZiAodGFzay0+dGtfc3Rh
dHVzID49IDAgJiYgcmVzcC0+Y291bnQgPCBhcmdwLT5jb3VudCAmJiAhcmVzcC0+ZW9mKSB7DQor
CQkvKiBIYXMgdGhlIHNlcnZlciBhdCBsZWFzdCBtYWRlIHNvbWUgcHJvZ3Jlc3M/ICovDQorCQlp
ZiAocmVzcC0+Y291bnQgIT0gMCkgew0KKwkJCS8qIFllcywgc28gcmV0cnkgdGhlIHJlYWQgYXQg
dGhlIGVuZCBvZiB0aGUgZGF0YSAqLw0KKwkJCWFyZ3AtPm9mZnNldCArPSByZXNwLT5jb3VudDsN
CisJCQlhcmdwLT5wZ2Jhc2UgKz0gcmVzcC0+Y291bnQ7DQorCQkJYXJncC0+Y291bnQgLT0gcmVz
cC0+Y291bnQ7DQorCQkJcnBjX3Jlc3RhcnRfY2FsbCh0YXNrKTsNCisJCQlyZXR1cm47DQorCQl9
DQorCQl0YXNrLT50a19zdGF0dXMgPSAtRUlPOw0KKwl9DQogCU5GU19GTEFHUyhkYXRhLT5pbm9k
ZSkgfD0gTkZTX0lOT19JTlZBTElEX0FUSU1FOw0KIAlkYXRhLT5jb21wbGV0ZShkYXRhLCBzdGF0
dXMpOw0KIH0NCmRpZmYgLXUgLS1yZWN1cnNpdmUgLS1uZXctZmlsZSAtLXNob3ctYy1mdW5jdGlv
biBsaW51eC0yLjYuNC0yNS1ycGNfZml4ZXMyL2ZzL25mcy93cml0ZS5jIGxpbnV4LTIuNi40LTI2
LXNob3J0X3J3L2ZzL25mcy93cml0ZS5jDQotLS0gbGludXgtMi42LjQtMjUtcnBjX2ZpeGVzMi9m
cy9uZnMvd3JpdGUuYwkyMDA0LTAzLTA2IDAyOjI1OjUxLjAwMDAwMDAwMCAtMDUwMA0KKysrIGxp
bnV4LTIuNi40LTI2LXNob3J0X3J3L2ZzL25mcy93cml0ZS5jCTIwMDQtMDMtMDYgMDI6NDg6Mjgu
MDAwMDAwMDAwIC0wNTAwDQpAQCAtMTE0MCwyMCArMTE0MCw4IEBAIHZvaWQgbmZzX3dyaXRlYmFj
a19kb25lKHN0cnVjdCBycGNfdGFzayANCiAJZHByaW50aygiTkZTOiAlNGQgbmZzX3dyaXRlYmFj
a19kb25lIChzdGF0dXMgJWQpXG4iLA0KIAkJdGFzay0+dGtfcGlkLCB0YXNrLT50a19zdGF0dXMp
Ow0KIA0KLQkvKiBXZSBjYW4ndCBoYW5kbGUgdGhhdCB5ZXQgYnV0IHdlIGNoZWNrIGZvciBpdCBu
ZXZlcnRoZWxlc3MgKi8NCi0JaWYgKHJlc3AtPmNvdW50IDwgYXJncC0+Y291bnQgJiYgdGFzay0+
dGtfc3RhdHVzID49IDApIHsNCi0JCXN0YXRpYyB1bnNpZ25lZCBsb25nICAgIGNvbXBsYWluOw0K
LQkJaWYgKHRpbWVfYmVmb3JlKGNvbXBsYWluLCBqaWZmaWVzKSkgew0KLQkJCXByaW50ayhLRVJO
X1dBUk5JTkcNCi0JCQkgICAgICAgIk5GUzogU2VydmVyIHdyb3RlIGxlc3MgdGhhbiByZXF1ZXN0
ZWQuXG4iKTsNCi0JCQljb21wbGFpbiA9IGppZmZpZXMgKyAzMDAgKiBIWjsNCi0JCX0NCi0JCS8q
IENhbid0IGRvIGFueXRoaW5nIGFib3V0IGl0IHJpZ2h0IG5vdyBleGNlcHQgdGhyb3cNCi0JCSAq
IGFuIGVycm9yLiAqLw0KLQkJdGFzay0+dGtfc3RhdHVzID0gLUVJTzsNCi0JfQ0KICNpZiBkZWZp
bmVkKENPTkZJR19ORlNfVjMpIHx8IGRlZmluZWQoQ09ORklHX05GU19WNCkNCi0JaWYgKGRhdGEt
PnZlcmYuY29tbWl0dGVkIDwgYXJncC0+c3RhYmxlICYmIHRhc2stPnRrX3N0YXR1cyA+PSAwKSB7
DQorCWlmIChyZXNwLT52ZXJmLT5jb21taXR0ZWQgPCBhcmdwLT5zdGFibGUgJiYgdGFzay0+dGtf
c3RhdHVzID49IDApIHsNCiAJCS8qIFdlIHRyaWVkIGEgd3JpdGUgY2FsbCwgYnV0IHRoZSBzZXJ2
ZXIgZGlkIG5vdA0KIAkJICogY29tbWl0IGRhdGEgdG8gc3RhYmxlIHN0b3JhZ2UgZXZlbiB0aG91
Z2ggd2UNCiAJCSAqIHJlcXVlc3RlZCBpdC4NCkBAIC0xMTY4LDExICsxMTU2LDQwIEBAIHZvaWQg
bmZzX3dyaXRlYmFja19kb25lKHN0cnVjdCBycGNfdGFzayANCiAJCQlkcHJpbnRrKCJORlM6IGZh
dWx0eSBORlMgc2VydmVyICVzOiINCiAJCQkJIiAoY29tbWl0dGVkID0gJWQpICE9IChzdGFibGUg
PSAlZClcbiIsDQogCQkJCU5GU19TRVJWRVIoZGF0YS0+aW5vZGUpLT5ob3N0bmFtZSwNCi0JCQkJ
ZGF0YS0+dmVyZi5jb21taXR0ZWQsIGFyZ3AtPnN0YWJsZSk7DQorCQkJCXJlc3AtPnZlcmYtPmNv
bW1pdHRlZCwgYXJncC0+c3RhYmxlKTsNCiAJCQljb21wbGFpbiA9IGppZmZpZXMgKyAzMDAgKiBI
WjsNCiAJCX0NCiAJfQ0KICNlbmRpZg0KKwkvKiBJcyB0aGlzIGEgc2hvcnQgd3JpdGU/ICovDQor
CWlmICh0YXNrLT50a19zdGF0dXMgPj0gMCAmJiByZXNwLT5jb3VudCA8IGFyZ3AtPmNvdW50KSB7
DQorCQlzdGF0aWMgdW5zaWduZWQgbG9uZyAgICBjb21wbGFpbjsNCisNCisJCS8qIEhhcyB0aGUg
c2VydmVyIGF0IGxlYXN0IG1hZGUgc29tZSBwcm9ncmVzcz8gKi8NCisJCWlmIChyZXNwLT5jb3Vu
dCAhPSAwKSB7DQorCQkJLyogV2FzIHRoaXMgYW4gTkZTdjIgd3JpdGUgb3IgYW4gTkZTdjMgc3Rh
YmxlIHdyaXRlPyAqLw0KKwkJCWlmIChyZXNwLT52ZXJmLT5jb21taXR0ZWQgIT0gTkZTX1VOU1RB
QkxFKSB7DQorCQkJCS8qIFJlc2VuZCBmcm9tIHdoZXJlIHRoZSBzZXJ2ZXIgbGVmdCBvZmYgKi8N
CisJCQkJYXJncC0+b2Zmc2V0ICs9IHJlc3AtPmNvdW50Ow0KKwkJCQlhcmdwLT5wZ2Jhc2UgKz0g
cmVzcC0+Y291bnQ7DQorCQkJCWFyZ3AtPmNvdW50IC09IHJlc3AtPmNvdW50Ow0KKwkJCX0gZWxz
ZSB7DQorCQkJCS8qIFJlc2VuZCBhcyBhIHN0YWJsZSB3cml0ZSBpbiBvcmRlciB0byBhdm9pZA0K
KwkJCQkgKiBoZWFkYWNoZXMgaW4gdGhlIGNhc2Ugb2YgYSBzZXJ2ZXIgY3Jhc2guDQorCQkJCSAq
Lw0KKwkJCQlhcmdwLT5zdGFibGUgPSBORlNfRklMRV9TWU5DOw0KKwkJCX0NCisJCQlycGNfcmVz
dGFydF9jYWxsKHRhc2spOw0KKwkJCXJldHVybjsNCisJCX0NCisJCWlmICh0aW1lX2JlZm9yZShj
b21wbGFpbiwgamlmZmllcykpIHsNCisJCQlwcmludGsoS0VSTl9XQVJOSU5HDQorCQkJICAgICAg
ICJORlM6IFNlcnZlciB3cm90ZSBsZXNzIHRoYW4gcmVxdWVzdGVkLlxuIik7DQorCQkJY29tcGxh
aW4gPSBqaWZmaWVzICsgMzAwICogSFo7DQorCQl9DQorCQkvKiBDYW4ndCBkbyBhbnl0aGluZyBh
Ym91dCBpdCBleGNlcHQgdGhyb3cgYW4gZXJyb3IuICovDQorCQl0YXNrLT50a19zdGF0dXMgPSAt
RUlPOw0KKwl9DQogDQogCS8qDQogCSAqIFByb2Nlc3MgdGhlIG5mc19wYWdlIGxpc3QNCk==

--=-FFtuzYZJrfmt3IifntWE--



---

 25-akpm/fs/nfs/read.c  |   19 +++++++++++++++----
 25-akpm/fs/nfs/write.c |   45 +++++++++++++++++++++++++++++++--------------
 2 files changed, 46 insertions(+), 18 deletions(-)

diff -puN fs/nfs/read.c~nfs-08-short_rw fs/nfs/read.c
--- 25/fs/nfs/read.c~nfs-08-short_rw	2004-03-23 22:59:31.137322936 -0800
+++ 25-akpm/fs/nfs/read.c	2004-03-23 22:59:31.141322328 -0800
@@ -422,8 +422,6 @@ static void nfs_readpage_result_partial(
 			memclear_highpage_flush(page,
 						data->args.pgbase + result,
 						request - result);
-			if (!data->res.eof)
-				SetPageError(page);
 		}
 	} else
 		SetPageError(page);
@@ -454,8 +452,6 @@ static void nfs_readpage_result_full(str
 					memclear_highpage_flush(page,
 							req->wb_pgbase + count,
 							req->wb_bytes - count);
-				if (!data->res.eof)
-					SetPageError(page);
 				count = 0;
 			} else
 				count -= PAGE_CACHE_SIZE;
@@ -473,11 +469,26 @@ static void nfs_readpage_result_full(str
 void nfs_readpage_result(struct rpc_task *task)
 {
 	struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
+	struct nfs_readargs *argp = &data->args;
+	struct nfs_readres *resp = &data->res;
 	int status = task->tk_status;
 
 	dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
 		task->tk_pid, status);
 
+	/* Is this a short read? */
+	if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) {
+		/* Has the server at least made some progress? */
+		if (resp->count != 0) {
+			/* Yes, so retry the read at the end of the data */
+			argp->offset += resp->count;
+			argp->pgbase += resp->count;
+			argp->count -= resp->count;
+			rpc_restart_call(task);
+			return;
+		}
+		task->tk_status = -EIO;
+	}
 	NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME;
 	data->complete(data, status);
 }
diff -puN fs/nfs/write.c~nfs-08-short_rw fs/nfs/write.c
--- 25/fs/nfs/write.c~nfs-08-short_rw	2004-03-23 22:59:31.138322784 -0800
+++ 25-akpm/fs/nfs/write.c	2004-03-23 22:59:31.142322176 -0800
@@ -1142,20 +1142,8 @@ void nfs_writeback_done(struct rpc_task 
 	dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
 		task->tk_pid, task->tk_status);
 
-	/* We can't handle that yet but we check for it nevertheless */
-	if (resp->count < argp->count && task->tk_status >= 0) {
-		static unsigned long    complain;
-		if (time_before(complain, jiffies)) {
-			printk(KERN_WARNING
-			       "NFS: Server wrote less than requested.\n");
-			complain = jiffies + 300 * HZ;
-		}
-		/* Can't do anything about it right now except throw
-		 * an error. */
-		task->tk_status = -EIO;
-	}
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-	if (data->verf.committed < argp->stable && task->tk_status >= 0) {
+	if (resp->verf->committed < argp->stable && task->tk_status >= 0) {
 		/* We tried a write call, but the server did not
 		 * commit data to stable storage even though we
 		 * requested it.
@@ -1170,11 +1158,40 @@ void nfs_writeback_done(struct rpc_task 
 			dprintk("NFS: faulty NFS server %s:"
 				" (committed = %d) != (stable = %d)\n",
 				NFS_SERVER(data->inode)->hostname,
-				data->verf.committed, argp->stable);
+				resp->verf->committed, argp->stable);
 			complain = jiffies + 300 * HZ;
 		}
 	}
 #endif
+	/* Is this a short write? */
+	if (task->tk_status >= 0 && resp->count < argp->count) {
+		static unsigned long    complain;
+
+		/* Has the server at least made some progress? */
+		if (resp->count != 0) {
+			/* Was this an NFSv2 write or an NFSv3 stable write? */
+			if (resp->verf->committed != NFS_UNSTABLE) {
+				/* Resend from where the server left off */
+				argp->offset += resp->count;
+				argp->pgbase += resp->count;
+				argp->count -= resp->count;
+			} else {
+				/* Resend as a stable write in order to avoid
+				 * headaches in the case of a server crash.
+				 */
+				argp->stable = NFS_FILE_SYNC;
+			}
+			rpc_restart_call(task);
+			return;
+		}
+		if (time_before(complain, jiffies)) {
+			printk(KERN_WARNING
+			       "NFS: Server wrote less than requested.\n");
+			complain = jiffies + 300 * HZ;
+		}
+		/* Can't do anything about it except throw an error. */
+		task->tk_status = -EIO;
+	}
 
 	/*
 	 * Process the nfs_page list

_