Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a52d726b authored by Jeff Layton's avatar Jeff Layton Committed by J. Bruce Fields
Browse files

nfsd: convert nfs4_client->cl_cb_flags to a generic flags field



We'll need a way to flag the nfs4_client as already being recorded on
stable storage so that we don't continually upcall. Currently, that's
recorded in the cl_firststate field of the client struct. Using an
entire u32 to store a flag is rather wasteful though.

The cl_cb_flags field is only using 2 bits right now, so repurpose that
to a generic flags field. Rename NFSD4_CLIENT_KILL to
NFSD4_CLIENT_CB_KILL to make it evident that it's part of the callback
flags. Add a mask that we can use for existing checks that look to see
whether any flags are set, so that the new flags don't interfere.

Convert all references to cl_firstate to the NFSD4_CLIENT_STABLE flag,
and add a new NFSD4_CLIENT_RECLAIM_COMPLETE flag.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 1df00640
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -754,9 +754,9 @@ static void do_probe_callback(struct nfs4_client *clp)
 */
 */
void nfsd4_probe_callback(struct nfs4_client *clp)
void nfsd4_probe_callback(struct nfs4_client *clp)
{
{
	/* XXX: atomicity?  Also, should we be using cl_cb_flags? */
	/* XXX: atomicity?  Also, should we be using cl_flags? */
	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
	set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
	set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
	do_probe_callback(clp);
	do_probe_callback(clp);
}
}


@@ -915,7 +915,7 @@ void nfsd4_destroy_callback_queue(void)
/* must be called under the state lock */
/* must be called under the state lock */
void nfsd4_shutdown_callback(struct nfs4_client *clp)
void nfsd4_shutdown_callback(struct nfs4_client *clp)
{
{
	set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags);
	set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags);
	/*
	/*
	 * Note this won't actually result in a null callback;
	 * Note this won't actually result in a null callback;
	 * instead, nfsd4_do_callback_rpc() will detect the killed
	 * instead, nfsd4_do_callback_rpc() will detect the killed
@@ -966,15 +966,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
		clp->cl_cb_conn.cb_xprt = NULL;
		clp->cl_cb_conn.cb_xprt = NULL;
	}
	}
	if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags))
	if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags))
		return;
		return;
	spin_lock(&clp->cl_lock);
	spin_lock(&clp->cl_lock);
	/*
	/*
	 * Only serialized callback code is allowed to clear these
	 * Only serialized callback code is allowed to clear these
	 * flags; main nfsd code can only set them:
	 * flags; main nfsd code can only set them:
	 */
	 */
	BUG_ON(!clp->cl_cb_flags);
	BUG_ON(!(clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK));
	clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
	clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
	memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
	memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
	c = __nfsd4_find_backchannel(clp);
	c = __nfsd4_find_backchannel(clp);
	if (c) {
	if (c) {
@@ -1000,7 +1000,7 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
	struct nfs4_client *clp = cb->cb_clp;
	struct nfs4_client *clp = cb->cb_clp;
	struct rpc_clnt *clnt;
	struct rpc_clnt *clnt;


	if (clp->cl_cb_flags)
	if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
		nfsd4_process_cb_update(cb);
		nfsd4_process_cb_update(cb);


	clnt = clp->cl_cb_client;
	clnt = clp->cl_cb_client;
+2 −1
Original line number Original line Diff line number Diff line
@@ -319,7 +319,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	 * Before RECLAIM_COMPLETE done, server should deny new lock
	 * Before RECLAIM_COMPLETE done, server should deny new lock
	 */
	 */
	if (nfsd4_has_session(cstate) &&
	if (nfsd4_has_session(cstate) &&
	    !cstate->session->se_client->cl_firststate &&
	    !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
		      &cstate->session->se_client->cl_flags) &&
	    open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
	    open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
		return nfserr_grace;
		return nfserr_grace;


+3 −4
Original line number Original line Diff line number Diff line
@@ -126,9 +126,8 @@ void nfsd4_create_clid_dir(struct nfs4_client *clp)


	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);


	if (clp->cl_firststate)
	if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
		return;
		return;
	clp->cl_firststate = 1;
	if (!rec_file)
	if (!rec_file)
		return;
		return;
	status = nfs4_save_creds(&original_cred);
	status = nfs4_save_creds(&original_cred);
@@ -271,13 +270,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
	const struct cred *original_cred;
	const struct cred *original_cred;
	int status;
	int status;


	if (!rec_file || !clp->cl_firststate)
	if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
		return;
		return;


	status = mnt_want_write_file(rec_file);
	status = mnt_want_write_file(rec_file);
	if (status)
	if (status)
		goto out;
		goto out;
	clp->cl_firststate = 0;
	clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);


	status = nfs4_save_creds(&original_cred);
	status = nfs4_save_creds(&original_cred);
	if (status < 0)
	if (status < 0)
+28 −17
Original line number Original line Diff line number Diff line
@@ -2069,7 +2069,8 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta


	nfs4_lock_state();
	nfs4_lock_state();
	status = nfserr_complete_already;
	status = nfserr_complete_already;
	if (cstate->session->se_client->cl_firststate)
	if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
			     &cstate->session->se_client->cl_flags))
		goto out;
		goto out;


	status = nfserr_stale_clientid;
	status = nfserr_stale_clientid;
@@ -2816,12 +2817,6 @@ static void
nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session)
nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session)
{
{
	open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
	open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
	/*
	 * On a 4.1+ client, we don't create a state record for a client
	 * until it performs RECLAIM_COMPLETE:
	 */
	if (!has_session)
		open->op_openowner->oo_owner.so_client->cl_firststate = 1;
}
}


/* Should we give out recallable state?: */
/* Should we give out recallable state?: */
@@ -4462,7 +4457,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
	clp = find_confirmed_client_by_str(name, strhashval);
	clp = find_confirmed_client_by_str(name, strhashval);
	if (!clp)
	if (!clp)
		return 0;
		return 0;
	return clp->cl_firststate;
	return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
}
}


/*
/*
@@ -4507,18 +4502,11 @@ nfs4_release_reclaim(void)
/*
/*
 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
static struct nfs4_client_reclaim *
static struct nfs4_client_reclaim *
nfs4_find_reclaim_client(clientid_t *clid)
nfsd4_find_reclaim_client(struct nfs4_client *clp)
{
{
	unsigned int strhashval;
	unsigned int strhashval;
	struct nfs4_client *clp;
	struct nfs4_client_reclaim *crp = NULL;
	struct nfs4_client_reclaim *crp = NULL;



	/* find clientid in conf_id_hashtbl */
	clp = find_confirmed_client(clid);
	if (clp == NULL)
		return NULL;

	dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
	dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
		            clp->cl_name.len, clp->cl_name.data,
		            clp->cl_name.len, clp->cl_name.data,
			    clp->cl_recdir);
			    clp->cl_recdir);
@@ -4533,13 +4521,36 @@ nfs4_find_reclaim_client(clientid_t *clid)
	return NULL;
	return NULL;
}
}


static int
nfsd4_client_record_check(struct nfs4_client *clp)
{
	/* did we already find that this client is stable? */
	if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
		return 0;

	/* look for it in the reclaim hashtable otherwise */
	if (nfsd4_find_reclaim_client(clp)) {
		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
		return 0;
	}

	return -ENOENT;
}

/*
/*
* Called from OPEN. Look for clientid in reclaim list.
* Called from OPEN. Look for clientid in reclaim list.
*/
*/
__be32
__be32
nfs4_check_open_reclaim(clientid_t *clid)
nfs4_check_open_reclaim(clientid_t *clid)
{
{
	return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
	struct nfs4_client *clp;

	/* find clientid in conf_id_hashtbl */
	clp = find_confirmed_client(clid);
	if (clp == NULL)
		return nfserr_reclaim_bad;

	return nfsd4_client_record_check(clp) ? nfserr_reclaim_bad : nfs_ok;
}
}


#ifdef CONFIG_NFSD_FAULT_INJECTION
#ifdef CONFIG_NFSD_FAULT_INJECTION
+7 −4
Original line number Original line Diff line number Diff line
@@ -236,14 +236,17 @@ struct nfs4_client {
	struct svc_cred		cl_cred; 	/* setclientid principal */
	struct svc_cred		cl_cred; 	/* setclientid principal */
	clientid_t		cl_clientid;	/* generated by server */
	clientid_t		cl_clientid;	/* generated by server */
	nfs4_verifier		cl_confirm;	/* generated by server */
	nfs4_verifier		cl_confirm;	/* generated by server */
	u32			cl_firststate;	/* recovery dir creation */
	u32			cl_minorversion;
	u32			cl_minorversion;


	/* for v4.0 and v4.1 callbacks: */
	/* for v4.0 and v4.1 callbacks: */
	struct nfs4_cb_conn	cl_cb_conn;
	struct nfs4_cb_conn	cl_cb_conn;
#define NFSD4_CLIENT_CB_UPDATE	1
#define NFSD4_CLIENT_CB_UPDATE		(0)
#define NFSD4_CLIENT_KILL	2
#define NFSD4_CLIENT_CB_KILL		(1)
	unsigned long		cl_cb_flags;
#define NFSD4_CLIENT_STABLE		(2)	/* client on stable storage */
#define NFSD4_CLIENT_RECLAIM_COMPLETE	(3)	/* reclaim_complete done */
#define NFSD4_CLIENT_CB_FLAG_MASK	(1 << NFSD4_CLIENT_CB_UPDATE | \
					 1 << NFSD4_CLIENT_CB_KILL)
	unsigned long		cl_flags;
	struct rpc_clnt		*cl_cb_client;
	struct rpc_clnt		*cl_cb_client;
	u32			cl_cb_ident;
	u32			cl_cb_ident;
#define NFSD4_CB_UP		0
#define NFSD4_CB_UP		0