make get_file() return its argument
[pandora-kernel.git] / fs / nfsd / nfs4state.c
index 6445fbd..d7f4965 100644 (file)
@@ -337,13 +337,22 @@ static void unhash_stid(struct nfs4_stid *s)
        idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
 }
 
+static void
+hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp)
+{
+       lockdep_assert_held(&recall_lock);
+
+       list_add(&dp->dl_perfile, &fp->fi_delegations);
+       list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
+}
+
 /* Called under the state lock. */
 static void
 unhash_delegation(struct nfs4_delegation *dp)
 {
        unhash_stid(&dp->dl_stid);
-       list_del_init(&dp->dl_perclnt);
        spin_lock(&recall_lock);
+       list_del_init(&dp->dl_perclnt);
        list_del_init(&dp->dl_perfile);
        list_del_init(&dp->dl_recall_lru);
        spin_unlock(&recall_lock);
@@ -2810,18 +2819,17 @@ static int nfs4_setlease(struct nfs4_delegation *dp, int flag)
        if (!fl)
                return -ENOMEM;
        fl->fl_file = find_readable_file(fp);
-       list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
        status = vfs_setlease(fl->fl_file, fl->fl_type, &fl);
        if (status) {
-               list_del_init(&dp->dl_perclnt);
                locks_free_lock(fl);
                return -ENOMEM;
        }
        fp->fi_lease = fl;
-       fp->fi_deleg_file = fl->fl_file;
-       get_file(fp->fi_deleg_file);
+       fp->fi_deleg_file = get_file(fl->fl_file);
        atomic_set(&fp->fi_delegees, 1);
-       list_add(&dp->dl_perfile, &fp->fi_delegations);
+       spin_lock(&recall_lock);
+       hash_delegation_locked(dp, fp);
+       spin_unlock(&recall_lock);
        return 0;
 }
 
@@ -2837,9 +2845,8 @@ static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag)
                return -EAGAIN;
        }
        atomic_inc(&fp->fi_delegees);
-       list_add(&dp->dl_perfile, &fp->fi_delegations);
+       hash_delegation_locked(dp, fp);
        spin_unlock(&recall_lock);
-       list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
        return 0;
 }
 
@@ -3264,10 +3271,17 @@ static int check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_sess
        return nfserr_old_stateid;
 }
 
+static __be32 nfsd4_check_openowner_confirmed(struct nfs4_ol_stateid *ols)
+{
+       if (ols->st_stateowner->so_is_open_owner &&
+           !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
+               return nfserr_bad_stateid;
+       return nfs_ok;
+}
+
 __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
 {
        struct nfs4_stid *s;
-       struct nfs4_ol_stateid *ols;
        __be32 status;
 
        if (STALE_STATEID(stateid))
@@ -3281,11 +3295,7 @@ __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
                return status;
        if (!(s->sc_type & (NFS4_OPEN_STID | NFS4_LOCK_STID)))
                return nfs_ok;
-       ols = openlockstateid(s);
-       if (ols->st_stateowner->so_is_open_owner
-           && !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
-               return nfserr_bad_stateid;
-       return nfs_ok;
+       return nfsd4_check_openowner_confirmed(openlockstateid(s));
 }
 
 static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s)
@@ -3352,8 +3362,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
                status = nfs4_check_fh(current_fh, stp);
                if (status)
                        goto out;
-               if (stp->st_stateowner->so_is_open_owner
-                   && !(openowner(stp->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
+               status = nfsd4_check_openowner_confirmed(stp);
+               if (status)
                        goto out;
                status = nfs4_check_openmode(stp, flags);
                if (status)
@@ -3385,7 +3395,7 @@ nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp)
         * correspondance, and we have to delete the lockowner when we
         * delete the lock stateid:
         */
-       unhash_lockowner(lo);
+       release_lockowner(lo);
        return nfs_ok;
 }
 
@@ -3820,6 +3830,10 @@ static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, c
 
        if (!same_owner_str(&lo->lo_owner, owner, clid))
                return false;
+       if (list_empty(&lo->lo_owner.so_stateids)) {
+               WARN_ON_ONCE(1);
+               return false;
+       }
        lst = list_first_entry(&lo->lo_owner.so_stateids,
                               struct nfs4_ol_stateid, st_perstateowner);
        return lst->st_file->fi_inode == inode;