aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c2
-rw-r--r--fs/nfsd/nfs4callback.c67
-rw-r--r--fs/nfsd/nfs4idmap.c4
-rw-r--r--fs/nfsd/nfs4proc.c8
-rw-r--r--fs/nfsd/nfs4recover.c21
-rw-r--r--fs/nfsd/nfs4state.c45
-rw-r--r--fs/nfsd/nfscache.c3
-rw-r--r--fs/nfsd/nfsctl.c1
-rw-r--r--fs/nfsd/nfsfh.c27
-rw-r--r--fs/nfsd/nfssvc.c1
-rw-r--r--fs/nfsd/stats.c10
-rw-r--r--fs/nfsd/vfs.c15
12 files changed, 106 insertions, 98 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 3eec30000f3f..01bc68c628ad 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -126,7 +126,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
126 if (*ep) 126 if (*ep)
127 goto out; 127 goto out;
128 dprintk("found fsidtype %d\n", fsidtype); 128 dprintk("found fsidtype %d\n", fsidtype);
129 if (fsidtype > 2) 129 if (key_len(fsidtype)==0) /* invalid type */
130 goto out; 130 goto out;
131 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) 131 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
132 goto out; 132 goto out;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index dbaf3f93f328..8583d99ee740 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -33,7 +33,6 @@
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 35
36#include <linux/config.h>
37#include <linux/module.h> 36#include <linux/module.h>
38#include <linux/list.h> 37#include <linux/list.h>
39#include <linux/inet.h> 38#include <linux/inet.h>
@@ -376,16 +375,28 @@ nfsd4_probe_callback(struct nfs4_client *clp)
376{ 375{
377 struct sockaddr_in addr; 376 struct sockaddr_in addr;
378 struct nfs4_callback *cb = &clp->cl_callback; 377 struct nfs4_callback *cb = &clp->cl_callback;
379 struct rpc_timeout timeparms; 378 struct rpc_timeout timeparms = {
380 struct rpc_xprt * xprt; 379 .to_initval = (NFSD_LEASE_TIME/4) * HZ,
380 .to_retries = 5,
381 .to_maxval = (NFSD_LEASE_TIME/2) * HZ,
382 .to_exponential = 1,
383 };
381 struct rpc_program * program = &cb->cb_program; 384 struct rpc_program * program = &cb->cb_program;
382 struct rpc_stat * stat = &cb->cb_stat; 385 struct rpc_create_args args = {
383 struct rpc_clnt * clnt; 386 .protocol = IPPROTO_TCP,
387 .address = (struct sockaddr *)&addr,
388 .addrsize = sizeof(addr),
389 .timeout = &timeparms,
390 .servername = clp->cl_name.data,
391 .program = program,
392 .version = nfs_cb_version[1]->number,
393 .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
394 .flags = (RPC_CLNT_CREATE_NOPING),
395 };
384 struct rpc_message msg = { 396 struct rpc_message msg = {
385 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], 397 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
386 .rpc_argp = clp, 398 .rpc_argp = clp,
387 }; 399 };
388 char hostname[32];
389 int status; 400 int status;
390 401
391 if (atomic_read(&cb->cb_set)) 402 if (atomic_read(&cb->cb_set))
@@ -397,51 +408,27 @@ nfsd4_probe_callback(struct nfs4_client *clp)
397 addr.sin_port = htons(cb->cb_port); 408 addr.sin_port = htons(cb->cb_port);
398 addr.sin_addr.s_addr = htonl(cb->cb_addr); 409 addr.sin_addr.s_addr = htonl(cb->cb_addr);
399 410
400 /* Initialize timeout */
401 timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ;
402 timeparms.to_retries = 0;
403 timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ;
404 timeparms.to_exponential = 1;
405
406 /* Create RPC transport */
407 xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms);
408 if (IS_ERR(xprt)) {
409 dprintk("NFSD: couldn't create callback transport!\n");
410 goto out_err;
411 }
412
413 /* Initialize rpc_program */ 411 /* Initialize rpc_program */
414 program->name = "nfs4_cb"; 412 program->name = "nfs4_cb";
415 program->number = cb->cb_prog; 413 program->number = cb->cb_prog;
416 program->nrvers = ARRAY_SIZE(nfs_cb_version); 414 program->nrvers = ARRAY_SIZE(nfs_cb_version);
417 program->version = nfs_cb_version; 415 program->version = nfs_cb_version;
418 program->stats = stat; 416 program->stats = &cb->cb_stat;
419 417
420 /* Initialize rpc_stat */ 418 /* Initialize rpc_stat */
421 memset(stat, 0, sizeof(struct rpc_stat)); 419 memset(program->stats, 0, sizeof(cb->cb_stat));
422 stat->program = program; 420 program->stats->program = program;
423 421
424 /* Create RPC client 422 /* Create RPC client */
425 * 423 cb->cb_client = rpc_create(&args);
426 * XXX AUTH_UNIX only - need AUTH_GSS.... 424 if (!cb->cb_client) {
427 */
428 sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
429 clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
430 if (IS_ERR(clnt)) {
431 dprintk("NFSD: couldn't create callback client\n"); 425 dprintk("NFSD: couldn't create callback client\n");
432 goto out_err; 426 goto out_err;
433 } 427 }
434 clnt->cl_intr = 0;
435 clnt->cl_softrtry = 1;
436 428
437 /* Kick rpciod, put the call on the wire. */ 429 /* Kick rpciod, put the call on the wire. */
438 430 if (rpciod_up() != 0)
439 if (rpciod_up() != 0) {
440 dprintk("nfsd: couldn't start rpciod for callbacks!\n");
441 goto out_clnt; 431 goto out_clnt;
442 }
443
444 cb->cb_client = clnt;
445 432
446 /* the task holds a reference to the nfs4_client struct */ 433 /* the task holds a reference to the nfs4_client struct */
447 atomic_inc(&clp->cl_count); 434 atomic_inc(&clp->cl_count);
@@ -449,7 +436,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
449 msg.rpc_cred = nfsd4_lookupcred(clp,0); 436 msg.rpc_cred = nfsd4_lookupcred(clp,0);
450 if (IS_ERR(msg.rpc_cred)) 437 if (IS_ERR(msg.rpc_cred))
451 goto out_rpciod; 438 goto out_rpciod;
452 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); 439 status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
453 put_rpccred(msg.rpc_cred); 440 put_rpccred(msg.rpc_cred);
454 441
455 if (status != 0) { 442 if (status != 0) {
@@ -463,7 +450,7 @@ out_rpciod:
463 rpciod_down(); 450 rpciod_down();
464 cb->cb_client = NULL; 451 cb->cb_client = NULL;
465out_clnt: 452out_clnt:
466 rpc_shutdown_client(clnt); 453 rpc_shutdown_client(cb->cb_client);
467out_err: 454out_err:
468 dprintk("NFSD: warning: no callback path to client %.*s\n", 455 dprintk("NFSD: warning: no callback path to client %.*s\n",
469 (int)clp->cl_name.len, clp->cl_name.data); 456 (int)clp->cl_name.len, clp->cl_name.data);
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 4b6aa60dfceb..b1902ebaab41 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -34,7 +34,6 @@
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */ 35 */
36 36
37#include <linux/config.h>
38#include <linux/module.h> 37#include <linux/module.h>
39#include <linux/init.h> 38#include <linux/init.h>
40 39
@@ -574,10 +573,9 @@ idmap_lookup(struct svc_rqst *rqstp,
574 struct idmap_defer_req *mdr; 573 struct idmap_defer_req *mdr;
575 int ret; 574 int ret;
576 575
577 mdr = kmalloc(sizeof(*mdr), GFP_KERNEL); 576 mdr = kzalloc(sizeof(*mdr), GFP_KERNEL);
578 if (!mdr) 577 if (!mdr)
579 return -ENOMEM; 578 return -ENOMEM;
580 memset(mdr, 0, sizeof(*mdr));
581 atomic_set(&mdr->count, 1); 579 atomic_set(&mdr->count, 1);
582 init_waitqueue_head(&mdr->waitq); 580 init_waitqueue_head(&mdr->waitq);
583 mdr->req.defer = idmap_defer; 581 mdr->req.defer = idmap_defer;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index b0e095ea0c03..ee4eff27aedc 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -721,6 +721,12 @@ nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
721 return nfs_ok; 721 return nfs_ok;
722} 722}
723 723
724static inline void nfsd4_increment_op_stats(u32 opnum)
725{
726 if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
727 nfsdstats.nfs4_opcount[opnum]++;
728}
729
724 730
725/* 731/*
726 * COMPOUND call. 732 * COMPOUND call.
@@ -930,6 +936,8 @@ encode_op:
930 /* XXX Ugh, we need to get rid of this kind of special case: */ 936 /* XXX Ugh, we need to get rid of this kind of special case: */
931 if (op->opnum == OP_READ && op->u.read.rd_filp) 937 if (op->opnum == OP_READ && op->u.read.rd_filp)
932 fput(op->u.read.rd_filp); 938 fput(op->u.read.rd_filp);
939
940 nfsd4_increment_op_stats(op->opnum);
933 } 941 }
934 942
935out: 943out:
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 06da7506363c..e35d7e52fdeb 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -33,7 +33,7 @@
33* 33*
34*/ 34*/
35 35
36 36#include <linux/err.h>
37#include <linux/sunrpc/svc.h> 37#include <linux/sunrpc/svc.h>
38#include <linux/nfsd/nfsd.h> 38#include <linux/nfsd/nfsd.h>
39#include <linux/nfs4.h> 39#include <linux/nfs4.h>
@@ -87,34 +87,35 @@ int
87nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) 87nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
88{ 88{
89 struct xdr_netobj cksum; 89 struct xdr_netobj cksum;
90 struct crypto_tfm *tfm; 90 struct hash_desc desc;
91 struct scatterlist sg[1]; 91 struct scatterlist sg[1];
92 int status = nfserr_resource; 92 int status = nfserr_resource;
93 93
94 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 94 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
95 clname->len, clname->data); 95 clname->len, clname->data);
96 tfm = crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); 96 desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
97 if (tfm == NULL) 97 desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
98 goto out; 98 if (IS_ERR(desc.tfm))
99 cksum.len = crypto_tfm_alg_digestsize(tfm); 99 goto out_no_tfm;
100 cksum.len = crypto_hash_digestsize(desc.tfm);
100 cksum.data = kmalloc(cksum.len, GFP_KERNEL); 101 cksum.data = kmalloc(cksum.len, GFP_KERNEL);
101 if (cksum.data == NULL) 102 if (cksum.data == NULL)
102 goto out; 103 goto out;
103 crypto_digest_init(tfm);
104 104
105 sg[0].page = virt_to_page(clname->data); 105 sg[0].page = virt_to_page(clname->data);
106 sg[0].offset = offset_in_page(clname->data); 106 sg[0].offset = offset_in_page(clname->data);
107 sg[0].length = clname->len; 107 sg[0].length = clname->len;
108 108
109 crypto_digest_update(tfm, sg, 1); 109 if (crypto_hash_digest(&desc, sg, sg->length, cksum.data))
110 crypto_digest_final(tfm, cksum.data); 110 goto out;
111 111
112 md5_to_hex(dname, cksum.data); 112 md5_to_hex(dname, cksum.data);
113 113
114 kfree(cksum.data); 114 kfree(cksum.data);
115 status = nfs_ok; 115 status = nfs_ok;
116out: 116out:
117 crypto_free_tfm(tfm); 117 crypto_free_hash(desc.tfm);
118out_no_tfm:
118 return status; 119 return status;
119} 120}
120 121
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 96c7578cbe1e..ebcf226a9e4a 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -123,7 +123,7 @@ static void release_stateid(struct nfs4_stateid *stp, int flags);
123 */ 123 */
124 124
125/* recall_lock protects the del_recall_lru */ 125/* recall_lock protects the del_recall_lru */
126static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED; 126static DEFINE_SPINLOCK(recall_lock);
127static struct list_head del_recall_lru; 127static struct list_head del_recall_lru;
128 128
129static void 129static void
@@ -339,8 +339,7 @@ alloc_client(struct xdr_netobj name)
339{ 339{
340 struct nfs4_client *clp; 340 struct nfs4_client *clp;
341 341
342 if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) { 342 if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
343 memset(clp, 0, sizeof(*clp));
344 if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) { 343 if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
345 memcpy(clp->cl_name.data, name.data, name.len); 344 memcpy(clp->cl_name.data, name.data, name.len);
346 clp->cl_name.len = name.len; 345 clp->cl_name.len = name.len;
@@ -529,8 +528,7 @@ move_to_confirmed(struct nfs4_client *clp)
529 528
530 dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp); 529 dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
531 list_del_init(&clp->cl_strhash); 530 list_del_init(&clp->cl_strhash);
532 list_del_init(&clp->cl_idhash); 531 list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
533 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
534 strhashval = clientstr_hashval(clp->cl_recdir); 532 strhashval = clientstr_hashval(clp->cl_recdir);
535 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); 533 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
536 renew_client(clp); 534 renew_client(clp);
@@ -1007,13 +1005,10 @@ alloc_init_file(struct inode *ino)
1007static void 1005static void
1008nfsd4_free_slab(kmem_cache_t **slab) 1006nfsd4_free_slab(kmem_cache_t **slab)
1009{ 1007{
1010 int status;
1011
1012 if (*slab == NULL) 1008 if (*slab == NULL)
1013 return; 1009 return;
1014 status = kmem_cache_destroy(*slab); 1010 kmem_cache_destroy(*slab);
1015 *slab = NULL; 1011 *slab = NULL;
1016 WARN_ON(status);
1017} 1012}
1018 1013
1019static void 1014static void
@@ -1238,8 +1233,15 @@ find_file(struct inode *ino)
1238 return NULL; 1233 return NULL;
1239} 1234}
1240 1235
1241#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0) 1236static int access_valid(u32 x)
1242#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0) 1237{
1238 return (x > 0 && x < 4);
1239}
1240
1241static int deny_valid(u32 x)
1242{
1243 return (x >= 0 && x < 5);
1244}
1243 1245
1244static void 1246static void
1245set_access(unsigned int *access, unsigned long bmap) { 1247set_access(unsigned int *access, unsigned long bmap) {
@@ -1746,7 +1748,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1746 int status; 1748 int status;
1747 1749
1748 status = nfserr_inval; 1750 status = nfserr_inval;
1749 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) 1751 if (!access_valid(open->op_share_access)
1752 || !deny_valid(open->op_share_deny))
1750 goto out; 1753 goto out;
1751 /* 1754 /*
1752 * Lookup file; if found, lookup stateid and check open request, 1755 * Lookup file; if found, lookup stateid and check open request,
@@ -1783,10 +1786,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1783 } else { 1786 } else {
1784 /* Stateid was not found, this is a new OPEN */ 1787 /* Stateid was not found, this is a new OPEN */
1785 int flags = 0; 1788 int flags = 0;
1789 if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
1790 flags |= MAY_READ;
1786 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 1791 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1787 flags = MAY_WRITE; 1792 flags |= MAY_WRITE;
1788 else
1789 flags = MAY_READ;
1790 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); 1793 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
1791 if (status) 1794 if (status)
1792 goto out; 1795 goto out;
@@ -2071,16 +2074,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
2071 if (!stateid->si_fileid) { /* delegation stateid */ 2074 if (!stateid->si_fileid) { /* delegation stateid */
2072 if(!(dp = find_delegation_stateid(ino, stateid))) { 2075 if(!(dp = find_delegation_stateid(ino, stateid))) {
2073 dprintk("NFSD: delegation stateid not found\n"); 2076 dprintk("NFSD: delegation stateid not found\n");
2074 if (nfs4_in_grace())
2075 status = nfserr_grace;
2076 goto out; 2077 goto out;
2077 } 2078 }
2078 stidp = &dp->dl_stateid; 2079 stidp = &dp->dl_stateid;
2079 } else { /* open or lock stateid */ 2080 } else { /* open or lock stateid */
2080 if (!(stp = find_stateid(stateid, flags))) { 2081 if (!(stp = find_stateid(stateid, flags))) {
2081 dprintk("NFSD: open or lock stateid not found\n"); 2082 dprintk("NFSD: open or lock stateid not found\n");
2082 if (nfs4_in_grace())
2083 status = nfserr_grace;
2084 goto out; 2083 goto out;
2085 } 2084 }
2086 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) 2085 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
@@ -2253,8 +2252,9 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
2253 (int)current_fh->fh_dentry->d_name.len, 2252 (int)current_fh->fh_dentry->d_name.len,
2254 current_fh->fh_dentry->d_name.name); 2253 current_fh->fh_dentry->d_name.name);
2255 2254
2256 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) 2255 status = fh_verify(rqstp, current_fh, S_IFREG, 0);
2257 goto out; 2256 if (status)
2257 return status;
2258 2258
2259 nfs4_lock_state(); 2259 nfs4_lock_state();
2260 2260
@@ -2321,7 +2321,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
2321 (int)current_fh->fh_dentry->d_name.len, 2321 (int)current_fh->fh_dentry->d_name.len,
2322 current_fh->fh_dentry->d_name.name); 2322 current_fh->fh_dentry->d_name.name);
2323 2323
2324 if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny)) 2324 if (!access_valid(od->od_share_access)
2325 || !deny_valid(od->od_share_deny))
2325 return nfserr_inval; 2326 return nfserr_inval;
2326 2327
2327 nfs4_lock_state(); 2328 nfs4_lock_state();
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index d852ebb538e3..fdf7cf3dfadc 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -103,8 +103,7 @@ nfsd_cache_shutdown(void)
103static void 103static void
104lru_put_end(struct svc_cacherep *rp) 104lru_put_end(struct svc_cacherep *rp)
105{ 105{
106 list_del(&rp->c_lru); 106 list_move_tail(&rp->c_lru, &lru_head);
107 list_add_tail(&rp->c_lru, &lru_head);
108} 107}
109 108
110/* 109/*
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index a1810e6a93e5..7046ac9cf97f 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -6,7 +6,6 @@
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8 8
9#include <linux/config.h>
10#include <linux/module.h> 9#include <linux/module.h>
11 10
12#include <linux/linkage.h> 11#include <linux/linkage.h>
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 3f2ec2e6d06c..501d83884530 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -188,11 +188,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
188 } 188 }
189 189
190 /* Set user creds for this exportpoint */ 190 /* Set user creds for this exportpoint */
191 error = nfsd_setuser(rqstp, exp); 191 error = nfserrno(nfsd_setuser(rqstp, exp));
192 if (error) { 192 if (error)
193 error = nfserrno(error);
194 goto out; 193 goto out;
195 }
196 194
197 /* 195 /*
198 * Look up the dentry using the NFS file handle. 196 * Look up the dentry using the NFS file handle.
@@ -248,9 +246,18 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
248 dprintk("nfsd: fh_verify - just checking\n"); 246 dprintk("nfsd: fh_verify - just checking\n");
249 dentry = fhp->fh_dentry; 247 dentry = fhp->fh_dentry;
250 exp = fhp->fh_export; 248 exp = fhp->fh_export;
249 /* Set user creds for this exportpoint; necessary even
250 * in the "just checking" case because this may be a
251 * filehandle that was created by fh_compose, and that
252 * is about to be used in another nfsv4 compound
253 * operation */
254 error = nfserrno(nfsd_setuser(rqstp, exp));
255 if (error)
256 goto out;
251 } 257 }
252 cache_get(&exp->h); 258 cache_get(&exp->h);
253 259
260
254 error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type); 261 error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
255 if (error) 262 if (error)
256 goto out; 263 goto out;
@@ -312,8 +319,8 @@ int
312fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) 319fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
313{ 320{
314 /* ref_fh is a reference file handle. 321 /* ref_fh is a reference file handle.
315 * if it is non-null, then we should compose a filehandle which is 322 * if it is non-null and for the same filesystem, then we should compose
316 * of the same version, where possible. 323 * a filehandle which is of the same version, where possible.
317 * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca 324 * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
318 * Then create a 32byte filehandle using nfs_fhbase_old 325 * Then create a 32byte filehandle using nfs_fhbase_old
319 * 326 *
@@ -332,7 +339,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
332 parent->d_name.name, dentry->d_name.name, 339 parent->d_name.name, dentry->d_name.name,
333 (inode ? inode->i_ino : 0)); 340 (inode ? inode->i_ino : 0));
334 341
335 if (ref_fh) { 342 if (ref_fh && ref_fh->fh_export == exp) {
336 ref_fh_version = ref_fh->fh_handle.fh_version; 343 ref_fh_version = ref_fh->fh_handle.fh_version;
337 if (ref_fh_version == 0xca) 344 if (ref_fh_version == 0xca)
338 ref_fh_fsid_type = 0; 345 ref_fh_fsid_type = 0;
@@ -461,7 +468,7 @@ fh_update(struct svc_fh *fhp)
461 } else { 468 } else {
462 int size; 469 int size;
463 if (fhp->fh_handle.fh_fileid_type != 0) 470 if (fhp->fh_handle.fh_fileid_type != 0)
464 goto out_uptodate; 471 goto out;
465 datap = fhp->fh_handle.fh_auth+ 472 datap = fhp->fh_handle.fh_auth+
466 fhp->fh_handle.fh_size/4 -1; 473 fhp->fh_handle.fh_size/4 -1;
467 size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; 474 size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
@@ -481,10 +488,6 @@ out_negative:
481 printk(KERN_ERR "fh_update: %s/%s still negative!\n", 488 printk(KERN_ERR "fh_update: %s/%s still negative!\n",
482 dentry->d_parent->d_name.name, dentry->d_name.name); 489 dentry->d_parent->d_name.name, dentry->d_name.name);
483 goto out; 490 goto out;
484out_uptodate:
485 printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
486 dentry->d_parent->d_name.name, dentry->d_name.name);
487 goto out;
488} 491}
489 492
490/* 493/*
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 3790727e5dfd..ec1decf29bab 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -8,7 +8,6 @@
8 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 8 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
9 */ 9 */
10 10
11#include <linux/config.h>
12#include <linux/module.h> 11#include <linux/module.h>
13 12
14#include <linux/time.h> 13#include <linux/time.h>
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 57265d563804..71944cddf680 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -72,6 +72,16 @@ static int nfsd_proc_show(struct seq_file *seq, void *v)
72 /* show my rpc info */ 72 /* show my rpc info */
73 svc_seq_show(seq, &nfsd_svcstats); 73 svc_seq_show(seq, &nfsd_svcstats);
74 74
75#ifdef CONFIG_NFSD_V4
76 /* Show count for individual nfsv4 operations */
77 /* Writing operation numbers 0 1 2 also for maintaining uniformity */
78 seq_printf(seq,"proc4ops %u", LAST_NFS4_OP + 1);
79 for (i = 0; i <= LAST_NFS4_OP; i++)
80 seq_printf(seq, " %u", nfsdstats.nfs4_opcount[i]);
81
82 seq_putc(seq, '\n');
83#endif
84
75 return 0; 85 return 0;
76} 86}
77 87
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 245eaa1fb59b..c9e3b5a8fe07 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -16,7 +16,6 @@
16 * Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp> 16 * Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp>
17 */ 17 */
18 18
19#include <linux/config.h>
20#include <linux/string.h> 19#include <linux/string.h>
21#include <linux/time.h> 20#include <linux/time.h>
22#include <linux/errno.h> 21#include <linux/errno.h>
@@ -673,7 +672,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
673 goto out_nfserr; 672 goto out_nfserr;
674 673
675 if (access & MAY_WRITE) { 674 if (access & MAY_WRITE) {
676 flags = O_WRONLY|O_LARGEFILE; 675 if (access & MAY_READ)
676 flags = O_RDWR|O_LARGEFILE;
677 else
678 flags = O_WRONLY|O_LARGEFILE;
677 679
678 DQUOT_INIT(inode); 680 DQUOT_INIT(inode);
679 } 681 }
@@ -834,7 +836,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
834 if (ra && ra->p_set) 836 if (ra && ra->p_set)
835 file->f_ra = ra->p_ra; 837 file->f_ra = ra->p_ra;
836 838
837 if (file->f_op->sendfile) { 839 if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
838 svc_pushback_unused_pages(rqstp); 840 svc_pushback_unused_pages(rqstp);
839 err = file->f_op->sendfile(file, &offset, *count, 841 err = file->f_op->sendfile(file, &offset, *count,
840 nfsd_read_actor, rqstp); 842 nfsd_read_actor, rqstp);
@@ -1517,14 +1519,15 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1517 err = nfserrno(err); 1519 err = nfserrno(err);
1518 } 1520 }
1519 1521
1520 fh_unlock(ffhp);
1521 dput(dnew); 1522 dput(dnew);
1523out_unlock:
1524 fh_unlock(ffhp);
1522out: 1525out:
1523 return err; 1526 return err;
1524 1527
1525out_nfserr: 1528out_nfserr:
1526 err = nfserrno(err); 1529 err = nfserrno(err);
1527 goto out; 1530 goto out_unlock;
1528} 1531}
1529 1532
1530/* 1533/*
@@ -1553,7 +1556,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1553 tdir = tdentry->d_inode; 1556 tdir = tdentry->d_inode;
1554 1557
1555 err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev; 1558 err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
1556 if (fdir->i_sb != tdir->i_sb) 1559 if (ffhp->fh_export != tfhp->fh_export)
1557 goto out; 1560 goto out;
1558 1561
1559 err = nfserr_perm; 1562 err = nfserr_perm;