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

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

NFSv2/v3/v4: Patch by Chuck Lever that add support for asynchronous
reads even if rsize<PAGE_CACHE_SIZE.

Cheers,
  Trond

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

IGZzL25mcy9kaXJlY3QuYyAgICAgICAgIHwgICAgMQ0KIGZzL25mcy9uZnMzcHJvYy5jICAgICAg
IHwgICAyMSAtLS0NCiBmcy9uZnMvbmZzNHByb2MuYyAgICAgICB8ICAgNDEgLS0tLS0NCiBmcy9u
ZnMvbmZzNHhkci5jICAgICAgICB8ICAgMjIgKystDQogZnMvbmZzL3Byb2MuYyAgICAgICAgICAg
fCAgIDIxIC0tLQ0KIGZzL25mcy9yZWFkLmMgICAgICAgICAgIHwgIDMzMSArKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0NCiBpbmNsdWRlL2xpbnV4L25mc19m
cy5oICB8ICAgIDENCiBpbmNsdWRlL2xpbnV4L25mc194ZHIuaCB8ICAgIDYNCiA4IGZpbGVzIGNo
YW5nZWQsIDI4OCBpbnNlcnRpb25zKCspLCAxNTYgZGVsZXRpb25zKC0pDQoNCmRpZmYgLXUgLS1y
ZWN1cnNpdmUgLS1uZXctZmlsZSAtLXNob3ctYy1mdW5jdGlvbiBsaW51eC0yLjYuMy0xOS1wcmVw
YXJlX25mc3BhZ2UvZnMvbmZzL2RpcmVjdC5jIGxpbnV4LTIuNi4zLTIwLXNtYWxsX3JzaXplL2Zz
L25mcy9kaXJlY3QuYw0KLS0tIGxpbnV4LTIuNi4zLTE5LXByZXBhcmVfbmZzcGFnZS9mcy9uZnMv
ZGlyZWN0LmMJMjAwNC0wMy0wMSAxOTozODoyOS4wMDAwMDAwMDAgLTA1MDANCisrKyBsaW51eC0y
LjYuMy0yMC1zbWFsbF9yc2l6ZS9mcy9uZnMvZGlyZWN0LmMJMjAwNC0wMy0wMSAxOTo0MTowNi4w
MDAwMDAwMDAgLTA1MDANCkBAIC0xMjgsNiArMTI4LDcgQEAgbmZzX2RpcmVjdF9yZWFkX3NlZyhz
dHJ1Y3QgaW5vZGUgKmlub2RlLA0KIAkJLmlub2RlCQk9IGlub2RlLA0KIAkJLmFyZ3MJCT0gew0K
IAkJCS5maAkJPSBORlNfRkgoaW5vZGUpLA0KKwkJCS5sb2Nrb3duZXIJPSBjdXJyZW50LT5maWxl
cywNCiAJCX0sDQogCQkucmVzCQk9IHsNCiAJCQkuZmF0dHIJCT0gJnJkYXRhLmZhdHRyLA0KZGlm
ZiAtdSAtLXJlY3Vyc2l2ZSAtLW5ldy1maWxlIC0tc2hvdy1jLWZ1bmN0aW9uIGxpbnV4LTIuNi4z
LTE5LXByZXBhcmVfbmZzcGFnZS9mcy9uZnMvbmZzM3Byb2MuYyBsaW51eC0yLjYuMy0yMC1zbWFs
bF9yc2l6ZS9mcy9uZnMvbmZzM3Byb2MuYw0KLS0tIGxpbnV4LTIuNi4zLTE5LXByZXBhcmVfbmZz
cGFnZS9mcy9uZnMvbmZzM3Byb2MuYwkyMDA0LTAzLTAxIDE5OjM4OjQ3LjAwMDAwMDAwMCAtMDUw
MA0KKysrIGxpbnV4LTIuNi4zLTIwLXNtYWxsX3JzaXplL2ZzL25mcy9uZnMzcHJvYy5jCTIwMDQt
MDMtMDEgMTk6NDE6MDYuMDAwMDAwMDAwIC0wNTAwDQpAQCAtNzI5LDExICs3MjksMTAgQEAgbmZz
M19yZWFkX2RvbmUoc3RydWN0IHJwY190YXNrICp0YXNrKQ0KIH0NCiANCiBzdGF0aWMgdm9pZA0K
LW5mczNfcHJvY19yZWFkX3NldHVwKHN0cnVjdCBuZnNfcmVhZF9kYXRhICpkYXRhLCB1bnNpZ25l
ZCBpbnQgY291bnQpDQorbmZzM19wcm9jX3JlYWRfc2V0dXAoc3RydWN0IG5mc19yZWFkX2RhdGEg
KmRhdGEpDQogew0KIAlzdHJ1Y3QgcnBjX3Rhc2sJCSp0YXNrID0gJmRhdGEtPnRhc2s7DQogCXN0
cnVjdCBpbm9kZQkJKmlub2RlID0gZGF0YS0+aW5vZGU7DQotCXN0cnVjdCBuZnNfcGFnZQkJKnJl
cTsNCiAJaW50CQkJZmxhZ3M7DQogCXN0cnVjdCBycGNfbWVzc2FnZQltc2cgPSB7DQogCQkucnBj
X3Byb2MJPSAmbmZzM19wcm9jZWR1cmVzW05GUzNQUk9DX1JFQURdLA0KQEAgLTc0MSwyNyArNzQw
LDEzIEBAIG5mczNfcHJvY19yZWFkX3NldHVwKHN0cnVjdCBuZnNfcmVhZF9kYXQNCiAJCS5ycGNf
cmVzcAk9ICZkYXRhLT5yZXMsDQogCQkucnBjX2NyZWQJPSBkYXRhLT5jcmVkLA0KIAl9Ow0KLQkN
Ci0JcmVxID0gbmZzX2xpc3RfZW50cnkoZGF0YS0+cGFnZXMubmV4dCk7DQotCWRhdGEtPmFyZ3Mu
ZmggICAgID0gTkZTX0ZIKGlub2RlKTsNCi0JZGF0YS0+YXJncy5vZmZzZXQgPSByZXFfb2Zmc2V0
KHJlcSk7DQotCWRhdGEtPmFyZ3MucGdiYXNlID0gcmVxLT53Yl9wZ2Jhc2U7DQotCWRhdGEtPmFy
Z3MucGFnZXMgID0gZGF0YS0+cGFnZXZlYzsNCi0JZGF0YS0+YXJncy5jb3VudCAgPSBjb3VudDsN
Ci0JZGF0YS0+cmVzLmZhdHRyICAgPSAmZGF0YS0+ZmF0dHI7DQotCWRhdGEtPnJlcy5jb3VudCAg
ID0gY291bnQ7DQotCWRhdGEtPnJlcy5lb2YgICAgID0gMDsNCi0JDQorDQogCS8qIE4uQi4gRG8g
d2UgbmVlZCB0byB0ZXN0PyBOZXZlciBjYWxsZWQgZm9yIHN3YXBmaWxlIGlub2RlICovDQogCWZs
YWdzID0gUlBDX1RBU0tfQVNZTkMgfCAoSVNfU1dBUEZJTEUoaW5vZGUpPyBORlNfUlBDX1NXQVBG
TEFHUyA6IDApOw0KIA0KIAkvKiBGaW5hbGl6ZSB0aGUgdGFzay4gKi8NCiAJcnBjX2luaXRfdGFz
ayh0YXNrLCBORlNfQ0xJRU5UKGlub2RlKSwgbmZzM19yZWFkX2RvbmUsIGZsYWdzKTsNCi0JdGFz
ay0+dGtfY2FsbGRhdGEgPSBkYXRhOw0KLQkvKiBSZWxlYXNlIHJlcXVlc3RzICovDQotCXRhc2st
PnRrX3JlbGVhc2UgPSBuZnNfcmVhZGRhdGFfcmVsZWFzZTsNCi0NCi0JcnBjX2NhbGxfc2V0dXAo
JmRhdGEtPnRhc2ssICZtc2csIDApOw0KKwlycGNfY2FsbF9zZXR1cCh0YXNrLCAmbXNnLCAwKTsN
CiB9DQogDQogc3RhdGljIHZvaWQNCmRpZmYgLXUgLS1yZWN1cnNpdmUgLS1uZXctZmlsZSAtLXNo
b3ctYy1mdW5jdGlvbiBsaW51eC0yLjYuMy0xOS1wcmVwYXJlX25mc3BhZ2UvZnMvbmZzL25mczRw
cm9jLmMgbGludXgtMi42LjMtMjAtc21hbGxfcnNpemUvZnMvbmZzL25mczRwcm9jLmMNCi0tLSBs
aW51eC0yLjYuMy0xOS1wcmVwYXJlX25mc3BhZ2UvZnMvbmZzL25mczRwcm9jLmMJMjAwNC0wMy0w
MSAxOTozOTozMi4wMDAwMDAwMDAgLTA1MDANCisrKyBsaW51eC0yLjYuMy0yMC1zbWFsbF9yc2l6
ZS9mcy9uZnMvbmZzNHByb2MuYwkyMDA0LTAzLTAxIDE5OjQxOjA2LjAwMDAwMDAwMCAtMDUwMA0K
QEAgLTEwODUsMTAgKzEwODUsMTAgQEAgbmZzNF9wcm9jX3JlYWQoc3RydWN0IG5mc19yZWFkX2Rh
dGEgKnJkYQ0KIAlpZiAoZmlscCkgew0KIAkJc3RydWN0IG5mczRfc3RhdGUgKnN0YXRlOw0KIAkJ
c3RhdGUgPSAoc3RydWN0IG5mczRfc3RhdGUgKilmaWxwLT5wcml2YXRlX2RhdGE7DQotCQluZnM0
X2NvcHlfc3RhdGVpZCgmcmRhdGEtPmFyZ3Muc3RhdGVpZCwgc3RhdGUsIHJkYXRhLT5sb2Nrb3du
ZXIpOw0KKwkJcmRhdGEtPmFyZ3Muc3RhdGUgPSBzdGF0ZTsNCiAJCW1zZy5ycGNfY3JlZCA9IHN0
YXRlLT5vd25lci0+c29fY3JlZDsNCiAJfSBlbHNlIHsNCi0JCW1lbWNweSgmcmRhdGEtPmFyZ3Mu
c3RhdGVpZCwgJnplcm9fc3RhdGVpZCwgc2l6ZW9mKHJkYXRhLT5hcmdzLnN0YXRlaWQpKTsNCisJ
CXJkYXRhLT5hcmdzLnN0YXRlID0gTlVMTDsNCiAJCW1zZy5ycGNfY3JlZCA9IE5GU19JKGlub2Rl
KS0+bW1fY3JlZDsNCiAJfQ0KIA0KQEAgLTE0OTksMjcgKzE0OTksMTMgQEAgbmZzNF9wcm9jX3Bh
dGhjb25mKHN0cnVjdCBuZnNfc2VydmVyICpzZQ0KIH0NCiANCiBzdGF0aWMgdm9pZA0KLW5mczRf
cmVzdGFydF9yZWFkKHN0cnVjdCBycGNfdGFzayAqdGFzaykNCi17DQotCXN0cnVjdCBuZnNfcmVh
ZF9kYXRhICpkYXRhID0gKHN0cnVjdCBuZnNfcmVhZF9kYXRhICopdGFzay0+dGtfY2FsbGRhdGE7
DQotCXN0cnVjdCBuZnNfcGFnZSAqcmVxOw0KLQ0KLQlycGNfcmVzdGFydF9jYWxsKHRhc2spOw0K
LQlyZXEgPSBuZnNfbGlzdF9lbnRyeShkYXRhLT5wYWdlcy5uZXh0KTsNCi0JaWYgKHJlcS0+d2Jf
c3RhdGUpDQotCQluZnM0X2NvcHlfc3RhdGVpZCgmZGF0YS0+YXJncy5zdGF0ZWlkLCByZXEtPndi
X3N0YXRlLCByZXEtPndiX2xvY2tvd25lcik7DQotCWVsc2UNCi0JCW1lbWNweSgmZGF0YS0+YXJn
cy5zdGF0ZWlkLCAmemVyb19zdGF0ZWlkLCBzaXplb2YoZGF0YS0+YXJncy5zdGF0ZWlkKSk7DQot
fQ0KLQ0KLXN0YXRpYyB2b2lkDQogbmZzNF9yZWFkX2RvbmUoc3RydWN0IHJwY190YXNrICp0YXNr
KQ0KIHsNCiAJc3RydWN0IG5mc19yZWFkX2RhdGEgKmRhdGEgPSAoc3RydWN0IG5mc19yZWFkX2Rh
dGEgKikgdGFzay0+dGtfY2FsbGRhdGE7DQogCXN0cnVjdCBpbm9kZSAqaW5vZGUgPSBkYXRhLT5p
bm9kZTsNCiANCiAJaWYgKG5mczRfYXN5bmNfaGFuZGxlX2Vycm9yKHRhc2ssIE5GU19TRVJWRVIo
aW5vZGUpKSA9PSAtRUFHQUlOKSB7DQotCQl0YXNrLT50a19hY3Rpb24gPSBuZnM0X3Jlc3RhcnRf
cmVhZDsNCisJCXJwY19yZXN0YXJ0X2NhbGwodGFzayk7DQogCQlyZXR1cm47DQogCX0NCiAJaWYg
KHRhc2stPnRrX3N0YXR1cyA+IDApDQpAQCAtMTUyOSw3ICsxNTE1LDcgQEAgbmZzNF9yZWFkX2Rv
bmUoc3RydWN0IHJwY190YXNrICp0YXNrKQ0KIH0NCiANCiBzdGF0aWMgdm9pZA0KLW5mczRfcHJv
Y19yZWFkX3NldHVwKHN0cnVjdCBuZnNfcmVhZF9kYXRhICpkYXRhLCB1bnNpZ25lZCBpbnQgY291
bnQpDQorbmZzNF9wcm9jX3JlYWRfc2V0dXAoc3RydWN0IG5mc19yZWFkX2RhdGEgKmRhdGEpDQog
ew0KIAlzdHJ1Y3QgcnBjX3Rhc2sJKnRhc2sgPSAmZGF0YS0+dGFzazsNCiAJc3RydWN0IHJwY19t
ZXNzYWdlIG1zZyA9IHsNCkBAIC0xNTM5LDM0ICsxNTI1LDE1IEBAIG5mczRfcHJvY19yZWFkX3Nl
dHVwKHN0cnVjdCBuZnNfcmVhZF9kYXQNCiAJCS5ycGNfY3JlZCA9IGRhdGEtPmNyZWQsDQogCX07
DQogCXN0cnVjdCBpbm9kZSAqaW5vZGUgPSBkYXRhLT5pbm9kZTsNCi0Jc3RydWN0IG5mc19wYWdl
ICpyZXEgPSBuZnNfbGlzdF9lbnRyeShkYXRhLT5wYWdlcy5uZXh0KTsNCiAJaW50IGZsYWdzOw0K
IA0KLQlkYXRhLT5hcmdzLmZoICAgICA9IE5GU19GSChpbm9kZSk7DQotCWRhdGEtPmFyZ3Mub2Zm
c2V0ID0gcmVxX29mZnNldChyZXEpOw0KLQlkYXRhLT5hcmdzLnBnYmFzZSA9IHJlcS0+d2JfcGdi
YXNlOw0KLQlkYXRhLT5hcmdzLnBhZ2VzICA9IGRhdGEtPnBhZ2V2ZWM7DQotCWRhdGEtPmFyZ3Mu
Y291bnQgID0gY291bnQ7DQotCWRhdGEtPnJlcy5mYXR0ciAgID0gJmRhdGEtPmZhdHRyOw0KLQlk
YXRhLT5yZXMuY291bnQgICA9IGNvdW50Ow0KLQlkYXRhLT5yZXMuZW9mICAgICA9IDA7DQogCWRh
dGEtPnRpbWVzdGFtcCAgID0gamlmZmllczsNCiANCi0JZGF0YS0+bG9ja293bmVyID0gcmVxLT53
Yl9sb2Nrb3duZXI7DQotCWlmIChyZXEtPndiX3N0YXRlKQ0KLQkJbmZzNF9jb3B5X3N0YXRlaWQo
JmRhdGEtPmFyZ3Muc3RhdGVpZCwgcmVxLT53Yl9zdGF0ZSwgcmVxLT53Yl9sb2Nrb3duZXIpOw0K
LQllbHNlDQotCQltZW1jcHkoJmRhdGEtPmFyZ3Muc3RhdGVpZCwgJnplcm9fc3RhdGVpZCwgc2l6
ZW9mKGRhdGEtPmFyZ3Muc3RhdGVpZCkpOw0KLQ0KIAkvKiBOLkIuIERvIHdlIG5lZWQgdG8gdGVz
dD8gTmV2ZXIgY2FsbGVkIGZvciBzd2FwZmlsZSBpbm9kZSAqLw0KIAlmbGFncyA9IFJQQ19UQVNL
X0FTWU5DIHwgKElTX1NXQVBGSUxFKGlub2RlKT8gTkZTX1JQQ19TV0FQRkxBR1MgOiAwKTsNCiAN
CiAJLyogRmluYWxpemUgdGhlIHRhc2suICovDQogCXJwY19pbml0X3Rhc2sodGFzaywgTkZTX0NM
SUVOVChpbm9kZSksIG5mczRfcmVhZF9kb25lLCBmbGFncyk7DQotCXRhc2stPnRrX2NhbGxkYXRh
ID0gZGF0YTsNCi0JLyogUmVsZWFzZSByZXF1ZXN0cyAqLw0KLQl0YXNrLT50a19yZWxlYXNlID0g
bmZzX3JlYWRkYXRhX3JlbGVhc2U7DQotDQogCXJwY19jYWxsX3NldHVwKHRhc2ssICZtc2csIDAp
Ow0KIH0NCiANCmRpZmYgLXUgLS1yZWN1cnNpdmUgLS1uZXctZmlsZSAtLXNob3ctYy1mdW5jdGlv
biBsaW51eC0yLjYuMy0xOS1wcmVwYXJlX25mc3BhZ2UvZnMvbmZzL25mczR4ZHIuYyBsaW51eC0y
LjYuMy0yMC1zbWFsbF9yc2l6ZS9mcy9uZnMvbmZzNHhkci5jDQotLS0gbGludXgtMi42LjMtMTkt
cHJlcGFyZV9uZnNwYWdlL2ZzL25mcy9uZnM0eGRyLmMJMjAwNC0wMy0wMSAxOTo0MDoyMS4wMDAw
MDAwMDAgLTA1MDANCisrKyBsaW51eC0yLjYuMy0yMC1zbWFsbF9yc2l6ZS9mcy9uZnMvbmZzNHhk
ci5jCTIwMDQtMDMtMDEgMTk6NDE6MDYuMDAwMDAwMDAwIC0wNTAwDQpAQCAtODY4LDE0ICs4Njgs
MzIgQEAgZW5jb2RlX3B1dHJvb3RmaChzdHJ1Y3QgeGRyX3N0cmVhbSAqeGRyKQ0KICAgICAgICAg
cmV0dXJuIDA7DQogfQ0KIA0KK3N0YXRpYyB2b2lkDQorZW5jb2RlX3N0YXRlaWQoc3RydWN0IHhk
cl9zdHJlYW0gKnhkciwgc3RydWN0IG5mczRfc3RhdGUgKnN0YXRlLCBmbF9vd25lcl90IGxvY2tv
d25lcikNCit7DQorCWV4dGVybiBuZnM0X3N0YXRlaWQgemVyb19zdGF0ZWlkOw0KKwluZnM0X3N0
YXRlaWQgc3RhdGVpZDsNCisJdWludDMyX3QgKnA7DQorDQorCVJFU0VSVkVfU1BBQ0UoMTYpOw0K
KwlpZiAoc3RhdGUgIT0gTlVMTCkgew0KKwkJbmZzNF9jb3B5X3N0YXRlaWQoJnN0YXRlaWQsIHN0
YXRlLCBsb2Nrb3duZXIpOw0KKwkJV1JJVEVNRU0oc3RhdGVpZC5kYXRhLCBzaXplb2Yoc3RhdGVp
ZC5kYXRhKSk7DQorCX0gZWxzZQ0KKwkJV1JJVEVNRU0oemVyb19zdGF0ZWlkLmRhdGEsIHNpemVv
Zih6ZXJvX3N0YXRlaWQuZGF0YSkpOw0KK30NCisNCiBzdGF0aWMgaW50DQogZW5jb2RlX3JlYWQo
c3RydWN0IHhkcl9zdHJlYW0gKnhkciwgc3RydWN0IG5mc19yZWFkYXJncyAqYXJncykNCiB7DQog
CXVpbnQzMl90ICpwOw0KIA0KLQlSRVNFUlZFX1NQQUNFKDMyKTsNCisJUkVTRVJWRV9TUEFDRSg0
KTsNCiAJV1JJVEUzMihPUF9SRUFEKTsNCi0JV1JJVEVNRU0oYXJncy0+c3RhdGVpZC5kYXRhLCBz
aXplb2YoYXJncy0+c3RhdGVpZC5kYXRhKSk7DQorDQorCWVuY29kZV9zdGF0ZWlkKHhkciwgYXJn
cy0+c3RhdGUsIGFyZ3MtPmxvY2tvd25lcik7DQorDQorCVJFU0VSVkVfU1BBQ0UoMTIpOw0KIAlX
UklURTY0KGFyZ3MtPm9mZnNldCk7DQogCVdSSVRFMzIoYXJncy0+Y291bnQpOw0KIA0KZGlmZiAt
dSAtLXJlY3Vyc2l2ZSAtLW5ldy1maWxlIC0tc2hvdy1jLWZ1bmN0aW9uIGxpbnV4LTIuNi4zLTE5
LXByZXBhcmVfbmZzcGFnZS9mcy9uZnMvcHJvYy5jIGxpbnV4LTIuNi4zLTIwLXNtYWxsX3JzaXpl
L2ZzL25mcy9wcm9jLmMNCi0tLSBsaW51eC0yLjYuMy0xOS1wcmVwYXJlX25mc3BhZ2UvZnMvbmZz
L3Byb2MuYwkyMDA0LTAzLTAxIDE5OjQwOjQ0LjAwMDAwMDAwMCAtMDUwMA0KKysrIGxpbnV4LTIu
Ni4zLTIwLXNtYWxsX3JzaXplL2ZzL25mcy9wcm9jLmMJMjAwNC0wMy0wMSAxOTo0MTowNi4wMDAw
MDAwMDAgLTA1MDANCkBAIC01NTksMTEgKzU1OSwxMCBAQCBuZnNfcmVhZF9kb25lKHN0cnVjdCBy
cGNfdGFzayAqdGFzaykNCiB9DQogDQogc3RhdGljIHZvaWQNCi1uZnNfcHJvY19yZWFkX3NldHVw
KHN0cnVjdCBuZnNfcmVhZF9kYXRhICpkYXRhLCB1bnNpZ25lZCBpbnQgY291bnQpDQorbmZzX3By
b2NfcmVhZF9zZXR1cChzdHJ1Y3QgbmZzX3JlYWRfZGF0YSAqZGF0YSkNCiB7DQogCXN0cnVjdCBy
cGNfdGFzawkJKnRhc2sgPSAmZGF0YS0+dGFzazsNCiAJc3RydWN0IGlub2RlCQkqaW5vZGUgPSBk
YXRhLT5pbm9kZTsNCi0Jc3RydWN0IG5mc19wYWdlCQkqcmVxOw0KIAlpbnQJCQlmbGFnczsNCiAJ
c3RydWN0IHJwY19tZXNzYWdlCW1zZyA9IHsNCiAJCS5ycGNfcHJvYwk9ICZuZnNfcHJvY2VkdXJl
c1tORlNQUk9DX1JFQURdLA0KQEAgLTU3MSwyNyArNTcwLDEzIEBAIG5mc19wcm9jX3JlYWRfc2V0
dXAoc3RydWN0IG5mc19yZWFkX2RhdGENCiAJCS5ycGNfcmVzcAk9ICZkYXRhLT5yZXMsDQogCQku
cnBjX2NyZWQJPSBkYXRhLT5jcmVkLA0KIAl9Ow0KLQkNCi0JcmVxID0gbmZzX2xpc3RfZW50cnko
ZGF0YS0+cGFnZXMubmV4dCk7DQotCWRhdGEtPmFyZ3MuZmggICAgID0gTkZTX0ZIKGlub2RlKTsN
Ci0JZGF0YS0+YXJncy5vZmZzZXQgPSByZXFfb2Zmc2V0KHJlcSk7DQotCWRhdGEtPmFyZ3MucGdi
YXNlID0gcmVxLT53Yl9wZ2Jhc2U7DQotCWRhdGEtPmFyZ3MucGFnZXMgID0gZGF0YS0+cGFnZXZl
YzsNCi0JZGF0YS0+YXJncy5jb3VudCAgPSBjb3VudDsNCi0JZGF0YS0+cmVzLmZhdHRyICAgPSAm
ZGF0YS0+ZmF0dHI7DQotCWRhdGEtPnJlcy5jb3VudCAgID0gY291bnQ7DQotCWRhdGEtPnJlcy5l
b2YgICAgID0gMDsNCi0JDQorDQogCS8qIE4uQi4gRG8gd2UgbmVlZCB0byB0ZXN0PyBOZXZlciBj
YWxsZWQgZm9yIHN3YXBmaWxlIGlub2RlICovDQogCWZsYWdzID0gUlBDX1RBU0tfQVNZTkMgfCAo
SVNfU1dBUEZJTEUoaW5vZGUpPyBORlNfUlBDX1NXQVBGTEFHUyA6IDApOw0KIA0KIAkvKiBGaW5h
bGl6ZSB0aGUgdGFzay4gKi8NCiAJcnBjX2luaXRfdGFzayh0YXNrLCBORlNfQ0xJRU5UKGlub2Rl
KSwgbmZzX3JlYWRfZG9uZSwgZmxhZ3MpOw0KLQl0YXNrLT50a19jYWxsZGF0YSA9IGRhdGE7DQot
CS8qIFJlbGVhc2UgcmVxdWVzdHMgKi8NCi0JdGFzay0+dGtfcmVsZWFzZSA9IG5mc19yZWFkZGF0
YV9yZWxlYXNlOw0KLQ0KLQlycGNfY2FsbF9zZXR1cCgmZGF0YS0+dGFzaywgJm1zZywgMCk7DQor
CXJwY19jYWxsX3NldHVwKHRhc2ssICZtc2csIDApOw0KIH0NCiANCiBzdGF0aWMgdm9pZA0KZGlm
ZiAtdSAtLXJlY3Vyc2l2ZSAtLW5ldy1maWxlIC0tc2hvdy1jLWZ1bmN0aW9uIGxpbnV4LTIuNi4z
LTE5LXByZXBhcmVfbmZzcGFnZS9mcy9uZnMvcmVhZC5jIGxpbnV4LTIuNi4zLTIwLXNtYWxsX3Jz
aXplL2ZzL25mcy9yZWFkLmMNCi0tLSBsaW51eC0yLjYuMy0xOS1wcmVwYXJlX25mc3BhZ2UvZnMv
bmZzL3JlYWQuYwkyMDA0LTAzLTAxIDE5OjQwOjQ0LjAwMDAwMDAwMCAtMDUwMA0KKysrIGxpbnV4
LTIuNi4zLTIwLXNtYWxsX3JzaXplL2ZzL25mcy9yZWFkLmMJMjAwNC0wMy0wMyAyMDo0MTowMS4w
MDAwMDAwMDAgLTA1MDANCkBAIC0zNSw2ICszNSw4IEBADQogI2RlZmluZSBORlNEQkdfRkFDSUxJ
VFkJCU5GU0RCR19QQUdFQ0FDSEUNCiANCiBzdGF0aWMgaW50IG5mc19wYWdlaW5fb25lKHN0cnVj
dCBsaXN0X2hlYWQgKiwgc3RydWN0IGlub2RlICopOw0KK3N0YXRpYyB2b2lkIG5mc19yZWFkcGFn
ZV9yZXN1bHRfcGFydGlhbChzdHJ1Y3QgbmZzX3JlYWRfZGF0YSAqLCBpbnQpOw0KK3N0YXRpYyB2
b2lkIG5mc19yZWFkcGFnZV9yZXN1bHRfZnVsbChzdHJ1Y3QgbmZzX3JlYWRfZGF0YSAqLCBpbnQp
Ow0KIA0KIHN0YXRpYyBrbWVtX2NhY2hlX3QgKm5mc19yZGF0YV9jYWNoZXA7DQogc3RhdGljIG1l
bXBvb2xfdCAqbmZzX3JkYXRhX21lbXBvb2w7DQpAQCAtNTcsMTIgKzU5LDM3IEBAIHN0YXRpYyBf
X2lubGluZV9fIHZvaWQgbmZzX3JlYWRkYXRhX2ZyZWUNCiAJbWVtcG9vbF9mcmVlKHAsIG5mc19y
ZGF0YV9tZW1wb29sKTsNCiB9DQogDQotdm9pZCBuZnNfcmVhZGRhdGFfcmVsZWFzZShzdHJ1Y3Qg
cnBjX3Rhc2sgKnRhc2spDQorc3RhdGljIHZvaWQgbmZzX3JlYWRkYXRhX3JlbGVhc2Uoc3RydWN0
IHJwY190YXNrICp0YXNrKQ0KIHsNCiAgICAgICAgIHN0cnVjdCBuZnNfcmVhZF9kYXRhICAgKmRh
dGEgPSAoc3RydWN0IG5mc19yZWFkX2RhdGEgKil0YXNrLT50a19jYWxsZGF0YTsNCiAgICAgICAg
IG5mc19yZWFkZGF0YV9mcmVlKGRhdGEpOw0KIH0NCiANCitzdGF0aWMNCit1bnNpZ25lZCBpbnQg
bmZzX3BhZ2VfbGVuZ3RoKHN0cnVjdCBpbm9kZSAqaW5vZGUsIHN0cnVjdCBwYWdlICpwYWdlKQ0K
K3sNCisJbG9mZl90IGlfc2l6ZSA9IGlfc2l6ZV9yZWFkKGlub2RlKTsNCisJdW5zaWduZWQgbG9u
ZyBpZHg7DQorDQorCWlmIChpX3NpemUgPD0gMCkNCisJCXJldHVybiAwOw0KKwlpZHggPSAoaV9z
aXplIC0gMSkgPj4gUEFHRV9DQUNIRV9TSElGVDsNCisJaWYgKHBhZ2UtPmluZGV4ID4gaWR4KQ0K
KwkJcmV0dXJuIDA7DQorCWlmIChwYWdlLT5pbmRleCAhPSBpZHgpDQorCQlyZXR1cm4gUEFHRV9D
QUNIRV9TSVpFOw0KKwlyZXR1cm4gMSArICgoaV9zaXplIC0gMSkgJiAoUEFHRV9DQUNIRV9TSVpF
IC0gMSkpOw0KK30NCisNCitzdGF0aWMNCitpbnQgbmZzX3JldHVybl9lbXB0eV9wYWdlKHN0cnVj
dCBwYWdlICpwYWdlKQ0KK3sNCisJbWVtY2xlYXJfaGlnaHBhZ2VfZmx1c2gocGFnZSwgMCwgUEFH
RV9DQUNIRV9TSVpFKTsNCisJU2V0UGFnZVVwdG9kYXRlKHBhZ2UpOw0KKwl1bmxvY2tfcGFnZShw
YWdlKTsNCisJcmV0dXJuIDA7DQorfQ0KKw0KIC8qDQogICogUmVhZCBhIHBhZ2Ugc3luY2hyb25v
dXNseS4NCiAgKi8NCkBAIC03OCw2ICsxMDUsNyBAQCBuZnNfcmVhZHBhZ2Vfc3luYyhzdHJ1Y3Qg
ZmlsZSAqZmlsZSwgc3RyDQogCQkuaW5vZGUJCT0gaW5vZGUsDQogCQkuYXJncwkJPSB7DQogCQkJ
LmZoCQk9IE5GU19GSChpbm9kZSksDQorCQkJLmxvY2tvd25lcgk9IGN1cnJlbnQtPmZpbGVzLA0K
IAkJCS5wYWdlcwkJPSAmcGFnZSwNCiAJCQkucGdiYXNlCQk9IDBVTCwNCiAJCQkuY291bnQJCT0g
cnNpemUsDQpAQCAtMTQ2LDg5ICsxNzQsMjA4IEBAIG5mc19yZWFkcGFnZV9hc3luYyhzdHJ1Y3Qg
ZmlsZSAqZmlsZSwgc3QNCiB7DQogCUxJU1RfSEVBRChvbmVfcmVxdWVzdCk7DQogCXN0cnVjdCBu
ZnNfcGFnZQkqbmV3Ow0KKwl1bnNpZ25lZCBpbnQgbGVuOw0KIA0KLQluZXcgPSBuZnNfY3JlYXRl
X3JlcXVlc3QoZmlsZSwgaW5vZGUsIHBhZ2UsIDAsIFBBR0VfQ0FDSEVfU0laRSk7DQorCWxlbiA9
IG5mc19wYWdlX2xlbmd0aChpbm9kZSwgcGFnZSk7DQorCWlmIChsZW4gPT0gMCkNCisJCXJldHVy
biBuZnNfcmV0dXJuX2VtcHR5X3BhZ2UocGFnZSk7DQorCW5ldyA9IG5mc19jcmVhdGVfcmVxdWVz
dChmaWxlLCBpbm9kZSwgcGFnZSwgMCwgbGVuKTsNCiAJaWYgKElTX0VSUihuZXcpKSB7DQogCQl1
bmxvY2tfcGFnZShwYWdlKTsNCiAJCXJldHVybiBQVFJfRVJSKG5ldyk7DQogCX0NCisJaWYgKGxl
biA8IFBBR0VfQ0FDSEVfU0laRSkNCisJCW1lbWNsZWFyX2hpZ2hwYWdlX2ZsdXNoKHBhZ2UsIGxl
biwgUEFHRV9DQUNIRV9TSVpFIC0gbGVuKTsNCisNCiAJbmZzX2xvY2tfcmVxdWVzdChuZXcpOw0K
IAluZnNfbGlzdF9hZGRfcmVxdWVzdChuZXcsICZvbmVfcmVxdWVzdCk7DQogCW5mc19wYWdlaW5f
b25lKCZvbmVfcmVxdWVzdCwgaW5vZGUpOw0KIAlyZXR1cm4gMDsNCiB9DQogDQorc3RhdGljIHZv
aWQgbmZzX3JlYWRwYWdlX3JlbGVhc2Uoc3RydWN0IG5mc19wYWdlICpyZXEpDQorew0KKwl1bmxv
Y2tfcGFnZShyZXEtPndiX3BhZ2UpOw0KKw0KKwluZnNfY2xlYXJfcmVxdWVzdChyZXEpOw0KKwlu
ZnNfcmVsZWFzZV9yZXF1ZXN0KHJlcSk7DQorCW5mc191bmxvY2tfcmVxdWVzdChyZXEpOw0KKw0K
KwlkcHJpbnRrKCJORlM6IHJlYWQgZG9uZSAoJXMvJUxkICVkQCVMZClcbiIsDQorCQkJcmVxLT53
Yl9pbm9kZS0+aV9zYi0+c19pZCwNCisJCQkobG9uZyBsb25nKU5GU19GSUxFSUQocmVxLT53Yl9p
bm9kZSksDQorCQkJcmVxLT53Yl9ieXRlcywNCisJCQkobG9uZyBsb25nKXJlcV9vZmZzZXQocmVx
KSk7DQorfQ0KKw0KIC8qDQogICogU2V0IHVwIHRoZSBORlMgcmVhZCByZXF1ZXN0IHN0cnVjdA0K
ICAqLw0KLXN0YXRpYyB2b2lkDQotbmZzX3JlYWRfcnBjc2V0dXAoc3RydWN0IGxpc3RfaGVhZCAq
aGVhZCwgc3RydWN0IG5mc19yZWFkX2RhdGEgKmRhdGEpDQorc3RhdGljIHZvaWQgbmZzX3JlYWRf
cnBjc2V0dXAoc3RydWN0IG5mc19wYWdlICpyZXEsIHN0cnVjdCBuZnNfcmVhZF9kYXRhICpkYXRh
LA0KKwkJdW5zaWduZWQgaW50IGNvdW50LCB1bnNpZ25lZCBpbnQgb2Zmc2V0KQ0KIHsNCiAJc3Ry
dWN0IGlub2RlCQkqaW5vZGU7DQotCXN0cnVjdCBuZnNfcGFnZQkJKnJlcTsNCi0Jc3RydWN0IHBh
Z2UJCSoqcGFnZXM7DQotCXVuc2lnbmVkIGludAkJY291bnQ7DQogDQotCXBhZ2VzID0gZGF0YS0+
cGFnZXZlYzsNCi0JY291bnQgPSAwOw0KLQl3aGlsZSAoIWxpc3RfZW1wdHkoaGVhZCkpIHsNCi0J
CXJlcSA9IG5mc19saXN0X2VudHJ5KGhlYWQtPm5leHQpOw0KLQkJbmZzX2xpc3RfcmVtb3ZlX3Jl
cXVlc3QocmVxKTsNCi0JCW5mc19saXN0X2FkZF9yZXF1ZXN0KHJlcSwgJmRhdGEtPnBhZ2VzKTsN
Ci0JCSpwYWdlcysrID0gcmVxLT53Yl9wYWdlOw0KLQkJY291bnQgKz0gcmVxLT53Yl9ieXRlczsN
Ci0JfQ0KLQlyZXEgPSBuZnNfbGlzdF9lbnRyeShkYXRhLT5wYWdlcy5uZXh0KTsNCisJZGF0YS0+
cmVxCSAgPSByZXE7DQogCWRhdGEtPmlub2RlCSAgPSBpbm9kZSA9IHJlcS0+d2JfaW5vZGU7DQog
CWRhdGEtPmNyZWQJICA9IHJlcS0+d2JfY3JlZDsNCiANCi0JTkZTX1BST1RPKGlub2RlKS0+cmVh
ZF9zZXR1cChkYXRhLCBjb3VudCk7DQorCWRhdGEtPmFyZ3MuZmggICAgID0gTkZTX0ZIKGlub2Rl
KTsNCisJZGF0YS0+YXJncy5vZmZzZXQgPSByZXFfb2Zmc2V0KHJlcSkgKyBvZmZzZXQ7DQorCWRh
dGEtPmFyZ3MucGdiYXNlID0gcmVxLT53Yl9wZ2Jhc2UgKyBvZmZzZXQ7DQorCWRhdGEtPmFyZ3Mu
cGFnZXMgID0gZGF0YS0+cGFnZXZlYzsNCisJZGF0YS0+YXJncy5jb3VudCAgPSBjb3VudDsNCisJ
ZGF0YS0+YXJncy5sb2Nrb3duZXIgPSByZXEtPndiX2xvY2tvd25lcjsNCisJZGF0YS0+YXJncy5z
dGF0ZSAgPSByZXEtPndiX3N0YXRlOw0KKw0KKwlkYXRhLT5yZXMuZmF0dHIgICA9ICZkYXRhLT5m
YXR0cjsNCisJZGF0YS0+cmVzLmNvdW50ICAgPSBjb3VudDsNCisJZGF0YS0+cmVzLmVvZiAgICAg
PSAwOw0KKw0KKwlORlNfUFJPVE8oaW5vZGUpLT5yZWFkX3NldHVwKGRhdGEpOw0KKw0KKwlkYXRh
LT50YXNrLnRrX2NhbGxkYXRhID0gZGF0YTsNCisJLyogUmVsZWFzZSByZXF1ZXN0cyAqLw0KKwlk
YXRhLT50YXNrLnRrX3JlbGVhc2UgPSBuZnNfcmVhZGRhdGFfcmVsZWFzZTsNCiANCi0JZHByaW50
aygiTkZTOiAlNGQgaW5pdGlhdGVkIHJlYWQgY2FsbCAocmVxICVzLyVMZCwgJXUgYnl0ZXMgQCBv
ZmZzZXQgJUx1LlxuIiwNCisJZHByaW50aygiTkZTOiAlNGQgaW5pdGlhdGVkIHJlYWQgY2FsbCAo
cmVxICVzLyVMZCwgJXUgYnl0ZXMgQCBvZmZzZXQgJUx1KVxuIiwNCiAJCQlkYXRhLT50YXNrLnRr
X3BpZCwNCiAJCQlpbm9kZS0+aV9zYi0+c19pZCwNCiAJCQkobG9uZyBsb25nKU5GU19GSUxFSUQo
aW5vZGUpLA0KIAkJCWNvdW50LA0KLQkJCSh1bnNpZ25lZCBsb25nIGxvbmcpcmVxX29mZnNldChy
ZXEpKTsNCisJCQlkYXRhLT5hcmdzLm9mZnNldCk7DQogfQ0KIA0KIHN0YXRpYyB2b2lkDQogbmZz
X2FzeW5jX3JlYWRfZXJyb3Ioc3RydWN0IGxpc3RfaGVhZCAqaGVhZCkNCiB7DQogCXN0cnVjdCBu
ZnNfcGFnZQkqcmVxOw0KLQlzdHJ1Y3QgcGFnZQkqcGFnZTsNCiANCiAJd2hpbGUgKCFsaXN0X2Vt
cHR5KGhlYWQpKSB7DQogCQlyZXEgPSBuZnNfbGlzdF9lbnRyeShoZWFkLT5uZXh0KTsNCi0JCXBh
Z2UgPSByZXEtPndiX3BhZ2U7DQogCQluZnNfbGlzdF9yZW1vdmVfcmVxdWVzdChyZXEpOw0KLQkJ
U2V0UGFnZUVycm9yKHBhZ2UpOw0KLQkJdW5sb2NrX3BhZ2UocGFnZSk7DQotCQluZnNfY2xlYXJf
cmVxdWVzdChyZXEpOw0KLQkJbmZzX3JlbGVhc2VfcmVxdWVzdChyZXEpOw0KLQkJbmZzX3VubG9j
a19yZXF1ZXN0KHJlcSk7DQorCQlTZXRQYWdlRXJyb3IocmVxLT53Yl9wYWdlKTsNCisJCW5mc19y
ZWFkcGFnZV9yZWxlYXNlKHJlcSk7DQogCX0NCiB9DQogDQotc3RhdGljIGludA0KLW5mc19wYWdl
aW5fb25lKHN0cnVjdCBsaXN0X2hlYWQgKmhlYWQsIHN0cnVjdCBpbm9kZSAqaW5vZGUpDQorLyoN
CisgKiBTdGFydCBhbiBhc3luYyByZWFkIG9wZXJhdGlvbg0KKyAqLw0KK3N0YXRpYyB2b2lkIG5m
c19leGVjdXRlX3JlYWQoc3RydWN0IG5mc19yZWFkX2RhdGEgKmRhdGEpDQorew0KKwlzdHJ1Y3Qg
cnBjX2NsbnQgKmNsbnQgPSBORlNfQ0xJRU5UKGRhdGEtPmlub2RlKTsNCisJc2lnc2V0X3Qgb2xk
c2V0Ow0KKw0KKwlycGNfY2xudF9zaWdtYXNrKGNsbnQsICZvbGRzZXQpOw0KKwlsb2NrX2tlcm5l
bCgpOw0KKwlycGNfZXhlY3V0ZSgmZGF0YS0+dGFzayk7DQorCXVubG9ja19rZXJuZWwoKTsNCisJ
cnBjX2NsbnRfc2lndW5tYXNrKGNsbnQsICZvbGRzZXQpOw0KK30NCisNCisvKg0KKyAqIEdlbmVy
YXRlIG11bHRpcGxlIHJlcXVlc3RzIHRvIGZpbGwgYSBzaW5nbGUgcGFnZS4NCisgKg0KKyAqIFdl
IG9wdGltaXplIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIHJlYWQgb3BlcmF0aW9ucyBvbiB0aGUg
d2lyZS4gIElmIHdlDQorICogZGV0ZWN0IHRoYXQgd2UncmUgcmVhZGluZyBhIHBhZ2UsIG9yIGFu
IGFyZWEgb2YgYSBwYWdlLCB0aGF0IGlzIHBhc3QgdGhlDQorICogZW5kIG9mIGZpbGUsIHdlIGRv
IG5vdCBnZW5lcmF0ZSBORlMgcmVhZCBvcGVyYXRpb25zIGJ1dCBqdXN0IGNsZWFyIHRoZQ0KKyAq
IHBhcnRzIG9mIHRoZSBwYWdlIHRoYXQgd291bGQgaGF2ZSBjb21lIGJhY2sgemVybyBmcm9tIHRo
ZSBzZXJ2ZXIgYW55d2F5Lg0KKyAqDQorICogV2UgcmVseSBvbiB0aGUgY2FjaGVkIHZhbHVlIG9m
IGlfc2l6ZSB0byBtYWtlIHRoaXMgZGV0ZXJtaW5hdGlvbjsgYW5vdGhlcg0KKyAqIGNsaWVudCBj
YW4gZmlsbCBwYWdlcyBvbiB0aGUgc2VydmVyIHBhc3Qgb3VyIGNhY2hlZCBlbmQtb2YtZmlsZSwg
YnV0IHdlDQorICogd29uJ3Qgc2VlIHRoZSBuZXcgZGF0YSB1bnRpbCBvdXIgYXR0cmlidXRlIGNh
Y2hlIGlzIHVwZGF0ZWQuICBUaGlzIGlzIG1vcmUNCisgKiBvciBsZXNzIGNvbnZlbnRpb25hbCBO
RlMgY2xpZW50IGJlaGF2aW9yLg0KKyAqLw0KK3N0YXRpYyBpbnQgbmZzX3BhZ2Vpbl9tdWx0aShz
dHJ1Y3QgbGlzdF9oZWFkICpoZWFkLCBzdHJ1Y3QgaW5vZGUgKmlub2RlKQ0KK3sNCisJc3RydWN0
IG5mc19wYWdlICpyZXEgPSBuZnNfbGlzdF9lbnRyeShoZWFkLT5uZXh0KTsNCisJc3RydWN0IHBh
Z2UgKnBhZ2UgPSByZXEtPndiX3BhZ2U7DQorCXN0cnVjdCBuZnNfcmVhZF9kYXRhICpkYXRhOw0K
Kwl1bnNpZ25lZCBpbnQgcnNpemUgPSBORlNfU0VSVkVSKGlub2RlKS0+cnNpemU7DQorCXVuc2ln
bmVkIGludCBuYnl0ZXMsIG9mZnNldDsNCisJaW50IHJlcXVlc3RzID0gMDsNCisJTElTVF9IRUFE
KGxpc3QpOw0KKw0KKwluZnNfbGlzdF9yZW1vdmVfcmVxdWVzdChyZXEpOw0KKw0KKwluYnl0ZXMg
PSByZXEtPndiX2J5dGVzOw0KKwlmb3IoOzspIHsNCisJCWRhdGEgPSBuZnNfcmVhZGRhdGFfYWxs
b2MoKTsNCisJCWlmICghZGF0YSkNCisJCQlnb3RvIG91dF9iYWQ7DQorCQlsaXN0X2FkZCgmZGF0
YS0+cGFnZXMsICZsaXN0KTsNCisJCXJlcXVlc3RzKys7DQorCQlpZiAobmJ5dGVzIDw9IHJzaXpl
KQ0KKwkJCWJyZWFrOw0KKwkJbmJ5dGVzIC09IHJzaXplOw0KKwl9DQorCWF0b21pY19zZXQoJnJl
cS0+d2JfY29tcGxldGUsIHJlcXVlc3RzKTsNCisNCisJQ2xlYXJQYWdlRXJyb3IocGFnZSk7DQor
CW9mZnNldCA9IDA7DQorCW5ieXRlcyA9IHJlcS0+d2JfYnl0ZXM7DQorCWRvIHsNCisJCWRhdGEg
PSBsaXN0X2VudHJ5KGxpc3QubmV4dCwgc3RydWN0IG5mc19yZWFkX2RhdGEsIHBhZ2VzKTsNCisJ
CWxpc3RfZGVsX2luaXQoJmRhdGEtPnBhZ2VzKTsNCisNCisJCWRhdGEtPnBhZ2V2ZWNbMF0gPSBw
YWdlOw0KKwkJZGF0YS0+Y29tcGxldGUgPSBuZnNfcmVhZHBhZ2VfcmVzdWx0X3BhcnRpYWw7DQor
DQorCQlpZiAobmJ5dGVzID4gcnNpemUpIHsNCisJCQluZnNfcmVhZF9ycGNzZXR1cChyZXEsIGRh
dGEsIHJzaXplLCBvZmZzZXQpOw0KKwkJCW9mZnNldCArPSByc2l6ZTsNCisJCQluYnl0ZXMgLT0g
cnNpemU7DQorCQl9IGVsc2Ugew0KKwkJCW5mc19yZWFkX3JwY3NldHVwKHJlcSwgZGF0YSwgbmJ5
dGVzLCBvZmZzZXQpOw0KKwkJCW5ieXRlcyA9IDA7DQorCQl9DQorCQluZnNfZXhlY3V0ZV9yZWFk
KGRhdGEpOw0KKwl9IHdoaWxlIChuYnl0ZXMgIT0gMCk7DQorDQorCXJldHVybiAwOw0KKw0KK291
dF9iYWQ6DQorCXdoaWxlICghbGlzdF9lbXB0eSgmbGlzdCkpIHsNCisJCWRhdGEgPSBsaXN0X2Vu
dHJ5KGxpc3QubmV4dCwgc3RydWN0IG5mc19yZWFkX2RhdGEsIHBhZ2VzKTsNCisJCWxpc3RfZGVs
KCZkYXRhLT5wYWdlcyk7DQorCQluZnNfcmVhZGRhdGFfZnJlZShkYXRhKTsNCisJfQ0KKwlTZXRQ
YWdlRXJyb3IocGFnZSk7DQorCW5mc19yZWFkcGFnZV9yZWxlYXNlKHJlcSk7DQorCXJldHVybiAt
RU5PTUVNOw0KK30NCisNCitzdGF0aWMgaW50IG5mc19wYWdlaW5fb25lKHN0cnVjdCBsaXN0X2hl
YWQgKmhlYWQsIHN0cnVjdCBpbm9kZSAqaW5vZGUpDQogew0KLQlzdHJ1Y3QgcnBjX2NsbnQJCSpj
bG50ID0gTkZTX0NMSUVOVChpbm9kZSk7DQorCXN0cnVjdCBuZnNfcGFnZQkJKnJlcTsNCisJc3Ry
dWN0IHBhZ2UJCSoqcGFnZXM7DQogCXN0cnVjdCBuZnNfcmVhZF9kYXRhCSpkYXRhOw0KLQlzaWdz
ZXRfdAkJb2xkc2V0Ow0KKwl1bnNpZ25lZCBpbnQJCWNvdW50Ow0KKw0KKwlpZiAoTkZTX1NFUlZF
Uihpbm9kZSktPnJzaXplIDwgUEFHRV9DQUNIRV9TSVpFKQ0KKwkJcmV0dXJuIG5mc19wYWdlaW5f
bXVsdGkoaGVhZCwgaW5vZGUpOw0KIA0KIAlkYXRhID0gbmZzX3JlYWRkYXRhX2FsbG9jKCk7DQog
CWlmICghZGF0YSkNCiAJCWdvdG8gb3V0X2JhZDsNCiANCi0JbmZzX3JlYWRfcnBjc2V0dXAoaGVh
ZCwgZGF0YSk7DQorCXBhZ2VzID0gZGF0YS0+cGFnZXZlYzsNCisJY291bnQgPSAwOw0KKwl3aGls
ZSAoIWxpc3RfZW1wdHkoaGVhZCkpIHsNCisJCXJlcSA9IG5mc19saXN0X2VudHJ5KGhlYWQtPm5l
eHQpOw0KKwkJbmZzX2xpc3RfcmVtb3ZlX3JlcXVlc3QocmVxKTsNCisJCW5mc19saXN0X2FkZF9y
ZXF1ZXN0KHJlcSwgJmRhdGEtPnBhZ2VzKTsNCisJCUNsZWFyUGFnZUVycm9yKHJlcS0+d2JfcGFn
ZSk7DQorCQkqcGFnZXMrKyA9IHJlcS0+d2JfcGFnZTsNCisJCWNvdW50ICs9IHJlcS0+d2JfYnl0
ZXM7DQorCX0NCisJcmVxID0gbmZzX2xpc3RfZW50cnkoZGF0YS0+cGFnZXMubmV4dCk7DQorDQor
CWRhdGEtPmNvbXBsZXRlID0gbmZzX3JlYWRwYWdlX3Jlc3VsdF9mdWxsOw0KKwluZnNfcmVhZF9y
cGNzZXR1cChyZXEsIGRhdGEsIGNvdW50LCAwKTsNCiANCi0JLyogU3RhcnQgdGhlIGFzeW5jIGNh
bGwgKi8NCi0JcnBjX2NsbnRfc2lnbWFzayhjbG50LCAmb2xkc2V0KTsNCi0JbG9ja19rZXJuZWwo
KTsNCi0JcnBjX2V4ZWN1dGUoJmRhdGEtPnRhc2spOw0KLQl1bmxvY2tfa2VybmVsKCk7DQotCXJw
Y19jbG50X3NpZ3VubWFzayhjbG50LCAmb2xkc2V0KTsNCisJbmZzX2V4ZWN1dGVfcmVhZChkYXRh
KTsNCiAJcmV0dXJuIDA7DQogb3V0X2JhZDoNCiAJbmZzX2FzeW5jX3JlYWRfZXJyb3IoaGVhZCk7
DQpAQCAtMjU4LDU1ICs0MDUsODQgQEAgbmZzX3BhZ2Vpbl9saXN0KHN0cnVjdCBsaXN0X2hlYWQg
KmhlYWQsIA0KIH0NCiANCiAvKg0KKyAqIEhhbmRsZSBhIHJlYWQgcmVwbHkgdGhhdCBmaWxscyBw
YXJ0IG9mIGEgcGFnZS4NCisgKi8NCitzdGF0aWMgdm9pZCBuZnNfcmVhZHBhZ2VfcmVzdWx0X3Bh
cnRpYWwoc3RydWN0IG5mc19yZWFkX2RhdGEgKmRhdGEsIGludCBzdGF0dXMpDQorew0KKwlzdHJ1
Y3QgbmZzX3BhZ2UgKnJlcSA9IGRhdGEtPnJlcTsNCisJc3RydWN0IHBhZ2UgKnBhZ2UgPSByZXEt
PndiX3BhZ2U7DQorIA0KKwlpZiAoc3RhdHVzID49IDApIHsNCisJCXVuc2lnbmVkIGludCByZXF1
ZXN0ID0gZGF0YS0+YXJncy5jb3VudDsNCisJCXVuc2lnbmVkIGludCByZXN1bHQgPSBkYXRhLT5y
ZXMuY291bnQ7DQorDQorCQlpZiAocmVzdWx0IDwgcmVxdWVzdCkgew0KKwkJCW1lbWNsZWFyX2hp
Z2hwYWdlX2ZsdXNoKHBhZ2UsDQorCQkJCQkJZGF0YS0+YXJncy5wZ2Jhc2UgKyByZXN1bHQsDQor
CQkJCQkJcmVxdWVzdCAtIHJlc3VsdCk7DQorCQkJaWYgKCFkYXRhLT5yZXMuZW9mKQ0KKwkJCQlT
ZXRQYWdlRXJyb3IocGFnZSk7DQorCQl9DQorCX0gZWxzZQ0KKwkJU2V0UGFnZUVycm9yKHBhZ2Up
Ow0KKw0KKwlpZiAoYXRvbWljX2RlY19hbmRfdGVzdCgmcmVxLT53Yl9jb21wbGV0ZSkpIHsNCisJ
CWlmICghUGFnZUVycm9yKHBhZ2UpKQ0KKwkJCVNldFBhZ2VVcHRvZGF0ZShwYWdlKTsNCisJCW5m
c19yZWFkcGFnZV9yZWxlYXNlKHJlcSk7DQorCX0NCit9DQorDQorLyoNCiAgKiBUaGlzIGlzIHRo
ZSBjYWxsYmFjayBmcm9tIFJQQyB0ZWxsaW5nIHVzIHdoZXRoZXIgYSByZXBseSB3YXMNCiAgKiBy
ZWNlaXZlZCBvciBzb21lIGVycm9yIG9jY3VycmVkICh0aW1lb3V0IG9yIHNvY2tldCBzaHV0ZG93
bikuDQogICovDQotdm9pZA0KLW5mc19yZWFkcGFnZV9yZXN1bHQoc3RydWN0IHJwY190YXNrICp0
YXNrKQ0KK3N0YXRpYyB2b2lkIG5mc19yZWFkcGFnZV9yZXN1bHRfZnVsbChzdHJ1Y3QgbmZzX3Jl
YWRfZGF0YSAqZGF0YSwgaW50IHN0YXR1cykNCiB7DQotCXN0cnVjdCBuZnNfcmVhZF9kYXRhICpk
YXRhID0gKHN0cnVjdCBuZnNfcmVhZF9kYXRhICopdGFzay0+dGtfY2FsbGRhdGE7DQogCXVuc2ln
bmVkIGludCBjb3VudCA9IGRhdGEtPnJlcy5jb3VudDsNCiANCi0JZHByaW50aygiTkZTOiAlNGQg
bmZzX3JlYWRwYWdlX3Jlc3VsdCwgKHN0YXR1cyAlZClcbiIsDQotCQl0YXNrLT50a19waWQsIHRh
c2stPnRrX3N0YXR1cyk7DQotDQotCU5GU19GTEFHUyhkYXRhLT5pbm9kZSkgfD0gTkZTX0lOT19J
TlZBTElEX0FUSU1FOw0KIAl3aGlsZSAoIWxpc3RfZW1wdHkoJmRhdGEtPnBhZ2VzKSkgew0KIAkJ
c3RydWN0IG5mc19wYWdlICpyZXEgPSBuZnNfbGlzdF9lbnRyeShkYXRhLT5wYWdlcy5uZXh0KTsN
CiAJCXN0cnVjdCBwYWdlICpwYWdlID0gcmVxLT53Yl9wYWdlOw0KIAkJbmZzX2xpc3RfcmVtb3Zl
X3JlcXVlc3QocmVxKTsNCiANCi0JCWlmICh0YXNrLT50a19zdGF0dXMgPj0gMCkgew0KKwkJaWYg
KHN0YXR1cyA+PSAwKSB7DQogCQkJaWYgKGNvdW50IDwgUEFHRV9DQUNIRV9TSVpFKSB7DQotCQkJ
CW1lbWNsZWFyX2hpZ2hwYWdlX2ZsdXNoKHBhZ2UsDQorCQkJCWlmIChjb3VudCA8IHJlcS0+d2Jf
Ynl0ZXMpDQorCQkJCQltZW1jbGVhcl9oaWdocGFnZV9mbHVzaChwYWdlLA0KIAkJCQkJCQlyZXEt
PndiX3BnYmFzZSArIGNvdW50LA0KIAkJCQkJCQlyZXEtPndiX2J5dGVzIC0gY291bnQpOw0KLQ0K
KwkJCQlpZiAoIWRhdGEtPnJlcy5lb2YpDQorCQkJCQlTZXRQYWdlRXJyb3IocGFnZSk7DQogCQkJ
CWNvdW50ID0gMDsNCiAJCQl9IGVsc2UNCiAJCQkJY291bnQgLT0gUEFHRV9DQUNIRV9TSVpFOw0K
IAkJCVNldFBhZ2VVcHRvZGF0ZShwYWdlKTsNCiAJCX0gZWxzZQ0KIAkJCVNldFBhZ2VFcnJvcihw
YWdlKTsNCi0JCXVubG9ja19wYWdlKHBhZ2UpOw0KLQ0KLQkJZHByaW50aygiTkZTOiByZWFkICgl
cy8lTGQgJWRAJUxkKVxuIiwNCi0gICAgICAgICAgICAgICAgICAgICAgICByZXEtPndiX2lub2Rl
LT5pX3NiLT5zX2lkLA0KLSAgICAgICAgICAgICAgICAgICAgICAgIChsb25nIGxvbmcpTkZTX0ZJ
TEVJRChyZXEtPndiX2lub2RlKSwNCi0gICAgICAgICAgICAgICAgICAgICAgICByZXEtPndiX2J5
dGVzLA0KLSAgICAgICAgICAgICAgICAgICAgICAgIChsb25nIGxvbmcpcmVxX29mZnNldChyZXEp
KTsNCi0JCW5mc19jbGVhcl9yZXF1ZXN0KHJlcSk7DQotCQluZnNfcmVsZWFzZV9yZXF1ZXN0KHJl
cSk7DQotCQluZnNfdW5sb2NrX3JlcXVlc3QocmVxKTsNCisJCW5mc19yZWFkcGFnZV9yZWxlYXNl
KHJlcSk7DQogCX0NCiB9DQogDQogLyoNCisgKiBUaGlzIGlzIHRoZSBjYWxsYmFjayBmcm9tIFJQ
QyB0ZWxsaW5nIHVzIHdoZXRoZXIgYSByZXBseSB3YXMNCisgKiByZWNlaXZlZCBvciBzb21lIGVy
cm9yIG9jY3VycmVkICh0aW1lb3V0IG9yIHNvY2tldCBzaHV0ZG93bikuDQorICovDQordm9pZCBu
ZnNfcmVhZHBhZ2VfcmVzdWx0KHN0cnVjdCBycGNfdGFzayAqdGFzaykNCit7DQorCXN0cnVjdCBu
ZnNfcmVhZF9kYXRhICpkYXRhID0gKHN0cnVjdCBuZnNfcmVhZF9kYXRhICopdGFzay0+dGtfY2Fs
bGRhdGE7DQorCWludCBzdGF0dXMgPSB0YXNrLT50a19zdGF0dXM7DQorDQorCWRwcmludGsoIk5G
UzogJTRkIG5mc19yZWFkcGFnZV9yZXN1bHQsIChzdGF0dXMgJWQpXG4iLA0KKwkJdGFzay0+dGtf
cGlkLCBzdGF0dXMpOw0KKw0KKwlORlNfRkxBR1MoZGF0YS0+aW5vZGUpIHw9IE5GU19JTk9fSU5W
QUxJRF9BVElNRTsNCisJZGF0YS0+Y29tcGxldGUoZGF0YSwgc3RhdHVzKTsNCit9DQorDQorLyoN
CiAgKiBSZWFkIGEgcGFnZSBvdmVyIE5GUy4NCi0gKiBXZSByZWFkIHRoZSBwYWdlIHN5bmNocm9u
b3VzbHkgaW4gdGhlIGZvbGxvd2luZyBjYXNlczoNCi0gKiAgLQlUaGUgTkZTIHJzaXplIGlzIHNt
YWxsZXIgdGhhbiBQQUdFX0NBQ0hFX1NJWkUuIFdlIGNvdWxkIGtsdWRnZSBvdXIgd2F5DQotICoJ
YXJvdW5kIHRoaXMgYnkgY3JlYXRpbmcgc2V2ZXJhbCBjb25zZWN1dGl2ZSByZWFkIHJlcXVlc3Rz
LCBidXQNCi0gKgl0aGF0J3MgaGFyZGx5IHdvcnRoIGl0Lg0KKyAqIFdlIHJlYWQgdGhlIHBhZ2Ug
c3luY2hyb25vdXNseSBpbiB0aGUgZm9sbG93aW5nIGNhc2U6DQogICogIC0JVGhlIGVycm9yIGZs
YWcgaXMgc2V0IGZvciB0aGlzIHBhZ2UuIFRoaXMgaGFwcGVucyBvbmx5IHdoZW4gYQ0KICAqCXBy
ZXZpb3VzIGFzeW5jIHJlYWQgb3BlcmF0aW9uIGZhaWxlZC4NCiAgKi8NCkBAIC0zMjksNyArNTA1
LDcgQEAgbmZzX3JlYWRwYWdlKHN0cnVjdCBmaWxlICpmaWxlLCBzdHJ1Y3QgcA0KIAlpZiAoZXJy
b3IpDQogCQlnb3RvIG91dF9lcnJvcjsNCiANCi0JaWYgKCFQYWdlRXJyb3IocGFnZSkgJiYgTkZT
X1NFUlZFUihpbm9kZSktPnJzaXplID49IFBBR0VfQ0FDSEVfU0laRSkgew0KKwlpZiAoIUlTX1NZ
TkMoaW5vZGUpKSB7DQogCQllcnJvciA9IG5mc19yZWFkcGFnZV9hc3luYyhmaWxlLCBpbm9kZSwg
cGFnZSk7DQogCQlnb3RvIG91dDsNCiAJfQ0KQEAgLTM1MSwyNiArNTI3LDI1IEBAIHN0cnVjdCBu
ZnNfcmVhZGRlc2Mgew0KIH07DQogDQogc3RhdGljIGludA0KLXJlYWRwYWdlX3N5bmNfZmlsbGVy
KHZvaWQgKmRhdGEsIHN0cnVjdCBwYWdlICpwYWdlKQ0KLXsNCi0Jc3RydWN0IG5mc19yZWFkZGVz
YyAqZGVzYyA9IChzdHJ1Y3QgbmZzX3JlYWRkZXNjICopZGF0YTsNCi0JcmV0dXJuIG5mc19yZWFk
cGFnZV9zeW5jKGRlc2MtPmZpbHAsIHBhZ2UtPm1hcHBpbmctPmhvc3QsIHBhZ2UpOw0KLX0NCi0N
Ci1zdGF0aWMgaW50DQogcmVhZHBhZ2VfYXN5bmNfZmlsbGVyKHZvaWQgKmRhdGEsIHN0cnVjdCBw
YWdlICpwYWdlKQ0KIHsNCiAJc3RydWN0IG5mc19yZWFkZGVzYyAqZGVzYyA9IChzdHJ1Y3QgbmZz
X3JlYWRkZXNjICopZGF0YTsNCiAJc3RydWN0IGlub2RlICppbm9kZSA9IHBhZ2UtPm1hcHBpbmct
Pmhvc3Q7DQogCXN0cnVjdCBuZnNfcGFnZSAqbmV3Ow0KKwl1bnNpZ25lZCBpbnQgbGVuOw0KIA0K
IAluZnNfd2JfcGFnZShpbm9kZSwgcGFnZSk7DQotCW5ldyA9IG5mc19jcmVhdGVfcmVxdWVzdChk
ZXNjLT5maWxwLCBpbm9kZSwgcGFnZSwgMCwgUEFHRV9DQUNIRV9TSVpFKTsNCisJbGVuID0gbmZz
X3BhZ2VfbGVuZ3RoKGlub2RlLCBwYWdlKTsNCisJaWYgKGxlbiA9PSAwKQ0KKwkJcmV0dXJuIG5m
c19yZXR1cm5fZW1wdHlfcGFnZShwYWdlKTsNCisJbmV3ID0gbmZzX2NyZWF0ZV9yZXF1ZXN0KGRl
c2MtPmZpbHAsIGlub2RlLCBwYWdlLCAwLCBsZW4pOw0KIAlpZiAoSVNfRVJSKG5ldykpIHsNCiAJ
CQlTZXRQYWdlRXJyb3IocGFnZSk7DQogCQkJdW5sb2NrX3BhZ2UocGFnZSk7DQogCQkJcmV0dXJu
IFBUUl9FUlIobmV3KTsNCiAJfQ0KKwlpZiAobGVuIDwgUEFHRV9DQUNIRV9TSVpFKQ0KKwkJbWVt
Y2xlYXJfaGlnaHBhZ2VfZmx1c2gocGFnZSwgbGVuLCBQQUdFX0NBQ0hFX1NJWkUgLSBsZW4pOw0K
IAluZnNfbG9ja19yZXF1ZXN0KG5ldyk7DQogCW5mc19saXN0X2FkZF9yZXF1ZXN0KG5ldywgZGVz
Yy0+aGVhZCk7DQogCXJldHVybiAwOw0KQEAgLTM4NSwxNCArNTYwLDE2IEBAIG5mc19yZWFkcGFn
ZXMoc3RydWN0IGZpbGUgKmZpbHAsIHN0cnVjdCANCiAJCS5maWxwCQk9IGZpbHAsDQogCQkuaGVh
ZAkJPSAmaGVhZCwNCiAJfTsNCi0Jc3RydWN0IG5mc19zZXJ2ZXIgKnNlcnZlciA9IE5GU19TRVJW
RVIobWFwcGluZy0+aG9zdCk7DQotCWludCBpc19zeW5jID0gc2VydmVyLT5yc2l6ZSA8IFBBR0Vf
Q0FDSEVfU0laRTsNCisJc3RydWN0IGlub2RlICppbm9kZSA9IG1hcHBpbmctPmhvc3Q7DQorCXN0
cnVjdCBuZnNfc2VydmVyICpzZXJ2ZXIgPSBORlNfU0VSVkVSKGlub2RlKTsNCiAJaW50IHJldDsN
CiANCi0JcmV0ID0gcmVhZF9jYWNoZV9wYWdlcyhtYXBwaW5nLCBwYWdlcywNCi0JCQkgICAgICAg
aXNfc3luYyA/IHJlYWRwYWdlX3N5bmNfZmlsbGVyIDoNCi0JCQkJCSByZWFkcGFnZV9hc3luY19m
aWxsZXIsDQotCQkJICAgICAgICZkZXNjKTsNCisJZHByaW50aygiTkZTOiBuZnNfcmVhZHBhZ2Vz
ICglcy8lTGQgJWQpXG4iLA0KKwkJCWlub2RlLT5pX3NiLT5zX2lkLA0KKwkJCShsb25nIGxvbmcp
TkZTX0ZJTEVJRChpbm9kZSksDQorCQkJbnJfcGFnZXMpOw0KKw0KKwlyZXQgPSByZWFkX2NhY2hl
X3BhZ2VzKG1hcHBpbmcsIHBhZ2VzLCByZWFkcGFnZV9hc3luY19maWxsZXIsICZkZXNjKTsNCiAJ
aWYgKCFsaXN0X2VtcHR5KCZoZWFkKSkgew0KIAkJaW50IGVyciA9IG5mc19wYWdlaW5fbGlzdCgm
aGVhZCwgc2VydmVyLT5ycGFnZXMpOw0KIAkJaWYgKCFyZXQpDQpkaWZmIC11IC0tcmVjdXJzaXZl
IC0tbmV3LWZpbGUgLS1zaG93LWMtZnVuY3Rpb24gbGludXgtMi42LjMtMTktcHJlcGFyZV9uZnNw
YWdlL2luY2x1ZGUvbGludXgvbmZzX2ZzLmggbGludXgtMi42LjMtMjAtc21hbGxfcnNpemUvaW5j
bHVkZS9saW51eC9uZnNfZnMuaA0KLS0tIGxpbnV4LTIuNi4zLTE5LXByZXBhcmVfbmZzcGFnZS9p
bmNsdWRlL2xpbnV4L25mc19mcy5oCTIwMDQtMDMtMDEgMTk6Mzk6MzMuMDAwMDAwMDAwIC0wNTAw
DQorKysgbGludXgtMi42LjMtMjAtc21hbGxfcnNpemUvaW5jbHVkZS9saW51eC9uZnNfZnMuaAky
MDA0LTAzLTAxIDE5OjQxOjA2LjAwMDAwMDAwMCAtMDUwMA0KQEAgLTM5NCw3ICszOTQsNiBAQCBl
eHRlcm4gaW50ICBuZnNfcmVhZHBhZ2VzKHN0cnVjdCBmaWxlICosDQogCQlzdHJ1Y3QgbGlzdF9o
ZWFkICosIHVuc2lnbmVkKTsNCiBleHRlcm4gaW50ICBuZnNfcGFnZWluX2xpc3Qoc3RydWN0IGxp
c3RfaGVhZCAqLCBpbnQpOw0KIGV4dGVybiB2b2lkIG5mc19yZWFkcGFnZV9yZXN1bHQoc3RydWN0
IHJwY190YXNrICopOw0KLWV4dGVybiB2b2lkIG5mc19yZWFkZGF0YV9yZWxlYXNlKHN0cnVjdCBy
cGNfdGFzayAqKTsNCiANCiAvKg0KICAqIGxpbnV4L2ZzL21vdW50X2NsbnQuYw0KZGlmZiAtdSAt
LXJlY3Vyc2l2ZSAtLW5ldy1maWxlIC0tc2hvdy1jLWZ1bmN0aW9uIGxpbnV4LTIuNi4zLTE5LXBy
ZXBhcmVfbmZzcGFnZS9pbmNsdWRlL2xpbnV4L25mc194ZHIuaCBsaW51eC0yLjYuMy0yMC1zbWFs
bF9yc2l6ZS9pbmNsdWRlL2xpbnV4L25mc194ZHIuaA0KLS0tIGxpbnV4LTIuNi4zLTE5LXByZXBh
cmVfbmZzcGFnZS9pbmNsdWRlL2xpbnV4L25mc194ZHIuaAkyMDA0LTAzLTAxIDE5OjQwOjU1LjAw
MDAwMDAwMCAtMDUwMA0KKysrIGxpbnV4LTIuNi4zLTIwLXNtYWxsX3JzaXplL2luY2x1ZGUvbGlu
dXgvbmZzX3hkci5oCTIwMDQtMDMtMDEgMTk6NDE6MDYuMDAwMDAwMDAwIC0wNTAwDQpAQCAtMjI5
LDcgKzIyOSw4IEBAIHN0cnVjdCBuZnNfbG9ja3JlcyB7DQogDQogc3RydWN0IG5mc19yZWFkYXJn
cyB7DQogCXN0cnVjdCBuZnNfZmggKgkJZmg7DQotCW5mczRfc3RhdGVpZAkJc3RhdGVpZDsNCisJ
Zmxfb3duZXJfdAkJbG9ja293bmVyOw0KKwlzdHJ1Y3QgbmZzNF9zdGF0ZSAqCXN0YXRlOw0KIAlf
X3U2NAkJCW9mZnNldDsNCiAJX191MzIJCQljb3VudDsNCiAJdW5zaWduZWQgaW50CQlwZ2Jhc2U7
DQpAQCAtNjYzLDcgKzY2NCw2IEBAIHN0cnVjdCBuZnNfcmVhZF9kYXRhIHsNCiAJc3RydWN0IHJw
Y190YXNrCQl0YXNrOw0KIAlzdHJ1Y3QgaW5vZGUJCSppbm9kZTsNCiAJc3RydWN0IHJwY19jcmVk
CQkqY3JlZDsNCi0JZmxfb3duZXJfdAkJbG9ja293bmVyOw0KIAlzdHJ1Y3QgbmZzX2ZhdHRyCWZh
dHRyOwkvKiBmYXR0ciBzdG9yYWdlICovDQogCXN0cnVjdCBsaXN0X2hlYWQJcGFnZXM7CS8qIENv
YWxlc2NlZCByZWFkIHJlcXVlc3RzICovDQogCXN0cnVjdCBuZnNfcGFnZQkJKnJlcTsJLyogbXVs
dGkgb3BzIHBlciBuZnNfcGFnZSAqLw0KQEAgLTc0MSw3ICs3NDEsNyBAQCBzdHJ1Y3QgbmZzX3Jw
Y19vcHMgew0KIAlpbnQJKCpwYXRoY29uZikgKHN0cnVjdCBuZnNfc2VydmVyICosIHN0cnVjdCBu
ZnNfZmggKiwNCiAJCQkgICAgIHN0cnVjdCBuZnNfcGF0aGNvbmYgKik7DQogCXUzMiAqCSgqZGVj
b2RlX2RpcmVudCkodTMyICosIHN0cnVjdCBuZnNfZW50cnkgKiwgaW50IHBsdXMpOw0KLQl2b2lk
CSgqcmVhZF9zZXR1cCkgICAoc3RydWN0IG5mc19yZWFkX2RhdGEgKiwgdW5zaWduZWQgaW50IGNv
dW50KTsNCisJdm9pZAkoKnJlYWRfc2V0dXApICAgKHN0cnVjdCBuZnNfcmVhZF9kYXRhICopOw0K
IAl2b2lkCSgqd3JpdGVfc2V0dXApICAoc3RydWN0IG5mc193cml0ZV9kYXRhICosIHVuc2lnbmVk
IGludCBjb3VudCwgaW50IGhvdyk7DQogCXZvaWQJKCpjb21taXRfc2V0dXApIChzdHJ1Y3QgbmZz
X3dyaXRlX2RhdGEgKiwgdTY0IHN0YXJ0LCB1MzIgbGVuLCBpbnQgaG93KTsNCiAJaW50CSgqZmls
ZV9vcGVuKSAgIChzdHJ1Y3QgaW5vZGUgKiwgc3RydWN0IGZpbGUgKik7DQo=

--=-O2aAqp6DrzPwP3KoW56V--



---

 25-akpm/fs/nfs/direct.c         |    1 
 25-akpm/fs/nfs/nfs3proc.c       |   21 --
 25-akpm/fs/nfs/nfs4proc.c       |   41 ----
 25-akpm/fs/nfs/nfs4xdr.c        |   22 ++
 25-akpm/fs/nfs/proc.c           |   21 --
 25-akpm/fs/nfs/read.c           |  331 ++++++++++++++++++++++++++++++----------
 25-akpm/include/linux/nfs_fs.h  |    1 
 25-akpm/include/linux/nfs_xdr.h |    6 
 8 files changed, 288 insertions(+), 156 deletions(-)

diff -puN fs/nfs/direct.c~nfs-02-small_rsize fs/nfs/direct.c
--- 25/fs/nfs/direct.c~nfs-02-small_rsize	2004-03-14 15:12:31.174991152 -0800
+++ 25-akpm/fs/nfs/direct.c	2004-03-14 15:12:31.186989328 -0800
@@ -128,6 +128,7 @@ nfs_direct_read_seg(struct inode *inode,
 		.inode		= inode,
 		.args		= {
 			.fh		= NFS_FH(inode),
+			.lockowner	= current->files,
 		},
 		.res		= {
 			.fattr		= &rdata.fattr,
diff -puN fs/nfs/nfs3proc.c~nfs-02-small_rsize fs/nfs/nfs3proc.c
--- 25/fs/nfs/nfs3proc.c~nfs-02-small_rsize	2004-03-14 15:12:31.175991000 -0800
+++ 25-akpm/fs/nfs/nfs3proc.c	2004-03-14 15:12:31.187989176 -0800
@@ -729,11 +729,10 @@ nfs3_read_done(struct rpc_task *task)
 }
 
 static void
-nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
+nfs3_proc_read_setup(struct nfs_read_data *data)
 {
 	struct rpc_task		*task = &data->task;
 	struct inode		*inode = data->inode;
-	struct nfs_page		*req;
 	int			flags;
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
@@ -741,27 +740,13 @@ nfs3_proc_read_setup(struct nfs_read_dat
 		.rpc_resp	= &data->res,
 		.rpc_cred	= data->cred,
 	};
-	
-	req = nfs_list_entry(data->pages.next);
-	data->args.fh     = NFS_FH(inode);
-	data->args.offset = req_offset(req);
-	data->args.pgbase = req->wb_pgbase;
-	data->args.pages  = data->pagevec;
-	data->args.count  = count;
-	data->res.fattr   = &data->fattr;
-	data->res.count   = count;
-	data->res.eof     = 0;
-	
+
 	/* N.B. Do we need to test? Never called for swapfile inode */
 	flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
 
 	/* Finalize the task. */
 	rpc_init_task(task, NFS_CLIENT(inode), nfs3_read_done, flags);
-	task->tk_calldata = data;
-	/* Release requests */
-	task->tk_release = nfs_readdata_release;
-
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(task, &msg, 0);
 }
 
 static void
diff -puN fs/nfs/nfs4proc.c~nfs-02-small_rsize fs/nfs/nfs4proc.c
--- 25/fs/nfs/nfs4proc.c~nfs-02-small_rsize	2004-03-14 15:12:31.177990696 -0800
+++ 25-akpm/fs/nfs/nfs4proc.c	2004-03-14 15:12:31.190988720 -0800
@@ -1096,10 +1096,10 @@ nfs4_proc_read(struct nfs_read_data *rda
 	if (filp) {
 		struct nfs4_state *state;
 		state = (struct nfs4_state *)filp->private_data;
-		nfs4_copy_stateid(&rdata->args.stateid, state, rdata->lockowner);
+		rdata->args.state = state;
 		msg.rpc_cred = state->owner->so_cred;
 	} else {
-		memcpy(&rdata->args.stateid, &zero_stateid, sizeof(rdata->args.stateid));
+		rdata->args.state = NULL;
 		msg.rpc_cred = NFS_I(inode)->mm_cred;
 	}
 
@@ -1510,27 +1510,13 @@ nfs4_proc_pathconf(struct nfs_server *se
 }
 
 static void
-nfs4_restart_read(struct rpc_task *task)
-{
-	struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
-	struct nfs_page *req;
-
-	rpc_restart_call(task);
-	req = nfs_list_entry(data->pages.next);
-	if (req->wb_state)
-		nfs4_copy_stateid(&data->args.stateid, req->wb_state, req->wb_lockowner);
-	else
-		memcpy(&data->args.stateid, &zero_stateid, sizeof(data->args.stateid));
-}
-
-static void
 nfs4_read_done(struct rpc_task *task)
 {
 	struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
 	struct inode *inode = data->inode;
 
 	if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
-		task->tk_action = nfs4_restart_read;
+		rpc_restart_call(task);
 		return;
 	}
 	if (task->tk_status > 0)
@@ -1540,7 +1526,7 @@ nfs4_read_done(struct rpc_task *task)
 }
 
 static void
-nfs4_proc_read_setup(struct nfs_read_data *data, unsigned int count)
+nfs4_proc_read_setup(struct nfs_read_data *data)
 {
 	struct rpc_task	*task = &data->task;
 	struct rpc_message msg = {
@@ -1550,34 +1536,15 @@ nfs4_proc_read_setup(struct nfs_read_dat
 		.rpc_cred = data->cred,
 	};
 	struct inode *inode = data->inode;
-	struct nfs_page *req = nfs_list_entry(data->pages.next);
 	int flags;
 
-	data->args.fh     = NFS_FH(inode);
-	data->args.offset = req_offset(req);
-	data->args.pgbase = req->wb_pgbase;
-	data->args.pages  = data->pagevec;
-	data->args.count  = count;
-	data->res.fattr   = &data->fattr;
-	data->res.count   = count;
-	data->res.eof     = 0;
 	data->timestamp   = jiffies;
 
-	data->lockowner = req->wb_lockowner;
-	if (req->wb_state)
-		nfs4_copy_stateid(&data->args.stateid, req->wb_state, req->wb_lockowner);
-	else
-		memcpy(&data->args.stateid, &zero_stateid, sizeof(data->args.stateid));
-
 	/* N.B. Do we need to test? Never called for swapfile inode */
 	flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
 
 	/* Finalize the task. */
 	rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags);
-	task->tk_calldata = data;
-	/* Release requests */
-	task->tk_release = nfs_readdata_release;
-
 	rpc_call_setup(task, &msg, 0);
 }
 
diff -puN fs/nfs/nfs4xdr.c~nfs-02-small_rsize fs/nfs/nfs4xdr.c
--- 25/fs/nfs/nfs4xdr.c~nfs-02-small_rsize	2004-03-14 15:12:31.179990392 -0800
+++ 25-akpm/fs/nfs/nfs4xdr.c	2004-03-14 15:12:31.192988416 -0800
@@ -868,14 +868,32 @@ encode_putrootfh(struct xdr_stream *xdr)
         return 0;
 }
 
+static void
+encode_stateid(struct xdr_stream *xdr, struct nfs4_state *state, fl_owner_t lockowner)
+{
+	extern nfs4_stateid zero_stateid;
+	nfs4_stateid stateid;
+	uint32_t *p;
+
+	RESERVE_SPACE(16);
+	if (state != NULL) {
+		nfs4_copy_stateid(&stateid, state, lockowner);
+		WRITEMEM(stateid.data, sizeof(stateid.data));
+	} else
+		WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
+}
+
 static int
 encode_read(struct xdr_stream *xdr, struct nfs_readargs *args)
 {
 	uint32_t *p;
 
-	RESERVE_SPACE(32);
+	RESERVE_SPACE(4);
 	WRITE32(OP_READ);
-	WRITEMEM(args->stateid.data, sizeof(args->stateid.data));
+
+	encode_stateid(xdr, args->state, args->lockowner);
+
+	RESERVE_SPACE(12);
 	WRITE64(args->offset);
 	WRITE32(args->count);
 
diff -puN fs/nfs/proc.c~nfs-02-small_rsize fs/nfs/proc.c
--- 25/fs/nfs/proc.c~nfs-02-small_rsize	2004-03-14 15:12:31.180990240 -0800
+++ 25-akpm/fs/nfs/proc.c	2004-03-14 15:12:31.193988264 -0800
@@ -559,11 +559,10 @@ nfs_read_done(struct rpc_task *task)
 }
 
 static void
-nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count)
+nfs_proc_read_setup(struct nfs_read_data *data)
 {
 	struct rpc_task		*task = &data->task;
 	struct inode		*inode = data->inode;
-	struct nfs_page		*req;
 	int			flags;
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
@@ -571,27 +570,13 @@ nfs_proc_read_setup(struct nfs_read_data
 		.rpc_resp	= &data->res,
 		.rpc_cred	= data->cred,
 	};
-	
-	req = nfs_list_entry(data->pages.next);
-	data->args.fh     = NFS_FH(inode);
-	data->args.offset = req_offset(req);
-	data->args.pgbase = req->wb_pgbase;
-	data->args.pages  = data->pagevec;
-	data->args.count  = count;
-	data->res.fattr   = &data->fattr;
-	data->res.count   = count;
-	data->res.eof     = 0;
-	
+
 	/* N.B. Do we need to test? Never called for swapfile inode */
 	flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
 
 	/* Finalize the task. */
 	rpc_init_task(task, NFS_CLIENT(inode), nfs_read_done, flags);
-	task->tk_calldata = data;
-	/* Release requests */
-	task->tk_release = nfs_readdata_release;
-
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(task, &msg, 0);
 }
 
 static void
diff -puN fs/nfs/read.c~nfs-02-small_rsize fs/nfs/read.c
--- 25/fs/nfs/read.c~nfs-02-small_rsize	2004-03-14 15:12:31.182989936 -0800
+++ 25-akpm/fs/nfs/read.c	2004-03-14 15:12:31.195987960 -0800
@@ -35,6 +35,8 @@
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
 static int nfs_pagein_one(struct list_head *, struct inode *);
+static void nfs_readpage_result_partial(struct nfs_read_data *, int);
+static void nfs_readpage_result_full(struct nfs_read_data *, int);
 
 static kmem_cache_t *nfs_rdata_cachep;
 static mempool_t *nfs_rdata_mempool;
@@ -57,12 +59,37 @@ static __inline__ void nfs_readdata_free
 	mempool_free(p, nfs_rdata_mempool);
 }
 
-void nfs_readdata_release(struct rpc_task *task)
+static void nfs_readdata_release(struct rpc_task *task)
 {
         struct nfs_read_data   *data = (struct nfs_read_data *)task->tk_calldata;
         nfs_readdata_free(data);
 }
 
+static
+unsigned int nfs_page_length(struct inode *inode, struct page *page)
+{
+	loff_t i_size = i_size_read(inode);
+	unsigned long idx;
+
+	if (i_size <= 0)
+		return 0;
+	idx = (i_size - 1) >> PAGE_CACHE_SHIFT;
+	if (page->index > idx)
+		return 0;
+	if (page->index != idx)
+		return PAGE_CACHE_SIZE;
+	return 1 + ((i_size - 1) & (PAGE_CACHE_SIZE - 1));
+}
+
+static
+int nfs_return_empty_page(struct page *page)
+{
+	memclear_highpage_flush(page, 0, PAGE_CACHE_SIZE);
+	SetPageUptodate(page);
+	unlock_page(page);
+	return 0;
+}
+
 /*
  * Read a page synchronously.
  */
@@ -78,6 +105,7 @@ nfs_readpage_sync(struct file *file, str
 		.inode		= inode,
 		.args		= {
 			.fh		= NFS_FH(inode),
+			.lockowner	= current->files,
 			.pages		= &page,
 			.pgbase		= 0UL,
 			.count		= rsize,
@@ -146,89 +174,208 @@ nfs_readpage_async(struct file *file, st
 {
 	LIST_HEAD(one_request);
 	struct nfs_page	*new;
+	unsigned int len;
 
-	new = nfs_create_request(file, inode, page, 0, PAGE_CACHE_SIZE);
+	len = nfs_page_length(inode, page);
+	if (len == 0)
+		return nfs_return_empty_page(page);
+	new = nfs_create_request(file, inode, page, 0, len);
 	if (IS_ERR(new)) {
 		unlock_page(page);
 		return PTR_ERR(new);
 	}
+	if (len < PAGE_CACHE_SIZE)
+		memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
+
 	nfs_lock_request(new);
 	nfs_list_add_request(new, &one_request);
 	nfs_pagein_one(&one_request, inode);
 	return 0;
 }
 
+static void nfs_readpage_release(struct nfs_page *req)
+{
+	unlock_page(req->wb_page);
+
+	nfs_clear_request(req);
+	nfs_release_request(req);
+	nfs_unlock_request(req);
+
+	dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
+			req->wb_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_inode),
+			req->wb_bytes,
+			(long long)req_offset(req));
+}
+
 /*
  * Set up the NFS read request struct
  */
-static void
-nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
+static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+		unsigned int count, unsigned int offset)
 {
 	struct inode		*inode;
-	struct nfs_page		*req;
-	struct page		**pages;
-	unsigned int		count;
 
-	pages = data->pagevec;
-	count = 0;
-	while (!list_empty(head)) {
-		req = nfs_list_entry(head->next);
-		nfs_list_remove_request(req);
-		nfs_list_add_request(req, &data->pages);
-		*pages++ = req->wb_page;
-		count += req->wb_bytes;
-	}
-	req = nfs_list_entry(data->pages.next);
+	data->req	  = req;
 	data->inode	  = inode = req->wb_inode;
 	data->cred	  = req->wb_cred;
 
-	NFS_PROTO(inode)->read_setup(data, count);
+	data->args.fh     = NFS_FH(inode);
+	data->args.offset = req_offset(req) + offset;
+	data->args.pgbase = req->wb_pgbase + offset;
+	data->args.pages  = data->pagevec;
+	data->args.count  = count;
+	data->args.lockowner = req->wb_lockowner;
+	data->args.state  = req->wb_state;
+
+	data->res.fattr   = &data->fattr;
+	data->res.count   = count;
+	data->res.eof     = 0;
+
+	NFS_PROTO(inode)->read_setup(data);
+
+	data->task.tk_calldata = data;
+	/* Release requests */
+	data->task.tk_release = nfs_readdata_release;
 
-	dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu.\n",
+	dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
 			data->task.tk_pid,
 			inode->i_sb->s_id,
 			(long long)NFS_FILEID(inode),
 			count,
-			(unsigned long long)req_offset(req));
+			data->args.offset);
 }
 
 static void
 nfs_async_read_error(struct list_head *head)
 {
 	struct nfs_page	*req;
-	struct page	*page;
 
 	while (!list_empty(head)) {
 		req = nfs_list_entry(head->next);
-		page = req->wb_page;
 		nfs_list_remove_request(req);
-		SetPageError(page);
-		unlock_page(page);
-		nfs_clear_request(req);
-		nfs_release_request(req);
-		nfs_unlock_request(req);
+		SetPageError(req->wb_page);
+		nfs_readpage_release(req);
 	}
 }
 
-static int
-nfs_pagein_one(struct list_head *head, struct inode *inode)
+/*
+ * Start an async read operation
+ */
+static void nfs_execute_read(struct nfs_read_data *data)
+{
+	struct rpc_clnt *clnt = NFS_CLIENT(data->inode);
+	sigset_t oldset;
+
+	rpc_clnt_sigmask(clnt, &oldset);
+	lock_kernel();
+	rpc_execute(&data->task);
+	unlock_kernel();
+	rpc_clnt_sigunmask(clnt, &oldset);
+}
+
+/*
+ * Generate multiple requests to fill a single page.
+ *
+ * We optimize to reduce the number of read operations on the wire.  If we
+ * detect that we're reading a page, or an area of a page, that is past the
+ * end of file, we do not generate NFS read operations but just clear the
+ * parts of the page that would have come back zero from the server anyway.
+ *
+ * We rely on the cached value of i_size to make this determination; another
+ * client can fill pages on the server past our cached end-of-file, but we
+ * won't see the new data until our attribute cache is updated.  This is more
+ * or less conventional NFS client behavior.
+ */
+static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
+{
+	struct nfs_page *req = nfs_list_entry(head->next);
+	struct page *page = req->wb_page;
+	struct nfs_read_data *data;
+	unsigned int rsize = NFS_SERVER(inode)->rsize;
+	unsigned int nbytes, offset;
+	int requests = 0;
+	LIST_HEAD(list);
+
+	nfs_list_remove_request(req);
+
+	nbytes = req->wb_bytes;
+	for(;;) {
+		data = nfs_readdata_alloc();
+		if (!data)
+			goto out_bad;
+		list_add(&data->pages, &list);
+		requests++;
+		if (nbytes <= rsize)
+			break;
+		nbytes -= rsize;
+	}
+	atomic_set(&req->wb_complete, requests);
+
+	ClearPageError(page);
+	offset = 0;
+	nbytes = req->wb_bytes;
+	do {
+		data = list_entry(list.next, struct nfs_read_data, pages);
+		list_del_init(&data->pages);
+
+		data->pagevec[0] = page;
+		data->complete = nfs_readpage_result_partial;
+
+		if (nbytes > rsize) {
+			nfs_read_rpcsetup(req, data, rsize, offset);
+			offset += rsize;
+			nbytes -= rsize;
+		} else {
+			nfs_read_rpcsetup(req, data, nbytes, offset);
+			nbytes = 0;
+		}
+		nfs_execute_read(data);
+	} while (nbytes != 0);
+
+	return 0;
+
+out_bad:
+	while (!list_empty(&list)) {
+		data = list_entry(list.next, struct nfs_read_data, pages);
+		list_del(&data->pages);
+		nfs_readdata_free(data);
+	}
+	SetPageError(page);
+	nfs_readpage_release(req);
+	return -ENOMEM;
+}
+
+static int nfs_pagein_one(struct list_head *head, struct inode *inode)
 {
-	struct rpc_clnt		*clnt = NFS_CLIENT(inode);
+	struct nfs_page		*req;
+	struct page		**pages;
 	struct nfs_read_data	*data;
-	sigset_t		oldset;
+	unsigned int		count;
+
+	if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
+		return nfs_pagein_multi(head, inode);
 
 	data = nfs_readdata_alloc();
 	if (!data)
 		goto out_bad;
 
-	nfs_read_rpcsetup(head, data);
+	pages = data->pagevec;
+	count = 0;
+	while (!list_empty(head)) {
+		req = nfs_list_entry(head->next);
+		nfs_list_remove_request(req);
+		nfs_list_add_request(req, &data->pages);
+		ClearPageError(req->wb_page);
+		*pages++ = req->wb_page;
+		count += req->wb_bytes;
+	}
+	req = nfs_list_entry(data->pages.next);
+
+	data->complete = nfs_readpage_result_full;
+	nfs_read_rpcsetup(req, data, count, 0);
 
-	/* Start the async call */
-	rpc_clnt_sigmask(clnt, &oldset);
-	lock_kernel();
-	rpc_execute(&data->task);
-	unlock_kernel();
-	rpc_clnt_sigunmask(clnt, &oldset);
+	nfs_execute_read(data);
 	return 0;
 out_bad:
 	nfs_async_read_error(head);
@@ -258,55 +405,84 @@ nfs_pagein_list(struct list_head *head, 
 }
 
 /*
+ * Handle a read reply that fills part of a page.
+ */
+static void nfs_readpage_result_partial(struct nfs_read_data *data, int status)
+{
+	struct nfs_page *req = data->req;
+	struct page *page = req->wb_page;
+
+	if (status >= 0) {
+		unsigned int request = data->args.count;
+		unsigned int result = data->res.count;
+
+		if (result < request) {
+			memclear_highpage_flush(page,
+						data->args.pgbase + result,
+						request - result);
+			if (!data->res.eof)
+				SetPageError(page);
+		}
+	} else
+		SetPageError(page);
+
+	if (atomic_dec_and_test(&req->wb_complete)) {
+		if (!PageError(page))
+			SetPageUptodate(page);
+		nfs_readpage_release(req);
+	}
+}
+
+/*
  * This is the callback from RPC telling us whether a reply was
  * received or some error occurred (timeout or socket shutdown).
  */
-void
-nfs_readpage_result(struct rpc_task *task)
+static void nfs_readpage_result_full(struct nfs_read_data *data, int status)
 {
-	struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
 	unsigned int count = data->res.count;
 
-	dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
-		task->tk_pid, task->tk_status);
-
-	NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME;
 	while (!list_empty(&data->pages)) {
 		struct nfs_page *req = nfs_list_entry(data->pages.next);
 		struct page *page = req->wb_page;
 		nfs_list_remove_request(req);
 
-		if (task->tk_status >= 0) {
+		if (status >= 0) {
 			if (count < PAGE_CACHE_SIZE) {
-				memclear_highpage_flush(page,
+				if (count < req->wb_bytes)
+					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;
 			SetPageUptodate(page);
 		} else
 			SetPageError(page);
-		unlock_page(page);
-
-		dprintk("NFS: read (%s/%Ld %d@%Ld)\n",
-                        req->wb_inode->i_sb->s_id,
-                        (long long)NFS_FILEID(req->wb_inode),
-                        req->wb_bytes,
-                        (long long)req_offset(req));
-		nfs_clear_request(req);
-		nfs_release_request(req);
-		nfs_unlock_request(req);
+		nfs_readpage_release(req);
 	}
 }
 
 /*
+ * This is the callback from RPC telling us whether a reply was
+ * received or some error occurred (timeout or socket shutdown).
+ */
+void nfs_readpage_result(struct rpc_task *task)
+{
+	struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
+	int status = task->tk_status;
+
+	dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
+		task->tk_pid, status);
+
+	NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME;
+	data->complete(data, status);
+}
+
+/*
  * Read a page over NFS.
- * We read the page synchronously in the following cases:
- *  -	The NFS rsize is smaller than PAGE_CACHE_SIZE. We could kludge our way
- *	around this by creating several consecutive read requests, but
- *	that's hardly worth it.
+ * We read the page synchronously in the following case:
  *  -	The error flag is set for this page. This happens only when a
  *	previous async read operation failed.
  */
@@ -329,7 +505,7 @@ nfs_readpage(struct file *file, struct p
 	if (error)
 		goto out_error;
 
-	if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
+	if (!IS_SYNC(inode)) {
 		error = nfs_readpage_async(file, inode, page);
 		goto out;
 	}
@@ -351,26 +527,25 @@ struct nfs_readdesc {
 };
 
 static int
-readpage_sync_filler(void *data, struct page *page)
-{
-	struct nfs_readdesc *desc = (struct nfs_readdesc *)data;
-	return nfs_readpage_sync(desc->filp, page->mapping->host, page);
-}
-
-static int
 readpage_async_filler(void *data, struct page *page)
 {
 	struct nfs_readdesc *desc = (struct nfs_readdesc *)data;
 	struct inode *inode = page->mapping->host;
 	struct nfs_page *new;
+	unsigned int len;
 
 	nfs_wb_page(inode, page);
-	new = nfs_create_request(desc->filp, inode, page, 0, PAGE_CACHE_SIZE);
+	len = nfs_page_length(inode, page);
+	if (len == 0)
+		return nfs_return_empty_page(page);
+	new = nfs_create_request(desc->filp, inode, page, 0, len);
 	if (IS_ERR(new)) {
 			SetPageError(page);
 			unlock_page(page);
 			return PTR_ERR(new);
 	}
+	if (len < PAGE_CACHE_SIZE)
+		memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
 	nfs_lock_request(new);
 	nfs_list_add_request(new, desc->head);
 	return 0;
@@ -385,14 +560,16 @@ nfs_readpages(struct file *filp, struct 
 		.filp		= filp,
 		.head		= &head,
 	};
-	struct nfs_server *server = NFS_SERVER(mapping->host);
-	int is_sync = server->rsize < PAGE_CACHE_SIZE;
+	struct inode *inode = mapping->host;
+	struct nfs_server *server = NFS_SERVER(inode);
 	int ret;
 
-	ret = read_cache_pages(mapping, pages,
-			       is_sync ? readpage_sync_filler :
-					 readpage_async_filler,
-			       &desc);
+	dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
+			inode->i_sb->s_id,
+			(long long)NFS_FILEID(inode),
+			nr_pages);
+
+	ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
 	if (!list_empty(&head)) {
 		int err = nfs_pagein_list(&head, server->rpages);
 		if (!ret)
diff -puN include/linux/nfs_fs.h~nfs-02-small_rsize include/linux/nfs_fs.h
--- 25/include/linux/nfs_fs.h~nfs-02-small_rsize	2004-03-14 15:12:31.183989784 -0800
+++ 25-akpm/include/linux/nfs_fs.h	2004-03-14 15:12:31.196987808 -0800
@@ -397,7 +397,6 @@ extern int  nfs_readpages(struct file *,
 		struct list_head *, unsigned);
 extern int  nfs_pagein_list(struct list_head *, int);
 extern void nfs_readpage_result(struct rpc_task *);
-extern void nfs_readdata_release(struct rpc_task *);
 
 /*
  * linux/fs/mount_clnt.c
diff -puN include/linux/nfs_xdr.h~nfs-02-small_rsize include/linux/nfs_xdr.h
--- 25/include/linux/nfs_xdr.h~nfs-02-small_rsize	2004-03-14 15:12:31.185989480 -0800
+++ 25-akpm/include/linux/nfs_xdr.h	2004-03-14 15:12:31.197987656 -0800
@@ -229,7 +229,8 @@ struct nfs_lockres {
 
 struct nfs_readargs {
 	struct nfs_fh *		fh;
-	nfs4_stateid		stateid;
+	fl_owner_t		lockowner;
+	struct nfs4_state *	state;
 	__u64			offset;
 	__u32			count;
 	unsigned int		pgbase;
@@ -663,7 +664,6 @@ struct nfs_read_data {
 	struct rpc_task		task;
 	struct inode		*inode;
 	struct rpc_cred		*cred;
-	fl_owner_t		lockowner;
 	struct nfs_fattr	fattr;	/* fattr storage */
 	struct list_head	pages;	/* Coalesced read requests */
 	struct nfs_page		*req;	/* multi ops per nfs_page */
@@ -741,7 +741,7 @@ struct nfs_rpc_ops {
 	int	(*pathconf) (struct nfs_server *, struct nfs_fh *,
 			     struct nfs_pathconf *);
 	u32 *	(*decode_dirent)(u32 *, struct nfs_entry *, int plus);
-	void	(*read_setup)   (struct nfs_read_data *, unsigned int count);
+	void	(*read_setup)   (struct nfs_read_data *);
 	void	(*write_setup)  (struct nfs_write_data *, unsigned int count, int how);
 	void	(*commit_setup) (struct nfs_write_data *, u64 start, u32 len, int how);
 	int	(*file_open)   (struct inode *, struct file *);

_