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
48int
49lst_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
85int
86lst_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
94int
95lst_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
116int
117lst_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
190out:
191	if (name != NULL)
192		LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
193
194	return rc;
195}
196
197int
198lst_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
231int
232lst_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
265int
266lst_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
323int
324lst_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
368int
369lst_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
385int
386lst_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		rc = -EFAULT;
445
446	return 0;
447}
448
449int
450lst_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
483int
484lst_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
518int
519lst_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
554int
555lst_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
596int
597lst_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
613int
614lst_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
678int
679lst_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
724int 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;
799out:
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
815int
816lstcon_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 = get_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;
921out:
922	mutex_unlock(&console_session.ses_mutex);
923
924	LIBCFS_FREE(buf, data->ioc_plen1);
925
926	return rc;
927}
928
929EXPORT_SYMBOL(lstcon_ioctl_entry);
930