ba2b166f9986d4c8bd3282cadbe47322a7eb8012
[mirror/scst/.git] / scst / src / scst_sysfs.c
1 /*
2  *  scst_sysfs.c
3  *
4  *  Copyright (C) 2009 Daniel Henrique Debonzi <debonzi@linux.vnet.ibm.com>
5  *  Copyright (C) 2009 Vladislav Bolkhovitin <vst@vlnb.net>
6  *  Copyright (C) 2009 ID7 Ltd.
7  *
8  *  This program is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU General Public License
10  *  as published by the Free Software Foundation, version 2
11  *  of the License.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  *  GNU General Public License for more details.
17  */
18
19 #include <linux/kobject.h>
20 #include <linux/string.h>
21 #include <linux/sysfs.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/ctype.h>
25
26 #include "scst.h"
27 #include "scst_priv.h"
28 #include "scst_mem.h"
29
30 static DEFINE_MUTEX(scst_sysfs_mutex);
31
32 static DECLARE_COMPLETION(scst_sysfs_root_release_completion);
33
34 static struct kobject scst_sysfs_root_kobj;
35 static struct kobject *scst_targets_kobj;
36 static struct kobject *scst_devices_kobj;
37 static struct kobject *scst_sgv_kobj;
38 static struct kobject *scst_handlers_kobj;
39
40 struct sysfs_ops scst_sysfs_ops;
41 EXPORT_SYMBOL(scst_sysfs_ops);
42
43 static const char *scst_dev_handler_types[] =
44 {
45     "Direct-access device (e.g., magnetic disk)",
46     "Sequential-access device (e.g., magnetic tape)",
47     "Printer device",
48     "Processor device",
49     "Write-once device (e.g., some optical disks)",
50     "CD-ROM device",
51     "Scanner device (obsolete)",
52     "Optical memory device (e.g., some optical disks)",
53     "Medium changer device (e.g., jukeboxes)",
54     "Communications device (obsolete)",
55     "Defined by ASC IT8 (Graphic arts pre-press devices)",
56     "Defined by ASC IT8 (Graphic arts pre-press devices)",
57     "Storage array controller device (e.g., RAID)",
58     "Enclosure services device",
59     "Simplified direct-access device (e.g., magnetic disk)",
60     "Optical card reader/writer device"
61 };
62
63 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
64
65 static DEFINE_MUTEX(scst_log_mutex);
66
67 static struct scst_trace_log scst_trace_tbl[] =
68 {
69     { TRACE_OUT_OF_MEM,         "out_of_mem" },
70     { TRACE_MINOR,              "minor" },
71     { TRACE_SG_OP,              "sg" },
72     { TRACE_MEMORY,             "mem" },
73     { TRACE_BUFF,               "buff" },
74 #ifndef GENERATING_UPSTREAM_PATCH
75     { TRACE_ENTRYEXIT,          "entryexit" },
76 #endif
77     { TRACE_PID,                "pid" },
78     { TRACE_LINE,               "line" },
79     { TRACE_FUNCTION,           "function" },
80     { TRACE_DEBUG,              "debug" },
81     { TRACE_SPECIAL,            "special" },
82     { TRACE_SCSI,               "scsi" },
83     { TRACE_MGMT,               "mgmt" },
84     { TRACE_MGMT_MINOR,         "mgmt_minor" },
85     { TRACE_MGMT_DEBUG,         "mgmt_dbg" },
86     { 0,                        NULL }
87 };
88
89 static struct scst_trace_log scst_local_trace_tbl[] =
90 {
91     { TRACE_RTRY,               "retry" },
92     { TRACE_SCSI_SERIALIZING,   "scsi_serializing" },
93     { TRACE_RCV_BOT,            "recv_bot" },
94     { TRACE_SND_BOT,            "send_bot" },
95     { TRACE_RCV_TOP,            "recv_top" },
96     { TRACE_SND_TOP,            "send_top" },
97     { 0,                        NULL }
98 };
99
100 static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
101         unsigned long log_level, char *buf, const char *help);
102 static int scst_write_trace(const char *buf, size_t length,
103         unsigned long *log_level, unsigned long default_level,
104         const char *name, const struct scst_trace_log *tbl);
105
106 #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
107
108 static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
109                                    struct kobj_attribute *attr,
110                                    char *buf);
111 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
112                                     struct kobj_attribute *attr,
113                                     const char *buf, size_t count);
114
115 static void scst_sysfs_release(struct kobject *kobj)
116 {
117         kfree(kobj);
118 }
119
120 /*
121  * Target Template
122  */
123
124 static void scst_tgtt_release(struct kobject *kobj)
125 {
126         struct scst_tgt_template *tgtt;
127
128         TRACE_ENTRY();
129
130         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
131
132         complete_all(&tgtt->tgtt_kobj_release_cmpl);
133
134         scst_tgtt_cleanup(tgtt);
135
136         TRACE_EXIT();
137         return;
138 }
139
140 static struct kobj_type tgtt_ktype = {
141         .sysfs_ops = &scst_sysfs_ops,
142         .release = scst_tgtt_release,
143 };
144
145 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
146
147 static ssize_t scst_tgtt_trace_level_show(struct kobject *kobj,
148         struct kobj_attribute *attr, char *buf)
149 {
150         struct scst_tgt_template *tgtt;
151
152         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
153
154         return scst_trace_level_show(tgtt->trace_tbl,
155                 tgtt->trace_flags ? *tgtt->trace_flags : 0, buf,
156                 tgtt->trace_tbl_help);
157 }
158
159 static ssize_t scst_tgtt_trace_level_store(struct kobject *kobj,
160         struct kobj_attribute *attr, const char *buf, size_t count)
161 {
162         int res;
163         struct scst_tgt_template *tgtt;
164
165         TRACE_ENTRY();
166
167         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
168
169         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
170                 res = -EINTR;
171                 goto out;
172         }
173
174         res = scst_write_trace(buf, count, tgtt->trace_flags,
175                 tgtt->default_trace_flags, tgtt->name, tgtt->trace_tbl);
176
177         mutex_unlock(&scst_log_mutex);
178
179 out:
180         TRACE_EXIT_RES(res);
181         return res;
182 }
183
184 static struct kobj_attribute tgtt_trace_attr =
185         __ATTR(trace_level, S_IRUGO | S_IWUSR,
186                scst_tgtt_trace_level_show, scst_tgtt_trace_level_store);
187
188 #endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
189
190 int scst_create_tgtt_sysfs(struct scst_tgt_template *tgtt)
191 {
192         int retval = 0;
193         const struct attribute **pattr;
194
195         TRACE_ENTRY();
196
197         init_completion(&tgtt->tgtt_kobj_release_cmpl);
198
199         tgtt->tgtt_kobj_initialized = 1;
200
201         retval = kobject_init_and_add(&tgtt->tgtt_kobj, &tgtt_ktype,
202                         scst_targets_kobj, tgtt->name);
203         if (retval != 0) {
204                 PRINT_ERROR("Can't add tgtt %s to sysfs", tgtt->name);
205                 goto out;
206         }
207
208         /*
209          * In case of errors there's no need for additional cleanup, because
210          * it will be done by the _put function() called by the caller.
211          */
212
213         pattr = tgtt->tgtt_attrs;
214         if (pattr != NULL) {
215                 while (*pattr != NULL) {
216                         TRACE_DBG("Creating attr %s for target driver %s",
217                                 (*pattr)->name, tgtt->name);
218                         retval = sysfs_create_file(&tgtt->tgtt_kobj, *pattr);
219                         if (retval != 0) {
220                                 PRINT_ERROR("Can't add attr %s for target "
221                                         "driver %s", (*pattr)->name,
222                                         tgtt->name);
223                                 goto out;
224                         }
225                         pattr++;
226                 }
227         }
228
229 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
230         if (tgtt->trace_flags != NULL) {
231                 retval = sysfs_create_file(&tgtt->tgtt_kobj,
232                                 &tgtt_trace_attr.attr);
233                 if (retval != 0) {
234                         PRINT_ERROR("Can't add trace_flag for target "
235                                 "driver %s", tgtt->name);
236                         goto out;
237                 }
238         }
239 #endif
240
241 out:
242         TRACE_EXIT_RES(retval);
243         return retval;
244 }
245
246 void scst_tgtt_sysfs_put(struct scst_tgt_template *tgtt)
247 {
248         TRACE_ENTRY();
249
250         if (tgtt->tgtt_kobj_initialized) {
251                 int rc;
252
253                 kobject_del(&tgtt->tgtt_kobj);
254                 kobject_put(&tgtt->tgtt_kobj);
255
256                 rc = wait_for_completion_timeout(&tgtt->tgtt_kobj_release_cmpl, HZ);
257                 if (rc == 0) {
258                         PRINT_INFO("Waiting for releasing sysfs entry "
259                                 "for target template %s...", tgtt->name);
260                         wait_for_completion(&tgtt->tgtt_kobj_release_cmpl);
261                         PRINT_INFO("Done waiting for releasing sysfs "
262                                 "entry for target template %s", tgtt->name);
263                 }
264         } else
265                 scst_tgtt_cleanup(tgtt);
266
267         TRACE_EXIT();
268         return;
269 }
270
271 /*
272  * Target directory implementation
273  */
274
275 static void scst_tgt_release(struct kobject *kobj)
276 {
277         struct scst_tgt *tgt;
278
279         TRACE_ENTRY();
280
281         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
282
283         scst_free_tgt(tgt);
284
285         TRACE_EXIT();
286         return;
287 }
288
289 static struct kobj_type tgt_ktype = {
290         .sysfs_ops = &scst_sysfs_ops,
291         .release = scst_tgt_release,
292 };
293
294 static struct kobj_attribute scst_luns_mgmt =
295         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
296                scst_luns_mgmt_store);
297
298 static ssize_t scst_tgt_enable_show(struct kobject *kobj,
299         struct kobj_attribute *attr, char *buf)
300 {
301         struct scst_tgt *tgt;
302         int res;
303         bool enabled;
304
305         TRACE_ENTRY();
306
307         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
308
309         enabled = tgt->tgtt->is_tgt_enabled(tgt);
310
311         res = sprintf(buf, "%d\n", enabled ? 1 : 0);
312
313         TRACE_EXIT_RES(res);
314         return res;
315 }
316
317 static ssize_t scst_tgt_enable_store(struct kobject *kobj,
318         struct kobj_attribute *attr, const char *buf, size_t count)
319 {
320         int res;
321         struct scst_tgt *tgt;
322
323         TRACE_ENTRY();
324
325         if (buf == NULL)
326                 goto out_err;
327
328         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
329
330         res = tgt->tgtt->enable_tgt(tgt, buf, count);
331
332 out:
333         TRACE_EXIT_RES(res);
334         return res;
335
336 out_err:
337         PRINT_ERROR("%s: Requested action not understood: %s", __func__, buf);
338         res = -EINVAL;
339         goto out;
340 }
341
342 static struct kobj_attribute tgt_enable_attr =
343         __ATTR(enabled, S_IRUGO | S_IWUSR,
344                scst_tgt_enable_show, scst_tgt_enable_store);
345
346 int scst_create_tgt_sysfs(struct scst_tgt *tgt)
347 {
348         int retval;
349         const struct attribute **pattr;
350
351         TRACE_ENTRY();
352
353         tgt->tgt_kobj_initialized = 1;
354
355         retval = kobject_init_and_add(&tgt->tgt_kobj, &tgt_ktype,
356                         &tgt->tgtt->tgtt_kobj, tgt->tgt_name);
357         if (retval != 0) {
358                 PRINT_ERROR("Can't add tgt %s to sysfs", tgt->tgt_name);
359                 goto out;
360         }
361
362         /*
363          * In case of errors there's no need for additional cleanup, because
364          * it will be done by the _put function() called by the caller.
365          */
366
367         if ((tgt->tgtt->enable_tgt != NULL) &&
368             (tgt->tgtt->is_tgt_enabled != NULL)) {
369                 retval = sysfs_create_file(&tgt->tgt_kobj,
370                                 &tgt_enable_attr.attr);
371                 if (retval != 0) {
372                         PRINT_ERROR("Can't add attr %s to sysfs",
373                                 tgt_enable_attr.attr.name);
374                         goto out;
375                 }
376         }
377
378         tgt->tgt_sess_kobj = kobject_create_and_add("sessions", &tgt->tgt_kobj);
379         if (tgt->tgt_sess_kobj == NULL) {
380                 PRINT_ERROR("Can't create sess kobj for tgt %s", tgt->tgt_name);
381                 goto out_nomem;
382         }
383
384         tgt->tgt_luns_kobj = kobject_create_and_add("luns", &tgt->tgt_kobj);
385         if (tgt->tgt_luns_kobj == NULL) {
386                 PRINT_ERROR("Can't create luns kobj for tgt %s", tgt->tgt_name);
387                 goto out_nomem;
388         }
389
390         retval = sysfs_create_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
391         if (retval != 0) {
392                 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
393                         scst_luns_mgmt.attr.name, tgt->tgt_name);
394                 goto out;
395         }
396
397         tgt->tgt_ini_grp_kobj = kobject_create_and_add("ini_group",
398                                         &tgt->tgt_kobj);
399         if (tgt->tgt_ini_grp_kobj == NULL) {
400                 PRINT_ERROR("Can't create ini_grp kobj for tgt %s",
401                         tgt->tgt_name);
402                 goto out_nomem;
403         }
404
405         pattr = tgt->tgtt->tgt_attrs;
406         if (pattr != NULL) {
407                 while (*pattr != NULL) {
408                         TRACE_DBG("Creating attr %s for tgt %s", (*pattr)->name,
409                                 tgt->tgt_name);
410                         retval = sysfs_create_file(&tgt->tgt_kobj, *pattr);
411                         if (retval != 0) {
412                                 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
413                                         (*pattr)->name, tgt->tgt_name);
414                                 goto out;
415                         }
416                         pattr++;
417                 }
418         }
419
420 out:
421         TRACE_EXIT_RES(retval);
422         return retval;
423
424 out_nomem:
425         retval = -ENOMEM;
426         goto out;
427 }
428
429 void scst_tgt_sysfs_put(struct scst_tgt *tgt)
430 {
431         if (tgt->tgt_kobj_initialized) {
432                 kobject_del(tgt->tgt_sess_kobj);
433                 kobject_put(tgt->tgt_sess_kobj);
434
435                 sysfs_remove_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
436
437                 kobject_del(tgt->tgt_luns_kobj);
438                 kobject_put(tgt->tgt_luns_kobj);
439
440                 kobject_del(tgt->tgt_ini_grp_kobj);
441                 kobject_put(tgt->tgt_ini_grp_kobj);
442
443                 kobject_del(&tgt->tgt_kobj);
444                 kobject_put(&tgt->tgt_kobj);
445         } else
446                 scst_free_tgt(tgt);
447         return;
448 }
449
450 /*
451  * Devices directory implementation
452  */
453
454 ssize_t scst_device_sysfs_type_show(struct kobject *kobj,
455                             struct kobj_attribute *attr, char *buf)
456 {
457         int pos = 0;
458
459         struct scst_device *dev;
460
461         dev = container_of(kobj, struct scst_device, dev_kobj);
462
463         pos = sprintf(buf, "%d - %s\n", dev->type,
464                 (unsigned)dev->type > ARRAY_SIZE(scst_dev_handler_types) ?
465                       "unknown" : scst_dev_handler_types[dev->type]);
466
467         return pos;
468 }
469
470 static struct kobj_attribute device_type_attr =
471         __ATTR(type, S_IRUGO, scst_device_sysfs_type_show, NULL);
472
473 static struct attribute *scst_device_attrs[] = {
474         &device_type_attr.attr,
475         NULL,
476 };
477
478 static void scst_sysfs_device_release(struct kobject *kobj)
479 {
480         struct scst_device *dev;
481
482         TRACE_ENTRY();
483
484         dev = container_of(kobj, struct scst_device, dev_kobj);
485
486         scst_free_device(dev);
487
488         TRACE_EXIT();
489         return;
490 }
491
492 int scst_create_devt_dev_sysfs(struct scst_device *dev)
493 {
494         int retval = 0;
495         const struct attribute **pattr;
496
497         TRACE_ENTRY();
498
499         if (dev->handler == &scst_null_devtype)
500                 goto out;
501
502         sBUG_ON(!dev->handler->devt_kobj_initialized);
503
504         /*
505          * In case of errors there's no need for additional cleanup, because
506          * it will be done by the _put function() called by the caller.
507          */
508
509         retval = sysfs_create_link(&dev->dev_kobj,
510                         &dev->handler->devt_kobj, "handler");
511         if (retval != 0) {
512                 PRINT_ERROR("Can't create handler link for dev %s",
513                         dev->virt_name);
514                 goto out;
515         }
516
517         pattr = dev->handler->dev_attrs;
518         if (pattr != NULL) {
519                 while (*pattr != NULL) {
520                         retval = sysfs_create_file(&dev->dev_kobj, *pattr);
521                         if (retval != 0) {
522                                 PRINT_ERROR("Can't add dev attr %s for dev %s",
523                                         (*pattr)->name, dev->virt_name);
524                                 goto out;
525                         }
526                         pattr++;
527                 }
528         }
529
530 out:
531         TRACE_EXIT_RES(retval);
532         return retval;
533 }
534
535 void scst_devt_dev_sysfs_put(struct scst_device *dev)
536 {
537         const struct attribute **pattr;
538
539         TRACE_ENTRY();
540
541         if (dev->handler == &scst_null_devtype)
542                 goto out;
543
544         sBUG_ON(!dev->handler->devt_kobj_initialized);
545
546         pattr = dev->handler->dev_attrs;
547         if (pattr != NULL) {
548                 while (*pattr != NULL) {
549                         sysfs_remove_file(&dev->dev_kobj, *pattr);
550                         pattr++;
551                 }
552         }
553
554         sysfs_remove_link(&dev->dev_kobj, "handler");
555
556 out:
557         TRACE_EXIT();
558         return;
559 }
560
561 static struct kobj_type scst_device_ktype = {
562         .sysfs_ops = &scst_sysfs_ops,
563         .release = scst_sysfs_device_release,
564         .default_attrs = scst_device_attrs,
565 };
566
567 int scst_create_device_sysfs(struct scst_device *dev)
568 {
569         int retval = 0;
570
571         TRACE_ENTRY();
572
573         dev->dev_kobj_initialized = 1;
574
575         retval = kobject_init_and_add(&dev->dev_kobj, &scst_device_ktype,
576                                       scst_devices_kobj, dev->virt_name);
577         if (retval != 0) {
578                 PRINT_ERROR("Can't add device %s to sysfs", dev->virt_name);
579                 goto out;
580         }
581
582         /*
583          * In case of errors there's no need for additional cleanup, because
584          * it will be done by the _put function() called by the caller.
585          */
586
587         dev->dev_exp_kobj = kobject_create_and_add("exported",
588                                                    &dev->dev_kobj);
589         if (dev->dev_exp_kobj == NULL) {
590                 PRINT_ERROR("Can't create exported link for device %s",
591                         dev->virt_name);
592                 retval = -ENOMEM;
593                 goto out;
594         }
595
596         if (dev->scsi_dev != NULL) {
597                 retval = sysfs_create_link(&dev->dev_kobj,
598                         &dev->scsi_dev->sdev_dev.kobj, "scsi_device");
599                 if (retval != 0) {
600                         PRINT_ERROR("Can't create scsi_device link for dev %s",
601                                 dev->virt_name);
602                         goto out;
603                 }
604         }
605
606 out:
607         TRACE_EXIT_RES(retval);
608         return retval;
609 }
610
611 void scst_device_sysfs_put(struct scst_device *dev)
612 {
613         TRACE_ENTRY();
614
615         if (dev->dev_kobj_initialized) {
616                 if (dev->dev_exp_kobj != NULL) {
617                         kobject_del(dev->dev_exp_kobj);
618                         kobject_put(dev->dev_exp_kobj);
619                 }
620                 kobject_del(&dev->dev_kobj);
621                 kobject_put(&dev->dev_kobj);
622         } else
623                 scst_free_device(dev);
624
625         TRACE_EXIT();
626         return;
627 }
628
629 /*
630  * Target sessions directory implementation
631  */
632
633 ssize_t scst_sess_sysfs_commands_show(struct kobject *kobj,
634                             struct kobj_attribute *attr, char *buf)
635 {
636         struct scst_session *sess;
637
638         sess = container_of(kobj, struct scst_session, sess_kobj);
639
640         return sprintf(buf, "%i\n", atomic_read(&sess->sess_cmd_count));
641 }
642
643 static struct kobj_attribute session_commands_attr =
644         __ATTR(commands, S_IRUGO, scst_sess_sysfs_commands_show, NULL);
645
646 static struct attribute *scst_session_attrs[] = {
647         &session_commands_attr.attr,
648         NULL,
649 };
650
651 static void scst_sysfs_session_release(struct kobject *kobj)
652 {
653         struct scst_session *sess;
654
655         TRACE_ENTRY();
656
657         sess = container_of(kobj, struct scst_session, sess_kobj);
658
659         scst_release_session(sess);
660
661         TRACE_EXIT();
662         return;
663 }
664
665 static struct kobj_type scst_session_ktype = {
666         .sysfs_ops = &scst_sysfs_ops,
667         .release = scst_sysfs_session_release,
668         .default_attrs = scst_session_attrs,
669 };
670
671 int scst_create_sess_sysfs(struct scst_session *sess)
672 {
673         int retval = 0;
674         const struct attribute **pattr;
675
676         TRACE_ENTRY();
677
678         sess->sess_kobj_initialized = 1;
679
680         retval = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
681                               sess->tgt->tgt_sess_kobj, sess->initiator_name);
682         if (retval != 0) {
683                 PRINT_ERROR("Can't add session %s to sysfs",
684                             sess->initiator_name);
685                 goto out;
686         }
687
688         /*
689          * In case of errors there's no need for additional cleanup, because
690          * it will be done by the _put function() called by the caller.
691          */
692
693         pattr = sess->tgt->tgtt->sess_attrs;
694         if (pattr != NULL) {
695                 while (*pattr != NULL) {
696                         retval = sysfs_create_file(&sess->sess_kobj, *pattr);
697                         if (retval != 0) {
698                                 PRINT_ERROR("Can't add sess attr %s for sess "
699                                         "for initiator %s", (*pattr)->name,
700                                         sess->initiator_name);
701                                 goto out;
702                         }
703                         pattr++;
704                 }
705         }
706
707 out:
708         TRACE_EXIT_RES(retval);
709         return retval;
710 }
711
712 void scst_sess_sysfs_put(struct scst_session *sess)
713 {
714         TRACE_ENTRY();
715
716         if (sess->sess_kobj_initialized) {
717                 kobject_del(&sess->sess_kobj);
718                 kobject_put(&sess->sess_kobj);
719         } else
720                 scst_release_session(sess);
721
722         TRACE_EXIT();
723         return;
724 }
725
726 /*
727  * Target luns directory implementation
728  */
729
730 static void scst_acg_dev_release(struct kobject *kobj)
731 {
732         struct scst_acg_dev *acg_dev;
733
734         TRACE_ENTRY();
735
736         acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
737
738         scst_acg_dev_destroy(acg_dev);
739
740         TRACE_EXIT();
741         return;
742 }
743
744 static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
745                                    struct kobj_attribute *attr,
746                                    char *buf)
747 {
748         struct scst_acg_dev *acg_dev;
749
750         acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
751
752         return sprintf(buf, "%d\n",
753                 (acg_dev->rd_only || acg_dev->dev->rd_only) ? 1 : 0);
754 }
755
756 static struct kobj_attribute lun_options_attr =
757         __ATTR(read_only, S_IRUGO, scst_lun_rd_only_show, NULL);
758
759 static struct attribute *lun_attrs[] = {
760         &lun_options_attr.attr,
761         NULL,
762 };
763
764 static struct kobj_type acg_dev_ktype = {
765         .sysfs_ops = &scst_sysfs_ops,
766         .release = scst_acg_dev_release,
767         .default_attrs = lun_attrs,
768 };
769
770 int scst_create_acg_dev_sysfs(struct scst_acg *acg, unsigned int virt_lun,
771         struct kobject *parent)
772 {
773         int retval;
774         struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
775         char str[10];
776
777         TRACE_ENTRY();
778
779         list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
780                             acg_dev_list_entry) {
781                 if (acg_dev_tmp->lun == virt_lun) {
782                         acg_dev = acg_dev_tmp;
783                         break;
784                 }
785         }
786         if (acg_dev == NULL) {
787                 PRINT_ERROR("%s", "acg_dev lookup for kobject creation failed");
788                 retval = -EINVAL;
789                 goto out;
790         }
791
792         snprintf(str, sizeof(str), "%u", acg_dev->dev->dev_exported_lun_num++);
793
794         acg_dev->acg_dev_kobj_initialized = 1;
795
796         retval = kobject_init_and_add(&acg_dev->acg_dev_kobj, &acg_dev_ktype,
797                                       parent, "%u", virt_lun);
798         if (retval != 0) {
799                 PRINT_ERROR("Can't add acg %s to sysfs", acg->acg_name);
800                 goto out;
801         }
802
803         /*
804          * In case of errors there's no need for additional cleanup, because
805          * it will be done by the _put function() called by the caller.
806          */
807
808         retval = sysfs_create_link(acg_dev->dev->dev_exp_kobj,
809                                    &acg_dev->acg_dev_kobj, str);
810         if (retval != 0) {
811                 PRINT_ERROR("Can't create acg %s LUN link", acg->acg_name);
812                 goto out;
813         }
814
815         retval = sysfs_create_link(&acg_dev->acg_dev_kobj,
816                         &acg_dev->dev->dev_kobj, "device");
817         if (retval != 0) {
818                 PRINT_ERROR("Can't create acg %s device link", acg->acg_name);
819                 goto out;
820         }
821
822 out:
823         return retval;
824 }
825
826 static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
827                                    struct kobj_attribute *attr,
828                                    char *buf)
829 {
830         static char *help = "Usage: echo \"add|del H:C:I:L lun [READ_ONLY]\" "
831                                         ">mgmt\n"
832                             "       echo \"add|del VNAME lun [READ_ONLY]\" "
833                                         ">mgmt\n";
834
835         return sprintf(buf, help);
836 }
837
838 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
839                                     struct kobj_attribute *attr,
840                                     const char *buf, size_t count)
841 {
842         int res, virt = 0, read_only = 0, action;
843         char *buffer, *p, *e = NULL;
844         unsigned int host, channel = 0, id = 0, lun = 0, virt_lun;
845         struct scst_acg *acg;
846         struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
847         struct scst_device *d, *dev = NULL;
848         struct scst_tgt *tgt;
849
850 #define SCST_LUN_ACTION_ADD     1
851 #define SCST_LUN_ACTION_DEL     2
852 #define SCST_LUN_ACTION_REPLACE 3
853
854         TRACE_ENTRY();
855
856         tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
857         acg = tgt->default_acg;
858
859         buffer = kzalloc(count+1, GFP_KERNEL);
860         if (buffer == NULL) {
861                 res = -ENOMEM;
862                 goto out;
863         }
864
865         memcpy(buffer, buf, count);
866         buffer[count] = '\0';
867         p = buffer;
868
869         p = buffer;
870         if (p[strlen(p) - 1] == '\n')
871                 p[strlen(p) - 1] = '\0';
872         if (strncasecmp("add", p, 3) == 0) {
873                 p += 3;
874                 action = SCST_LUN_ACTION_ADD;
875         } else if (strncasecmp("del", p, 3) == 0) {
876                 p += 3;
877                 action = SCST_LUN_ACTION_DEL;
878         } else if (!strncasecmp("replace", p, 7)) {
879                 p += 7;
880                 action = SCST_LUN_ACTION_REPLACE;
881         } else {
882                 PRINT_ERROR("Unknown action \"%s\"", p);
883                 res = -EINVAL;
884                 goto out_free;
885         }
886
887         if (!isspace(*p)) {
888                 PRINT_ERROR("%s", "Syntax error");
889                 res = -EINVAL;
890                 goto out_free;
891         }
892
893         res = scst_suspend_activity(true);
894         if (res != 0)
895                 goto out_free;
896
897         if (mutex_lock_interruptible(&scst_mutex) != 0) {
898                 res = -EINTR;
899                 goto out_free_resume;
900         }
901
902         while (isspace(*p) && *p != '\0')
903                 p++;
904         e = p; /* save p */
905         host = simple_strtoul(p, &p, 0);
906         if (*p == ':') {
907                 channel = simple_strtoul(p + 1, &p, 0);
908                 id = simple_strtoul(p + 1, &p, 0);
909                 lun = simple_strtoul(p + 1, &p, 0);
910                 e = p;
911         } else {
912                 virt++;
913                 p = e; /* restore p */
914                 while (!isspace(*e) && *e != '\0')
915                         e++;
916                 *e = '\0';
917         }
918
919         list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
920                 if (virt) {
921                         if (d->virt_id && !strcmp(d->virt_name, p)) {
922                                 dev = d;
923                                 TRACE_DBG("Virt device %p (%s) found",
924                                           dev, p);
925                                 break;
926                         }
927                 } else {
928                         if (d->scsi_dev &&
929                             d->scsi_dev->host->host_no == host &&
930                             d->scsi_dev->channel == channel &&
931                             d->scsi_dev->id == id &&
932                             d->scsi_dev->lun == lun) {
933                                 dev = d;
934                                 TRACE_DBG("Dev %p (%d:%d:%d:%d) found",
935                                           dev, host, channel, id, lun);
936                                 break;
937                         }
938                 }
939         }
940         if (dev == NULL) {
941                 if (virt) {
942                         PRINT_ERROR("Virt device %s not found", p);
943                 } else {
944                         PRINT_ERROR("Device %d:%d:%d:%d not found",
945                                     host, channel, id, lun);
946                 }
947                 res = -EINVAL;
948                 goto out_free_up;
949         }
950
951         switch (action) {
952         case SCST_LUN_ACTION_ADD:
953         case SCST_LUN_ACTION_REPLACE:
954         {
955                 bool dev_replaced = false;
956
957                 e++;
958                 while (isspace(*e) && *e != '\0')
959                         e++;
960                 virt_lun = simple_strtoul(e, &e, 0);
961
962                 while (isspace(*e) && *e != '\0')
963                         e++;
964
965                 if (*e != '\0') {
966                         if ((strncasecmp("READ_ONLY", e, 9) == 0) &&
967                             (isspace(e[9]) || (e[9] == '\0')))
968                                 read_only = 1;
969                         else {
970                                 PRINT_ERROR("Unknown option \"%s\"", e);
971                                 res = -EINVAL;
972                                 goto out_free_up;
973                         }
974                 }
975
976                 acg_dev = NULL;
977                 list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
978                                     acg_dev_list_entry) {
979                         if (acg_dev_tmp->lun == virt_lun) {
980                                 acg_dev = acg_dev_tmp;
981                                 break;
982                         }
983                 }
984
985                 if (acg_dev != NULL) {
986                         if (action == SCST_LUN_ACTION_ADD) {
987                                 PRINT_ERROR("virt lun %d already exists in "
988                                         "group %s", virt_lun, acg->acg_name);
989                                 res = -EINVAL;
990                                 goto out_free_up;
991                         } else {
992                                 /* Replace */
993                                 res = scst_acg_remove_dev(acg, acg_dev->dev,
994                                                 false);
995                                 if (res != 0)
996                                         goto out_free_up;
997
998                                 dev_replaced = true;
999                         }
1000                 }
1001
1002                 res = scst_acg_add_dev(acg, dev, virt_lun, read_only,
1003                                         !dev_replaced);
1004                 if (res != 0)
1005                         goto out_free_up;
1006
1007                 res = scst_create_acg_dev_sysfs(acg, virt_lun, kobj);
1008                 if (res != 0) {
1009                         PRINT_ERROR("%s", "Creation of acg_dev kobject failed");
1010                         goto out_remove_acg_dev;
1011                 }
1012
1013                 if (dev_replaced) {
1014                         struct scst_tgt_dev *tgt_dev;
1015
1016                         list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
1017                                         dev_tgt_dev_list_entry) {
1018                                 if ((tgt_dev->acg_dev->acg == acg) &&
1019                                     (tgt_dev->lun == virt_lun)) {
1020                                         TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
1021                                                 " on tgt_dev %p", tgt_dev);
1022                                         scst_gen_aen_or_ua(tgt_dev,
1023                                                 SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
1024                                 }
1025                         }
1026                 }
1027
1028                 break;
1029         }
1030         case SCST_LUN_ACTION_DEL:
1031                 res = scst_acg_remove_dev(acg, dev, true);
1032                 if (res != 0)
1033                         goto out_free_up;
1034                 break;
1035         }
1036
1037         res = count;
1038
1039 out_free_up:
1040         mutex_unlock(&scst_mutex);
1041
1042 out_free_resume:
1043         scst_resume_activity();
1044
1045 out_free:
1046         kfree(buffer);
1047
1048 out:
1049         TRACE_EXIT_RES(res);
1050         return res;
1051
1052 out_remove_acg_dev:
1053         scst_acg_remove_dev(acg, dev, true);
1054         goto out_free_up;
1055
1056 #undef SCST_LUN_ACTION_ADD
1057 #undef SCST_LUN_ACTION_DEL
1058 #undef SCST_LUN_ACTION_REPLACE
1059 }
1060
1061 /*
1062  * SGV directory implementation
1063  */
1064
1065 static struct kobj_attribute sgv_stat_attr =
1066         __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show,
1067                 sgv_sysfs_stat_reset);
1068
1069 static struct attribute *sgv_attrs[] = {
1070         &sgv_stat_attr.attr,
1071         NULL,
1072 };
1073
1074 static void sgv_kobj_release(struct kobject *kobj)
1075 {
1076         struct sgv_pool *pool;
1077
1078         TRACE_ENTRY();
1079
1080         pool = container_of(kobj, struct sgv_pool, sgv_kobj);
1081
1082         sgv_pool_destroy(pool);
1083
1084         TRACE_EXIT();
1085         return;
1086 }
1087
1088 static struct kobj_type sgv_pool_ktype = {
1089         .sysfs_ops = &scst_sysfs_ops,
1090         .release = sgv_kobj_release,
1091         .default_attrs = sgv_attrs,
1092 };
1093
1094 int scst_create_sgv_sysfs(struct sgv_pool *pool)
1095 {
1096         int retval;
1097
1098         TRACE_ENTRY();
1099
1100         pool->sgv_kobj_initialized = 1;
1101
1102         retval = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype,
1103                         scst_sgv_kobj, pool->name);
1104         if (retval != 0) {
1105                 PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name);
1106                 goto out;
1107         }
1108
1109 out:
1110         TRACE_EXIT_RES(retval);
1111         return retval;
1112 }
1113
1114 /* pool can be dead upon exit from this function! */
1115 void scst_sgv_sysfs_put(struct sgv_pool *pool)
1116 {
1117         if (pool->sgv_kobj_initialized) {
1118                 kobject_del(&pool->sgv_kobj);
1119                 kobject_put(&pool->sgv_kobj);
1120         } else
1121                 sgv_pool_destroy(pool);
1122         return;
1123 }
1124
1125 static struct kobj_attribute sgv_global_stat_attr =
1126         __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show,
1127                 sgv_sysfs_global_stat_reset);
1128
1129 static struct attribute *sgv_default_attrs[] = {
1130         &sgv_global_stat_attr.attr,
1131         NULL,
1132 };
1133
1134 static struct kobj_type sgv_ktype = {
1135         .sysfs_ops = &scst_sysfs_ops,
1136         .release = scst_sysfs_release,
1137         .default_attrs = sgv_default_attrs,
1138 };
1139
1140 /*
1141  * SCST sysfs root directory implementation
1142  */
1143
1144 static ssize_t scst_threads_show(struct kobject *kobj,
1145         struct kobj_attribute *attr, char *buf)
1146 {
1147         int count;
1148
1149         TRACE_ENTRY();
1150
1151         count = sprintf(buf, "%d\n", scst_global_threads_count());
1152
1153         TRACE_EXIT();
1154         return count;
1155 }
1156
1157 static ssize_t scst_threads_store(struct kobject *kobj,
1158         struct kobj_attribute *attr, const char *buf, size_t count)
1159 {
1160         int res = count;
1161         int oldtn, newtn, delta;
1162
1163         TRACE_ENTRY();
1164
1165         if (mutex_lock_interruptible(&scst_sysfs_mutex) != 0) {
1166                 res = -EINTR;
1167                 goto out;
1168         }
1169
1170         mutex_lock(&scst_global_threads_mutex);
1171
1172         oldtn = scst_nr_global_threads;
1173         sscanf(buf, "%du", &newtn);
1174
1175         if (newtn <= 0) {
1176                 PRINT_ERROR("Illegal threads num value %d", newtn);
1177                 res = -EINVAL;
1178                 goto out_up_thr_free;
1179         }
1180         delta = newtn - oldtn;
1181         if (delta < 0)
1182                 __scst_del_global_threads(-delta);
1183         else
1184                 __scst_add_global_threads(delta);
1185
1186         PRINT_INFO("Changed cmd threads num: old %d, new %d", oldtn, newtn);
1187
1188 out_up_thr_free:
1189         mutex_unlock(&scst_global_threads_mutex);
1190
1191         mutex_unlock(&scst_sysfs_mutex);
1192
1193 out:
1194         TRACE_EXIT_RES(res);
1195         return res;
1196 }
1197
1198 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1199
1200 static void scst_read_trace_tlb(const struct scst_trace_log *tbl, char *buf,
1201         unsigned long log_level, int *pos)
1202 {
1203         const struct scst_trace_log *t = tbl;
1204
1205         if (t == NULL)
1206                 goto out;
1207
1208         while (t->token) {
1209                 if (log_level & t->val) {
1210                         *pos += sprintf(&buf[*pos], "%s%s",
1211                                         (*pos == 0) ? "" : " | ",
1212                                         t->token);
1213                 }
1214                 t++;
1215         }
1216 out:
1217         return;
1218 }
1219
1220 static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
1221         unsigned long log_level, char *buf, const char *help)
1222 {
1223         int pos = 0;
1224
1225         scst_read_trace_tlb(scst_trace_tbl, buf, log_level, &pos);
1226         scst_read_trace_tlb(local_tbl, buf, log_level, &pos);
1227
1228         pos += sprintf(&buf[pos], "\n\n\nUsage:\n"
1229                 "       echo \"all|none|default\" >trace_level\n"
1230                 "       echo \"value DEC|0xHEX|0OCT\" >trace_level\n"
1231                 "       echo \"add|del TOKEN\" >trace_level\n"
1232                 "\nwhere TOKEN is one of [debug, function, line, pid,\n"
1233 #ifndef GENERATING_UPSTREAM_PATCH
1234                 "                      entryexit, buff, mem, sg, out_of_mem,\n"
1235 #else
1236                 "                      buff, mem, sg, out_of_mem,\n"
1237 #endif
1238                 "                      special, scsi, mgmt, minor,\n"
1239                 "                      mgmt_minor, mgmt_dbg, scsi_serializing,\n"
1240                 "                      retry, recv_bot, send_bot, recv_top,\n"
1241                 "                      send_top%s]", help != NULL ? help : "");
1242
1243         return pos;
1244 }
1245
1246 static ssize_t scst_main_trace_level_show(struct kobject *kobj,
1247         struct kobj_attribute *attr, char *buf)
1248 {
1249         return scst_trace_level_show(scst_local_trace_tbl, trace_flag,
1250                         buf, NULL);
1251 }
1252
1253 static int scst_write_trace(const char *buf, size_t length,
1254         unsigned long *log_level, unsigned long default_level,
1255         const char *name, const struct scst_trace_log *tbl)
1256 {
1257         int res = length;
1258         int action;
1259         unsigned long level = 0, oldlevel;
1260         char *buffer, *p, *e;
1261         const struct scst_trace_log *t;
1262
1263 #define SCST_TRACE_ACTION_ALL           1
1264 #define SCST_TRACE_ACTION_NONE          2
1265 #define SCST_TRACE_ACTION_DEFAULT       3
1266 #define SCST_TRACE_ACTION_ADD           4
1267 #define SCST_TRACE_ACTION_DEL           5
1268 #define SCST_TRACE_ACTION_VALUE         6
1269
1270         TRACE_ENTRY();
1271
1272         if ((buf == NULL) || (length == 0)) {
1273                 res = -EINVAL;
1274                 goto out;
1275         }
1276
1277         buffer = kmalloc(length+1, GFP_KERNEL);
1278         if (buffer == NULL) {
1279                 PRINT_ERROR("Unable to alloc intermediate buffer (size %zd)",
1280                         length+1);
1281                 res = -ENOMEM;
1282                 goto out;
1283         }
1284         memcpy(buffer, buf, length);
1285         buffer[length] = '\0';
1286
1287         p = buffer;
1288         if (!strncasecmp("all", p, 3)) {
1289                 action = SCST_TRACE_ACTION_ALL;
1290         } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
1291                 action = SCST_TRACE_ACTION_NONE;
1292         } else if (!strncasecmp("default", p, 7)) {
1293                 action = SCST_TRACE_ACTION_DEFAULT;
1294         } else if (!strncasecmp("add", p, 3)) {
1295                 p += 3;
1296                 action = SCST_TRACE_ACTION_ADD;
1297         } else if (!strncasecmp("del", p, 3)) {
1298                 p += 3;
1299                 action = SCST_TRACE_ACTION_DEL;
1300         } else if (!strncasecmp("value", p, 5)) {
1301                 p += 5;
1302                 action = SCST_TRACE_ACTION_VALUE;
1303         } else {
1304                 if (p[strlen(p) - 1] == '\n')
1305                         p[strlen(p) - 1] = '\0';
1306                 PRINT_ERROR("Unknown action \"%s\"", p);
1307                 res = -EINVAL;
1308                 goto out_free;
1309         }
1310
1311         switch (action) {
1312         case SCST_TRACE_ACTION_ADD:
1313         case SCST_TRACE_ACTION_DEL:
1314         case SCST_TRACE_ACTION_VALUE:
1315                 if (!isspace(*p)) {
1316                         PRINT_ERROR("%s", "Syntax error");
1317                         res = -EINVAL;
1318                         goto out_free;
1319                 }
1320         }
1321
1322         switch (action) {
1323         case SCST_TRACE_ACTION_ALL:
1324                 level = TRACE_ALL;
1325                 break;
1326         case SCST_TRACE_ACTION_DEFAULT:
1327                 level = default_level;
1328                 break;
1329         case SCST_TRACE_ACTION_NONE:
1330                 level = TRACE_NULL;
1331                 break;
1332         case SCST_TRACE_ACTION_ADD:
1333         case SCST_TRACE_ACTION_DEL:
1334                 while (isspace(*p) && *p != '\0')
1335                         p++;
1336                 e = p;
1337                 while (!isspace(*e) && *e != '\0')
1338                         e++;
1339                 *e = 0;
1340                 if (tbl) {
1341                         t = tbl;
1342                         while (t->token) {
1343                                 if (!strcasecmp(p, t->token)) {
1344                                         level = t->val;
1345                                         break;
1346                                 }
1347                                 t++;
1348                         }
1349                 }
1350                 if (level == 0) {
1351                         t = scst_trace_tbl;
1352                         while (t->token) {
1353                                 if (!strcasecmp(p, t->token)) {
1354                                         level = t->val;
1355                                         break;
1356                                 }
1357                                 t++;
1358                         }
1359                 }
1360                 if (level == 0) {
1361                         PRINT_ERROR("Unknown token \"%s\"", p);
1362                         res = -EINVAL;
1363                         goto out_free;
1364                 }
1365                 break;
1366         case SCST_TRACE_ACTION_VALUE:
1367                 while (isspace(*p) && *p != '\0')
1368                         p++;
1369                 res = strict_strtoul(p, 0, &level);
1370                 if (res != 0) {
1371                         PRINT_ERROR("Invalud trace value \"%s\"", p);
1372                         res = -EINVAL;
1373                         goto out_free;
1374                 }
1375                 break;
1376         }
1377
1378         oldlevel = *log_level;
1379
1380         switch (action) {
1381         case SCST_TRACE_ACTION_ADD:
1382                 *log_level |= level;
1383                 break;
1384         case SCST_TRACE_ACTION_DEL:
1385                 *log_level &= ~level;
1386                 break;
1387         default:
1388                 *log_level = level;
1389                 break;
1390         }
1391
1392         PRINT_INFO("Changed trace level for \"%s\": old 0x%08lx, new 0x%08lx",
1393                 name, oldlevel, *log_level);
1394
1395 out_free:
1396         kfree(buffer);
1397 out:
1398         TRACE_EXIT_RES(res);
1399         return res;
1400
1401 #undef SCST_TRACE_ACTION_ALL
1402 #undef SCST_TRACE_ACTION_NONE
1403 #undef SCST_TRACE_ACTION_DEFAULT
1404 #undef SCST_TRACE_ACTION_ADD
1405 #undef SCST_TRACE_ACTION_DEL
1406 #undef SCST_TRACE_ACTION_VALUE
1407 }
1408
1409 static ssize_t scst_main_trace_level_store(struct kobject *kobj,
1410         struct kobj_attribute *attr, const char *buf, size_t count)
1411 {
1412         int res;
1413
1414         TRACE_ENTRY();
1415
1416         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
1417                 res = -EINTR;
1418                 goto out;
1419         }
1420
1421         res = scst_write_trace(buf, count, &trace_flag,
1422                 SCST_DEFAULT_LOG_FLAGS, "scst", scst_local_trace_tbl);
1423
1424         mutex_unlock(&scst_log_mutex);
1425
1426 out:
1427         TRACE_EXIT_RES(res);
1428         return res;
1429 }
1430
1431 #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
1432
1433 static ssize_t scst_version_show(struct kobject *kobj,
1434                                  struct kobj_attribute *attr,
1435                                  char *buf)
1436 {
1437         TRACE_ENTRY();
1438
1439         sprintf(buf, "%s\n", SCST_VERSION_STRING);
1440
1441 #ifdef CONFIG_SCST_STRICT_SERIALIZING
1442         strcat(buf, "Strict serializing enabled\n");
1443 #endif
1444
1445 #ifdef CONFIG_SCST_EXTRACHECKS
1446         strcat(buf, "EXTRACHECKS\n");
1447 #endif
1448
1449 #ifdef CONFIG_SCST_TRACING
1450         strcat(buf, "TRACING\n");
1451 #endif
1452
1453 #ifdef CONFIG_SCST_DEBUG
1454         strcat(buf, "DEBUG\n");
1455 #endif
1456
1457 #ifdef CONFIG_SCST_DEBUG_TM
1458         strcat(buf, "DEBUG_TM\n");
1459 #endif
1460
1461 #ifdef CONFIG_SCST_DEBUG_RETRY
1462         strcat(buf, "DEBUG_RETRY\n");
1463 #endif
1464
1465 #ifdef CONFIG_SCST_DEBUG_OOM
1466         strcat(buf, "DEBUG_OOM\n");
1467 #endif
1468
1469 #ifdef CONFIG_SCST_DEBUG_SN
1470         strcat(buf, "DEBUG_SN\n");
1471 #endif
1472
1473 #ifdef CONFIG_SCST_USE_EXPECTED_VALUES
1474         strcat(buf, "USE_EXPECTED_VALUES\n");
1475 #endif
1476
1477 #ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
1478         strcat(buf, "ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ\n");
1479 #endif
1480
1481 #ifdef CONFIG_SCST_STRICT_SECURITY
1482         strcat(buf, "SCST_STRICT_SECURITY\n");
1483 #endif
1484
1485         TRACE_EXIT();
1486         return strlen(buf);
1487 }
1488
1489 static struct kobj_attribute scst_threads_attr =
1490         __ATTR(threads, S_IRUGO | S_IWUSR, scst_threads_show,
1491                scst_threads_store);
1492
1493 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1494 static struct kobj_attribute scst_trace_level_attr =
1495         __ATTR(trace_level, S_IRUGO | S_IWUSR, scst_main_trace_level_show,
1496                scst_main_trace_level_store);
1497 #endif
1498
1499 static struct kobj_attribute scst_version_attr =
1500         __ATTR(version, S_IRUGO, scst_version_show, NULL);
1501
1502 static struct attribute *scst_sysfs_root_default_attrs[] = {
1503         &scst_threads_attr.attr,
1504 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1505         &scst_trace_level_attr.attr,
1506 #endif
1507         &scst_version_attr.attr,
1508         NULL,
1509 };
1510
1511 static void scst_sysfs_root_release(struct kobject *kobj)
1512 {
1513         complete_all(&scst_sysfs_root_release_completion);
1514 }
1515
1516 static ssize_t scst_show(struct kobject *kobj, struct attribute *attr,
1517                          char *buf)
1518 {
1519         struct kobj_attribute *kobj_attr;
1520         kobj_attr = container_of(attr, struct kobj_attribute, attr);
1521
1522         return kobj_attr->show(kobj, kobj_attr, buf);
1523 }
1524
1525 static ssize_t scst_store(struct kobject *kobj, struct attribute *attr,
1526                           const char *buf, size_t count)
1527 {
1528         struct kobj_attribute *kobj_attr;
1529         kobj_attr = container_of(attr, struct kobj_attribute, attr);
1530
1531         return kobj_attr->store(kobj, kobj_attr, buf, count);
1532 }
1533
1534 struct sysfs_ops scst_sysfs_ops = {
1535         .show = scst_show,
1536         .store = scst_store,
1537 };
1538
1539 static struct kobj_type scst_sysfs_root_ktype = {
1540         .sysfs_ops = &scst_sysfs_ops,
1541         .release = scst_sysfs_root_release,
1542         .default_attrs = scst_sysfs_root_default_attrs,
1543 };
1544
1545 static void scst_devt_free(struct kobject *kobj)
1546 {
1547         struct scst_dev_type *devt;
1548
1549         TRACE_ENTRY();
1550
1551         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1552
1553         complete_all(&devt->devt_kobj_release_compl);
1554
1555         scst_devt_cleanup(devt);
1556
1557         TRACE_EXIT();
1558         return;
1559 }
1560
1561 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1562
1563 static ssize_t scst_devt_trace_level_show(struct kobject *kobj,
1564         struct kobj_attribute *attr, char *buf)
1565 {
1566         struct scst_dev_type *devt;
1567
1568         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1569
1570         return scst_trace_level_show(devt->trace_tbl,
1571                 devt->trace_flags ? *devt->trace_flags : 0, buf,
1572                 devt->trace_tbl_help);
1573 }
1574
1575 static ssize_t scst_devt_trace_level_store(struct kobject *kobj,
1576         struct kobj_attribute *attr, const char *buf, size_t count)
1577 {
1578         int res;
1579         struct scst_dev_type *devt;
1580
1581         TRACE_ENTRY();
1582
1583         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1584
1585         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
1586                 res = -EINTR;
1587                 goto out;
1588         }
1589
1590         res = scst_write_trace(buf, count, devt->trace_flags,
1591                 devt->default_trace_flags, devt->name, devt->trace_tbl);
1592
1593         mutex_unlock(&scst_log_mutex);
1594
1595 out:
1596         TRACE_EXIT_RES(res);
1597         return res;
1598 }
1599
1600 static struct kobj_attribute devt_trace_attr =
1601         __ATTR(trace_level, S_IRUGO | S_IWUSR,
1602                scst_devt_trace_level_show, scst_devt_trace_level_store);
1603
1604 #endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
1605
1606 static ssize_t scst_devt_type_show(struct kobject *kobj,
1607         struct kobj_attribute *attr, char *buf)
1608 {
1609         int pos;
1610         struct scst_dev_type *devt;
1611
1612         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1613
1614         pos = sprintf(buf, "%d - %s\n", devt->type,
1615                 (unsigned)devt->type > ARRAY_SIZE(scst_dev_handler_types) ?
1616                         "unknown" : scst_dev_handler_types[devt->type]);
1617
1618         return pos;
1619 }
1620
1621 static struct kobj_attribute scst_devt_type_attr =
1622         __ATTR(type, S_IRUGO, scst_devt_type_show, NULL);
1623
1624 static struct attribute *scst_devt_default_attrs[] = {
1625         &scst_devt_type_attr.attr,
1626         NULL,
1627 };
1628
1629 static struct kobj_type scst_devt_ktype = {
1630         .sysfs_ops = &scst_sysfs_ops,
1631         .release = scst_devt_free,
1632         .default_attrs = scst_devt_default_attrs,
1633 };
1634
1635 int scst_create_devt_sysfs(struct scst_dev_type *devt)
1636 {
1637         int retval;
1638         struct kobject *parent;
1639         const struct attribute **pattr;
1640
1641         TRACE_ENTRY();
1642
1643         init_completion(&devt->devt_kobj_release_compl);
1644
1645         if (devt->parent != NULL)
1646                 parent = &devt->parent->devt_kobj;
1647         else
1648                 parent = scst_handlers_kobj;
1649
1650         devt->devt_kobj_initialized = 1;
1651
1652         retval = kobject_init_and_add(&devt->devt_kobj, &scst_devt_ktype,
1653                         parent, devt->name);
1654         if (retval != 0) {
1655                 PRINT_ERROR("Can't add devt %s to sysfs", devt->name);
1656                 goto out;
1657         }
1658
1659         /*
1660          * In case of errors there's no need for additional cleanup, because
1661          * it will be done by the _put function() called by the caller.
1662          */
1663
1664         pattr = devt->devt_attrs;
1665         if (pattr != NULL) {
1666                 while (*pattr != NULL) {
1667                         retval = sysfs_create_file(&devt->devt_kobj, *pattr);
1668                         if (retval != 0) {
1669                                 PRINT_ERROR("Can't add devt attr %s for dev "
1670                                         "handler %s", (*pattr)->name,
1671                                         devt->name);
1672                                 goto out;
1673                         }
1674                         pattr++;
1675                 }
1676         }
1677
1678 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1679         if (devt->trace_flags != NULL) {
1680                 retval = sysfs_create_file(&devt->devt_kobj,
1681                                 &devt_trace_attr.attr);
1682                 if (retval != 0) {
1683                         PRINT_ERROR("Can't add devt trace_flag for dev "
1684                                 "handler %s", devt->name);
1685                         goto out;
1686                 }
1687         }
1688 #endif
1689
1690 out:
1691         TRACE_EXIT_RES(retval);
1692         return retval;
1693 }
1694
1695 void scst_devt_sysfs_put(struct scst_dev_type *devt)
1696 {
1697         TRACE_ENTRY();
1698
1699         if (devt->devt_kobj_initialized) {
1700                 int rc;
1701
1702                 kobject_del(&devt->devt_kobj);
1703                 kobject_put(&devt->devt_kobj);
1704
1705                 rc = wait_for_completion_timeout(&devt->devt_kobj_release_compl, HZ);
1706                 if (rc == 0) {
1707                         PRINT_INFO("Waiting for releasing sysfs entry "
1708                                 "for dev handler template %s...", devt->name);
1709                         wait_for_completion(&devt->devt_kobj_release_compl);
1710                         PRINT_INFO("Done waiting for releasing sysfs entry "
1711                                 "for dev handler template %s", devt->name);
1712                 }
1713         } else
1714                 scst_devt_cleanup(devt);
1715
1716         TRACE_EXIT();
1717         return;
1718 }
1719
1720 int __init scst_sysfs_init(void)
1721 {
1722         int retval = 0;
1723
1724         TRACE_ENTRY();
1725
1726         retval = kobject_init_and_add(&scst_sysfs_root_kobj,
1727                         &scst_sysfs_root_ktype, kernel_kobj, "%s", "scst_tgt");
1728         if (retval != 0)
1729                 goto sysfs_root_add_error;
1730
1731         scst_targets_kobj = kobject_create_and_add("targets",
1732                                 &scst_sysfs_root_kobj);
1733         if (scst_targets_kobj == NULL)
1734                 goto targets_kobj_error;
1735
1736         scst_devices_kobj = kobject_create_and_add("devices",
1737                                 &scst_sysfs_root_kobj);
1738         if (scst_devices_kobj == NULL)
1739                 goto devices_kobj_error;
1740
1741         scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL);
1742         if (scst_sgv_kobj == NULL)
1743                 goto sgv_kobj_error;
1744
1745         retval = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype,
1746                         &scst_sysfs_root_kobj, "%s", "sgv");
1747         if (retval != 0)
1748                 goto sgv_kobj_add_error;
1749
1750         scst_handlers_kobj = kobject_create_and_add("handlers",
1751                                         &scst_sysfs_root_kobj);
1752         if (scst_handlers_kobj == NULL)
1753                 goto handlers_kobj_error;
1754
1755 out:
1756         TRACE_EXIT_RES(retval);
1757         return retval;
1758
1759 handlers_kobj_error:
1760         kobject_del(scst_sgv_kobj);
1761
1762 sgv_kobj_add_error:
1763         kobject_put(scst_sgv_kobj);
1764
1765 sgv_kobj_error:
1766         kobject_del(scst_devices_kobj);
1767         kobject_put(scst_devices_kobj);
1768
1769 devices_kobj_error:
1770         kobject_del(scst_targets_kobj);
1771         kobject_put(scst_targets_kobj);
1772
1773 targets_kobj_error:
1774         kobject_del(&scst_sysfs_root_kobj);
1775
1776 sysfs_root_add_error:
1777         kobject_put(&scst_sysfs_root_kobj);
1778
1779         if (retval == 0)
1780                 retval = -EINVAL;
1781         goto out;
1782 }
1783
1784 void __exit scst_sysfs_cleanup(void)
1785 {
1786         TRACE_ENTRY();
1787
1788         PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
1789
1790         kobject_del(scst_sgv_kobj);
1791         kobject_put(scst_sgv_kobj);
1792
1793         kobject_del(scst_devices_kobj);
1794         kobject_put(scst_devices_kobj);
1795
1796         kobject_del(scst_targets_kobj);
1797         kobject_put(scst_targets_kobj);
1798
1799         kobject_del(scst_handlers_kobj);
1800         kobject_put(scst_handlers_kobj);
1801
1802         kobject_del(&scst_sysfs_root_kobj);
1803         kobject_put(&scst_sysfs_root_kobj);
1804
1805         wait_for_completion(&scst_sysfs_root_release_completion);
1806
1807         PRINT_INFO("%s", "Exiting SCST sysfs hierarchy done");
1808
1809         TRACE_EXIT();
1810         return;
1811 }