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