1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lnet/selftest/conctl.c
37  *
38  * IOC handle in kernel
39  *
40  * Author: Liang Zhen <liangzhen@clusterfs.com>
41  */
42 
43 #include "../../include/linux/libcfs/libcfs.h"
44 #include "../../include/linux/lnet/lib-lnet.h"
45 #include "../../include/linux/lnet/lnetst.h"
46 #include "console.h"
47 
48 static int
lst_session_new_ioctl(lstio_session_new_args_t * args)49 lst_session_new_ioctl(lstio_session_new_args_t *args)
50 {
51 	char *name;
52 	int rc;
53 
54 	if (args->lstio_ses_idp   == NULL || /* address for output sid */
55 	    args->lstio_ses_key   == 0 ||    /* no key is specified */
56 	    args->lstio_ses_namep == NULL || /* session name */
57 	    args->lstio_ses_nmlen <= 0 ||
58 	    args->lstio_ses_nmlen > LST_NAME_SIZE)
59 		return -EINVAL;
60 
61 	LIBCFS_ALLOC(name, args->lstio_ses_nmlen + 1);
62 	if (name == NULL)
63 		return -ENOMEM;
64 
65 	if (copy_from_user(name,
66 			       args->lstio_ses_namep,
67 			       args->lstio_ses_nmlen)) {
68 		LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
69 		return -EFAULT;
70 	}
71 
72 	name[args->lstio_ses_nmlen] = 0;
73 
74 	rc = lstcon_session_new(name,
75 				args->lstio_ses_key,
76 				args->lstio_ses_feats,
77 				args->lstio_ses_force,
78 				args->lstio_ses_timeout,
79 				args->lstio_ses_idp);
80 
81 	LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
82 	return rc;
83 }
84 
85 static int
lst_session_end_ioctl(lstio_session_end_args_t * args)86 lst_session_end_ioctl(lstio_session_end_args_t *args)
87 {
88 	if (args->lstio_ses_key != console_session.ses_key)
89 		return -EACCES;
90 
91 	return lstcon_session_end();
92 }
93 
94 static int
lst_session_info_ioctl(lstio_session_info_args_t * args)95 lst_session_info_ioctl(lstio_session_info_args_t *args)
96 {
97 	/* no checking of key */
98 
99 	if (args->lstio_ses_idp    == NULL || /* address for output sid */
100 	    args->lstio_ses_keyp   == NULL || /* address for output key */
101 	    args->lstio_ses_featp  == NULL || /* address for output features */
102 	    args->lstio_ses_ndinfo == NULL || /* address for output ndinfo */
103 	    args->lstio_ses_namep  == NULL || /* address for output name */
104 	    args->lstio_ses_nmlen  <= 0 ||
105 	    args->lstio_ses_nmlen > LST_NAME_SIZE)
106 		return -EINVAL;
107 
108 	return lstcon_session_info(args->lstio_ses_idp,
109 				   args->lstio_ses_keyp,
110 				   args->lstio_ses_featp,
111 				   args->lstio_ses_ndinfo,
112 				   args->lstio_ses_namep,
113 				   args->lstio_ses_nmlen);
114 }
115 
116 static int
lst_debug_ioctl(lstio_debug_args_t * args)117 lst_debug_ioctl(lstio_debug_args_t *args)
118 {
119 	char   *name   = NULL;
120 	int     client = 1;
121 	int     rc;
122 
123 	if (args->lstio_dbg_key != console_session.ses_key)
124 		return -EACCES;
125 
126 	if (args->lstio_dbg_resultp == NULL)
127 		return -EINVAL;
128 
129 	if (args->lstio_dbg_namep != NULL && /* name of batch/group */
130 	    (args->lstio_dbg_nmlen <= 0 ||
131 	     args->lstio_dbg_nmlen > LST_NAME_SIZE))
132 		return -EINVAL;
133 
134 	if (args->lstio_dbg_namep != NULL) {
135 		LIBCFS_ALLOC(name, args->lstio_dbg_nmlen + 1);
136 		if (name == NULL)
137 			return -ENOMEM;
138 
139 		if (copy_from_user(name, args->lstio_dbg_namep,
140 				       args->lstio_dbg_nmlen)) {
141 			LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
142 
143 			return -EFAULT;
144 		}
145 
146 		name[args->lstio_dbg_nmlen] = 0;
147 	}
148 
149 	rc = -EINVAL;
150 
151 	switch (args->lstio_dbg_type) {
152 	case LST_OPC_SESSION:
153 		rc = lstcon_session_debug(args->lstio_dbg_timeout,
154 					  args->lstio_dbg_resultp);
155 		break;
156 
157 	case LST_OPC_BATCHSRV:
158 		client = 0;
159 	case LST_OPC_BATCHCLI:
160 		if (name == NULL)
161 			goto out;
162 
163 		rc = lstcon_batch_debug(args->lstio_dbg_timeout,
164 					name, client, args->lstio_dbg_resultp);
165 		break;
166 
167 	case LST_OPC_GROUP:
168 		if (name == NULL)
169 			goto out;
170 
171 		rc = lstcon_group_debug(args->lstio_dbg_timeout,
172 					name, args->lstio_dbg_resultp);
173 		break;
174 
175 	case LST_OPC_NODES:
176 		if (args->lstio_dbg_count <= 0 ||
177 		    args->lstio_dbg_idsp == NULL)
178 			goto out;
179 
180 		rc = lstcon_nodes_debug(args->lstio_dbg_timeout,
181 					args->lstio_dbg_count,
182 					args->lstio_dbg_idsp,
183 					args->lstio_dbg_resultp);
184 		break;
185 
186 	default:
187 		break;
188 	}
189 
190 out:
191 	if (name != NULL)
192 		LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
193 
194 	return rc;
195 }
196 
197 static int
lst_group_add_ioctl(lstio_group_add_args_t * args)198 lst_group_add_ioctl(lstio_group_add_args_t *args)
199 {
200 	char *name;
201 	int rc;
202 
203 	if (args->lstio_grp_key != console_session.ses_key)
204 		return -EACCES;
205 
206 	if (args->lstio_grp_namep == NULL ||
207 	    args->lstio_grp_nmlen <= 0 ||
208 	    args->lstio_grp_nmlen > LST_NAME_SIZE)
209 		return -EINVAL;
210 
211 	LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
212 	if (name == NULL)
213 		return -ENOMEM;
214 
215 	if (copy_from_user(name,
216 			       args->lstio_grp_namep,
217 			       args->lstio_grp_nmlen)) {
218 		LIBCFS_FREE(name, args->lstio_grp_nmlen);
219 		return -EFAULT;
220 	}
221 
222 	name[args->lstio_grp_nmlen] = 0;
223 
224 	rc = lstcon_group_add(name);
225 
226 	LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
227 
228 	return rc;
229 }
230 
231 static int
lst_group_del_ioctl(lstio_group_del_args_t * args)232 lst_group_del_ioctl(lstio_group_del_args_t *args)
233 {
234 	int     rc;
235 	char   *name;
236 
237 	if (args->lstio_grp_key != console_session.ses_key)
238 		return -EACCES;
239 
240 	if (args->lstio_grp_namep == NULL ||
241 	    args->lstio_grp_nmlen <= 0 ||
242 	    args->lstio_grp_nmlen > LST_NAME_SIZE)
243 		return -EINVAL;
244 
245 	LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
246 	if (name == NULL)
247 		return -ENOMEM;
248 
249 	if (copy_from_user(name,
250 			       args->lstio_grp_namep,
251 			       args->lstio_grp_nmlen)) {
252 		LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
253 		return -EFAULT;
254 	}
255 
256 	name[args->lstio_grp_nmlen] = 0;
257 
258 	rc = lstcon_group_del(name);
259 
260 	LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
261 
262 	return rc;
263 }
264 
265 static int
lst_group_update_ioctl(lstio_group_update_args_t * args)266 lst_group_update_ioctl(lstio_group_update_args_t *args)
267 {
268 	int     rc;
269 	char   *name;
270 
271 	if (args->lstio_grp_key != console_session.ses_key)
272 		return -EACCES;
273 
274 	if (args->lstio_grp_resultp == NULL ||
275 	    args->lstio_grp_namep == NULL ||
276 	    args->lstio_grp_nmlen <= 0 ||
277 	    args->lstio_grp_nmlen > LST_NAME_SIZE)
278 		return -EINVAL;
279 
280 	LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
281 	if (name == NULL)
282 		return -ENOMEM;
283 
284 	if (copy_from_user(name,
285 			   args->lstio_grp_namep,
286 			   args->lstio_grp_nmlen)) {
287 		LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
288 		return -EFAULT;
289 	}
290 
291 	name[args->lstio_grp_nmlen] = 0;
292 
293 	switch (args->lstio_grp_opc) {
294 	case LST_GROUP_CLEAN:
295 		rc = lstcon_group_clean(name, args->lstio_grp_args);
296 		break;
297 
298 	case LST_GROUP_REFRESH:
299 		rc = lstcon_group_refresh(name, args->lstio_grp_resultp);
300 		break;
301 
302 	case LST_GROUP_RMND:
303 		if (args->lstio_grp_count  <= 0 ||
304 		    args->lstio_grp_idsp == NULL) {
305 			rc = -EINVAL;
306 			break;
307 		}
308 		rc = lstcon_nodes_remove(name, args->lstio_grp_count,
309 					 args->lstio_grp_idsp,
310 					 args->lstio_grp_resultp);
311 		break;
312 
313 	default:
314 		rc = -EINVAL;
315 		break;
316 	}
317 
318 	LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
319 
320 	return rc;
321 }
322 
323 static int
lst_nodes_add_ioctl(lstio_group_nodes_args_t * args)324 lst_nodes_add_ioctl(lstio_group_nodes_args_t *args)
325 {
326 	unsigned feats;
327 	int rc;
328 	char *name;
329 
330 	if (args->lstio_grp_key != console_session.ses_key)
331 		return -EACCES;
332 
333 	if (args->lstio_grp_idsp == NULL || /* array of ids */
334 	    args->lstio_grp_count <= 0 ||
335 	    args->lstio_grp_resultp == NULL ||
336 	    args->lstio_grp_featp == NULL ||
337 	    args->lstio_grp_namep == NULL ||
338 	    args->lstio_grp_nmlen <= 0 ||
339 	    args->lstio_grp_nmlen > LST_NAME_SIZE)
340 		return -EINVAL;
341 
342 	LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
343 	if (name == NULL)
344 		return -ENOMEM;
345 
346 	if (copy_from_user(name, args->lstio_grp_namep,
347 			       args->lstio_grp_nmlen)) {
348 		LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
349 
350 		return -EFAULT;
351 	}
352 
353 	name[args->lstio_grp_nmlen] = 0;
354 
355 	rc = lstcon_nodes_add(name, args->lstio_grp_count,
356 			      args->lstio_grp_idsp, &feats,
357 			      args->lstio_grp_resultp);
358 
359 	LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
360 	if (rc == 0 &&
361 	    copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) {
362 		return -EINVAL;
363 	}
364 
365 	return rc;
366 }
367 
368 static int
lst_group_list_ioctl(lstio_group_list_args_t * args)369 lst_group_list_ioctl(lstio_group_list_args_t *args)
370 {
371 	if (args->lstio_grp_key != console_session.ses_key)
372 		return -EACCES;
373 
374 	if (args->lstio_grp_idx   < 0 ||
375 	    args->lstio_grp_namep == NULL ||
376 	    args->lstio_grp_nmlen <= 0 ||
377 	    args->lstio_grp_nmlen > LST_NAME_SIZE)
378 		return -EINVAL;
379 
380 	return lstcon_group_list(args->lstio_grp_idx,
381 			      args->lstio_grp_nmlen,
382 			      args->lstio_grp_namep);
383 }
384 
385 static int
lst_group_info_ioctl(lstio_group_info_args_t * args)386 lst_group_info_ioctl(lstio_group_info_args_t *args)
387 {
388 	char *name;
389 	int ndent;
390 	int index;
391 	int rc;
392 
393 	if (args->lstio_grp_key != console_session.ses_key)
394 		return -EACCES;
395 
396 	if (args->lstio_grp_namep == NULL ||
397 	    args->lstio_grp_nmlen <= 0 ||
398 	    args->lstio_grp_nmlen > LST_NAME_SIZE)
399 		return -EINVAL;
400 
401 	if (args->lstio_grp_entp  == NULL && /* output: group entry */
402 	    args->lstio_grp_dentsp == NULL)  /* output: node entry */
403 		return -EINVAL;
404 
405 	if (args->lstio_grp_dentsp != NULL) { /* have node entry */
406 		if (args->lstio_grp_idxp == NULL || /* node index */
407 		    args->lstio_grp_ndentp == NULL) /* # of node entry */
408 			return -EINVAL;
409 
410 		if (copy_from_user(&ndent, args->lstio_grp_ndentp,
411 				       sizeof(ndent)) ||
412 		    copy_from_user(&index, args->lstio_grp_idxp,
413 				       sizeof(index)))
414 			return -EFAULT;
415 
416 		if (ndent <= 0 || index < 0)
417 			return -EINVAL;
418 	}
419 
420 	LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
421 	if (name == NULL)
422 		return -ENOMEM;
423 
424 	if (copy_from_user(name,
425 			       args->lstio_grp_namep,
426 			       args->lstio_grp_nmlen)) {
427 		LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
428 		return -EFAULT;
429 	}
430 
431 	name[args->lstio_grp_nmlen] = 0;
432 
433 	rc = lstcon_group_info(name, args->lstio_grp_entp,
434 			       &index, &ndent, args->lstio_grp_dentsp);
435 
436 	LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
437 
438 	if (rc != 0)
439 		return rc;
440 
441 	if (args->lstio_grp_dentsp != NULL &&
442 	    (copy_to_user(args->lstio_grp_idxp, &index, sizeof(index)) ||
443 	     copy_to_user(args->lstio_grp_ndentp, &ndent, sizeof(ndent))))
444 		return -EFAULT;
445 
446 	return 0;
447 }
448 
449 static int
lst_batch_add_ioctl(lstio_batch_add_args_t * args)450 lst_batch_add_ioctl(lstio_batch_add_args_t *args)
451 {
452 	int rc;
453 	char *name;
454 
455 	if (args->lstio_bat_key != console_session.ses_key)
456 		return -EACCES;
457 
458 	if (args->lstio_bat_namep == NULL ||
459 	    args->lstio_bat_nmlen <= 0 ||
460 	    args->lstio_bat_nmlen > LST_NAME_SIZE)
461 		return -EINVAL;
462 
463 	LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
464 	if (name == NULL)
465 		return -ENOMEM;
466 
467 	if (copy_from_user(name,
468 			       args->lstio_bat_namep,
469 			       args->lstio_bat_nmlen)) {
470 		LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
471 		return -EFAULT;
472 	}
473 
474 	name[args->lstio_bat_nmlen] = 0;
475 
476 	rc = lstcon_batch_add(name);
477 
478 	LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
479 
480 	return rc;
481 }
482 
483 static int
lst_batch_run_ioctl(lstio_batch_run_args_t * args)484 lst_batch_run_ioctl(lstio_batch_run_args_t *args)
485 {
486 	int rc;
487 	char *name;
488 
489 	if (args->lstio_bat_key != console_session.ses_key)
490 		return -EACCES;
491 
492 	if (args->lstio_bat_namep == NULL ||
493 	    args->lstio_bat_nmlen <= 0 ||
494 	    args->lstio_bat_nmlen > LST_NAME_SIZE)
495 		return -EINVAL;
496 
497 	LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
498 	if (name == NULL)
499 		return -ENOMEM;
500 
501 	if (copy_from_user(name,
502 			       args->lstio_bat_namep,
503 			       args->lstio_bat_nmlen)) {
504 		LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
505 		return -EFAULT;
506 	}
507 
508 	name[args->lstio_bat_nmlen] = 0;
509 
510 	rc = lstcon_batch_run(name, args->lstio_bat_timeout,
511 			      args->lstio_bat_resultp);
512 
513 	LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
514 
515 	return rc;
516 }
517 
518 static int
lst_batch_stop_ioctl(lstio_batch_stop_args_t * args)519 lst_batch_stop_ioctl(lstio_batch_stop_args_t *args)
520 {
521 	int rc;
522 	char *name;
523 
524 	if (args->lstio_bat_key != console_session.ses_key)
525 		return -EACCES;
526 
527 	if (args->lstio_bat_resultp == NULL ||
528 	    args->lstio_bat_namep == NULL ||
529 	    args->lstio_bat_nmlen <= 0 ||
530 	    args->lstio_bat_nmlen > LST_NAME_SIZE)
531 		return -EINVAL;
532 
533 	LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
534 	if (name == NULL)
535 		return -ENOMEM;
536 
537 	if (copy_from_user(name,
538 			       args->lstio_bat_namep,
539 			       args->lstio_bat_nmlen)) {
540 		LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
541 		return -EFAULT;
542 	}
543 
544 	name[args->lstio_bat_nmlen] = 0;
545 
546 	rc = lstcon_batch_stop(name, args->lstio_bat_force,
547 			       args->lstio_bat_resultp);
548 
549 	LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
550 
551 	return rc;
552 }
553 
554 static int
lst_batch_query_ioctl(lstio_batch_query_args_t * args)555 lst_batch_query_ioctl(lstio_batch_query_args_t *args)
556 {
557 	char   *name;
558 	int     rc;
559 
560 	if (args->lstio_bat_key != console_session.ses_key)
561 		return -EACCES;
562 
563 	if (args->lstio_bat_resultp == NULL ||
564 	    args->lstio_bat_namep == NULL ||
565 	    args->lstio_bat_nmlen <= 0 ||
566 	    args->lstio_bat_nmlen > LST_NAME_SIZE)
567 		return -EINVAL;
568 
569 	if (args->lstio_bat_testidx < 0)
570 		return -EINVAL;
571 
572 	LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
573 	if (name == NULL)
574 		return -ENOMEM;
575 
576 	if (copy_from_user(name,
577 			       args->lstio_bat_namep,
578 			       args->lstio_bat_nmlen)) {
579 		LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
580 		return -EFAULT;
581 	}
582 
583 	name[args->lstio_bat_nmlen] = 0;
584 
585 	rc = lstcon_test_batch_query(name,
586 				     args->lstio_bat_testidx,
587 				     args->lstio_bat_client,
588 				     args->lstio_bat_timeout,
589 				     args->lstio_bat_resultp);
590 
591 	LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
592 
593 	return rc;
594 }
595 
596 static int
lst_batch_list_ioctl(lstio_batch_list_args_t * args)597 lst_batch_list_ioctl(lstio_batch_list_args_t *args)
598 {
599 	if (args->lstio_bat_key != console_session.ses_key)
600 		return -EACCES;
601 
602 	if (args->lstio_bat_idx   < 0 ||
603 	    args->lstio_bat_namep == NULL ||
604 	    args->lstio_bat_nmlen <= 0 ||
605 	    args->lstio_bat_nmlen > LST_NAME_SIZE)
606 		return -EINVAL;
607 
608 	return lstcon_batch_list(args->lstio_bat_idx,
609 			      args->lstio_bat_nmlen,
610 			      args->lstio_bat_namep);
611 }
612 
613 static int
lst_batch_info_ioctl(lstio_batch_info_args_t * args)614 lst_batch_info_ioctl(lstio_batch_info_args_t *args)
615 {
616 	char *name;
617 	int rc;
618 	int index;
619 	int ndent;
620 
621 	if (args->lstio_bat_key != console_session.ses_key)
622 		return -EACCES;
623 
624 	if (args->lstio_bat_namep == NULL || /* batch name */
625 	    args->lstio_bat_nmlen <= 0 ||
626 	    args->lstio_bat_nmlen > LST_NAME_SIZE)
627 		return -EINVAL;
628 
629 	if (args->lstio_bat_entp == NULL && /* output: batch entry */
630 	    args->lstio_bat_dentsp == NULL) /* output: node entry */
631 		return -EINVAL;
632 
633 	if (args->lstio_bat_dentsp != NULL) { /* have node entry */
634 		if (args->lstio_bat_idxp == NULL || /* node index */
635 		    args->lstio_bat_ndentp == NULL) /* # of node entry */
636 			return -EINVAL;
637 
638 		if (copy_from_user(&index, args->lstio_bat_idxp,
639 				       sizeof(index)) ||
640 		    copy_from_user(&ndent, args->lstio_bat_ndentp,
641 				       sizeof(ndent)))
642 			return -EFAULT;
643 
644 		if (ndent <= 0 || index < 0)
645 			return -EINVAL;
646 	}
647 
648 	LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
649 	if (name == NULL)
650 		return -ENOMEM;
651 
652 	if (copy_from_user(name,
653 			       args->lstio_bat_namep, args->lstio_bat_nmlen)) {
654 		LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
655 		return -EFAULT;
656 	}
657 
658 	name[args->lstio_bat_nmlen] = 0;
659 
660 	rc = lstcon_batch_info(name,
661 			    args->lstio_bat_entp, args->lstio_bat_server,
662 			    args->lstio_bat_testidx, &index, &ndent,
663 			    args->lstio_bat_dentsp);
664 
665 	LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
666 
667 	if (rc != 0)
668 		return rc;
669 
670 	if (args->lstio_bat_dentsp != NULL &&
671 	    (copy_to_user(args->lstio_bat_idxp, &index, sizeof(index)) ||
672 	     copy_to_user(args->lstio_bat_ndentp, &ndent, sizeof(ndent))))
673 		rc = -EFAULT;
674 
675 	return rc;
676 }
677 
678 static int
lst_stat_query_ioctl(lstio_stat_args_t * args)679 lst_stat_query_ioctl(lstio_stat_args_t *args)
680 {
681 	int rc;
682 	char *name;
683 
684 	/* TODO: not finished */
685 	if (args->lstio_sta_key != console_session.ses_key)
686 		return -EACCES;
687 
688 	if (args->lstio_sta_resultp == NULL ||
689 	    (args->lstio_sta_namep  == NULL &&
690 	     args->lstio_sta_idsp   == NULL) ||
691 	    args->lstio_sta_nmlen <= 0 ||
692 	    args->lstio_sta_nmlen > LST_NAME_SIZE)
693 		return -EINVAL;
694 
695 	if (args->lstio_sta_idsp != NULL &&
696 	    args->lstio_sta_count <= 0)
697 		return -EINVAL;
698 
699 	LIBCFS_ALLOC(name, args->lstio_sta_nmlen + 1);
700 	if (name == NULL)
701 		return -ENOMEM;
702 
703 	if (copy_from_user(name, args->lstio_sta_namep,
704 			       args->lstio_sta_nmlen)) {
705 		LIBCFS_FREE(name, args->lstio_sta_nmlen + 1);
706 		return -EFAULT;
707 	}
708 
709 	if (args->lstio_sta_idsp == NULL) {
710 		rc = lstcon_group_stat(name, args->lstio_sta_timeout,
711 				       args->lstio_sta_resultp);
712 	} else {
713 		rc = lstcon_nodes_stat(args->lstio_sta_count,
714 				       args->lstio_sta_idsp,
715 				       args->lstio_sta_timeout,
716 				       args->lstio_sta_resultp);
717 	}
718 
719 	LIBCFS_FREE(name, args->lstio_sta_nmlen + 1);
720 
721 	return rc;
722 }
723 
lst_test_add_ioctl(lstio_test_args_t * args)724 static int lst_test_add_ioctl(lstio_test_args_t *args)
725 {
726 	char		*batch_name;
727 	char		*src_name = NULL;
728 	char		*dst_name = NULL;
729 	void		*param = NULL;
730 	int		ret = 0;
731 	int		rc = -ENOMEM;
732 
733 	if (args->lstio_tes_resultp == NULL ||
734 	    args->lstio_tes_retp == NULL ||
735 	    args->lstio_tes_bat_name == NULL || /* no specified batch */
736 	    args->lstio_tes_bat_nmlen <= 0 ||
737 	    args->lstio_tes_bat_nmlen > LST_NAME_SIZE ||
738 	    args->lstio_tes_sgrp_name == NULL || /* no source group */
739 	    args->lstio_tes_sgrp_nmlen <= 0 ||
740 	    args->lstio_tes_sgrp_nmlen > LST_NAME_SIZE ||
741 	    args->lstio_tes_dgrp_name == NULL || /* no target group */
742 	    args->lstio_tes_dgrp_nmlen <= 0 ||
743 	    args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE)
744 		return -EINVAL;
745 
746 	if (args->lstio_tes_loop == 0 || /* negative is infinite */
747 	    args->lstio_tes_concur <= 0 ||
748 	    args->lstio_tes_dist <= 0 ||
749 	    args->lstio_tes_span <= 0)
750 		return -EINVAL;
751 
752 	/* have parameter, check if parameter length is valid */
753 	if (args->lstio_tes_param != NULL &&
754 	    (args->lstio_tes_param_len <= 0 ||
755 	     args->lstio_tes_param_len > PAGE_CACHE_SIZE - sizeof(lstcon_test_t)))
756 		return -EINVAL;
757 
758 	LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1);
759 	if (batch_name == NULL)
760 		return rc;
761 
762 	LIBCFS_ALLOC(src_name, args->lstio_tes_sgrp_nmlen + 1);
763 	if (src_name == NULL)
764 		goto out;
765 
766 	LIBCFS_ALLOC(dst_name, args->lstio_tes_dgrp_nmlen + 1);
767 	 if (dst_name == NULL)
768 		goto out;
769 
770 	if (args->lstio_tes_param != NULL) {
771 		LIBCFS_ALLOC(param, args->lstio_tes_param_len);
772 		if (param == NULL)
773 			goto out;
774 	}
775 
776 	rc = -EFAULT;
777 	if (copy_from_user(batch_name, args->lstio_tes_bat_name,
778 			   args->lstio_tes_bat_nmlen) ||
779 	    copy_from_user(src_name, args->lstio_tes_sgrp_name,
780 			   args->lstio_tes_sgrp_nmlen) ||
781 	    copy_from_user(dst_name, args->lstio_tes_dgrp_name,
782 			   args->lstio_tes_dgrp_nmlen) ||
783 	    copy_from_user(param, args->lstio_tes_param,
784 			      args->lstio_tes_param_len))
785 		goto out;
786 
787 	rc = lstcon_test_add(batch_name,
788 			    args->lstio_tes_type,
789 			    args->lstio_tes_loop,
790 			    args->lstio_tes_concur,
791 			    args->lstio_tes_dist, args->lstio_tes_span,
792 			    src_name, dst_name, param,
793 			    args->lstio_tes_param_len,
794 			    &ret, args->lstio_tes_resultp);
795 
796 	if (ret != 0)
797 		rc = (copy_to_user(args->lstio_tes_retp, &ret,
798 				       sizeof(ret))) ? -EFAULT : 0;
799 out:
800 	if (batch_name != NULL)
801 		LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1);
802 
803 	if (src_name != NULL)
804 		LIBCFS_FREE(src_name, args->lstio_tes_sgrp_nmlen + 1);
805 
806 	if (dst_name != NULL)
807 		LIBCFS_FREE(dst_name, args->lstio_tes_dgrp_nmlen + 1);
808 
809 	if (param != NULL)
810 		LIBCFS_FREE(param, args->lstio_tes_param_len);
811 
812 	return rc;
813 }
814 
815 int
lstcon_ioctl_entry(unsigned int cmd,struct libcfs_ioctl_data * data)816 lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data)
817 {
818 	char   *buf;
819 	int     opc = data->ioc_u32[0];
820 	int     rc;
821 
822 	if (cmd != IOC_LIBCFS_LNETST)
823 		return -EINVAL;
824 
825 	if (data->ioc_plen1 > PAGE_CACHE_SIZE)
826 		return -EINVAL;
827 
828 	LIBCFS_ALLOC(buf, data->ioc_plen1);
829 	if (buf == NULL)
830 		return -ENOMEM;
831 
832 	/* copy in parameter */
833 	if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
834 		LIBCFS_FREE(buf, data->ioc_plen1);
835 		return -EFAULT;
836 	}
837 
838 	mutex_lock(&console_session.ses_mutex);
839 
840 	console_session.ses_laststamp = ktime_get_real_seconds();
841 
842 	if (console_session.ses_shutdown) {
843 		rc = -ESHUTDOWN;
844 		goto out;
845 	}
846 
847 	if (console_session.ses_expired)
848 		lstcon_session_end();
849 
850 	if (opc != LSTIO_SESSION_NEW &&
851 	    console_session.ses_state == LST_SESSION_NONE) {
852 		CDEBUG(D_NET, "LST no active session\n");
853 		rc = -ESRCH;
854 		goto out;
855 	}
856 
857 	memset(&console_session.ses_trans_stat, 0, sizeof(lstcon_trans_stat_t));
858 
859 	switch (opc) {
860 	case LSTIO_SESSION_NEW:
861 		rc = lst_session_new_ioctl((lstio_session_new_args_t *)buf);
862 		break;
863 	case LSTIO_SESSION_END:
864 		rc = lst_session_end_ioctl((lstio_session_end_args_t *)buf);
865 		break;
866 	case LSTIO_SESSION_INFO:
867 		rc = lst_session_info_ioctl((lstio_session_info_args_t *)buf);
868 		break;
869 	case LSTIO_DEBUG:
870 		rc = lst_debug_ioctl((lstio_debug_args_t *)buf);
871 		break;
872 	case LSTIO_GROUP_ADD:
873 		rc = lst_group_add_ioctl((lstio_group_add_args_t *)buf);
874 		break;
875 	case LSTIO_GROUP_DEL:
876 		rc = lst_group_del_ioctl((lstio_group_del_args_t *)buf);
877 		break;
878 	case LSTIO_GROUP_UPDATE:
879 		rc = lst_group_update_ioctl((lstio_group_update_args_t *)buf);
880 		break;
881 	case LSTIO_NODES_ADD:
882 		rc = lst_nodes_add_ioctl((lstio_group_nodes_args_t *)buf);
883 		break;
884 	case LSTIO_GROUP_LIST:
885 		rc = lst_group_list_ioctl((lstio_group_list_args_t *)buf);
886 		break;
887 	case LSTIO_GROUP_INFO:
888 		rc = lst_group_info_ioctl((lstio_group_info_args_t *)buf);
889 		break;
890 	case LSTIO_BATCH_ADD:
891 		rc = lst_batch_add_ioctl((lstio_batch_add_args_t *)buf);
892 		break;
893 	case LSTIO_BATCH_START:
894 		rc = lst_batch_run_ioctl((lstio_batch_run_args_t *)buf);
895 		break;
896 	case LSTIO_BATCH_STOP:
897 		rc = lst_batch_stop_ioctl((lstio_batch_stop_args_t *)buf);
898 		break;
899 	case LSTIO_BATCH_QUERY:
900 		rc = lst_batch_query_ioctl((lstio_batch_query_args_t *)buf);
901 		break;
902 	case LSTIO_BATCH_LIST:
903 		rc = lst_batch_list_ioctl((lstio_batch_list_args_t *)buf);
904 		break;
905 	case LSTIO_BATCH_INFO:
906 		rc = lst_batch_info_ioctl((lstio_batch_info_args_t *)buf);
907 		break;
908 	case LSTIO_TEST_ADD:
909 		rc = lst_test_add_ioctl((lstio_test_args_t *)buf);
910 		break;
911 	case LSTIO_STAT_QUERY:
912 		rc = lst_stat_query_ioctl((lstio_stat_args_t *)buf);
913 		break;
914 	default:
915 		rc = -EINVAL;
916 	}
917 
918 	if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
919 			     sizeof(lstcon_trans_stat_t)))
920 		rc = -EFAULT;
921 out:
922 	mutex_unlock(&console_session.ses_mutex);
923 
924 	LIBCFS_FREE(buf, data->ioc_plen1);
925 
926 	return rc;
927 }
928 
929 EXPORT_SYMBOL(lstcon_ioctl_entry);
930