Re: [bug report] nfsd: perform all find_openstateowner_str calls in the one place.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 08 Mar 2024, Dan Carpenter wrote:
> Hello NeilBrown,
> 
> Commit 11c3d0a15bbc ("nfsd: perform all find_openstateowner_str calls
> in the one place.") from Mar 5, 2024 (linux-next), leads to the
> following Smatch static checker warning:
> 
> 	fs/nfsd/nfs4state.c:1674 release_openowner()
> 	warn: sleeping in atomic context
> 
> fs/nfsd/nfs4state.c
>     1657 static void release_openowner(struct nfs4_openowner *oo)
>     1658 {
>     1659         struct nfs4_ol_stateid *stp;
>     1660         struct nfs4_client *clp = oo->oo_owner.so_client;
>     1661         struct list_head reaplist;
>     1662 
>     1663         INIT_LIST_HEAD(&reaplist);
>     1664 
>     1665         spin_lock(&clp->cl_lock);
>     1666         unhash_openowner_locked(oo);
>     1667         while (!list_empty(&oo->oo_owner.so_stateids)) {
>     1668                 stp = list_first_entry(&oo->oo_owner.so_stateids,
>     1669                                 struct nfs4_ol_stateid, st_perstateowner);
>     1670                 if (unhash_open_stateid(stp, &reaplist))
>     1671                         put_ol_stateid_locked(stp, &reaplist);
>     1672         }
>     1673         spin_unlock(&clp->cl_lock);
> --> 1674         free_ol_stateid_reaplist(&reaplist);
>                  ^^^^^^^^^^^^^^^^^^^^^^^^
> This is a might sleep function.

Thanks Dan - very helpful as always!


> 
>     1675         release_last_closed_stateid(oo);
>     1676         nfs4_put_stateowner(&oo->oo_owner);
>     1677 }
> 
> The caller is find_or_alloc_open_stateowner()
> 
> fs/nfsd/nfs4state.c
>   4863  find_or_alloc_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
>   4864                                struct nfsd4_compound_state *cstate)
>   4865  {
>   4866          struct nfs4_client *clp = cstate->clp;
>   4867          struct nfs4_openowner *oo, *new = NULL;
>   4868  
>   4869          while (1) {
>   4870                  spin_lock(&clp->cl_lock);
>                        ^^^^^^^^^^^^^^^^^^^^^^^^^
> Huh...  This looks like the same lock that we take in
> release_openowner().  Why do I not see a static checker warning for
> double lock?

Good question.  Maybe the relationship between oo and clp is too subtle
for the checker to follow?
It would certainly have deadlocked if ever NFS4_OO_CONFIRMED was not
set.

Fortunately this is easily fixed.

Thanks again,
NeilBrown


> 
> 
>   4871                  oo = find_openstateowner_str(strhashval, open, clp);
>   4872                  if (oo && !(oo->oo_flags & NFS4_OO_CONFIRMED)) {
>   4873                          /* Replace unconfirmed owners without checking for replay. */
>   4874                          release_openowner(oo);
>                                 ^^^^^^^^^^^^^^^^^^^^^^
> Here
> 
>   4875                          oo = NULL;
>   4876                  }
>   4877                  if (oo) {
>   4878                          spin_unlock(&clp->cl_lock);
>   4879                          if (new)
>   4880                                  nfs4_free_stateowner(&new->oo_owner);
>   4881                          return oo;
>   4882                  }
>   4883                  if (new) {
>   4884                          hash_openowner(new, clp, strhashval);
>   4885                          spin_unlock(&clp->cl_lock);
>   4886                          return new;
>   4887                  }
>   4888                  spin_unlock(&clp->cl_lock);
> 
> 
> 
> regards,
> dan carpenter
> 
> 






[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux