Various sysfs related fixes
[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 ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
647                             struct kobj_attribute *attr, char *buf)
648 {
649         struct scst_session *sess;
650
651         sess = container_of(kobj, struct scst_session, sess_kobj);
652
653         return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
654                 sess->initiator_name);
655 }
656
657 static struct kobj_attribute session_initiator_name_attr =
658         __ATTR(initiator_name, S_IRUGO, scst_sess_sysfs_initiator_name_show, NULL);
659
660 static struct attribute *scst_session_attrs[] = {
661         &session_commands_attr.attr,
662         &session_initiator_name_attr.attr,
663         NULL,
664 };
665
666 static void scst_sysfs_session_release(struct kobject *kobj)
667 {
668         struct scst_session *sess;
669
670         TRACE_ENTRY();
671
672         sess = container_of(kobj, struct scst_session, sess_kobj);
673
674         scst_release_session(sess);
675
676         TRACE_EXIT();
677         return;
678 }
679
680 static struct kobj_type scst_session_ktype = {
681         .sysfs_ops = &scst_sysfs_ops,
682         .release = scst_sysfs_session_release,
683         .default_attrs = scst_session_attrs,
684 };
685
686 /* scst_mutex supposed to be locked */
687 int scst_create_sess_sysfs(struct scst_session *sess)
688 {
689         int retval = 0;
690         struct scst_session *s;
691         const struct attribute **pattr;
692         char *name = (char *)sess->initiator_name;
693         int len = strlen(name) + 1, n = 1;
694
695         TRACE_ENTRY();
696
697 restart:
698         list_for_each_entry(s, &sess->tgt->sess_list, sess_list_entry) {
699                 if (!s->sess_kobj_initialized)
700                         continue;
701
702                 if (strcmp(name, s->sess_kobj.name) == 0) {
703                         if (s == sess)
704                                 continue;
705
706                         TRACE_DBG("Dublicated session from the same initiator "
707                                 "%s found", name);
708
709                         if (name == sess->initiator_name) {
710                                 len = strlen(sess->initiator_name);
711                                 len += 20;
712                                 name = kmalloc(len, GFP_KERNEL);
713                                 if (name == NULL) {
714                                         PRINT_ERROR("Unable to allocate a "
715                                                 "replacement name (size %d)",
716                                                 len);
717                                 }
718                         }
719
720                         snprintf(name, len, "%s_%d", sess->initiator_name, n);
721                         n++;
722                         goto restart;
723                 }
724         }
725
726         sess->sess_kobj_initialized = 1;
727
728         retval = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
729                               sess->tgt->tgt_sess_kobj, name);
730         if (retval != 0) {
731                 PRINT_ERROR("Can't add session %s to sysfs", name);
732                 goto out_free;
733         }
734
735         /*
736          * In case of errors there's no need for additional cleanup, because
737          * it will be done by the _put function() called by the caller.
738          */
739
740         pattr = sess->tgt->tgtt->sess_attrs;
741         if (pattr != NULL) {
742                 while (*pattr != NULL) {
743                         retval = sysfs_create_file(&sess->sess_kobj, *pattr);
744                         if (retval != 0) {
745                                 PRINT_ERROR("Can't add sess attr %s for sess "
746                                         "for initiator %s", (*pattr)->name,
747                                         name);
748                                 goto out_free;
749                         }
750                         pattr++;
751                 }
752         }
753
754 out_free:
755         if (name != sess->initiator_name)
756                 kfree(name);
757
758         TRACE_EXIT_RES(retval);
759         return retval;
760 }
761
762 void scst_sess_sysfs_put(struct scst_session *sess)
763 {
764         TRACE_ENTRY();
765
766         if (sess->sess_kobj_initialized) {
767                 kobject_del(&sess->sess_kobj);
768                 kobject_put(&sess->sess_kobj);
769         } else
770                 scst_release_session(sess);
771
772         TRACE_EXIT();
773         return;
774 }
775
776 /*
777  * Target luns directory implementation
778  */
779
780 static void scst_acg_dev_release(struct kobject *kobj)
781 {
782         struct scst_acg_dev *acg_dev;
783
784         TRACE_ENTRY();
785
786         acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
787
788         scst_acg_dev_destroy(acg_dev);
789
790         TRACE_EXIT();
791         return;
792 }
793
794 static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
795                                    struct kobj_attribute *attr,
796                                    char *buf)
797 {
798         struct scst_acg_dev *acg_dev;
799
800         acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
801
802         return sprintf(buf, "%d\n",
803                 (acg_dev->rd_only || acg_dev->dev->rd_only) ? 1 : 0);
804 }
805
806 static struct kobj_attribute lun_options_attr =
807         __ATTR(read_only, S_IRUGO, scst_lun_rd_only_show, NULL);
808
809 static struct attribute *lun_attrs[] = {
810         &lun_options_attr.attr,
811         NULL,
812 };
813
814 static struct kobj_type acg_dev_ktype = {
815         .sysfs_ops = &scst_sysfs_ops,
816         .release = scst_acg_dev_release,
817         .default_attrs = lun_attrs,
818 };
819
820 int scst_create_acg_dev_sysfs(struct scst_acg *acg, unsigned int virt_lun,
821         struct kobject *parent)
822 {
823         int retval;
824         struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
825         char str[20];
826
827         TRACE_ENTRY();
828
829         list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
830                             acg_dev_list_entry) {
831                 if (acg_dev_tmp->lun == virt_lun) {
832                         acg_dev = acg_dev_tmp;
833                         break;
834                 }
835         }
836         if (acg_dev == NULL) {
837                 PRINT_ERROR("%s", "acg_dev lookup for kobject creation failed");
838                 retval = -EINVAL;
839                 goto out;
840         }
841
842         snprintf(str, sizeof(str), "export%u",
843                 acg_dev->dev->dev_exported_lun_num++);
844
845         acg_dev->acg_dev_kobj_initialized = 1;
846
847         retval = kobject_init_and_add(&acg_dev->acg_dev_kobj, &acg_dev_ktype,
848                                       parent, "%u", virt_lun);
849         if (retval != 0) {
850                 PRINT_ERROR("Can't add acg %s to sysfs", acg->acg_name);
851                 goto out;
852         }
853
854         /*
855          * In case of errors there's no need for additional cleanup, because
856          * it will be done by the _put function() called by the caller.
857          */
858
859         retval = sysfs_create_link(acg_dev->dev->dev_exp_kobj,
860                                    &acg_dev->acg_dev_kobj, str);
861         if (retval != 0) {
862                 PRINT_ERROR("Can't create acg %s LUN link", acg->acg_name);
863                 goto out;
864         }
865
866         retval = sysfs_create_link(&acg_dev->acg_dev_kobj,
867                         &acg_dev->dev->dev_kobj, "device");
868         if (retval != 0) {
869                 PRINT_ERROR("Can't create acg %s device link", acg->acg_name);
870                 goto out;
871         }
872
873 out:
874         return retval;
875 }
876
877 static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
878                                    struct kobj_attribute *attr,
879                                    char *buf)
880 {
881         static char *help = "Usage: echo \"add|del H:C:I:L lun [READ_ONLY]\" "
882                                         ">mgmt\n"
883                             "       echo \"add|del VNAME lun [READ_ONLY]\" "
884                                         ">mgmt\n";
885
886         return sprintf(buf, help);
887 }
888
889 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
890                                     struct kobj_attribute *attr,
891                                     const char *buf, size_t count)
892 {
893         int res, virt = 0, read_only = 0, action;
894         char *buffer, *p, *e = NULL;
895         unsigned int host, channel = 0, id = 0, lun = 0, virt_lun;
896         struct scst_acg *acg;
897         struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
898         struct scst_device *d, *dev = NULL;
899         struct scst_tgt *tgt;
900
901 #define SCST_LUN_ACTION_ADD     1
902 #define SCST_LUN_ACTION_DEL     2
903 #define SCST_LUN_ACTION_REPLACE 3
904
905         TRACE_ENTRY();
906
907         tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
908         acg = tgt->default_acg;
909
910         buffer = kzalloc(count+1, GFP_KERNEL);
911         if (buffer == NULL) {
912                 res = -ENOMEM;
913                 goto out;
914         }
915
916         memcpy(buffer, buf, count);
917         buffer[count] = '\0';
918         p = buffer;
919
920         p = buffer;
921         if (p[strlen(p) - 1] == '\n')
922                 p[strlen(p) - 1] = '\0';
923         if (strncasecmp("add", p, 3) == 0) {
924                 p += 3;
925                 action = SCST_LUN_ACTION_ADD;
926         } else if (strncasecmp("del", p, 3) == 0) {
927                 p += 3;
928                 action = SCST_LUN_ACTION_DEL;
929         } else if (!strncasecmp("replace", p, 7)) {
930                 p += 7;
931                 action = SCST_LUN_ACTION_REPLACE;
932         } else {
933                 PRINT_ERROR("Unknown action \"%s\"", p);
934                 res = -EINVAL;
935                 goto out_free;
936         }
937
938         if (!isspace(*p)) {
939                 PRINT_ERROR("%s", "Syntax error");
940                 res = -EINVAL;
941                 goto out_free;
942         }
943
944         res = scst_suspend_activity(true);
945         if (res != 0)
946                 goto out_free;
947
948         if (mutex_lock_interruptible(&scst_mutex) != 0) {
949                 res = -EINTR;
950                 goto out_free_resume;
951         }
952
953         while (isspace(*p) && *p != '\0')
954                 p++;
955         e = p; /* save p */
956         host = simple_strtoul(p, &p, 0);
957         if (*p == ':') {
958                 channel = simple_strtoul(p + 1, &p, 0);
959                 id = simple_strtoul(p + 1, &p, 0);
960                 lun = simple_strtoul(p + 1, &p, 0);
961                 e = p;
962         } else {
963                 virt++;
964                 p = e; /* restore p */
965                 while (!isspace(*e) && *e != '\0')
966                         e++;
967                 *e = '\0';
968         }
969
970         list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
971                 if (virt) {
972                         if (d->virt_id && !strcmp(d->virt_name, p)) {
973                                 dev = d;
974                                 TRACE_DBG("Virt device %p (%s) found",
975                                           dev, p);
976                                 break;
977                         }
978                 } else {
979                         if (d->scsi_dev &&
980                             d->scsi_dev->host->host_no == host &&
981                             d->scsi_dev->channel == channel &&
982                             d->scsi_dev->id == id &&
983                             d->scsi_dev->lun == lun) {
984                                 dev = d;
985                                 TRACE_DBG("Dev %p (%d:%d:%d:%d) found",
986                                           dev, host, channel, id, lun);
987                                 break;
988                         }
989                 }
990         }
991         if (dev == NULL) {
992                 if (virt) {
993                         PRINT_ERROR("Virt device %s not found", p);
994                 } else {
995                         PRINT_ERROR("Device %d:%d:%d:%d not found",
996                                     host, channel, id, lun);
997                 }
998                 res = -EINVAL;
999                 goto out_free_up;
1000         }
1001
1002         switch (action) {
1003         case SCST_LUN_ACTION_ADD:
1004         case SCST_LUN_ACTION_REPLACE:
1005         {
1006                 bool dev_replaced = false;
1007
1008                 e++;
1009                 while (isspace(*e) && *e != '\0')
1010                         e++;
1011                 virt_lun = simple_strtoul(e, &e, 0);
1012
1013                 while (isspace(*e) && *e != '\0')
1014                         e++;
1015
1016                 if (*e != '\0') {
1017                         if ((strncasecmp("READ_ONLY", e, 9) == 0) &&
1018                             (isspace(e[9]) || (e[9] == '\0')))
1019                                 read_only = 1;
1020                         else {
1021                                 PRINT_ERROR("Unknown option \"%s\"", e);
1022                                 res = -EINVAL;
1023                                 goto out_free_up;
1024                         }
1025                 }
1026
1027                 acg_dev = NULL;
1028                 list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
1029                                     acg_dev_list_entry) {
1030                         if (acg_dev_tmp->lun == virt_lun) {
1031                                 acg_dev = acg_dev_tmp;
1032                                 break;
1033                         }
1034                 }
1035
1036                 if (acg_dev != NULL) {
1037                         if (action == SCST_LUN_ACTION_ADD) {
1038                                 PRINT_ERROR("virt lun %d already exists in "
1039                                         "group %s", virt_lun, acg->acg_name);
1040                                 res = -EINVAL;
1041                                 goto out_free_up;
1042                         } else {
1043                                 /* Replace */
1044                                 res = scst_acg_remove_dev(acg, acg_dev->dev,
1045                                                 false);
1046                                 if (res != 0)
1047                                         goto out_free_up;
1048
1049                                 dev_replaced = true;
1050                         }
1051                 }
1052
1053                 res = scst_acg_add_dev(acg, dev, virt_lun, read_only,
1054                                         !dev_replaced);
1055                 if (res != 0)
1056                         goto out_free_up;
1057
1058                 res = scst_create_acg_dev_sysfs(acg, virt_lun, kobj);
1059                 if (res != 0) {
1060                         PRINT_ERROR("%s", "Creation of acg_dev kobject failed");
1061                         goto out_remove_acg_dev;
1062                 }
1063
1064                 if (dev_replaced) {
1065                         struct scst_tgt_dev *tgt_dev;
1066
1067                         list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
1068                                         dev_tgt_dev_list_entry) {
1069                                 if ((tgt_dev->acg_dev->acg == acg) &&
1070                                     (tgt_dev->lun == virt_lun)) {
1071                                         TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
1072                                                 " on tgt_dev %p", tgt_dev);
1073                                         scst_gen_aen_or_ua(tgt_dev,
1074                                                 SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
1075                                 }
1076                         }
1077                 }
1078
1079                 break;
1080         }
1081         case SCST_LUN_ACTION_DEL:
1082                 res = scst_acg_remove_dev(acg, dev, true);
1083                 if (res != 0)
1084                         goto out_free_up;
1085                 break;
1086         }
1087
1088         res = count;
1089
1090 out_free_up:
1091         mutex_unlock(&scst_mutex);
1092
1093 out_free_resume:
1094         scst_resume_activity();
1095
1096 out_free:
1097         kfree(buffer);
1098
1099 out:
1100         TRACE_EXIT_RES(res);
1101         return res;
1102
1103 out_remove_acg_dev:
1104         scst_acg_remove_dev(acg, dev, true);
1105         goto out_free_up;
1106
1107 #undef SCST_LUN_ACTION_ADD
1108 #undef SCST_LUN_ACTION_DEL
1109 #undef SCST_LUN_ACTION_REPLACE
1110 }
1111
1112 /*
1113  * SGV directory implementation
1114  */
1115
1116 static struct kobj_attribute sgv_stat_attr =
1117         __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show,
1118                 sgv_sysfs_stat_reset);
1119
1120 static struct attribute *sgv_attrs[] = {
1121         &sgv_stat_attr.attr,
1122         NULL,
1123 };
1124
1125 static void sgv_kobj_release(struct kobject *kobj)
1126 {
1127         struct sgv_pool *pool;
1128
1129         TRACE_ENTRY();
1130
1131         pool = container_of(kobj, struct sgv_pool, sgv_kobj);
1132
1133         sgv_pool_destroy(pool);
1134
1135         TRACE_EXIT();
1136         return;
1137 }
1138
1139 static struct kobj_type sgv_pool_ktype = {
1140         .sysfs_ops = &scst_sysfs_ops,
1141         .release = sgv_kobj_release,
1142         .default_attrs = sgv_attrs,
1143 };
1144
1145 int scst_create_sgv_sysfs(struct sgv_pool *pool)
1146 {
1147         int retval;
1148
1149         TRACE_ENTRY();
1150
1151         pool->sgv_kobj_initialized = 1;
1152
1153         retval = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype,
1154                         scst_sgv_kobj, pool->name);
1155         if (retval != 0) {
1156                 PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name);
1157                 goto out;
1158         }
1159
1160 out:
1161         TRACE_EXIT_RES(retval);
1162         return retval;
1163 }
1164
1165 /* pool can be dead upon exit from this function! */
1166 void scst_sgv_sysfs_put(struct sgv_pool *pool)
1167 {
1168         if (pool->sgv_kobj_initialized) {
1169                 kobject_del(&pool->sgv_kobj);
1170                 kobject_put(&pool->sgv_kobj);
1171         } else
1172                 sgv_pool_destroy(pool);
1173         return;
1174 }
1175
1176 static struct kobj_attribute sgv_global_stat_attr =
1177         __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show,
1178                 sgv_sysfs_global_stat_reset);
1179
1180 static struct attribute *sgv_default_attrs[] = {
1181         &sgv_global_stat_attr.attr,
1182         NULL,
1183 };
1184
1185 static struct kobj_type sgv_ktype = {
1186         .sysfs_ops = &scst_sysfs_ops,
1187         .release = scst_sysfs_release,
1188         .default_attrs = sgv_default_attrs,
1189 };
1190
1191 /*
1192  * SCST sysfs root directory implementation
1193  */
1194
1195 static ssize_t scst_threads_show(struct kobject *kobj,
1196         struct kobj_attribute *attr, char *buf)
1197 {
1198         int count;
1199
1200         TRACE_ENTRY();
1201
1202         count = sprintf(buf, "%d\n", scst_global_threads_count());
1203
1204         TRACE_EXIT();
1205         return count;
1206 }
1207
1208 static ssize_t scst_threads_store(struct kobject *kobj,
1209         struct kobj_attribute *attr, const char *buf, size_t count)
1210 {
1211         int res = count;
1212         int oldtn, newtn, delta;
1213
1214         TRACE_ENTRY();
1215
1216         if (mutex_lock_interruptible(&scst_sysfs_mutex) != 0) {
1217                 res = -EINTR;
1218                 goto out;
1219         }
1220
1221         mutex_lock(&scst_global_threads_mutex);
1222
1223         oldtn = scst_nr_global_threads;
1224         sscanf(buf, "%du", &newtn);
1225
1226         if (newtn <= 0) {
1227                 PRINT_ERROR("Illegal threads num value %d", newtn);
1228                 res = -EINVAL;
1229                 goto out_up_thr_free;
1230         }
1231         delta = newtn - oldtn;
1232         if (delta < 0)
1233                 __scst_del_global_threads(-delta);
1234         else
1235                 __scst_add_global_threads(delta);
1236
1237         PRINT_INFO("Changed cmd threads num: old %d, new %d", oldtn, newtn);
1238
1239 out_up_thr_free:
1240         mutex_unlock(&scst_global_threads_mutex);
1241
1242         mutex_unlock(&scst_sysfs_mutex);
1243
1244 out:
1245         TRACE_EXIT_RES(res);
1246         return res;
1247 }
1248
1249 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1250
1251 static void scst_read_trace_tlb(const struct scst_trace_log *tbl, char *buf,
1252         unsigned long log_level, int *pos)
1253 {
1254         const struct scst_trace_log *t = tbl;
1255
1256         if (t == NULL)
1257                 goto out;
1258
1259         while (t->token) {
1260                 if (log_level & t->val) {
1261                         *pos += sprintf(&buf[*pos], "%s%s",
1262                                         (*pos == 0) ? "" : " | ",
1263                                         t->token);
1264                 }
1265                 t++;
1266         }
1267 out:
1268         return;
1269 }
1270
1271 static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
1272         unsigned long log_level, char *buf, const char *help)
1273 {
1274         int pos = 0;
1275
1276         scst_read_trace_tlb(scst_trace_tbl, buf, log_level, &pos);
1277         scst_read_trace_tlb(local_tbl, buf, log_level, &pos);
1278
1279         pos += sprintf(&buf[pos], "\n\n\nUsage:\n"
1280                 "       echo \"all|none|default\" >trace_level\n"
1281                 "       echo \"value DEC|0xHEX|0OCT\" >trace_level\n"
1282                 "       echo \"add|del TOKEN\" >trace_level\n"
1283                 "\nwhere TOKEN is one of [debug, function, line, pid,\n"
1284 #ifndef GENERATING_UPSTREAM_PATCH
1285                 "                      entryexit, buff, mem, sg, out_of_mem,\n"
1286 #else
1287                 "                      buff, mem, sg, out_of_mem,\n"
1288 #endif
1289                 "                      special, scsi, mgmt, minor,\n"
1290                 "                      mgmt_minor, mgmt_dbg, scsi_serializing,\n"
1291                 "                      retry, recv_bot, send_bot, recv_top,\n"
1292                 "                      send_top%s]", help != NULL ? help : "");
1293
1294         return pos;
1295 }
1296
1297 static ssize_t scst_main_trace_level_show(struct kobject *kobj,
1298         struct kobj_attribute *attr, char *buf)
1299 {
1300         return scst_trace_level_show(scst_local_trace_tbl, trace_flag,
1301                         buf, NULL);
1302 }
1303
1304 static int scst_write_trace(const char *buf, size_t length,
1305         unsigned long *log_level, unsigned long default_level,
1306         const char *name, const struct scst_trace_log *tbl)
1307 {
1308         int res = length;
1309         int action;
1310         unsigned long level = 0, oldlevel;
1311         char *buffer, *p, *e;
1312         const struct scst_trace_log *t;
1313
1314 #define SCST_TRACE_ACTION_ALL           1
1315 #define SCST_TRACE_ACTION_NONE          2
1316 #define SCST_TRACE_ACTION_DEFAULT       3
1317 #define SCST_TRACE_ACTION_ADD           4
1318 #define SCST_TRACE_ACTION_DEL           5
1319 #define SCST_TRACE_ACTION_VALUE         6
1320
1321         TRACE_ENTRY();
1322
1323         if ((buf == NULL) || (length == 0)) {
1324                 res = -EINVAL;
1325                 goto out;
1326         }
1327
1328         buffer = kmalloc(length+1, GFP_KERNEL);
1329         if (buffer == NULL) {
1330                 PRINT_ERROR("Unable to alloc intermediate buffer (size %zd)",
1331                         length+1);
1332                 res = -ENOMEM;
1333                 goto out;
1334         }
1335         memcpy(buffer, buf, length);
1336         buffer[length] = '\0';
1337
1338         p = buffer;
1339         if (!strncasecmp("all", p, 3)) {
1340                 action = SCST_TRACE_ACTION_ALL;
1341         } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
1342                 action = SCST_TRACE_ACTION_NONE;
1343         } else if (!strncasecmp("default", p, 7)) {
1344                 action = SCST_TRACE_ACTION_DEFAULT;
1345         } else if (!strncasecmp("add", p, 3)) {
1346                 p += 3;
1347                 action = SCST_TRACE_ACTION_ADD;
1348         } else if (!strncasecmp("del", p, 3)) {
1349                 p += 3;
1350                 action = SCST_TRACE_ACTION_DEL;
1351         } else if (!strncasecmp("value", p, 5)) {
1352                 p += 5;
1353                 action = SCST_TRACE_ACTION_VALUE;
1354         } else {
1355                 if (p[strlen(p) - 1] == '\n')
1356                         p[strlen(p) - 1] = '\0';
1357                 PRINT_ERROR("Unknown action \"%s\"", p);
1358                 res = -EINVAL;
1359                 goto out_free;
1360         }
1361
1362         switch (action) {
1363         case SCST_TRACE_ACTION_ADD:
1364         case SCST_TRACE_ACTION_DEL:
1365         case SCST_TRACE_ACTION_VALUE:
1366                 if (!isspace(*p)) {
1367                         PRINT_ERROR("%s", "Syntax error");
1368                         res = -EINVAL;
1369                         goto out_free;
1370                 }
1371         }
1372
1373         switch (action) {
1374         case SCST_TRACE_ACTION_ALL:
1375                 level = TRACE_ALL;
1376                 break;
1377         case SCST_TRACE_ACTION_DEFAULT:
1378                 level = default_level;
1379                 break;
1380         case SCST_TRACE_ACTION_NONE:
1381                 level = TRACE_NULL;
1382                 break;
1383         case SCST_TRACE_ACTION_ADD:
1384         case SCST_TRACE_ACTION_DEL:
1385                 while (isspace(*p) && *p != '\0')
1386                         p++;
1387                 e = p;
1388                 while (!isspace(*e) && *e != '\0')
1389                         e++;
1390                 *e = 0;
1391                 if (tbl) {
1392                         t = tbl;
1393                         while (t->token) {
1394                                 if (!strcasecmp(p, t->token)) {
1395                                         level = t->val;
1396                                         break;
1397                                 }
1398                                 t++;
1399                         }
1400                 }
1401                 if (level == 0) {
1402                         t = scst_trace_tbl;
1403                         while (t->token) {
1404                                 if (!strcasecmp(p, t->token)) {
1405                                         level = t->val;
1406                                         break;
1407                                 }
1408                                 t++;
1409                         }
1410                 }
1411                 if (level == 0) {
1412                         PRINT_ERROR("Unknown token \"%s\"", p);
1413                         res = -EINVAL;
1414                         goto out_free;
1415                 }
1416                 break;
1417         case SCST_TRACE_ACTION_VALUE:
1418                 while (isspace(*p) && *p != '\0')
1419                         p++;
1420                 res = strict_strtoul(p, 0, &level);
1421                 if (res != 0) {
1422                         PRINT_ERROR("Invalud trace value \"%s\"", p);
1423                         res = -EINVAL;
1424                         goto out_free;
1425                 }
1426                 break;
1427         }
1428
1429         oldlevel = *log_level;
1430
1431         switch (action) {
1432         case SCST_TRACE_ACTION_ADD:
1433                 *log_level |= level;
1434                 break;
1435         case SCST_TRACE_ACTION_DEL:
1436                 *log_level &= ~level;
1437                 break;
1438         default:
1439                 *log_level = level;
1440                 break;
1441         }
1442
1443         PRINT_INFO("Changed trace level for \"%s\": old 0x%08lx, new 0x%08lx",
1444                 name, oldlevel, *log_level);
1445
1446 out_free:
1447         kfree(buffer);
1448 out:
1449         TRACE_EXIT_RES(res);
1450         return res;
1451
1452 #undef SCST_TRACE_ACTION_ALL
1453 #undef SCST_TRACE_ACTION_NONE
1454 #undef SCST_TRACE_ACTION_DEFAULT
1455 #undef SCST_TRACE_ACTION_ADD
1456 #undef SCST_TRACE_ACTION_DEL
1457 #undef SCST_TRACE_ACTION_VALUE
1458 }
1459
1460 static ssize_t scst_main_trace_level_store(struct kobject *kobj,
1461         struct kobj_attribute *attr, const char *buf, size_t count)
1462 {
1463         int res;
1464
1465         TRACE_ENTRY();
1466
1467         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
1468                 res = -EINTR;
1469                 goto out;
1470         }
1471
1472         res = scst_write_trace(buf, count, &trace_flag,
1473                 SCST_DEFAULT_LOG_FLAGS, "scst", scst_local_trace_tbl);
1474
1475         mutex_unlock(&scst_log_mutex);
1476
1477 out:
1478         TRACE_EXIT_RES(res);
1479         return res;
1480 }
1481
1482 #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
1483
1484 static ssize_t scst_version_show(struct kobject *kobj,
1485                                  struct kobj_attribute *attr,
1486                                  char *buf)
1487 {
1488         TRACE_ENTRY();
1489
1490         sprintf(buf, "%s\n", SCST_VERSION_STRING);
1491
1492 #ifdef CONFIG_SCST_STRICT_SERIALIZING
1493         strcat(buf, "Strict serializing enabled\n");
1494 #endif
1495
1496 #ifdef CONFIG_SCST_EXTRACHECKS
1497         strcat(buf, "EXTRACHECKS\n");
1498 #endif
1499
1500 #ifdef CONFIG_SCST_TRACING
1501         strcat(buf, "TRACING\n");
1502 #endif
1503
1504 #ifdef CONFIG_SCST_DEBUG
1505         strcat(buf, "DEBUG\n");
1506 #endif
1507
1508 #ifdef CONFIG_SCST_DEBUG_TM
1509         strcat(buf, "DEBUG_TM\n");
1510 #endif
1511
1512 #ifdef CONFIG_SCST_DEBUG_RETRY
1513         strcat(buf, "DEBUG_RETRY\n");
1514 #endif
1515
1516 #ifdef CONFIG_SCST_DEBUG_OOM
1517         strcat(buf, "DEBUG_OOM\n");
1518 #endif
1519
1520 #ifdef CONFIG_SCST_DEBUG_SN
1521         strcat(buf, "DEBUG_SN\n");
1522 #endif
1523
1524 #ifdef CONFIG_SCST_USE_EXPECTED_VALUES
1525         strcat(buf, "USE_EXPECTED_VALUES\n");
1526 #endif
1527
1528 #ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
1529         strcat(buf, "ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ\n");
1530 #endif
1531
1532 #ifdef CONFIG_SCST_STRICT_SECURITY
1533         strcat(buf, "SCST_STRICT_SECURITY\n");
1534 #endif
1535
1536         TRACE_EXIT();
1537         return strlen(buf);
1538 }
1539
1540 static struct kobj_attribute scst_threads_attr =
1541         __ATTR(threads, S_IRUGO | S_IWUSR, scst_threads_show,
1542                scst_threads_store);
1543
1544 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1545 static struct kobj_attribute scst_trace_level_attr =
1546         __ATTR(trace_level, S_IRUGO | S_IWUSR, scst_main_trace_level_show,
1547                scst_main_trace_level_store);
1548 #endif
1549
1550 static struct kobj_attribute scst_version_attr =
1551         __ATTR(version, S_IRUGO, scst_version_show, NULL);
1552
1553 static struct attribute *scst_sysfs_root_default_attrs[] = {
1554         &scst_threads_attr.attr,
1555 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1556         &scst_trace_level_attr.attr,
1557 #endif
1558         &scst_version_attr.attr,
1559         NULL,
1560 };
1561
1562 static void scst_sysfs_root_release(struct kobject *kobj)
1563 {
1564         complete_all(&scst_sysfs_root_release_completion);
1565 }
1566
1567 static ssize_t scst_show(struct kobject *kobj, struct attribute *attr,
1568                          char *buf)
1569 {
1570         struct kobj_attribute *kobj_attr;
1571         kobj_attr = container_of(attr, struct kobj_attribute, attr);
1572
1573         return kobj_attr->show(kobj, kobj_attr, buf);
1574 }
1575
1576 static ssize_t scst_store(struct kobject *kobj, struct attribute *attr,
1577                           const char *buf, size_t count)
1578 {
1579         struct kobj_attribute *kobj_attr;
1580         kobj_attr = container_of(attr, struct kobj_attribute, attr);
1581
1582         return kobj_attr->store(kobj, kobj_attr, buf, count);
1583 }
1584
1585 struct sysfs_ops scst_sysfs_ops = {
1586         .show = scst_show,
1587         .store = scst_store,
1588 };
1589
1590 static struct kobj_type scst_sysfs_root_ktype = {
1591         .sysfs_ops = &scst_sysfs_ops,
1592         .release = scst_sysfs_root_release,
1593         .default_attrs = scst_sysfs_root_default_attrs,
1594 };
1595
1596 static void scst_devt_free(struct kobject *kobj)
1597 {
1598         struct scst_dev_type *devt;
1599
1600         TRACE_ENTRY();
1601
1602         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1603
1604         complete_all(&devt->devt_kobj_release_compl);
1605
1606         scst_devt_cleanup(devt);
1607
1608         TRACE_EXIT();
1609         return;
1610 }
1611
1612 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1613
1614 static ssize_t scst_devt_trace_level_show(struct kobject *kobj,
1615         struct kobj_attribute *attr, char *buf)
1616 {
1617         struct scst_dev_type *devt;
1618
1619         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1620
1621         return scst_trace_level_show(devt->trace_tbl,
1622                 devt->trace_flags ? *devt->trace_flags : 0, buf,
1623                 devt->trace_tbl_help);
1624 }
1625
1626 static ssize_t scst_devt_trace_level_store(struct kobject *kobj,
1627         struct kobj_attribute *attr, const char *buf, size_t count)
1628 {
1629         int res;
1630         struct scst_dev_type *devt;
1631
1632         TRACE_ENTRY();
1633
1634         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1635
1636         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
1637                 res = -EINTR;
1638                 goto out;
1639         }
1640
1641         res = scst_write_trace(buf, count, devt->trace_flags,
1642                 devt->default_trace_flags, devt->name, devt->trace_tbl);
1643
1644         mutex_unlock(&scst_log_mutex);
1645
1646 out:
1647         TRACE_EXIT_RES(res);
1648         return res;
1649 }
1650
1651 static struct kobj_attribute devt_trace_attr =
1652         __ATTR(trace_level, S_IRUGO | S_IWUSR,
1653                scst_devt_trace_level_show, scst_devt_trace_level_store);
1654
1655 #endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
1656
1657 static ssize_t scst_devt_type_show(struct kobject *kobj,
1658         struct kobj_attribute *attr, char *buf)
1659 {
1660         int pos;
1661         struct scst_dev_type *devt;
1662
1663         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1664
1665         pos = sprintf(buf, "%d - %s\n", devt->type,
1666                 (unsigned)devt->type > ARRAY_SIZE(scst_dev_handler_types) ?
1667                         "unknown" : scst_dev_handler_types[devt->type]);
1668
1669         return pos;
1670 }
1671
1672 static struct kobj_attribute scst_devt_type_attr =
1673         __ATTR(type, S_IRUGO, scst_devt_type_show, NULL);
1674
1675 static struct attribute *scst_devt_default_attrs[] = {
1676         &scst_devt_type_attr.attr,
1677         NULL,
1678 };
1679
1680 static struct kobj_type scst_devt_ktype = {
1681         .sysfs_ops = &scst_sysfs_ops,
1682         .release = scst_devt_free,
1683         .default_attrs = scst_devt_default_attrs,
1684 };
1685
1686 int scst_create_devt_sysfs(struct scst_dev_type *devt)
1687 {
1688         int retval;
1689         struct kobject *parent;
1690         const struct attribute **pattr;
1691
1692         TRACE_ENTRY();
1693
1694         init_completion(&devt->devt_kobj_release_compl);
1695
1696         if (devt->parent != NULL)
1697                 parent = &devt->parent->devt_kobj;
1698         else
1699                 parent = scst_handlers_kobj;
1700
1701         devt->devt_kobj_initialized = 1;
1702
1703         retval = kobject_init_and_add(&devt->devt_kobj, &scst_devt_ktype,
1704                         parent, devt->name);
1705         if (retval != 0) {
1706                 PRINT_ERROR("Can't add devt %s to sysfs", devt->name);
1707                 goto out;
1708         }
1709
1710         /*
1711          * In case of errors there's no need for additional cleanup, because
1712          * it will be done by the _put function() called by the caller.
1713          */
1714
1715         pattr = devt->devt_attrs;
1716         if (pattr != NULL) {
1717                 while (*pattr != NULL) {
1718                         retval = sysfs_create_file(&devt->devt_kobj, *pattr);
1719                         if (retval != 0) {
1720                                 PRINT_ERROR("Can't add devt attr %s for dev "
1721                                         "handler %s", (*pattr)->name,
1722                                         devt->name);
1723                                 goto out;
1724                         }
1725                         pattr++;
1726                 }
1727         }
1728
1729 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1730         if (devt->trace_flags != NULL) {
1731                 retval = sysfs_create_file(&devt->devt_kobj,
1732                                 &devt_trace_attr.attr);
1733                 if (retval != 0) {
1734                         PRINT_ERROR("Can't add devt trace_flag for dev "
1735                                 "handler %s", devt->name);
1736                         goto out;
1737                 }
1738         }
1739 #endif
1740
1741 out:
1742         TRACE_EXIT_RES(retval);
1743         return retval;
1744 }
1745
1746 void scst_devt_sysfs_put(struct scst_dev_type *devt)
1747 {
1748         TRACE_ENTRY();
1749
1750         if (devt->devt_kobj_initialized) {
1751                 int rc;
1752
1753                 kobject_del(&devt->devt_kobj);
1754                 kobject_put(&devt->devt_kobj);
1755
1756                 rc = wait_for_completion_timeout(&devt->devt_kobj_release_compl, HZ);
1757                 if (rc == 0) {
1758                         PRINT_INFO("Waiting for releasing sysfs entry "
1759                                 "for dev handler template %s...", devt->name);
1760                         wait_for_completion(&devt->devt_kobj_release_compl);
1761                         PRINT_INFO("Done waiting for releasing sysfs entry "
1762                                 "for dev handler template %s", devt->name);
1763                 }
1764         } else
1765                 scst_devt_cleanup(devt);
1766
1767         TRACE_EXIT();
1768         return;
1769 }
1770
1771 int __init scst_sysfs_init(void)
1772 {
1773         int retval = 0;
1774
1775         TRACE_ENTRY();
1776
1777         retval = kobject_init_and_add(&scst_sysfs_root_kobj,
1778                         &scst_sysfs_root_ktype, kernel_kobj, "%s", "scst_tgt");
1779         if (retval != 0)
1780                 goto sysfs_root_add_error;
1781
1782         scst_targets_kobj = kobject_create_and_add("targets",
1783                                 &scst_sysfs_root_kobj);
1784         if (scst_targets_kobj == NULL)
1785                 goto targets_kobj_error;
1786
1787         scst_devices_kobj = kobject_create_and_add("devices",
1788                                 &scst_sysfs_root_kobj);
1789         if (scst_devices_kobj == NULL)
1790                 goto devices_kobj_error;
1791
1792         scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL);
1793         if (scst_sgv_kobj == NULL)
1794                 goto sgv_kobj_error;
1795
1796         retval = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype,
1797                         &scst_sysfs_root_kobj, "%s", "sgv");
1798         if (retval != 0)
1799                 goto sgv_kobj_add_error;
1800
1801         scst_handlers_kobj = kobject_create_and_add("handlers",
1802                                         &scst_sysfs_root_kobj);
1803         if (scst_handlers_kobj == NULL)
1804                 goto handlers_kobj_error;
1805
1806 out:
1807         TRACE_EXIT_RES(retval);
1808         return retval;
1809
1810 handlers_kobj_error:
1811         kobject_del(scst_sgv_kobj);
1812
1813 sgv_kobj_add_error:
1814         kobject_put(scst_sgv_kobj);
1815
1816 sgv_kobj_error:
1817         kobject_del(scst_devices_kobj);
1818         kobject_put(scst_devices_kobj);
1819
1820 devices_kobj_error:
1821         kobject_del(scst_targets_kobj);
1822         kobject_put(scst_targets_kobj);
1823
1824 targets_kobj_error:
1825         kobject_del(&scst_sysfs_root_kobj);
1826
1827 sysfs_root_add_error:
1828         kobject_put(&scst_sysfs_root_kobj);
1829
1830         if (retval == 0)
1831                 retval = -EINVAL;
1832         goto out;
1833 }
1834
1835 void __exit scst_sysfs_cleanup(void)
1836 {
1837         TRACE_ENTRY();
1838
1839         PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
1840
1841         kobject_del(scst_sgv_kobj);
1842         kobject_put(scst_sgv_kobj);
1843
1844         kobject_del(scst_devices_kobj);
1845         kobject_put(scst_devices_kobj);
1846
1847         kobject_del(scst_targets_kobj);
1848         kobject_put(scst_targets_kobj);
1849
1850         kobject_del(scst_handlers_kobj);
1851         kobject_put(scst_handlers_kobj);
1852
1853         kobject_del(&scst_sysfs_root_kobj);
1854         kobject_put(&scst_sysfs_root_kobj);
1855
1856         wait_for_completion(&scst_sysfs_root_release_completion);
1857
1858         PRINT_INFO("%s", "Exiting SCST sysfs hierarchy done");
1859
1860         TRACE_EXIT();
1861         return;
1862 }