aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c1
-rw-r--r--fs/nfsd/lockd.c1
-rw-r--r--fs/nfsd/nfs3xdr.c2
-rw-r--r--fs/nfsd/nfs4idmap.c1
-rw-r--r--fs/nfsd/nfs4proc.c4
-rw-r--r--fs/nfsd/nfs4state.c170
-rw-r--r--fs/nfsd/nfs4xdr.c5
-rw-r--r--fs/nfsd/nfsctl.c35
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/nfsd/state.h12
-rw-r--r--fs/nfsd/vfs.c11
11 files changed, 142 insertions, 102 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 8b31e5f8795d..ad000aeb21a2 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -299,7 +299,6 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
299 299
300#define EXPORT_HASHBITS 8 300#define EXPORT_HASHBITS 8
301#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) 301#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
302#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
303 302
304static struct cache_head *export_table[EXPORT_HASHMAX]; 303static struct cache_head *export_table[EXPORT_HASHMAX];
305 304
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 0c6d81670137..7c831a2731fa 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -38,7 +38,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
38 exp_readlock(); 38 exp_readlock();
39 nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp); 39 nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
40 fh_put(&fh); 40 fh_put(&fh);
41 rqstp->rq_client = NULL;
42 exp_readunlock(); 41 exp_readunlock();
43 /* We return nlm error codes as nlm doesn't know 42 /* We return nlm error codes as nlm doesn't know
44 * about nfsd, but nfsd does know about nlm.. 43 * about nfsd, but nfsd does know about nlm..
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 7e84a852cdae..ad48faca20fc 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -702,7 +702,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
702 *p++ = htonl(resp->eof); 702 *p++ = htonl(resp->eof);
703 *p++ = htonl(resp->count); /* xdr opaque count */ 703 *p++ = htonl(resp->count); /* xdr opaque count */
704 xdr_ressize_check(rqstp, p); 704 xdr_ressize_check(rqstp, p);
705 /* now update rqstp->rq_res to reflect data aswell */ 705 /* now update rqstp->rq_res to reflect data as well */
706 rqstp->rq_res.page_len = resp->count; 706 rqstp->rq_res.page_len = resp->count;
707 if (resp->count & 3) { 707 if (resp->count & 3) {
708 /* need to pad the tail */ 708 /* need to pad the tail */
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 6d2c397d458b..55780a22fdbd 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -63,7 +63,6 @@ struct ent {
63 63
64#define ENT_HASHBITS 8 64#define ENT_HASHBITS 8
65#define ENT_HASHMAX (1 << ENT_HASHBITS) 65#define ENT_HASHMAX (1 << ENT_HASHBITS)
66#define ENT_HASHMASK (ENT_HASHMAX - 1)
67 66
68static void 67static void
69ent_init(struct cache_head *cnew, struct cache_head *citm) 68ent_init(struct cache_head *cnew, struct cache_head *citm)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index db52546143d1..5fcb1396a7e3 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -984,8 +984,8 @@ typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
984 void *); 984 void *);
985enum nfsd4_op_flags { 985enum nfsd4_op_flags {
986 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ 986 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
987 ALLOWED_ON_ABSENT_FS = 2 << 0, /* ops processed on absent fs */ 987 ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */
988 ALLOWED_AS_FIRST_OP = 3 << 0, /* ops reqired first in compound */ 988 ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */
989}; 989};
990 990
991struct nfsd4_operation { 991struct nfsd4_operation {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 7b566ec14e18..4cf04e11c66c 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -148,7 +148,7 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
148/* hash table for nfs4_file */ 148/* hash table for nfs4_file */
149#define FILE_HASH_BITS 8 149#define FILE_HASH_BITS 8
150#define FILE_HASH_SIZE (1 << FILE_HASH_BITS) 150#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
151#define FILE_HASH_MASK (FILE_HASH_SIZE - 1) 151
152/* hash table for (open)nfs4_stateid */ 152/* hash table for (open)nfs4_stateid */
153#define STATEID_HASH_BITS 10 153#define STATEID_HASH_BITS 10
154#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS) 154#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
@@ -258,6 +258,7 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp)
258 if (atomic_dec_and_test(&fp->fi_delegees)) { 258 if (atomic_dec_and_test(&fp->fi_delegees)) {
259 vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); 259 vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
260 fp->fi_lease = NULL; 260 fp->fi_lease = NULL;
261 fput(fp->fi_deleg_file);
261 fp->fi_deleg_file = NULL; 262 fp->fi_deleg_file = NULL;
262 } 263 }
263} 264}
@@ -316,64 +317,6 @@ static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE];
316static struct list_head client_lru; 317static struct list_head client_lru;
317static struct list_head close_lru; 318static struct list_head close_lru;
318 319
319static void unhash_generic_stateid(struct nfs4_stateid *stp)
320{
321 list_del(&stp->st_hash);
322 list_del(&stp->st_perfile);
323 list_del(&stp->st_perstateowner);
324}
325
326static void free_generic_stateid(struct nfs4_stateid *stp)
327{
328 put_nfs4_file(stp->st_file);
329 kmem_cache_free(stateid_slab, stp);
330}
331
332static void release_lock_stateid(struct nfs4_stateid *stp)
333{
334 struct file *file;
335
336 unhash_generic_stateid(stp);
337 file = find_any_file(stp->st_file);
338 if (file)
339 locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
340 free_generic_stateid(stp);
341}
342
343static void unhash_lockowner(struct nfs4_stateowner *sop)
344{
345 struct nfs4_stateid *stp;
346
347 list_del(&sop->so_idhash);
348 list_del(&sop->so_strhash);
349 list_del(&sop->so_perstateid);
350 while (!list_empty(&sop->so_stateids)) {
351 stp = list_first_entry(&sop->so_stateids,
352 struct nfs4_stateid, st_perstateowner);
353 release_lock_stateid(stp);
354 }
355}
356
357static void release_lockowner(struct nfs4_stateowner *sop)
358{
359 unhash_lockowner(sop);
360 nfs4_put_stateowner(sop);
361}
362
363static void
364release_stateid_lockowners(struct nfs4_stateid *open_stp)
365{
366 struct nfs4_stateowner *lock_sop;
367
368 while (!list_empty(&open_stp->st_lockowners)) {
369 lock_sop = list_entry(open_stp->st_lockowners.next,
370 struct nfs4_stateowner, so_perstateid);
371 /* list_del(&open_stp->st_lockowners); */
372 BUG_ON(lock_sop->so_is_open_owner);
373 release_lockowner(lock_sop);
374 }
375}
376
377/* 320/*
378 * We store the NONE, READ, WRITE, and BOTH bits separately in the 321 * We store the NONE, READ, WRITE, and BOTH bits separately in the
379 * st_{access,deny}_bmap field of the stateid, in order to track not 322 * st_{access,deny}_bmap field of the stateid, in order to track not
@@ -446,13 +389,74 @@ static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
446 return nfs4_access_to_omode(access); 389 return nfs4_access_to_omode(access);
447} 390}
448 391
449static void release_open_stateid(struct nfs4_stateid *stp) 392static void unhash_generic_stateid(struct nfs4_stateid *stp)
450{ 393{
451 int oflag = nfs4_access_bmap_to_omode(stp); 394 list_del(&stp->st_hash);
395 list_del(&stp->st_perfile);
396 list_del(&stp->st_perstateowner);
397}
452 398
399static void free_generic_stateid(struct nfs4_stateid *stp)
400{
401 int oflag;
402
403 if (stp->st_access_bmap) {
404 oflag = nfs4_access_bmap_to_omode(stp);
405 nfs4_file_put_access(stp->st_file, oflag);
406 }
407 put_nfs4_file(stp->st_file);
408 kmem_cache_free(stateid_slab, stp);
409}
410
411static void release_lock_stateid(struct nfs4_stateid *stp)
412{
413 struct file *file;
414
415 unhash_generic_stateid(stp);
416 file = find_any_file(stp->st_file);
417 if (file)
418 locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
419 free_generic_stateid(stp);
420}
421
422static void unhash_lockowner(struct nfs4_stateowner *sop)
423{
424 struct nfs4_stateid *stp;
425
426 list_del(&sop->so_idhash);
427 list_del(&sop->so_strhash);
428 list_del(&sop->so_perstateid);
429 while (!list_empty(&sop->so_stateids)) {
430 stp = list_first_entry(&sop->so_stateids,
431 struct nfs4_stateid, st_perstateowner);
432 release_lock_stateid(stp);
433 }
434}
435
436static void release_lockowner(struct nfs4_stateowner *sop)
437{
438 unhash_lockowner(sop);
439 nfs4_put_stateowner(sop);
440}
441
442static void
443release_stateid_lockowners(struct nfs4_stateid *open_stp)
444{
445 struct nfs4_stateowner *lock_sop;
446
447 while (!list_empty(&open_stp->st_lockowners)) {
448 lock_sop = list_entry(open_stp->st_lockowners.next,
449 struct nfs4_stateowner, so_perstateid);
450 /* list_del(&open_stp->st_lockowners); */
451 BUG_ON(lock_sop->so_is_open_owner);
452 release_lockowner(lock_sop);
453 }
454}
455
456static void release_open_stateid(struct nfs4_stateid *stp)
457{
453 unhash_generic_stateid(stp); 458 unhash_generic_stateid(stp);
454 release_stateid_lockowners(stp); 459 release_stateid_lockowners(stp);
455 nfs4_file_put_access(stp->st_file, oflag);
456 free_generic_stateid(stp); 460 free_generic_stateid(stp);
457} 461}
458 462
@@ -608,7 +612,8 @@ static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4
608 u32 maxrpc = nfsd_serv->sv_max_mesg; 612 u32 maxrpc = nfsd_serv->sv_max_mesg;
609 613
610 new->maxreqs = numslots; 614 new->maxreqs = numslots;
611 new->maxresp_cached = slotsize + NFSD_MIN_HDR_SEQ_SZ; 615 new->maxresp_cached = min_t(u32, req->maxresp_cached,
616 slotsize + NFSD_MIN_HDR_SEQ_SZ);
612 new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc); 617 new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc);
613 new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc); 618 new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc);
614 new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND); 619 new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
@@ -3054,7 +3059,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
3054 if (ONE_STATEID(stateid) && (flags & RD_STATE)) 3059 if (ONE_STATEID(stateid) && (flags & RD_STATE))
3055 return nfs_ok; 3060 return nfs_ok;
3056 else if (locks_in_grace()) { 3061 else if (locks_in_grace()) {
3057 /* Answer in remaining cases depends on existance of 3062 /* Answer in remaining cases depends on existence of
3058 * conflicting state; so we must wait out the grace period. */ 3063 * conflicting state; so we must wait out the grace period. */
3059 return nfserr_grace; 3064 return nfserr_grace;
3060 } else if (flags & WR_STATE) 3065 } else if (flags & WR_STATE)
@@ -3674,7 +3679,7 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
3674/* 3679/*
3675 * Alloc a lock owner structure. 3680 * Alloc a lock owner structure.
3676 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has 3681 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has
3677 * occured. 3682 * occurred.
3678 * 3683 *
3679 * strhashval = lock_ownerstr_hashval 3684 * strhashval = lock_ownerstr_hashval
3680 */ 3685 */
@@ -3735,6 +3740,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
3735 stp->st_stateid.si_stateownerid = sop->so_id; 3740 stp->st_stateid.si_stateownerid = sop->so_id;
3736 stp->st_stateid.si_fileid = fp->fi_id; 3741 stp->st_stateid.si_fileid = fp->fi_id;
3737 stp->st_stateid.si_generation = 0; 3742 stp->st_stateid.si_generation = 0;
3743 stp->st_access_bmap = 0;
3738 stp->st_deny_bmap = open_stp->st_deny_bmap; 3744 stp->st_deny_bmap = open_stp->st_deny_bmap;
3739 stp->st_openstp = open_stp; 3745 stp->st_openstp = open_stp;
3740 3746
@@ -3749,6 +3755,17 @@ check_lock_length(u64 offset, u64 length)
3749 LOFF_OVERFLOW(offset, length))); 3755 LOFF_OVERFLOW(offset, length)));
3750} 3756}
3751 3757
3758static void get_lock_access(struct nfs4_stateid *lock_stp, u32 access)
3759{
3760 struct nfs4_file *fp = lock_stp->st_file;
3761 int oflag = nfs4_access_to_omode(access);
3762
3763 if (test_bit(access, &lock_stp->st_access_bmap))
3764 return;
3765 nfs4_file_get_access(fp, oflag);
3766 __set_bit(access, &lock_stp->st_access_bmap);
3767}
3768
3752/* 3769/*
3753 * LOCK operation 3770 * LOCK operation
3754 */ 3771 */
@@ -3765,7 +3782,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3765 struct file_lock conflock; 3782 struct file_lock conflock;
3766 __be32 status = 0; 3783 __be32 status = 0;
3767 unsigned int strhashval; 3784 unsigned int strhashval;
3768 unsigned int cmd;
3769 int err; 3785 int err;
3770 3786
3771 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", 3787 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
@@ -3847,22 +3863,18 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3847 switch (lock->lk_type) { 3863 switch (lock->lk_type) {
3848 case NFS4_READ_LT: 3864 case NFS4_READ_LT:
3849 case NFS4_READW_LT: 3865 case NFS4_READW_LT:
3850 if (find_readable_file(lock_stp->st_file)) { 3866 filp = find_readable_file(lock_stp->st_file);
3851 nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ); 3867 if (filp)
3852 filp = find_readable_file(lock_stp->st_file); 3868 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
3853 }
3854 file_lock.fl_type = F_RDLCK; 3869 file_lock.fl_type = F_RDLCK;
3855 cmd = F_SETLK; 3870 break;
3856 break;
3857 case NFS4_WRITE_LT: 3871 case NFS4_WRITE_LT:
3858 case NFS4_WRITEW_LT: 3872 case NFS4_WRITEW_LT:
3859 if (find_writeable_file(lock_stp->st_file)) { 3873 filp = find_writeable_file(lock_stp->st_file);
3860 nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE); 3874 if (filp)
3861 filp = find_writeable_file(lock_stp->st_file); 3875 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
3862 }
3863 file_lock.fl_type = F_WRLCK; 3876 file_lock.fl_type = F_WRLCK;
3864 cmd = F_SETLK; 3877 break;
3865 break;
3866 default: 3878 default:
3867 status = nfserr_inval; 3879 status = nfserr_inval;
3868 goto out; 3880 goto out;
@@ -3886,7 +3898,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3886 * Note: locks.c uses the BKL to protect the inode's lock list. 3898 * Note: locks.c uses the BKL to protect the inode's lock list.
3887 */ 3899 */
3888 3900
3889 err = vfs_lock_file(filp, cmd, &file_lock, &conflock); 3901 err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock);
3890 switch (-err) { 3902 switch (-err) {
3891 case 0: /* success! */ 3903 case 0: /* success! */
3892 update_stateid(&lock_stp->st_stateid); 3904 update_stateid(&lock_stp->st_stateid);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 615f0a9f0600..c6766af00d98 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1142,7 +1142,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1142 1142
1143 u32 dummy; 1143 u32 dummy;
1144 char *machine_name; 1144 char *machine_name;
1145 int i, j; 1145 int i;
1146 int nr_secflavs; 1146 int nr_secflavs;
1147 1147
1148 READ_BUF(16); 1148 READ_BUF(16);
@@ -1215,8 +1215,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1215 READ_BUF(4); 1215 READ_BUF(4);
1216 READ32(dummy); 1216 READ32(dummy);
1217 READ_BUF(dummy * 4); 1217 READ_BUF(dummy * 4);
1218 for (j = 0; j < dummy; ++j)
1219 READ32(dummy);
1220 break; 1218 break;
1221 case RPC_AUTH_GSS: 1219 case RPC_AUTH_GSS:
1222 dprintk("RPC_AUTH_GSS callback secflavor " 1220 dprintk("RPC_AUTH_GSS callback secflavor "
@@ -1232,7 +1230,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1232 READ_BUF(4); 1230 READ_BUF(4);
1233 READ32(dummy); 1231 READ32(dummy);
1234 READ_BUF(dummy); 1232 READ_BUF(dummy);
1235 p += XDR_QUADLEN(dummy);
1236 break; 1233 break;
1237 default: 1234 default:
1238 dprintk("Illegal callback secflavor\n"); 1235 dprintk("Illegal callback secflavor\n");
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 33b3e2b06779..1f5eae40f34e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -12,13 +12,14 @@
12#include <linux/nfsd/syscall.h> 12#include <linux/nfsd/syscall.h>
13#include <linux/lockd/lockd.h> 13#include <linux/lockd/lockd.h>
14#include <linux/sunrpc/clnt.h> 14#include <linux/sunrpc/clnt.h>
15#include <linux/sunrpc/gss_api.h>
15 16
16#include "idmap.h" 17#include "idmap.h"
17#include "nfsd.h" 18#include "nfsd.h"
18#include "cache.h" 19#include "cache.h"
19 20
20/* 21/*
21 * We have a single directory with 9 nodes in it. 22 * We have a single directory with several nodes in it.
22 */ 23 */
23enum { 24enum {
24 NFSD_Root = 1, 25 NFSD_Root = 1,
@@ -42,6 +43,7 @@ enum {
42 NFSD_Versions, 43 NFSD_Versions,
43 NFSD_Ports, 44 NFSD_Ports,
44 NFSD_MaxBlkSize, 45 NFSD_MaxBlkSize,
46 NFSD_SupportedEnctypes,
45 /* 47 /*
46 * The below MUST come last. Otherwise we leave a hole in nfsd_files[] 48 * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
47 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops 49 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
@@ -187,6 +189,34 @@ static struct file_operations export_features_operations = {
187 .release = single_release, 189 .release = single_release,
188}; 190};
189 191
192#ifdef CONFIG_SUNRPC_GSS
193static int supported_enctypes_show(struct seq_file *m, void *v)
194{
195 struct gss_api_mech *k5mech;
196
197 k5mech = gss_mech_get_by_name("krb5");
198 if (k5mech == NULL)
199 goto out;
200 if (k5mech->gm_upcall_enctypes != NULL)
201 seq_printf(m, k5mech->gm_upcall_enctypes);
202 gss_mech_put(k5mech);
203out:
204 return 0;
205}
206
207static int supported_enctypes_open(struct inode *inode, struct file *file)
208{
209 return single_open(file, supported_enctypes_show, NULL);
210}
211
212static struct file_operations supported_enctypes_ops = {
213 .open = supported_enctypes_open,
214 .read = seq_read,
215 .llseek = seq_lseek,
216 .release = single_release,
217};
218#endif /* CONFIG_SUNRPC_GSS */
219
190extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); 220extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
191extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); 221extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
192 222
@@ -1397,6 +1427,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1397 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, 1427 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1398 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, 1428 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1399 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, 1429 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1430#ifdef CONFIG_SUNRPC_GSS
1431 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1432#endif /* CONFIG_SUNRPC_GSS */
1400#ifdef CONFIG_NFSD_V4 1433#ifdef CONFIG_NFSD_V4
1401 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1434 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1402 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1435 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 4ce005dbf3e6..65ec595e2226 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -451,7 +451,7 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
451 *p++ = htonl(resp->count); 451 *p++ = htonl(resp->count);
452 xdr_ressize_check(rqstp, p); 452 xdr_ressize_check(rqstp, p);
453 453
454 /* now update rqstp->rq_res to reflect data aswell */ 454 /* now update rqstp->rq_res to reflect data as well */
455 rqstp->rq_res.page_len = resp->count; 455 rqstp->rq_res.page_len = resp->count;
456 if (resp->count & 3) { 456 if (resp->count & 3) {
457 /* need to pad the tail */ 457 /* need to pad the tail */
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 2d31224b07bf..6bd2f3c21f2b 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -367,16 +367,12 @@ struct nfs4_file {
367 struct list_head fi_delegations; 367 struct list_head fi_delegations;
368 /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ 368 /* One each for O_RDONLY, O_WRONLY, O_RDWR: */
369 struct file * fi_fds[3]; 369 struct file * fi_fds[3];
370 /* One each for O_RDONLY, O_WRONLY: */
371 atomic_t fi_access[2];
372 /* 370 /*
373 * Each open stateid contributes 1 to either fi_readers or 371 * Each open or lock stateid contributes 1 to either
374 * fi_writers, or both, depending on the open mode. A 372 * fi_access[O_RDONLY], fi_access[O_WRONLY], or both, depending
375 * delegation also takes an fi_readers reference. Lock 373 * on open or lock mode:
376 * stateid's take none.
377 */ 374 */
378 atomic_t fi_readers; 375 atomic_t fi_access[2];
379 atomic_t fi_writers;
380 struct file *fi_deleg_file; 376 struct file *fi_deleg_file;
381 struct file_lock *fi_lease; 377 struct file_lock *fi_lease;
382 atomic_t fi_delegees; 378 atomic_t fi_delegees;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index ff93025ae2f7..129f3c9f62d5 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1363,7 +1363,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1363 goto out; 1363 goto out;
1364 if (!(iap->ia_valid & ATTR_MODE)) 1364 if (!(iap->ia_valid & ATTR_MODE))
1365 iap->ia_mode = 0; 1365 iap->ia_mode = 0;
1366 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); 1366 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
1367 if (err) 1367 if (err)
1368 goto out; 1368 goto out;
1369 1369
@@ -1385,6 +1385,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1385 if (IS_ERR(dchild)) 1385 if (IS_ERR(dchild))
1386 goto out_nfserr; 1386 goto out_nfserr;
1387 1387
1388 /* If file doesn't exist, check for permissions to create one */
1389 if (!dchild->d_inode) {
1390 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
1391 if (err)
1392 goto out;
1393 }
1394
1388 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); 1395 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1389 if (err) 1396 if (err)
1390 goto out; 1397 goto out;
@@ -1749,8 +1756,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1749 if (host_err) 1756 if (host_err)
1750 goto out_drop_write; 1757 goto out_drop_write;
1751 } 1758 }
1752 if (host_err)
1753 goto out_drop_write;
1754 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1759 host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1755 if (!host_err) { 1760 if (!host_err) {
1756 host_err = commit_metadata(tfhp); 1761 host_err = commit_metadata(tfhp);