aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c160
1 files changed, 84 insertions, 76 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 7b566ec14e1..fbde6f79922 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)
@@ -316,64 +316,6 @@ static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE];
316static struct list_head client_lru; 316static struct list_head client_lru;
317static struct list_head close_lru; 317static struct list_head close_lru;
318 318
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/* 319/*
378 * We store the NONE, READ, WRITE, and BOTH bits separately in the 320 * 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 321 * st_{access,deny}_bmap field of the stateid, in order to track not
@@ -446,13 +388,71 @@ static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
446 return nfs4_access_to_omode(access); 388 return nfs4_access_to_omode(access);
447} 389}
448 390
449static void release_open_stateid(struct nfs4_stateid *stp) 391static void unhash_generic_stateid(struct nfs4_stateid *stp)
392{
393 list_del(&stp->st_hash);
394 list_del(&stp->st_perfile);
395 list_del(&stp->st_perstateowner);
396}
397
398static void free_generic_stateid(struct nfs4_stateid *stp)
450{ 399{
451 int oflag = nfs4_access_bmap_to_omode(stp); 400 int oflag = nfs4_access_bmap_to_omode(stp);
452 401
402 nfs4_file_put_access(stp->st_file, oflag);
403 put_nfs4_file(stp->st_file);
404 kmem_cache_free(stateid_slab, stp);
405}
406
407static void release_lock_stateid(struct nfs4_stateid *stp)
408{
409 struct file *file;
410
411 unhash_generic_stateid(stp);
412 file = find_any_file(stp->st_file);
413 if (file)
414 locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
415 free_generic_stateid(stp);
416}
417
418static void unhash_lockowner(struct nfs4_stateowner *sop)
419{
420 struct nfs4_stateid *stp;
421
422 list_del(&sop->so_idhash);
423 list_del(&sop->so_strhash);
424 list_del(&sop->so_perstateid);
425 while (!list_empty(&sop->so_stateids)) {
426 stp = list_first_entry(&sop->so_stateids,
427 struct nfs4_stateid, st_perstateowner);
428 release_lock_stateid(stp);
429 }
430}
431
432static void release_lockowner(struct nfs4_stateowner *sop)
433{
434 unhash_lockowner(sop);
435 nfs4_put_stateowner(sop);
436}
437
438static void
439release_stateid_lockowners(struct nfs4_stateid *open_stp)
440{
441 struct nfs4_stateowner *lock_sop;
442
443 while (!list_empty(&open_stp->st_lockowners)) {
444 lock_sop = list_entry(open_stp->st_lockowners.next,
445 struct nfs4_stateowner, so_perstateid);
446 /* list_del(&open_stp->st_lockowners); */
447 BUG_ON(lock_sop->so_is_open_owner);
448 release_lockowner(lock_sop);
449 }
450}
451
452static void release_open_stateid(struct nfs4_stateid *stp)
453{
453 unhash_generic_stateid(stp); 454 unhash_generic_stateid(stp);
454 release_stateid_lockowners(stp); 455 release_stateid_lockowners(stp);
455 nfs4_file_put_access(stp->st_file, oflag);
456 free_generic_stateid(stp); 456 free_generic_stateid(stp);
457} 457}
458 458
@@ -608,7 +608,8 @@ static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4
608 u32 maxrpc = nfsd_serv->sv_max_mesg; 608 u32 maxrpc = nfsd_serv->sv_max_mesg;
609 609
610 new->maxreqs = numslots; 610 new->maxreqs = numslots;
611 new->maxresp_cached = slotsize + NFSD_MIN_HDR_SEQ_SZ; 611 new->maxresp_cached = min_t(u32, req->maxresp_cached,
612 slotsize + NFSD_MIN_HDR_SEQ_SZ);
612 new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc); 613 new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc);
613 new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc); 614 new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc);
614 new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND); 615 new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
@@ -3735,6 +3736,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
3735 stp->st_stateid.si_stateownerid = sop->so_id; 3736 stp->st_stateid.si_stateownerid = sop->so_id;
3736 stp->st_stateid.si_fileid = fp->fi_id; 3737 stp->st_stateid.si_fileid = fp->fi_id;
3737 stp->st_stateid.si_generation = 0; 3738 stp->st_stateid.si_generation = 0;
3739 stp->st_access_bmap = 0;
3738 stp->st_deny_bmap = open_stp->st_deny_bmap; 3740 stp->st_deny_bmap = open_stp->st_deny_bmap;
3739 stp->st_openstp = open_stp; 3741 stp->st_openstp = open_stp;
3740 3742
@@ -3749,6 +3751,17 @@ check_lock_length(u64 offset, u64 length)
3749 LOFF_OVERFLOW(offset, length))); 3751 LOFF_OVERFLOW(offset, length)));
3750} 3752}
3751 3753
3754static void get_lock_access(struct nfs4_stateid *lock_stp, u32 access)
3755{
3756 struct nfs4_file *fp = lock_stp->st_file;
3757 int oflag = nfs4_access_to_omode(access);
3758
3759 if (test_bit(access, &lock_stp->st_access_bmap))
3760 return;
3761 nfs4_file_get_access(fp, oflag);
3762 __set_bit(access, &lock_stp->st_access_bmap);
3763}
3764
3752/* 3765/*
3753 * LOCK operation 3766 * LOCK operation
3754 */ 3767 */
@@ -3765,7 +3778,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3765 struct file_lock conflock; 3778 struct file_lock conflock;
3766 __be32 status = 0; 3779 __be32 status = 0;
3767 unsigned int strhashval; 3780 unsigned int strhashval;
3768 unsigned int cmd;
3769 int err; 3781 int err;
3770 3782
3771 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", 3783 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
@@ -3847,22 +3859,18 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3847 switch (lock->lk_type) { 3859 switch (lock->lk_type) {
3848 case NFS4_READ_LT: 3860 case NFS4_READ_LT:
3849 case NFS4_READW_LT: 3861 case NFS4_READW_LT:
3850 if (find_readable_file(lock_stp->st_file)) { 3862 filp = find_readable_file(lock_stp->st_file);
3851 nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ); 3863 if (filp)
3852 filp = find_readable_file(lock_stp->st_file); 3864 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
3853 }
3854 file_lock.fl_type = F_RDLCK; 3865 file_lock.fl_type = F_RDLCK;
3855 cmd = F_SETLK; 3866 break;
3856 break;
3857 case NFS4_WRITE_LT: 3867 case NFS4_WRITE_LT:
3858 case NFS4_WRITEW_LT: 3868 case NFS4_WRITEW_LT:
3859 if (find_writeable_file(lock_stp->st_file)) { 3869 filp = find_writeable_file(lock_stp->st_file);
3860 nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE); 3870 if (filp)
3861 filp = find_writeable_file(lock_stp->st_file); 3871 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
3862 }
3863 file_lock.fl_type = F_WRLCK; 3872 file_lock.fl_type = F_WRLCK;
3864 cmd = F_SETLK; 3873 break;
3865 break;
3866 default: 3874 default:
3867 status = nfserr_inval; 3875 status = nfserr_inval;
3868 goto out; 3876 goto out;
@@ -3886,7 +3894,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. 3894 * Note: locks.c uses the BKL to protect the inode's lock list.
3887 */ 3895 */
3888 3896
3889 err = vfs_lock_file(filp, cmd, &file_lock, &conflock); 3897 err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock);
3890 switch (-err) { 3898 switch (-err) {
3891 case 0: /* success! */ 3899 case 0: /* success! */
3892 update_stateid(&lock_stp->st_stateid); 3900 update_stateid(&lock_stp->st_stateid);