+ set_bit(ops->owner_flag_bit, &sp->so_flags);
+ nfs4_put_state_owner(sp);
+ nfs4_recovery_handle_error(clp, status);
+ return status;
+ }
+ nfs4_put_state_owner(sp);
+ goto restart;
+ }
+ spin_unlock(&clp->cl_lock);
+ return status;
+}
+
+static int nfs4_check_lease(struct nfs_client *clp)
+{
+ struct rpc_cred *cred;
+ int status = -NFS4ERR_EXPIRED;
+
+ /* Is the client already known to have an expired lease? */
+ if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
+ return 0;
+ cred = nfs4_get_renew_cred(clp);
+ if (cred == NULL) {
+ cred = nfs4_get_setclientid_cred(clp);
+ if (cred == NULL)
+ goto out;
+ }
+ status = nfs4_proc_renew(clp, cred);
+ put_rpccred(cred);
+out:
+ nfs4_recovery_handle_error(clp, status);
+ return status;
+}
+
+static int nfs4_reclaim_lease(struct nfs_client *clp)
+{
+ struct rpc_cred *cred;
+ int status = -ENOENT;
+
+ cred = nfs4_get_setclientid_cred(clp);
+ if (cred != NULL) {
+ status = nfs4_init_client(clp, cred);
+ put_rpccred(cred);
+ /* Handle case where the user hasn't set up machine creds */
+ if (status == -EACCES && cred == clp->cl_machine_cred) {
+ nfs4_clear_machine_cred(clp);
+ status = -EAGAIN;
+ }
+ }
+ return status;
+}
+
+static int reclaimer(void *ptr)
+{
+ struct nfs_client *clp = ptr;
+ int status = 0;
+
+ allow_signal(SIGKILL);
+
+ /* Ensure exclusive access to NFSv4 state */
+ while (!list_empty(&clp->cl_superblocks)) {
+ if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
+ /* We're going to have to re-establish a clientid */
+ status = nfs4_reclaim_lease(clp);
+ if (status) {
+ set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+ if (status == -EAGAIN)
+ continue;
+ goto out_error;