Merge tag 'gfs2-4.20.fixes3' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2...
[sfrench/cifs-2.6.git] / fs / nfsd / nfs4state.c
index b0ca0efd287510417387fe916ea9668c587ddec1..f093fbe471338b06a2d544ebe00983cb065968fa 100644 (file)
@@ -713,6 +713,36 @@ out_free:
        return NULL;
 }
 
+/*
+ * Create a unique stateid_t to represent each COPY.
+ */
+int nfs4_init_cp_state(struct nfsd_net *nn, struct nfsd4_copy *copy)
+{
+       int new_id;
+
+       idr_preload(GFP_KERNEL);
+       spin_lock(&nn->s2s_cp_lock);
+       new_id = idr_alloc_cyclic(&nn->s2s_cp_stateids, copy, 0, 0, GFP_NOWAIT);
+       spin_unlock(&nn->s2s_cp_lock);
+       idr_preload_end();
+       if (new_id < 0)
+               return 0;
+       copy->cp_stateid.si_opaque.so_id = new_id;
+       copy->cp_stateid.si_opaque.so_clid.cl_boot = nn->boot_time;
+       copy->cp_stateid.si_opaque.so_clid.cl_id = nn->s2s_cp_cl_id;
+       return 1;
+}
+
+void nfs4_free_cp_state(struct nfsd4_copy *copy)
+{
+       struct nfsd_net *nn;
+
+       nn = net_generic(copy->cp_clp->net, nfsd_net_id);
+       spin_lock(&nn->s2s_cp_lock);
+       idr_remove(&nn->s2s_cp_stateids, copy->cp_stateid.si_opaque.so_id);
+       spin_unlock(&nn->s2s_cp_lock);
+}
+
 static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp)
 {
        struct nfs4_stid *stid;
@@ -1827,6 +1857,8 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
 #ifdef CONFIG_NFSD_PNFS
        INIT_LIST_HEAD(&clp->cl_lo_states);
 #endif
+       INIT_LIST_HEAD(&clp->async_copies);
+       spin_lock_init(&clp->async_lock);
        spin_lock_init(&clp->cl_lock);
        rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
        return clp;
@@ -1942,6 +1974,7 @@ __destroy_client(struct nfs4_client *clp)
                }
        }
        nfsd4_return_all_client_layouts(clp);
+       nfsd4_shutdown_copy(clp);
        nfsd4_shutdown_callback(clp);
        if (clp->cl_cb_conn.cb_xprt)
                svc_xprt_put(clp->cl_cb_conn.cb_xprt);
@@ -2475,7 +2508,8 @@ static bool client_has_state(struct nfs4_client *clp)
                || !list_empty(&clp->cl_lo_states)
 #endif
                || !list_empty(&clp->cl_delegations)
-               || !list_empty(&clp->cl_sessions);
+               || !list_empty(&clp->cl_sessions)
+               || !list_empty(&clp->async_copies);
 }
 
 __be32
@@ -4364,7 +4398,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
 
        fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
        if (!fl)
-               goto out_stid;
+               goto out_clnt_odstate;
 
        status = vfs_setlease(fp->fi_deleg_file, fl->fl_type, &fl, NULL);
        if (fl)
@@ -4389,7 +4423,6 @@ out_unlock:
        vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp);
 out_clnt_odstate:
        put_clnt_odstate(dp->dl_clnt_odstate);
-out_stid:
        nfs4_put_stid(&dp->dl_stid);
 out_delegees:
        put_deleg_file(fp);
@@ -7161,6 +7194,8 @@ static int nfs4_state_create_net(struct net *net)
        INIT_LIST_HEAD(&nn->close_lru);
        INIT_LIST_HEAD(&nn->del_recall_lru);
        spin_lock_init(&nn->client_lock);
+       spin_lock_init(&nn->s2s_cp_lock);
+       idr_init(&nn->s2s_cp_stateids);
 
        spin_lock_init(&nn->blocked_locks_lock);
        INIT_LIST_HEAD(&nn->blocked_locks_lru);