Whamcloud - gitweb
185813edcad87da6cf036314198f0698048d2316
[fs/lustre-release.git] / lnet / selftest / conctl.c
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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2014, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  *
31  * lnet/selftest/conctl.c
32  *
33  * IOC handle in kernel
34  *
35  * Author: Liang Zhen <liangzhen@clusterfs.com>
36  */
37
38 #include <libcfs/linux/linux-net.h>
39 #include <libcfs/libcfs.h>
40 #include <lnet/lib-lnet.h>
41 #include "console.h"
42
43 static int
44 lst_debug_ioctl(struct lstio_debug_args *args)
45 {
46         char *name = NULL;
47         int client = 1;
48         int rc;
49
50         if (args->lstio_dbg_key != console_session.ses_key)
51                 return -EACCES;
52
53         if (args->lstio_dbg_resultp == NULL)
54                 return -EINVAL;
55
56         if (args->lstio_dbg_namep != NULL && /* name of batch/group */
57             (args->lstio_dbg_nmlen <= 0 ||
58              args->lstio_dbg_nmlen > LST_NAME_SIZE))
59                 return -EINVAL;
60
61         if (args->lstio_dbg_namep != NULL) {
62                 LIBCFS_ALLOC(name, args->lstio_dbg_nmlen + 1);
63                 if (name == NULL)
64                         return -ENOMEM;
65
66                 if (copy_from_user(name, args->lstio_dbg_namep,
67                                    args->lstio_dbg_nmlen)) {
68                         LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
69
70                         return -EFAULT;
71                 }
72
73                 name[args->lstio_dbg_nmlen] = 0;
74         }
75
76         rc = -EINVAL;
77
78         switch (args->lstio_dbg_type) {
79         case LST_OPC_SESSION:
80                 rc = lstcon_session_debug(args->lstio_dbg_timeout,
81                                           args->lstio_dbg_resultp);
82                 break;
83
84         case LST_OPC_BATCHSRV:
85                 client = 0;
86                 fallthrough;
87         case LST_OPC_BATCHCLI:
88                 if (name == NULL)
89                         goto out;
90
91                 rc = lstcon_batch_debug(args->lstio_dbg_timeout,
92                                         name, client, args->lstio_dbg_resultp);
93                 break;
94
95         case LST_OPC_GROUP:
96                 if (name == NULL)
97                         goto out;
98
99                 rc = lstcon_group_debug(args->lstio_dbg_timeout,
100                                         name, args->lstio_dbg_resultp);
101                 break;
102
103         case LST_OPC_NODES:
104                 if (args->lstio_dbg_count <= 0 ||
105                     args->lstio_dbg_idsp == NULL)
106                         goto out;
107
108                 rc = lstcon_nodes_debug(args->lstio_dbg_timeout,
109                                         args->lstio_dbg_count,
110                                         args->lstio_dbg_idsp,
111                                         args->lstio_dbg_resultp);
112                 break;
113
114         default:
115                 break;
116         }
117
118 out:
119         if (name != NULL)
120                 LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
121
122         return rc;
123 }
124
125 static int
126 lst_group_add_ioctl(struct lstio_group_add_args *args)
127 {
128         char *name;
129         int rc;
130
131         if (args->lstio_grp_key != console_session.ses_key)
132                 return -EACCES;
133
134         if (args->lstio_grp_namep == NULL ||
135             args->lstio_grp_nmlen <= 0 ||
136             args->lstio_grp_nmlen > LST_NAME_SIZE)
137                 return -EINVAL;
138
139         LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
140         if (name == NULL)
141                 return -ENOMEM;
142
143         if (copy_from_user(name, args->lstio_grp_namep,
144                            args->lstio_grp_nmlen)) {
145                 LIBCFS_FREE(name, args->lstio_grp_nmlen);
146                 return -EFAULT;
147         }
148
149         name[args->lstio_grp_nmlen] = 0;
150
151         rc = lstcon_group_add(name);
152
153         LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
154
155         return rc;
156 }
157
158 static int
159 lst_group_del_ioctl(struct lstio_group_del_args *args)
160 {
161         int rc;
162         char *name;
163
164         if (args->lstio_grp_key != console_session.ses_key)
165                 return -EACCES;
166
167         if (args->lstio_grp_namep == NULL ||
168             args->lstio_grp_nmlen <= 0 ||
169             args->lstio_grp_nmlen > LST_NAME_SIZE)
170                 return -EINVAL;
171
172         LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
173         if (name == NULL)
174                 return -ENOMEM;
175
176         if (copy_from_user(name, args->lstio_grp_namep,
177                            args->lstio_grp_nmlen)) {
178                 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
179                 return -EFAULT;
180         }
181
182         name[args->lstio_grp_nmlen] = 0;
183
184         rc = lstcon_group_del(name);
185
186         LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
187
188         return rc;
189 }
190
191 static int
192 lst_group_update_ioctl(struct lstio_group_update_args *args)
193 {
194         int rc;
195         char *name;
196
197         if (args->lstio_grp_key != console_session.ses_key)
198                 return -EACCES;
199
200         if (args->lstio_grp_resultp == NULL ||
201             args->lstio_grp_namep == NULL ||
202             args->lstio_grp_nmlen <= 0 ||
203             args->lstio_grp_nmlen > LST_NAME_SIZE)
204                 return -EINVAL;
205
206         LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
207         if (name == NULL)
208                 return -ENOMEM;
209
210         if (copy_from_user(name, args->lstio_grp_namep,
211                            args->lstio_grp_nmlen)) {
212                 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
213                 return -EFAULT;
214         }
215
216         name[args->lstio_grp_nmlen] = 0;
217
218         switch (args->lstio_grp_opc) {
219         case LST_GROUP_CLEAN:
220                 rc = lstcon_group_clean(name, args->lstio_grp_args);
221                 break;
222
223         case LST_GROUP_REFRESH:
224                 rc = lstcon_group_refresh(name, args->lstio_grp_resultp);
225                 break;
226
227         case LST_GROUP_RMND:
228                 if (args->lstio_grp_count <= 0 ||
229                     args->lstio_grp_idsp == NULL) {
230                         rc = -EINVAL;
231                         break;
232                 }
233                 rc = lstcon_nodes_remove(name, args->lstio_grp_count,
234                                          args->lstio_grp_idsp,
235                                          args->lstio_grp_resultp);
236                 break;
237
238         default:
239                 rc = -EINVAL;
240                 break;
241         }
242
243         LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
244
245         return rc;
246 }
247
248 static int
249 lst_nodes_add_ioctl(struct lstio_group_nodes_args *args)
250 {
251         unsigned int feats;
252         int rc;
253         char *name;
254
255         if (args->lstio_grp_key != console_session.ses_key)
256                 return -EACCES;
257
258         if (args->lstio_grp_idsp == NULL || /* array of ids */
259             args->lstio_grp_count <= 0 ||
260             args->lstio_grp_resultp == NULL ||
261             args->lstio_grp_featp == NULL ||
262             args->lstio_grp_namep == NULL ||
263             args->lstio_grp_nmlen <= 0 ||
264             args->lstio_grp_nmlen > LST_NAME_SIZE)
265                 return -EINVAL;
266
267         LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
268         if (name == NULL)
269                 return -ENOMEM;
270
271         if (copy_from_user(name, args->lstio_grp_namep,
272                            args->lstio_grp_nmlen)) {
273                 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
274
275                 return -EFAULT;
276         }
277
278         name[args->lstio_grp_nmlen] = 0;
279
280         rc = lstcon_nodes_add(name, args->lstio_grp_count,
281                               args->lstio_grp_idsp, &feats,
282                               args->lstio_grp_resultp);
283
284         LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
285         if (rc == 0 &&
286             copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) {
287                 return -EINVAL;
288         }
289
290         return rc;
291 }
292
293 static int
294 lst_group_list_ioctl(struct lstio_group_list_args *args)
295 {
296         if (args->lstio_grp_key != console_session.ses_key)
297                 return -EACCES;
298
299         if (args->lstio_grp_idx   < 0 ||
300             args->lstio_grp_namep == NULL ||
301             args->lstio_grp_nmlen <= 0 ||
302             args->lstio_grp_nmlen > LST_NAME_SIZE)
303                 return -EINVAL;
304
305         return lstcon_group_list(args->lstio_grp_idx,
306                                  args->lstio_grp_nmlen,
307                                  args->lstio_grp_namep);
308 }
309
310 static int
311 lst_group_info_ioctl(struct lstio_group_info_args *args)
312 {
313         char *name;
314         int ndent;
315         int index;
316         int rc;
317
318         if (args->lstio_grp_key != console_session.ses_key)
319                 return -EACCES;
320
321         if (args->lstio_grp_namep == NULL ||
322             args->lstio_grp_nmlen <= 0 ||
323             args->lstio_grp_nmlen > LST_NAME_SIZE)
324                 return -EINVAL;
325
326         if (args->lstio_grp_entp == NULL && /* output: group entry */
327             args->lstio_grp_dentsp == NULL)  /* output: node entry */
328                 return -EINVAL;
329
330         if (args->lstio_grp_dentsp != NULL) { /* have node entry */
331                 if (args->lstio_grp_idxp == NULL || /* node index */
332                     args->lstio_grp_ndentp == NULL) /* # of node entry */
333                         return -EINVAL;
334
335                 if (copy_from_user(&ndent, args->lstio_grp_ndentp,
336                                    sizeof(ndent)) ||
337                     copy_from_user(&index, args->lstio_grp_idxp,
338                                    sizeof(index)))
339                         return -EFAULT;
340
341                 if (ndent <= 0 || index < 0)
342                         return -EINVAL;
343         }
344
345         LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
346         if (name == NULL)
347                 return -ENOMEM;
348
349         if (copy_from_user(name, args->lstio_grp_namep,
350                            args->lstio_grp_nmlen)) {
351                 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
352                 return -EFAULT;
353         }
354
355         name[args->lstio_grp_nmlen] = 0;
356
357         rc = lstcon_group_info(name, args->lstio_grp_entp,
358                                &index, &ndent, args->lstio_grp_dentsp);
359
360         LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
361
362         if (rc != 0)
363                 return rc;
364
365         if (args->lstio_grp_dentsp != NULL &&
366             (copy_to_user(args->lstio_grp_idxp, &index, sizeof(index)) ||
367              copy_to_user(args->lstio_grp_ndentp, &ndent, sizeof(ndent))))
368                 return -EFAULT;
369
370         return 0;
371 }
372
373 static int
374 lst_batch_add_ioctl(struct lstio_batch_add_args *args)
375 {
376         int rc;
377         char *name;
378
379         if (args->lstio_bat_key != console_session.ses_key)
380                 return -EACCES;
381
382         if (args->lstio_bat_namep == NULL ||
383             args->lstio_bat_nmlen <= 0 ||
384             args->lstio_bat_nmlen > LST_NAME_SIZE)
385                 return -EINVAL;
386
387         LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
388         if (name == NULL)
389                 return -ENOMEM;
390
391         if (copy_from_user(name, args->lstio_bat_namep,
392                            args->lstio_bat_nmlen)) {
393                 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
394                 return -EFAULT;
395         }
396
397         name[args->lstio_bat_nmlen] = 0;
398
399         rc = lstcon_batch_add(name);
400
401         LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
402
403         return rc;
404 }
405
406 static int
407 lst_batch_run_ioctl(struct lstio_batch_run_args *args)
408 {
409         int rc;
410         char *name;
411
412         if (args->lstio_bat_key != console_session.ses_key)
413                 return -EACCES;
414
415         if (args->lstio_bat_namep == NULL ||
416             args->lstio_bat_nmlen <= 0 ||
417             args->lstio_bat_nmlen > LST_NAME_SIZE)
418                 return -EINVAL;
419
420         LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
421         if (name == NULL)
422                 return -ENOMEM;
423
424         if (copy_from_user(name, args->lstio_bat_namep,
425                            args->lstio_bat_nmlen)) {
426                 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
427                 return -EFAULT;
428         }
429
430         name[args->lstio_bat_nmlen] = 0;
431
432         rc = lstcon_batch_run(name, args->lstio_bat_timeout,
433                               args->lstio_bat_resultp);
434
435         LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
436
437         return rc;
438 }
439
440 static int
441 lst_batch_stop_ioctl(struct lstio_batch_stop_args *args)
442 {
443         int rc;
444         char *name;
445
446         if (args->lstio_bat_key != console_session.ses_key)
447                 return -EACCES;
448
449         if (args->lstio_bat_resultp == NULL ||
450             args->lstio_bat_namep == NULL ||
451             args->lstio_bat_nmlen <= 0 ||
452             args->lstio_bat_nmlen > LST_NAME_SIZE)
453                 return -EINVAL;
454
455         LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
456         if (name == NULL)
457                 return -ENOMEM;
458
459         if (copy_from_user(name, args->lstio_bat_namep,
460                            args->lstio_bat_nmlen)) {
461                 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
462                 return -EFAULT;
463         }
464
465         name[args->lstio_bat_nmlen] = 0;
466
467         rc = lstcon_batch_stop(name, args->lstio_bat_force,
468                                args->lstio_bat_resultp);
469
470         LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
471
472         return rc;
473 }
474
475 static int
476 lst_batch_query_ioctl(struct lstio_batch_query_args *args)
477 {
478         char *name;
479         int rc;
480
481         if (args->lstio_bat_key != console_session.ses_key)
482                 return -EACCES;
483
484         if (args->lstio_bat_resultp == NULL ||
485             args->lstio_bat_namep == NULL ||
486             args->lstio_bat_nmlen <= 0 ||
487             args->lstio_bat_nmlen > LST_NAME_SIZE)
488                 return -EINVAL;
489
490         if (args->lstio_bat_testidx < 0)
491                 return -EINVAL;
492
493         LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
494         if (name == NULL)
495                 return -ENOMEM;
496
497         if (copy_from_user(name, args->lstio_bat_namep,
498                            args->lstio_bat_nmlen)) {
499                 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
500                 return -EFAULT;
501         }
502
503         name[args->lstio_bat_nmlen] = 0;
504
505         rc = lstcon_test_batch_query(name,
506                                      args->lstio_bat_testidx,
507                                      args->lstio_bat_client,
508                                      args->lstio_bat_timeout,
509                                      args->lstio_bat_resultp);
510
511         LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
512
513         return rc;
514 }
515
516 static int
517 lst_batch_list_ioctl(struct lstio_batch_list_args *args)
518 {
519         if (args->lstio_bat_key != console_session.ses_key)
520                 return -EACCES;
521
522         if (args->lstio_bat_idx < 0 ||
523             args->lstio_bat_namep == NULL ||
524             args->lstio_bat_nmlen <= 0 ||
525             args->lstio_bat_nmlen > LST_NAME_SIZE)
526                 return -EINVAL;
527
528         return lstcon_batch_list(args->lstio_bat_idx,
529                                  args->lstio_bat_nmlen,
530                                  args->lstio_bat_namep);
531 }
532
533 static int
534 lst_batch_info_ioctl(struct lstio_batch_info_args *args)
535 {
536         char *name;
537         int rc;
538         int index;
539         int ndent;
540
541         if (args->lstio_bat_key != console_session.ses_key)
542                 return -EACCES;
543
544         if (args->lstio_bat_namep == NULL || /* batch name */
545             args->lstio_bat_nmlen <= 0 ||
546             args->lstio_bat_nmlen > LST_NAME_SIZE)
547                 return -EINVAL;
548
549         if (args->lstio_bat_entp == NULL && /* output: batch entry */
550             args->lstio_bat_dentsp == NULL) /* output: node entry */
551                 return -EINVAL;
552
553         if (args->lstio_bat_dentsp != NULL) { /* have node entry */
554                 if (args->lstio_bat_idxp == NULL || /* node index */
555                     args->lstio_bat_ndentp == NULL) /* # of node entry */
556                         return -EINVAL;
557
558                 if (copy_from_user(&index, args->lstio_bat_idxp,
559                                    sizeof(index)) ||
560                     copy_from_user(&ndent, args->lstio_bat_ndentp,
561                                    sizeof(ndent)))
562                         return -EFAULT;
563
564                 if (ndent <= 0 || index < 0)
565                         return -EINVAL;
566         }
567
568         LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
569         if (name == NULL)
570                 return -ENOMEM;
571
572         if (copy_from_user(name, args->lstio_bat_namep,
573                            args->lstio_bat_nmlen)) {
574                 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
575                 return -EFAULT;
576         }
577
578         name[args->lstio_bat_nmlen] = 0;
579
580         rc = lstcon_batch_info(name,
581                                args->lstio_bat_entp, args->lstio_bat_server,
582                                args->lstio_bat_testidx, &index, &ndent,
583                                args->lstio_bat_dentsp);
584
585         LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
586
587         if (rc != 0)
588                 return rc;
589
590         if (args->lstio_bat_dentsp != NULL &&
591             (copy_to_user(args->lstio_bat_idxp, &index, sizeof(index)) ||
592              copy_to_user(args->lstio_bat_ndentp, &ndent, sizeof(ndent))))
593                 rc = -EFAULT;
594
595         return rc;
596 }
597
598 static int
599 lst_stat_query_ioctl(struct lstio_stat_args *args)
600 {
601         int rc;
602         char *name = NULL;
603
604         /* TODO: not finished */
605         if (args->lstio_sta_key != console_session.ses_key)
606                 return -EACCES;
607
608         if (args->lstio_sta_resultp == NULL)
609                 return -EINVAL;
610
611         if (args->lstio_sta_idsp != NULL) {
612                 if (args->lstio_sta_count <= 0)
613                         return -EINVAL;
614
615                 rc = lstcon_nodes_stat(args->lstio_sta_count,
616                                        args->lstio_sta_idsp,
617                                        args->lstio_sta_timeout,
618                                        args->lstio_sta_resultp);
619         } else if (args->lstio_sta_namep != NULL) {
620                 if (args->lstio_sta_nmlen <= 0 ||
621                     args->lstio_sta_nmlen > LST_NAME_SIZE)
622                         return -EINVAL;
623
624                 LIBCFS_ALLOC(name, args->lstio_sta_nmlen + 1);
625                 if (name == NULL)
626                         return -ENOMEM;
627
628                 rc = copy_from_user(name, args->lstio_sta_namep,
629                                     args->lstio_sta_nmlen);
630                 if (rc == 0)
631                         rc = lstcon_group_stat(name, args->lstio_sta_timeout,
632                                                args->lstio_sta_resultp);
633                 else
634                         rc = -EFAULT;
635
636         } else {
637                 rc = -EINVAL;
638         }
639
640         if (name != NULL)
641                 LIBCFS_FREE(name, args->lstio_sta_nmlen + 1);
642         return rc;
643 }
644
645 static int lst_test_add_ioctl(struct lstio_test_args *args)
646 {
647         char *batch_name;
648         char *src_name = NULL;
649         char *dst_name = NULL;
650         void *param = NULL;
651         int ret = 0;
652         int rc = -ENOMEM;
653
654         if (args->lstio_tes_resultp == NULL ||
655             args->lstio_tes_retp == NULL ||
656             args->lstio_tes_bat_name == NULL || /* no specified batch */
657             args->lstio_tes_bat_nmlen <= 0 ||
658             args->lstio_tes_bat_nmlen > LST_NAME_SIZE ||
659             args->lstio_tes_sgrp_name == NULL || /* no source group */
660             args->lstio_tes_sgrp_nmlen <= 0 ||
661             args->lstio_tes_sgrp_nmlen > LST_NAME_SIZE ||
662             args->lstio_tes_dgrp_name == NULL || /* no target group */
663             args->lstio_tes_dgrp_nmlen <= 0 ||
664             args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE)
665                 return -EINVAL;
666
667         if (args->lstio_tes_loop == 0 || /* negative is infinite */
668             args->lstio_tes_concur <= 0 ||
669             args->lstio_tes_dist <= 0 ||
670             args->lstio_tes_span <= 0)
671                 return -EINVAL;
672
673         /* have parameter, check if parameter length is valid */
674         if (args->lstio_tes_param != NULL &&
675             (args->lstio_tes_param_len <= 0 ||
676              args->lstio_tes_param_len >
677              PAGE_SIZE - sizeof(struct lstcon_test)))
678                 return -EINVAL;
679
680         LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1);
681         if (batch_name == NULL)
682                 return rc;
683
684         LIBCFS_ALLOC(src_name, args->lstio_tes_sgrp_nmlen + 1);
685         if (src_name == NULL)
686                 goto out;
687
688         LIBCFS_ALLOC(dst_name, args->lstio_tes_dgrp_nmlen + 1);
689         if (dst_name == NULL)
690                 goto out;
691
692         if (args->lstio_tes_param != NULL) {
693                 LIBCFS_ALLOC(param, args->lstio_tes_param_len);
694                 if (param == NULL)
695                         goto out;
696                 if (copy_from_user(param, args->lstio_tes_param,
697                                    args->lstio_tes_param_len)) {
698                         rc = -EFAULT;
699                         goto out;
700                 }
701         }
702
703         rc = -EFAULT;
704         if (copy_from_user(batch_name, args->lstio_tes_bat_name,
705                            args->lstio_tes_bat_nmlen) ||
706             copy_from_user(src_name, args->lstio_tes_sgrp_name,
707                            args->lstio_tes_sgrp_nmlen) ||
708             copy_from_user(dst_name, args->lstio_tes_dgrp_name,
709                            args->lstio_tes_dgrp_nmlen))
710                 goto out;
711
712         rc = lstcon_test_add(batch_name,
713                              args->lstio_tes_type,
714                              args->lstio_tes_loop,
715                              args->lstio_tes_concur,
716                              args->lstio_tes_dist, args->lstio_tes_span,
717                              src_name, dst_name, param,
718                              args->lstio_tes_param_len,
719                              &ret, args->lstio_tes_resultp);
720
721         if (ret != 0)
722                 rc = (copy_to_user(args->lstio_tes_retp, &ret,
723                                    sizeof(ret))) ? -EFAULT : 0;
724 out:
725         if (batch_name != NULL)
726                 LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1);
727
728         if (src_name != NULL)
729                 LIBCFS_FREE(src_name, args->lstio_tes_sgrp_nmlen + 1);
730
731         if (dst_name != NULL)
732                 LIBCFS_FREE(dst_name, args->lstio_tes_dgrp_nmlen + 1);
733
734         if (param != NULL)
735                 LIBCFS_FREE(param, args->lstio_tes_param_len);
736
737         return rc;
738 }
739
740 int
741 lstcon_ioctl_entry(struct notifier_block *nb,
742                    unsigned long cmd, void *vdata)
743 {
744         struct libcfs_ioctl_hdr *hdr = vdata;
745         struct libcfs_ioctl_data *data;
746         char *buf = NULL;
747         int rc = -EINVAL;
748         int opc;
749
750         if (cmd != IOC_LIBCFS_LNETST)
751                 goto err;
752
753         data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
754
755         opc = data->ioc_u32[0];
756
757         if (data->ioc_plen1 > PAGE_SIZE)
758                 goto err;
759
760         LIBCFS_ALLOC(buf, data->ioc_plen1);
761         if (buf == NULL) {
762                 rc = -ENOMEM;
763                 goto err;
764         }
765
766         /* copy in parameter */
767         if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
768                 rc = -EFAULT;
769                 goto out_free_buf;
770         }
771
772         mutex_lock(&console_session.ses_mutex);
773
774         console_session.ses_laststamp = ktime_get_real_seconds();
775
776         if (console_session.ses_shutdown) {
777                 rc = -ESHUTDOWN;
778                 goto out;
779         }
780
781         if (console_session.ses_expired)
782                 lstcon_session_end();
783
784         if (opc != LSTIO_SESSION_NEW &&
785             console_session.ses_state == LST_SESSION_NONE) {
786                 CDEBUG(D_NET, "LST no active session\n");
787                 rc = -ESRCH;
788                 goto out;
789         }
790
791         memset(&console_session.ses_trans_stat, 0,
792                sizeof(struct lstcon_trans_stat));
793
794         switch (opc) {
795         case LSTIO_SESSION_NEW:
796                 fallthrough;
797         case LSTIO_SESSION_END:
798                 fallthrough;
799         case LSTIO_SESSION_INFO:
800                 rc = -EOPNOTSUPP;
801                 break;
802         case LSTIO_DEBUG:
803                 rc = lst_debug_ioctl((struct lstio_debug_args *)buf);
804                 break;
805         case LSTIO_GROUP_ADD:
806                 rc = lst_group_add_ioctl((struct lstio_group_add_args *)buf);
807                 break;
808         case LSTIO_GROUP_DEL:
809                 rc = lst_group_del_ioctl((struct lstio_group_del_args *)buf);
810                 break;
811         case LSTIO_GROUP_UPDATE:
812                 rc = lst_group_update_ioctl((struct lstio_group_update_args *)buf);
813                 break;
814         case LSTIO_NODES_ADD:
815                 rc = lst_nodes_add_ioctl((struct lstio_group_nodes_args *)buf);
816                 break;
817         case LSTIO_GROUP_LIST:
818                 rc = lst_group_list_ioctl((struct lstio_group_list_args *)buf);
819                 break;
820         case LSTIO_GROUP_INFO:
821                 rc = lst_group_info_ioctl((struct lstio_group_info_args *)buf);
822                 break;
823         case LSTIO_BATCH_ADD:
824                 rc = lst_batch_add_ioctl((struct lstio_batch_add_args *)buf);
825                 break;
826         case LSTIO_BATCH_START:
827                 rc = lst_batch_run_ioctl((struct lstio_batch_run_args *)buf);
828                 break;
829         case LSTIO_BATCH_STOP:
830                 rc = lst_batch_stop_ioctl((struct lstio_batch_stop_args *)buf);
831                 break;
832         case LSTIO_BATCH_QUERY:
833                 rc = lst_batch_query_ioctl((struct lstio_batch_query_args *)buf);
834                 break;
835         case LSTIO_BATCH_LIST:
836                 rc = lst_batch_list_ioctl((struct lstio_batch_list_args *)buf);
837                 break;
838         case LSTIO_BATCH_INFO:
839                 rc = lst_batch_info_ioctl((struct lstio_batch_info_args *)buf);
840                 break;
841         case LSTIO_TEST_ADD:
842                 rc = lst_test_add_ioctl((struct lstio_test_args *)buf);
843                 break;
844         case LSTIO_STAT_QUERY:
845                 rc = lst_stat_query_ioctl((struct lstio_stat_args *)buf);
846                 break;
847         default:
848                 rc = -EINVAL;
849                 goto out;
850         }
851
852         if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
853                          sizeof(struct lstcon_trans_stat)))
854                 rc = -EFAULT;
855 out:
856         mutex_unlock(&console_session.ses_mutex);
857 out_free_buf:
858         LIBCFS_FREE(buf, data->ioc_plen1);
859 err:
860         return notifier_from_ioctl_errno(rc);
861 }
862
863 static struct genl_family lst_family;
864
865 static const struct ln_key_list lst_session_keys = {
866         .lkl_maxattr                    = LNET_SELFTEST_SESSION_MAX,
867         .lkl_list                       = {
868                 [LNET_SELFTEST_SESSION_HDR]     = {
869                         .lkp_value              = "session",
870                         .lkp_key_format         = LNKF_MAPPING,
871                         .lkp_data_type          = NLA_NUL_STRING,
872                 },
873                 [LNET_SELFTEST_SESSION_NAME]    = {
874                         .lkp_value              = "name",
875                         .lkp_data_type          = NLA_STRING,
876                 },
877                 [LNET_SELFTEST_SESSION_KEY]     = {
878                         .lkp_value              = "key",
879                         .lkp_data_type          = NLA_U32,
880                 },
881                 [LNET_SELFTEST_SESSION_TIMESTAMP] = {
882                         .lkp_value              = "timestamp",
883                         .lkp_data_type          = NLA_S64,
884                 },
885                 [LNET_SELFTEST_SESSION_NID]     = {
886                         .lkp_value              = "nid",
887                         .lkp_data_type          = NLA_STRING,
888                 },
889                 [LNET_SELFTEST_SESSION_NODE_COUNT] = {
890                         .lkp_value              = "nodes",
891                         .lkp_data_type          = NLA_U16,
892                 },
893         },
894 };
895
896 static int lst_sessions_show_dump(struct sk_buff *msg,
897                                   struct netlink_callback *cb)
898 {
899         const struct ln_key_list *all[] = {
900                 &lst_session_keys, NULL
901         };
902 #ifdef HAVE_NL_PARSE_WITH_EXT_ACK
903         struct netlink_ext_ack *extack = NULL;
904 #endif
905         int portid = NETLINK_CB(cb->skb).portid;
906         int seq = cb->nlh->nlmsg_seq;
907         unsigned int node_count = 0;
908         struct lstcon_ndlink *ndl;
909         int flag = NLM_F_MULTI;
910         int rc = 0;
911         void *hdr;
912
913 #ifdef HAVE_NL_DUMP_WITH_EXT_ACK
914         extack = cb->extack;
915 #endif
916         if (console_session.ses_state != LST_SESSION_ACTIVE) {
917                 NL_SET_ERR_MSG(extack, "session is not active");
918                 GOTO(out_unlock, rc = -ESRCH);
919         }
920
921         list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
922                 node_count++;
923
924         rc = lnet_genl_send_scalar_list(msg, portid, seq, &lst_family,
925                                         NLM_F_CREATE | NLM_F_MULTI,
926                                         LNET_SELFTEST_CMD_SESSIONS, all);
927         if (rc < 0) {
928                 NL_SET_ERR_MSG(extack, "failed to send key table");
929                 GOTO(out_unlock, rc);
930         }
931
932         if (console_session.ses_force)
933                 flag |= NLM_F_REPLACE;
934
935         hdr = genlmsg_put(msg, portid, seq, &lst_family, flag,
936                           LNET_SELFTEST_CMD_SESSIONS);
937         if (!hdr) {
938                 NL_SET_ERR_MSG(extack, "failed to send values");
939                 genlmsg_cancel(msg, hdr);
940                 GOTO(out_unlock, rc = -EMSGSIZE);
941         }
942
943         nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
944                        console_session.ses_name);
945         nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
946                     console_session.ses_key);
947         nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
948                           console_session.ses_id.ses_stamp,
949                           LNET_SELFTEST_SESSION_PAD);
950         nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
951                        libcfs_nidstr(&console_session.ses_id.ses_nid));
952         nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT,
953                     node_count);
954         genlmsg_end(msg, hdr);
955 out_unlock:
956         return lnet_nl_send_error(cb->skb, portid, seq, rc);
957 }
958
959 static int lst_sessions_cmd(struct sk_buff *skb, struct genl_info *info)
960 {
961         struct sk_buff *msg = NULL;
962         int rc = 0;
963
964         mutex_lock(&console_session.ses_mutex);
965
966         console_session.ses_laststamp = ktime_get_real_seconds();
967
968         if (console_session.ses_shutdown) {
969                 GENL_SET_ERR_MSG(info, "session is shutdown");
970                 GOTO(out_unlock, rc = -ESHUTDOWN);
971         }
972
973         if (console_session.ses_expired)
974                 lstcon_session_end();
975
976         if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE) &&
977             console_session.ses_state == LST_SESSION_NONE) {
978                 GENL_SET_ERR_MSG(info, "session is not active");
979                 GOTO(out_unlock, rc = -ESRCH);
980         }
981
982         memset(&console_session.ses_trans_stat, 0,
983                sizeof(struct lstcon_trans_stat));
984
985         if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE)) {
986                 lstcon_session_end();
987                 GOTO(out_unlock, rc);
988         }
989
990         if (info->attrs[LN_SCALAR_ATTR_LIST]) {
991                 struct genlmsghdr *gnlh = nlmsg_data(info->nlhdr);
992                 const struct ln_key_list *all[] = {
993                         &lst_session_keys, NULL
994                 };
995                 char name[LST_NAME_SIZE];
996                 struct nlmsghdr *nlh;
997                 struct nlattr *item;
998                 bool force = false;
999                 s64 timeout = 300;
1000                 void *hdr;
1001                 int rem;
1002
1003                 if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
1004                         force = true;
1005
1006                 nla_for_each_nested(item, info->attrs[LN_SCALAR_ATTR_LIST],
1007                                     rem) {
1008                         if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
1009                                 continue;
1010
1011                         if (nla_strcmp(item, "name") == 0) {
1012                                 ssize_t len;
1013
1014                                 item = nla_next(item, &rem);
1015                                 if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
1016                                         GOTO(err_conf, rc = -EINVAL);
1017
1018                                 len = nla_strscpy(name, item, sizeof(name));
1019                                 if (len < 0)
1020                                         rc = len;
1021                         } else if (nla_strcmp(item, "timeout") == 0) {
1022                                 item = nla_next(item, &rem);
1023                                 if (nla_type(item) !=
1024                                     LN_SCALAR_ATTR_INT_VALUE)
1025                                         GOTO(err_conf, rc = -EINVAL);
1026
1027                                 timeout = nla_get_s64(item);
1028                                 if (timeout < 0)
1029                                         rc = -ERANGE;
1030                         }
1031                         if (rc < 0) {
1032 err_conf:
1033                                 GENL_SET_ERR_MSG(info,
1034                                                  "failed to get config");
1035                                 GOTO(out_unlock, rc);
1036                         }
1037                 }
1038
1039                 rc = lstcon_session_new(name, info->nlhdr->nlmsg_pid,
1040                                         gnlh->version, timeout,
1041                                         force);
1042                 if (rc < 0) {
1043                         GENL_SET_ERR_MSG(info, "new session creation failed");
1044                         lstcon_session_end();
1045                         GOTO(out_unlock, rc);
1046                 }
1047
1048                 msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1049                 if (!msg) {
1050                         GENL_SET_ERR_MSG(info, "msg allocation failed");
1051                         GOTO(out_unlock, rc = -ENOMEM);
1052                 }
1053
1054                 rc = lnet_genl_send_scalar_list(msg, info->snd_portid,
1055                                                 info->snd_seq, &lst_family,
1056                                                 NLM_F_CREATE | NLM_F_MULTI,
1057                                                 LNET_SELFTEST_CMD_SESSIONS,
1058                                                 all);
1059                 if (rc < 0) {
1060                         GENL_SET_ERR_MSG(info, "failed to send key table");
1061                         GOTO(out_unlock, rc);
1062                 }
1063
1064                 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
1065                                   &lst_family, NLM_F_MULTI,
1066                                   LNET_SELFTEST_CMD_SESSIONS);
1067                 if (!hdr) {
1068                         GENL_SET_ERR_MSG(info, "failed to send values");
1069                         genlmsg_cancel(msg, hdr);
1070                         GOTO(out_unlock, rc = -EMSGSIZE);
1071                 }
1072
1073                 nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
1074                                console_session.ses_name);
1075                 nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
1076                             console_session.ses_key);
1077                 nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
1078                                   console_session.ses_id.ses_stamp,
1079                                   LNET_SELFTEST_SESSION_PAD);
1080                 nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
1081                                libcfs_nidstr(&console_session.ses_id.ses_nid));
1082                 nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT, 0);
1083
1084                 genlmsg_end(msg, hdr);
1085
1086                 nlh = nlmsg_put(msg, info->snd_portid, info->snd_seq,
1087                                 NLMSG_DONE, 0, NLM_F_MULTI);
1088                 if (!nlh) {
1089                         GENL_SET_ERR_MSG(info, "failed to complete message");
1090                         genlmsg_cancel(msg, hdr);
1091                         GOTO(out_unlock, rc = -ENOMEM);
1092                 }
1093                 rc = genlmsg_reply(msg, info);
1094                 if (rc)
1095                         GENL_SET_ERR_MSG(info, "failed to send reply");
1096         }
1097 out_unlock:
1098         if (rc < 0 && msg)
1099                 nlmsg_free(msg);
1100         mutex_unlock(&console_session.ses_mutex);
1101         return rc;
1102 }
1103
1104 static const struct genl_multicast_group lst_mcast_grps[] = {
1105         { .name = "sessions",           },
1106 };
1107
1108 static const struct genl_ops lst_genl_ops[] = {
1109         {
1110                 .cmd            = LNET_SELFTEST_CMD_SESSIONS,
1111                 .dumpit         = lst_sessions_show_dump,
1112                 .doit           = lst_sessions_cmd,
1113         },
1114 };
1115
1116 static struct genl_family lst_family = {
1117         .name           = LNET_SELFTEST_GENL_NAME,
1118         .version        = LNET_SELFTEST_GENL_VERSION,
1119         .maxattr        = LN_SCALAR_MAX,
1120         .module         = THIS_MODULE,
1121         .ops            = lst_genl_ops,
1122         .n_ops          = ARRAY_SIZE(lst_genl_ops),
1123         .mcgrps         = lst_mcast_grps,
1124         .n_mcgrps       = ARRAY_SIZE(lst_mcast_grps),
1125 };
1126
1127 int lstcon_init_netlink(void)
1128 {
1129         return genl_register_family(&lst_family);
1130 }
1131
1132 void lstcon_fini_netlink(void)
1133 {
1134         genl_unregister_family(&lst_family);
1135 }