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.c170
1 files changed, 91 insertions, 79 deletions
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);