NFSv4.1: Add DESTROY_CLIENTID
[firefly-linux-kernel-4.4.55.git] / fs / nfs / nfs4proc.c
index 3fdff0cd558de8c757012a192483181fc732258c..485a6c0cdc409e0876709c1259ead4753c72877e 100644 (file)
@@ -5261,6 +5261,65 @@ out:
        return status;
 }
 
+static int _nfs4_proc_destroy_clientid(struct nfs_client *clp,
+               struct rpc_cred *cred)
+{
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_CLIENTID],
+               .rpc_argp = clp,
+               .rpc_cred = cred,
+       };
+       int status;
+
+       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
+       if (status)
+               pr_warn("NFS: Got error %d from the server %s on "
+                       "DESTROY_CLIENTID.", status, clp->cl_hostname);
+       return status;
+}
+
+static int nfs4_proc_destroy_clientid(struct nfs_client *clp,
+               struct rpc_cred *cred)
+{
+       unsigned int loop;
+       int ret;
+
+       for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) {
+               ret = _nfs4_proc_destroy_clientid(clp, cred);
+               switch (ret) {
+               case -NFS4ERR_DELAY:
+               case -NFS4ERR_CLIENTID_BUSY:
+                       ssleep(1);
+                       break;
+               default:
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+int nfs4_destroy_clientid(struct nfs_client *clp)
+{
+       struct rpc_cred *cred;
+       int ret = 0;
+
+       if (clp->cl_mvops->minor_version < 1)
+               goto out;
+       if (clp->cl_exchange_flags == 0)
+               goto out;
+       cred = nfs4_get_exchange_id_cred(clp);
+       ret = nfs4_proc_destroy_clientid(clp, cred);
+       if (cred)
+               put_rpccred(cred);
+       switch (ret) {
+       case 0:
+       case -NFS4ERR_STALE_CLIENTID:
+               clp->cl_exchange_flags = 0;
+       }
+out:
+       return ret;
+}
+
 struct nfs4_get_lease_time_data {
        struct nfs4_get_lease_time_args *args;
        struct nfs4_get_lease_time_res *res;