1    	/*
2    	 * vim:noexpandtab:shiftwidth=8:tabstop=8:
3    	 *
4    	 * Copyright CEA/DAM/DIF  (2008)
5    	 * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
6    	 *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
7    	 *
8    	 *
9    	 * This program is free software; you can redistribute it and/or
10   	 * modify it under the terms of the GNU Lesser General Public License
11   	 * as published by the Free Software Foundation; either version 3 of
12   	 * the License, or (at your option) any later version.
13   	 *
14   	 * This program is distributed in the hope that it will be useful, but
15   	 * WITHOUT ANY WARRANTY; without even the implied warranty of
16   	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   	 * Lesser General Public License for more details.
18   	 *
19   	 * You should have received a copy of the GNU Lesser General Public
20   	 * License along with this library; if not, write to the Free Software
21   	 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22   	 * 02110-1301 USA
23   	 *
24   	 * ---------------------------------------
25   	 */
26   	
27   	/**
28   	 * @file    nfs4_op_create_session.c
29   	 * @brief   Routines used for managing the NFS4_OP_CREATE_SESSION operation.
30   	 */
31   	
32   	#include "config.h"
33   	#include <pthread.h>
34   	#include <assert.h>
35   	#include "log.h"
36   	#include "nfs4.h"
37   	#include "nfs_core.h"
38   	#include "nfs_rpc_callback.h"
39   	#include "nfs_proto_functions.h"
40   	#include "sal_functions.h"
41   	#include "nfs_creds.h"
42   	#include "client_mgr.h"
43   	#include "fsal.h"
44   	#ifdef USE_LTTNG
45   	#include "gsh_lttng/nfs4.h"
46   	#endif
47   	
48   	#define log_channel_attributes(component, chan_attrs, name) \
49   		LogFullDebug(component,					\
50   			     "%s attributes ca_headerpadsize %"PRIu32	\
51   			     " ca_maxrequestsize %"PRIu32		\
52   			     " ca_maxresponsesize %"PRIu32		\
53   			     " ca_maxresponsesize_cached %"PRIu32	\
54   			     " ca_maxoperations %"PRIu32		\
55   			     " ca_maxrequests %"PRIu32,			\
56   			     name,					\
57   			     (chan_attrs)->ca_headerpadsize,		\
58   			     (chan_attrs)->ca_maxrequestsize,		\
59   			     (chan_attrs)->ca_maxresponsesize,		\
60   			     (chan_attrs)->ca_maxresponsesize_cached,	\
61   			     (chan_attrs)->ca_maxoperations,		\
62   			     (chan_attrs)->ca_maxrequests)
63   	
64   	/**
65   	 *
66   	 * @brief The NFS4_OP_CREATE_SESSION operation
67   	 *
68   	 * @param[in]     op    nfs4_op arguments
69   	 * @param[in,out] data  Compound request's data
70   	 * @param[out]    resp  nfs4_op results
71   	 *
72   	 * @return Values as per RFC5661 p. 363
73   	 *
74   	 * @see nfs4_Compound
75   	 *
76   	 */
77   	
78   	enum nfs_req_result nfs4_op_create_session(struct nfs_argop4 *op,
79   						   compound_data_t *data,
80   						   struct nfs_resop4 *resp)
81   	{
82   		/* Result of looking up the clientid in the confirmed ID
83   		   table */
84   		nfs_client_id_t *conf = NULL;	/* XXX these are not good names */
85   		/* Result of looking up the clientid in the unconfirmed ID
86   		   table */
87   		nfs_client_id_t *unconf = NULL;
88   		/* The found clientid (either one of the preceding) */
89   		nfs_client_id_t *found = NULL;
90   		/* The found client record */
91   		nfs_client_record_t *client_record;
92   		/* The created session */
93   		nfs41_session_t *nfs41_session = NULL;
94   		/* Client supplied clientid */
95   		clientid4 clientid = 0;
96   		/* The client address as a string, for gratuitous logging */
97   		const char *str_client_addr = "(unknown)";
98   		/* The client name, for gratuitous logging */
99   		char str_client[CLIENTNAME_BUFSIZE];
100  		/* Display buffer for client name */
101  		struct display_buffer dspbuf_client = {
102  			sizeof(str_client), str_client, str_client};
103  		/* The clientid4 broken down into fields */
104  		char str_clientid4[DISPLAY_CLIENTID_SIZE];
105  		/* Display buffer for clientid4 */
106  		struct display_buffer dspbuf_clientid4 = {
107  			sizeof(str_clientid4), str_clientid4, str_clientid4};
108  		/* Return code from clientid calls */
109  		int i, rc = 0;
110  		/* Component for logging */
111  		log_components_t component = COMPONENT_CLIENTID;
112  		/* Abbreviated alias for arguments */
113  		CREATE_SESSION4args * const arg_CREATE_SESSION4 =
114  		    &op->nfs_argop4_u.opcreate_session;
115  		/* Abbreviated alias for response */
116  		CREATE_SESSION4res * const res_CREATE_SESSION4 =
117  		    &resp->nfs_resop4_u.opcreate_session;
118  		/* Abbreviated alias for successful response */
119  		CREATE_SESSION4resok * const res_CREATE_SESSION4ok =
120  		    &res_CREATE_SESSION4->CREATE_SESSION4res_u.csr_resok4;
121  	
122  		/* Make sure str_client is always printable even
123  		 * if log level changes midstream.
124  		 */
125  		display_printf(&dspbuf_client, "(unknown)");
126  		display_reset_buffer(&dspbuf_client);
127  	
(1) Event cond_true: Condition "op_ctx->client != NULL", taking true branch.
128  		if (op_ctx->client != NULL)
129  			str_client_addr = op_ctx->client->hostaddr_str;
130  	
(2) Event cond_true: Condition "!!(component_log_level[COMPONENT_SESSIONS] >= NIV_DEBUG)", taking true branch.
(3) Event cond_true: Condition "!!(component_log_level[COMPONENT_SESSIONS] >= NIV_DEBUG)", taking true branch.
131  		if (isDebug(COMPONENT_SESSIONS))
132  			component = COMPONENT_SESSIONS;
133  	
134  		resp->resop = NFS4_OP_CREATE_SESSION;
(4) Event missing_lock: Accessing "res_CREATE_SESSION4->csr_status" without holding lock "nfs_client_record_t.cr_mutex". Elsewhere, "CREATE_SESSION4res.csr_status" is accessed with "nfs_client_record_t.cr_mutex" held 10 out of 13 times.
Also see events: [example_lock][example_access][example_lock][example_access][example_lock][example_access][example_lock][example_access][example_lock][example_access]
135  		res_CREATE_SESSION4->csr_status = NFS4_OK;
136  		clientid = arg_CREATE_SESSION4->csa_clientid;
137  	
138  		display_clientid(&dspbuf_clientid4, clientid);
139  	
140  		if (data->minorversion == 0) {
141  			res_CREATE_SESSION4->csr_status = NFS4ERR_INVAL;
142  			return NFS_REQ_ERROR;
143  		}
144  	
145  		LogDebug(component,
146  			 "CREATE_SESSION client addr=%s clientid=%s -------------------",
147  			 str_client_addr, str_clientid4);
148  	
149  		/* First try to look up unconfirmed record */
150  		rc = nfs_client_id_get_unconfirmed(clientid, &unconf);
151  	
152  		if (rc == CLIENT_ID_SUCCESS) {
153  			client_record = unconf->cid_client_record;
154  			found = unconf;
155  		} else {
156  			rc = nfs_client_id_get_confirmed(clientid, &conf);
157  			if (rc != CLIENT_ID_SUCCESS) {
158  				/* No record whatsoever of this clientid */
159  				LogDebug(component,
160  					 "%s clientid=%s",
161  					 clientid_error_to_str(rc), str_clientid4);
162  	
163  				if (rc == CLIENT_ID_EXPIRED)
164  					rc = CLIENT_ID_STALE;
165  	
166  				res_CREATE_SESSION4->csr_status =
167  				    clientid_error_to_nfsstat_no_expire(rc);
168  	
169  				return NFS_REQ_ERROR;
170  			}
171  	
172  			client_record = conf->cid_client_record;
173  			found = conf;
174  		}
175  	
(5) Event example_lock: Example 1: Locking "nfs_client_record_t.cr_mutex".
(7) Event example_lock: Example 2: Locking "nfs_client_record_t.cr_mutex".
(9) Event example_lock: Example 3: Locking "nfs_client_record_t.cr_mutex".
(11) Event example_lock: Example 4: Locking "nfs_client_record_t.cr_mutex".
Also see events: [missing_lock][example_access][example_access][example_access][example_access][example_lock][example_access]
176  		PTHREAD_MUTEX_lock(&client_record->cr_mutex);
177  	
178  		inc_client_record_ref(client_record);
179  	
180  		if (isFullDebug(component)) {
181  			char str[LOG_BUFF_LEN] = "\0";
182  			struct display_buffer dspbuf = {sizeof(str), str, str};
183  	
184  			display_client_record(&dspbuf, client_record);
185  	
186  			LogFullDebug(component,
187  				     "Client Record %s cr_confirmed_rec=%p cr_unconfirmed_rec=%p",
188  				     str,
189  				     client_record->cr_confirmed_rec,
190  				     client_record->cr_unconfirmed_rec);
191  		}
192  	
193  		/* At this point one and only one of conf and unconf is
194  		 * non-NULL, and found also references the single clientid
195  		 * record that was found.
196  		 */
197  	
198  		LogDebug(component,
199  			 "CREATE_SESSION clientid=%s csa_sequence=%" PRIu32
200  			 " clientid_cs_seq=%" PRIu32
201  			 " data_oppos=%d",
202  			 str_clientid4, arg_CREATE_SESSION4->csa_sequence,
203  			 found->cid_create_session_sequence, data->oppos);
204  	
205  		if (isFullDebug(component)) {
206  			char str[LOG_BUFF_LEN] = "\0";
207  			struct display_buffer dspbuf = {sizeof(str), str, str};
208  	
209  			display_client_id_rec(&dspbuf, found);
210  			LogFullDebug(component, "Found %s", str);
211  		}
212  	
213  		if ((arg_CREATE_SESSION4->csa_sequence + 1) ==
214  		     found->cid_create_session_sequence) {
215  			*res_CREATE_SESSION4 = found->cid_create_session_slot;
216  	
217  			LogDebug(component,
218  				 "CREATE_SESSION special replay case, used response in cid_create_session_slot");
219  			goto out;
220  		} else if (arg_CREATE_SESSION4->csa_sequence !=
221  			   found->cid_create_session_sequence) {
(6) Event example_access: Example 1 (cont.): "CREATE_SESSION4res.csr_status" is accessed with lock "nfs_client_record_t.cr_mutex" held.
Also see events: [missing_lock][example_lock][example_lock][example_access][example_lock][example_access][example_lock][example_access][example_lock][example_access]
222  			res_CREATE_SESSION4->csr_status = NFS4ERR_SEQ_MISORDERED;
223  	
224  			LogDebug(component,
225  				 "CREATE_SESSION returning NFS4ERR_SEQ_MISORDERED");
226  			goto out;
227  		}
228  	
229  		if (unconf != NULL) {
230  			/* First must match principal */
231  			if (!nfs_compare_clientcred(&unconf->cid_credential,
232  						    &data->credential)) {
233  				if (isDebug(component)) {
234  					char *unconfirmed_addr = "(unknown)";
235  	
236  					if (unconf->gsh_client != NULL)
237  						unconfirmed_addr =
238  						    unconf->gsh_client->hostaddr_str;
239  	
240  					LogDebug(component,
241  						 "Unconfirmed ClientId %s->'%s': Principals do not match... unconfirmed addr=%s Return NFS4ERR_CLID_INUSE",
242  						 str_clientid4,
243  						 str_client_addr,
244  						 unconfirmed_addr);
245  				}
246  	
(8) Event example_access: Example 2 (cont.): "CREATE_SESSION4res.csr_status" is accessed with lock "nfs_client_record_t.cr_mutex" held.
Also see events: [missing_lock][example_lock][example_access][example_lock][example_lock][example_access][example_lock][example_access][example_lock][example_access]
247  				res_CREATE_SESSION4->csr_status = NFS4ERR_CLID_INUSE;
248  				goto out;
249  			}
250  		}
251  	
252  		if (conf != NULL) {
253  			if (isDebug(component) && conf != NULL)
254  				display_clientid_name(&dspbuf_client, conf);
255  	
256  			/* First must match principal */
257  			if (!nfs_compare_clientcred(&conf->cid_credential,
258  						    &data->credential)) {
259  				if (isDebug(component)) {
260  					char *confirmed_addr = "(unknown)";
261  	
262  					if (conf->gsh_client != NULL)
263  						confirmed_addr =
264  						    conf->gsh_client->hostaddr_str;
265  	
266  					LogDebug(component,
267  						 "Confirmed ClientId %s->%s addr=%s: Principals do not match... confirmed addr=%s Return NFS4ERR_CLID_INUSE",
268  						 str_clientid4, str_client,
269  						 str_client_addr, confirmed_addr);
270  				}
271  	
(10) Event example_access: Example 3 (cont.): "CREATE_SESSION4res.csr_status" is accessed with lock "nfs_client_record_t.cr_mutex" held.
Also see events: [missing_lock][example_lock][example_access][example_lock][example_access][example_lock][example_lock][example_access][example_lock][example_access]
272  				res_CREATE_SESSION4->csr_status = NFS4ERR_CLID_INUSE;
273  				goto out;
274  			}
275  	
276  			/* In this case, the record was confirmed proceed with
277  			   CREATE_SESSION */
278  		}
279  	
280  		/* We don't need to do any further principal checks, we can't
281  		 * have a confirmed clientid record with a different principal
282  		 * than the unconfirmed record.
283  		 */
284  	
285  		/* At this point, we need to try and create the session before
286  		 * we modify the confirmed and/or unconfirmed clientid
287  		 * records.
288  		 */
289  	
290  		/* Check flags value (test CSESS15) */
291  		if (arg_CREATE_SESSION4->csa_flags &
292  				~(CREATE_SESSION4_FLAG_PERSIST |
293  				  CREATE_SESSION4_FLAG_CONN_BACK_CHAN |
294  				  CREATE_SESSION4_FLAG_CONN_RDMA)) {
295  			LogDebug(component,
296  				 "Invalid create session flags %" PRIu32,
297  				 arg_CREATE_SESSION4->csa_flags);
(12) Event example_access: Example 4 (cont.): "CREATE_SESSION4res.csr_status" is accessed with lock "nfs_client_record_t.cr_mutex" held.
Also see events: [missing_lock][example_lock][example_access][example_lock][example_access][example_lock][example_access][example_lock][example_lock][example_access]
298  			res_CREATE_SESSION4->csr_status = NFS4ERR_INVAL;
299  			goto out;
300  		}
301  	
302  		log_channel_attributes(component,
303  				       &arg_CREATE_SESSION4->csa_fore_chan_attrs,
304  				       "Fore Channel");
305  		log_channel_attributes(component,
306  				       &arg_CREATE_SESSION4->csa_back_chan_attrs,
307  				       "Back Channel");
308  	
309  		/* Let's verify the channel attributes for the session first. */
310  		if (arg_CREATE_SESSION4->csa_fore_chan_attrs.ca_maxrequestsize <
311  							NFS41_MIN_REQUEST_SIZE ||
312  		    arg_CREATE_SESSION4->csa_fore_chan_attrs.ca_maxresponsesize <
313  							NFS41_MIN_RESPONSE_SIZE ||
314  		    arg_CREATE_SESSION4->csa_fore_chan_attrs.ca_maxoperations <
315  							NFS41_MIN_OPERATIONS ||
316  		    arg_CREATE_SESSION4->csa_fore_chan_attrs.ca_maxrequests == 0 ||
317  		    arg_CREATE_SESSION4->csa_back_chan_attrs.ca_maxrequestsize <
318  							NFS41_MIN_REQUEST_SIZE ||
319  		    arg_CREATE_SESSION4->csa_back_chan_attrs.ca_maxresponsesize <
320  							NFS41_MIN_RESPONSE_SIZE ||
321  		    arg_CREATE_SESSION4->csa_back_chan_attrs.ca_maxoperations <
322  							NFS41_MIN_OPERATIONS ||
323  		    arg_CREATE_SESSION4->csa_back_chan_attrs.ca_maxrequests == 0) {
324  			LogWarn(component,
325  				"Invalid channel attributes for %s",
326  				data->tagname);
327  			res_CREATE_SESSION4->csr_status = NFS4ERR_TOOSMALL;
328  			goto out;
329  		}
330  	
331  		/* Record session related information at the right place */
332  		nfs41_session = pool_alloc(nfs41_session_pool);
333  	
334  		if (nfs41_session == NULL) {
335  			LogCrit(component, "Could not allocate memory for a session");
336  			res_CREATE_SESSION4->csr_status = NFS4ERR_SERVERFAULT;
337  			goto out;
338  		}
339  	
340  		copy_xprt_addr(&nfs41_session->connections[0], data->req->rq_xprt);
341  		nfs41_session->num_conn = 1;
342  		nfs41_session->clientid = clientid;
343  		nfs41_session->clientid_record = found;
344  		nfs41_session->refcount = 2;	/* sentinel ref + call path ref */
345  		nfs41_session->fore_channel_attrs =
346  		    arg_CREATE_SESSION4->csa_fore_chan_attrs;
347  		nfs41_session->back_channel_attrs =
348  		    arg_CREATE_SESSION4->csa_back_chan_attrs;
349  		nfs41_session->flags = false;
350  		nfs41_session->cb_program = 0;
351  		PTHREAD_MUTEX_init(&nfs41_session->cb_mutex, NULL);
352  		PTHREAD_COND_init(&nfs41_session->cb_cond, NULL);
353  		PTHREAD_RWLOCK_init(&nfs41_session->conn_lock, NULL);
354  		nfs41_session->nb_slots = MIN(nfs_param.nfsv4_param.nb_slots,
355  				nfs41_session->fore_channel_attrs.ca_maxrequests);
356  		nfs41_session->fc_slots = gsh_calloc(nfs41_session->nb_slots,
357  						     sizeof(nfs41_session_slot_t));
358  		nfs41_session->bc_slots = gsh_calloc(nfs41_session->nb_slots,
359  						     sizeof(nfs41_cb_session_slot_t));
360  		for (i = 0; i < nfs41_session->nb_slots; i++)
361  			PTHREAD_MUTEX_init(&nfs41_session->fc_slots[i].lock, NULL);
362  	
363  		/* Take reference to clientid record on behalf the session. */
364  		inc_client_id_ref(found);
365  	
366  		/* add to head of session list (encapsulate?) */
367  		PTHREAD_MUTEX_lock(&found->cid_mutex);
368  		glist_add(&found->cid_cb.v41.cb_session_list,
369  			  &nfs41_session->session_link);
370  		PTHREAD_MUTEX_unlock(&found->cid_mutex);
371  	
372  		/* Set ca_maxrequests */
373  		nfs41_session->fore_channel_attrs.ca_maxrequests =
374  			nfs41_session->nb_slots;
375  		nfs41_Build_sessionid(&clientid, nfs41_session->session_id);
376  	
377  		res_CREATE_SESSION4ok->csr_sequence = arg_CREATE_SESSION4->csa_sequence;
378  	
379  		/* return the input for wanting of something better (will
380  		 * change in later versions)
381  		 */
382  		res_CREATE_SESSION4ok->csr_fore_chan_attrs =
383  		    nfs41_session->fore_channel_attrs;
384  		res_CREATE_SESSION4ok->csr_back_chan_attrs =
385  		    nfs41_session->back_channel_attrs;
386  		res_CREATE_SESSION4ok->csr_flags = 0;
387  	
388  		memcpy(res_CREATE_SESSION4ok->csr_sessionid,
389  		       nfs41_session->session_id,
390  		       NFS4_SESSIONID_SIZE);
391  	
392  	#ifdef USE_LTTNG
393  		tracepoint(nfs4, session_ref, __func__, __LINE__, nfs41_session, 2);
394  	#endif
395  	
396  		if (!nfs41_Session_Set(nfs41_session)) {
397  			LogDebug(component, "Could not insert session into table");
398  	
399  			/* Release the sentinel session resource (our reference will
400  			 * be dropped on exit.
401  			 */
402  			dec_session_ref(nfs41_session);
403  	
404  			/* Maybe a more precise status would be better */
405  			res_CREATE_SESSION4->csr_status = NFS4ERR_SERVERFAULT;
406  			goto out;
407  		}
408  	
409  		/* Make sure we have a reference to the confirmed clientid
410  		   record if any */
411  		if (conf == NULL) {
412  			conf = client_record->cr_confirmed_rec;
413  	
414  			if (isDebug(component) && conf != NULL)
415  				display_clientid_name(&dspbuf_client, conf);
416  	
417  			/* Need a reference to the confirmed record for below */
418  			if (conf != NULL) {
419  				/* This is the only point at which we have BOTH an
420  				 * unconfirmed AND confirmed record. found MUST be
421  				 * the unconfirmed record.
422  				 */
423  				inc_client_id_ref(conf);
424  			}
425  		}
426  	
427  		if (conf != NULL && conf->cid_clientid != clientid) {
428  			/* Old confirmed record - need to expire it */
429  			if (isDebug(component)) {
430  				char str[LOG_BUFF_LEN] = "\0";
431  				struct display_buffer dspbuf = {sizeof(str), str, str};
432  	
433  				display_client_id_rec(&dspbuf, conf);
434  				LogDebug(component, "Expiring %s", str);
435  			}
436  	
437  			/* Expire clientid and release our reference.
438  			 * NOTE: found MUST NOT BE conf (otherwise clientid would have
439  			 *       matched).
440  			 */
441  			nfs_client_id_expire(conf, false);
442  			dec_client_id_ref(conf);
443  			conf = NULL;
444  		}
445  	
446  		if (conf != NULL) {
447  			/* At this point we are updating the confirmed
448  			 * clientid.  Update the confirmed record from the
449  			 * unconfirmed record.
450  			 */
451  			display_clientid(&dspbuf_clientid4, conf->cid_clientid);
452  			LogDebug(component,
453  				 "Updating clientid %s->%s cb_program=%u",
454  				 str_clientid4, str_client,
455  				 arg_CREATE_SESSION4->csa_cb_program);
456  	
457  			if (unconf != NULL) {
458  				/* Deal with the ONLY situation where we have both a
459  				 * confirmed and unconfirmed record by unhashing
460  				 * the unconfirmed clientid record
461  				 */
462  				remove_unconfirmed_client_id(unconf);
463  	
464  				/* Release our reference to the unconfirmed entry */
465  				dec_client_id_ref(unconf);
466  	
467  				/* And now to keep code simple, set found to the
468  				 * confirmed record.
469  				 */
470  				found = conf;
471  			}
472  	
473  			if (isDebug(component)) {
474  				char str[LOG_BUFF_LEN] = "\0";
475  				struct display_buffer dspbuf = {sizeof(str), str, str};
476  	
477  				display_client_id_rec(&dspbuf, conf);
478  				LogDebug(component, "Updated %s", str);
479  			}
480  		} else {
481  			/* This is a new clientid */
482  			if (isFullDebug(component)) {
483  				char str[LOG_BUFF_LEN] = "\0";
484  				struct display_buffer dspbuf = {sizeof(str), str, str};
485  	
486  				display_client_id_rec(&dspbuf, unconf);
487  				LogFullDebug(component, "Confirming new %s", str);
488  			}
489  	
490  			rc = nfs_client_id_confirm(unconf, component);
491  	
492  			if (rc != CLIENT_ID_SUCCESS) {
493  				res_CREATE_SESSION4->csr_status =
494  				    clientid_error_to_nfsstat_no_expire(rc);
495  	
496  				/* Need to destroy the session */
497  				if (!nfs41_Session_Del(nfs41_session->session_id))
498  					LogDebug(component,
499  						 "Oops nfs41_Session_Del failed");
500  	
501  				goto out;
502  			}
503  			nfs4_chk_clid(unconf);
504  	
505  			conf = unconf;
506  			unconf = NULL;
507  	
508  			if (isDebug(component)) {
509  				char str[LOG_BUFF_LEN] = "\0";
510  				struct display_buffer dspbuf = {sizeof(str), str, str};
511  	
512  				display_client_id_rec(&dspbuf, conf);
513  				LogDebug(component, "Confirmed %s", str);
514  			}
515  		}
516  		conf->cid_create_session_sequence++;
517  	
518  		/* Bump the lease timer */
519  		conf->cid_last_renew = time(NULL);
520  	
521  		if (isFullDebug(component)) {
522  			char str[LOG_BUFF_LEN] = "\0";
523  			struct display_buffer dspbuf = {sizeof(str), str, str};
524  	
525  			display_client_record(&dspbuf, client_record);
526  			LogFullDebug(component,
527  				     "Client Record %s cr_confirmed_rec=%p cr_unconfirmed_rec=%p",
528  				     str,
529  				     client_record->cr_confirmed_rec,
530  				     client_record->cr_unconfirmed_rec);
531  		}
532  	
533  		/* Handle the creation of the back channel, if the client
534  		   requested one. */
535  		if (arg_CREATE_SESSION4->csa_flags &
536  		    CREATE_SESSION4_FLAG_CONN_BACK_CHAN) {
537  			nfs41_session->cb_program = arg_CREATE_SESSION4->csa_cb_program;
538  			if (nfs_rpc_create_chan_v41(
539  				data->req->rq_xprt, nfs41_session,
540  				arg_CREATE_SESSION4->csa_sec_parms.csa_sec_parms_len,
541  				arg_CREATE_SESSION4->csa_sec_parms.csa_sec_parms_val)
542  			    == 0) {
543  				res_CREATE_SESSION4ok->csr_flags |=
544  				    CREATE_SESSION4_FLAG_CONN_BACK_CHAN;
545  			}
546  		}
547  	
548  		if (isDebug(component)) {
549  			char str[LOG_BUFF_LEN] = "\0";
550  			struct display_buffer dspbuf = {sizeof(str), str, str};
551  	
552  			display_session(&dspbuf, nfs41_session);
553  	
554  			LogDebug(component,
555  				 "success %s csa_flags 0x%X csr_flags 0x%X",
556  				  str, arg_CREATE_SESSION4->csa_flags,
557  				  res_CREATE_SESSION4ok->csr_flags);
558  		}
559  	
560  		/* Successful exit */
561  		res_CREATE_SESSION4->csr_status = NFS4_OK;
562  	
563  		/* Cache response */
564  		/** @todo: Warning, if we ever have ca_rdma_ird_len == 1, we need to be
565  		 *         more careful since there would be allocated memory attached
566  		 *         to the response.
567  		 */
568  		conf->cid_create_session_slot = *res_CREATE_SESSION4;
569  	
570  	 out:
571  	
572  		/* Release our reference to the found record (confirmed or unconfirmed)
573  		 */
574  		dec_client_id_ref(found);
575  	
576  		if (nfs41_session != NULL) {
577  			/* Release our reference to the session */
578  			dec_session_ref(nfs41_session);
579  		}
580  	
581  		PTHREAD_MUTEX_unlock(&client_record->cr_mutex);
582  		/* Release our reference to the client record and return */
583  		dec_client_record_ref(client_record);
584  		return nfsstat4_to_nfs_req_result(res_CREATE_SESSION4->csr_status);
585  	}
586  	
587  	/**
588  	 * @brief free what was allocated to handle nfs41_op_create_session
589  	 *
590  	 * @param[in,out] resp nfs4_op results
591  	 *
592  	 */
593  	void nfs4_op_create_session_Free(nfs_resop4 *resp)
594  	{
595  		/* Nothing to be done */
596  	}
597