Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfsd-4.8-1' of git://linux-nfs.org/~bfields/linux

Pull nfsd fixes from Bruce Fields:
"Fixes for the dentry refcounting leak I introduced in 4.8-rc1, and for
races in the LOCK code which appear to go back to the big nfsd state
lock removal from 3.17"

* tag 'nfsd-4.8-1' of git://linux-nfs.org/~bfields/linux:
nfsd: don't return an unhashed lock stateid after taking mutex
nfsd: Fix race between FREE_STATEID and LOCK
nfsd: fix dentry refcounting on create

+54 -20
+48 -17
fs/nfsd/nfs4state.c
··· 4903 4903 return nfs_ok; 4904 4904 } 4905 4905 4906 + static __be32 4907 + nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s) 4908 + { 4909 + struct nfs4_ol_stateid *stp = openlockstateid(s); 4910 + __be32 ret; 4911 + 4912 + mutex_lock(&stp->st_mutex); 4913 + 4914 + ret = check_stateid_generation(stateid, &s->sc_stateid, 1); 4915 + if (ret) 4916 + goto out; 4917 + 4918 + ret = nfserr_locks_held; 4919 + if (check_for_locks(stp->st_stid.sc_file, 4920 + lockowner(stp->st_stateowner))) 4921 + goto out; 4922 + 4923 + release_lock_stateid(stp); 4924 + ret = nfs_ok; 4925 + 4926 + out: 4927 + mutex_unlock(&stp->st_mutex); 4928 + nfs4_put_stid(s); 4929 + return ret; 4930 + } 4931 + 4906 4932 __be32 4907 4933 nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 4908 4934 struct nfsd4_free_stateid *free_stateid) ··· 4936 4910 stateid_t *stateid = &free_stateid->fr_stateid; 4937 4911 struct nfs4_stid *s; 4938 4912 struct nfs4_delegation *dp; 4939 - struct nfs4_ol_stateid *stp; 4940 4913 struct nfs4_client *cl = cstate->session->se_client; 4941 4914 __be32 ret = nfserr_bad_stateid; 4942 4915 ··· 4954 4929 ret = nfserr_locks_held; 4955 4930 break; 4956 4931 case NFS4_LOCK_STID: 4957 - ret = check_stateid_generation(stateid, &s->sc_stateid, 1); 4958 - if (ret) 4959 - break; 4960 - stp = openlockstateid(s); 4961 - ret = nfserr_locks_held; 4962 - if (check_for_locks(stp->st_stid.sc_file, 4963 - lockowner(stp->st_stateowner))) 4964 - break; 4965 - WARN_ON(!unhash_lock_stateid(stp)); 4932 + atomic_inc(&s->sc_count); 4966 4933 spin_unlock(&cl->cl_lock); 4967 - nfs4_put_stid(s); 4968 - ret = nfs_ok; 4934 + ret = nfsd4_free_lock_stateid(stateid, s); 4969 4935 goto out; 4970 4936 case NFS4_REVOKED_DELEG_STID: 4971 4937 dp = delegstateid(s); ··· 5523 5507 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, 5524 5508 struct nfs4_ol_stateid *ost, 5525 5509 struct nfsd4_lock *lock, 5526 - struct nfs4_ol_stateid **lst, bool *new) 5510 + struct nfs4_ol_stateid **plst, bool *new) 5527 5511 { 5528 5512 __be32 status; 5529 5513 struct nfs4_file *fi = ost->st_stid.sc_file; ··· 5531 5515 struct nfs4_client *cl = oo->oo_owner.so_client; 5532 5516 struct inode *inode = d_inode(cstate->current_fh.fh_dentry); 5533 5517 struct nfs4_lockowner *lo; 5518 + struct nfs4_ol_stateid *lst; 5534 5519 unsigned int strhashval; 5520 + bool hashed; 5535 5521 5536 5522 lo = find_lockowner_str(cl, &lock->lk_new_owner); 5537 5523 if (!lo) { ··· 5549 5531 goto out; 5550 5532 } 5551 5533 5552 - *lst = find_or_create_lock_stateid(lo, fi, inode, ost, new); 5553 - if (*lst == NULL) { 5534 + retry: 5535 + lst = find_or_create_lock_stateid(lo, fi, inode, ost, new); 5536 + if (lst == NULL) { 5554 5537 status = nfserr_jukebox; 5555 5538 goto out; 5556 5539 } 5540 + 5541 + mutex_lock(&lst->st_mutex); 5542 + 5543 + /* See if it's still hashed to avoid race with FREE_STATEID */ 5544 + spin_lock(&cl->cl_lock); 5545 + hashed = !list_empty(&lst->st_perfile); 5546 + spin_unlock(&cl->cl_lock); 5547 + 5548 + if (!hashed) { 5549 + mutex_unlock(&lst->st_mutex); 5550 + nfs4_put_stid(&lst->st_stid); 5551 + goto retry; 5552 + } 5557 5553 status = nfs_ok; 5554 + *plst = lst; 5558 5555 out: 5559 5556 nfs4_put_stateowner(&lo->lo_owner); 5560 5557 return status; ··· 5636 5603 goto out; 5637 5604 status = lookup_or_create_lock_state(cstate, open_stp, lock, 5638 5605 &lock_stp, &new); 5639 - if (status == nfs_ok) 5640 - mutex_lock(&lock_stp->st_mutex); 5641 5606 } else { 5642 5607 status = nfs4_preprocess_seqid_op(cstate, 5643 5608 lock->lk_old_lock_seqid,
+6 -3
fs/nfsd/vfs.c
··· 1252 1252 if (IS_ERR(dchild)) 1253 1253 return nfserrno(host_err); 1254 1254 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); 1255 - if (err) { 1256 - dput(dchild); 1255 + /* 1256 + * We unconditionally drop our ref to dchild as fh_compose will have 1257 + * already grabbed its own ref for it. 1258 + */ 1259 + dput(dchild); 1260 + if (err) 1257 1261 return err; 1258 - } 1259 1262 return nfsd_create_locked(rqstp, fhp, fname, flen, iap, type, 1260 1263 rdev, resfhp); 1261 1264 }