- SysfsRules file added
[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 DECLARE_COMPLETION(scst_sysfs_root_release_completion);
31
32 static struct kobject scst_sysfs_root_kobj;
33 static struct kobject *scst_targets_kobj;
34 static struct kobject *scst_devices_kobj;
35 static struct kobject *scst_sgv_kobj;
36 static struct kobject *scst_handlers_kobj;
37
38 struct sysfs_ops scst_sysfs_ops;
39 EXPORT_SYMBOL(scst_sysfs_ops);
40
41 static const char *scst_dev_handler_types[] = {
42     "Direct-access device (e.g., magnetic disk)",
43     "Sequential-access device (e.g., magnetic tape)",
44     "Printer device",
45     "Processor device",
46     "Write-once device (e.g., some optical disks)",
47     "CD-ROM device",
48     "Scanner device (obsolete)",
49     "Optical memory device (e.g., some optical disks)",
50     "Medium changer device (e.g., jukeboxes)",
51     "Communications device (obsolete)",
52     "Defined by ASC IT8 (Graphic arts pre-press devices)",
53     "Defined by ASC IT8 (Graphic arts pre-press devices)",
54     "Storage array controller device (e.g., RAID)",
55     "Enclosure services device",
56     "Simplified direct-access device (e.g., magnetic disk)",
57     "Optical card reader/writer device"
58 };
59
60 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
61
62 static DEFINE_MUTEX(scst_log_mutex);
63
64 static struct scst_trace_log scst_trace_tbl[] = {
65     { TRACE_OUT_OF_MEM,         "out_of_mem" },
66     { TRACE_MINOR,              "minor" },
67     { TRACE_SG_OP,              "sg" },
68     { TRACE_MEMORY,             "mem" },
69     { TRACE_BUFF,               "buff" },
70 #ifndef GENERATING_UPSTREAM_PATCH
71     { TRACE_ENTRYEXIT,          "entryexit" },
72 #endif
73     { TRACE_PID,                "pid" },
74     { TRACE_LINE,               "line" },
75     { TRACE_FUNCTION,           "function" },
76     { TRACE_DEBUG,              "debug" },
77     { TRACE_SPECIAL,            "special" },
78     { TRACE_SCSI,               "scsi" },
79     { TRACE_MGMT,               "mgmt" },
80     { TRACE_MGMT_DEBUG,         "mgmt_dbg" },
81     { TRACE_FLOW_CONTROL,       "flow_control" },
82     { 0,                        NULL }
83 };
84
85 static struct scst_trace_log scst_local_trace_tbl[] = {
86     { TRACE_RTRY,               "retry" },
87     { TRACE_SCSI_SERIALIZING,   "scsi_serializing" },
88     { TRACE_RCV_BOT,            "recv_bot" },
89     { TRACE_SND_BOT,            "send_bot" },
90     { TRACE_RCV_TOP,            "recv_top" },
91     { TRACE_SND_TOP,            "send_top" },
92     { 0,                        NULL }
93 };
94
95 static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
96         unsigned long log_level, char *buf, const char *help);
97 static int scst_write_trace(const char *buf, size_t length,
98         unsigned long *log_level, unsigned long default_level,
99         const char *name, const struct scst_trace_log *tbl);
100
101 #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
102
103 static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
104                                    struct kobj_attribute *attr,
105                                    char *buf);
106 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
107                                     struct kobj_attribute *attr,
108                                     const char *buf, size_t count);
109 static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
110                                    struct kobj_attribute *attr,
111                                    char *buf);
112 static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
113                                     struct kobj_attribute *attr,
114                                     const char *buf, size_t count);
115 static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
116                                    struct kobj_attribute *attr,
117                                    char *buf);
118 static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
119                                     struct kobj_attribute *attr,
120                                     const char *buf, size_t count);
121 static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
122                                     struct kobj_attribute *attr,
123                                     const char *buf, size_t count);
124 static ssize_t scst_acg_ini_mgmt_show(struct kobject *kobj,
125                                    struct kobj_attribute *attr,
126                                    char *buf);
127 static ssize_t scst_acg_ini_mgmt_store(struct kobject *kobj,
128                                     struct kobj_attribute *attr,
129                                     const char *buf, size_t count);
130 static ssize_t scst_acn_file_show(struct kobject *kobj,
131         struct kobj_attribute *attr, char *buf);
132
133 static void scst_sysfs_release(struct kobject *kobj)
134 {
135         kfree(kobj);
136 }
137
138 /*
139  * Target Template
140  */
141
142 static void scst_tgtt_release(struct kobject *kobj)
143 {
144         struct scst_tgt_template *tgtt;
145
146         TRACE_ENTRY();
147
148         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
149
150         complete_all(&tgtt->tgtt_kobj_release_cmpl);
151
152         scst_tgtt_cleanup(tgtt);
153
154         TRACE_EXIT();
155         return;
156 }
157
158 static struct kobj_type tgtt_ktype = {
159         .sysfs_ops = &scst_sysfs_ops,
160         .release = scst_tgtt_release,
161 };
162
163 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
164
165 static ssize_t scst_tgtt_trace_level_show(struct kobject *kobj,
166         struct kobj_attribute *attr, char *buf)
167 {
168         struct scst_tgt_template *tgtt;
169
170         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
171
172         return scst_trace_level_show(tgtt->trace_tbl,
173                 tgtt->trace_flags ? *tgtt->trace_flags : 0, buf,
174                 tgtt->trace_tbl_help);
175 }
176
177 static ssize_t scst_tgtt_trace_level_store(struct kobject *kobj,
178         struct kobj_attribute *attr, const char *buf, size_t count)
179 {
180         int res;
181         struct scst_tgt_template *tgtt;
182
183         TRACE_ENTRY();
184
185         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
186
187         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
188                 res = -EINTR;
189                 goto out;
190         }
191
192         res = scst_write_trace(buf, count, tgtt->trace_flags,
193                 tgtt->default_trace_flags, tgtt->name, tgtt->trace_tbl);
194
195         mutex_unlock(&scst_log_mutex);
196
197 out:
198         TRACE_EXIT_RES(res);
199         return res;
200 }
201
202 static struct kobj_attribute tgtt_trace_attr =
203         __ATTR(trace_level, S_IRUGO | S_IWUSR,
204                scst_tgtt_trace_level_show, scst_tgtt_trace_level_store);
205
206 #endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
207
208 static ssize_t scst_tgtt_mgmt_show(struct kobject *kobj,
209         struct kobj_attribute *attr, char *buf)
210 {
211         char *help = "Usage: echo \"add_target target_name [parameters]\" "
212                                 ">mgmt\n"
213                      "       echo \"del_target target_name\" >mgmt\n"
214                      "%s"
215                      "\n"
216                      "where parameters are one or more "
217                      "param_name=value pairs separated by ';'\n"
218                      "%s%s";
219         struct scst_tgt_template *tgtt;
220
221         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
222
223         if (tgtt->add_target_parameters_help != NULL)
224                 return sprintf(buf, help,
225                         (tgtt->mgmt_cmd_help) ? tgtt->mgmt_cmd_help : "",
226                         "\nThe following parameters available: ",
227                         tgtt->add_target_parameters_help);
228         else
229                 return sprintf(buf, help,
230                         (tgtt->mgmt_cmd_help) ? tgtt->mgmt_cmd_help : "",
231                         "", "");
232 }
233
234 static ssize_t scst_tgtt_mgmt_store(struct kobject *kobj,
235                                     struct kobj_attribute *attr,
236                                     const char *buf, size_t count)
237 {
238         int res;
239         char *buffer, *p, *pp, *target_name;
240         struct scst_tgt_template *tgtt;
241
242         TRACE_ENTRY();
243
244         tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
245
246         buffer = kzalloc(count+1, GFP_KERNEL);
247         if (buffer == NULL) {
248                 res = -ENOMEM;
249                 goto out;
250         }
251
252         memcpy(buffer, buf, count);
253         buffer[count] = '\0';
254
255         pp = buffer;
256         if (pp[strlen(pp) - 1] == '\n')
257                 pp[strlen(pp) - 1] = '\0';
258
259         p = scst_get_next_lexem(&pp);
260
261         if (strcasecmp("add_target", p) == 0) {
262                 target_name = scst_get_next_lexem(&pp);
263                 if (*target_name == '\0') {
264                         PRINT_ERROR("%s", "Target name required");
265                         res = -EINVAL;
266                         goto out_free;
267                 }
268                 res = tgtt->add_target(target_name, pp);
269         } else if (strcasecmp("del_target", p) == 0) {
270                 target_name = scst_get_next_lexem(&pp);
271                 if (*target_name == '\0') {
272                         PRINT_ERROR("%s", "Target name required");
273                         res = -EINVAL;
274                         goto out_free;
275                 }
276
277                 p = scst_get_next_lexem(&pp);
278                 if (*p != '\0')
279                         goto out_syntax_err;
280
281                 res = tgtt->del_target(target_name);
282         } else if (tgtt->mgmt_cmd != NULL) {
283                 scst_restore_token_str(p, pp);
284                 res = tgtt->mgmt_cmd(buffer);
285         } else {
286                 PRINT_ERROR("Unknown action \"%s\"", p);
287                 res = -EINVAL;
288                 goto out_free;
289         }
290
291         if (res == 0)
292                 res = count;
293
294 out_free:
295         kfree(buffer);
296
297 out:
298         TRACE_EXIT_RES(res);
299         return res;
300
301 out_syntax_err:
302         PRINT_ERROR("Syntax error on \"%s\"", p);
303         res = -EINVAL;
304         goto out_free;
305 }
306
307 static struct kobj_attribute scst_tgtt_mgmt =
308         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_tgtt_mgmt_show,
309                scst_tgtt_mgmt_store);
310
311 int scst_create_tgtt_sysfs(struct scst_tgt_template *tgtt)
312 {
313         int retval = 0;
314         const struct attribute **pattr;
315
316         TRACE_ENTRY();
317
318         init_completion(&tgtt->tgtt_kobj_release_cmpl);
319
320         tgtt->tgtt_kobj_initialized = 1;
321
322         retval = kobject_init_and_add(&tgtt->tgtt_kobj, &tgtt_ktype,
323                         scst_targets_kobj, tgtt->name);
324         if (retval != 0) {
325                 PRINT_ERROR("Can't add tgtt %s to sysfs", tgtt->name);
326                 goto out;
327         }
328
329         /*
330          * In case of errors there's no need for additional cleanup, because
331          * it will be done by the _put function() called by the caller.
332          */
333
334         if (tgtt->add_target != NULL) {
335                 retval = sysfs_create_file(&tgtt->tgtt_kobj,
336                                 &scst_tgtt_mgmt.attr);
337                 if (retval != 0) {
338                         PRINT_ERROR("Can't add mgmt attr for target driver %s",
339                                 tgtt->name);
340                         goto out;
341                 }
342         }
343
344         pattr = tgtt->tgtt_attrs;
345         if (pattr != NULL) {
346                 while (*pattr != NULL) {
347                         TRACE_DBG("Creating attr %s for target driver %s",
348                                 (*pattr)->name, tgtt->name);
349                         retval = sysfs_create_file(&tgtt->tgtt_kobj, *pattr);
350                         if (retval != 0) {
351                                 PRINT_ERROR("Can't add attr %s for target "
352                                         "driver %s", (*pattr)->name,
353                                         tgtt->name);
354                                 goto out;
355                         }
356                         pattr++;
357                 }
358         }
359
360 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
361         if (tgtt->trace_flags != NULL) {
362                 retval = sysfs_create_file(&tgtt->tgtt_kobj,
363                                 &tgtt_trace_attr.attr);
364                 if (retval != 0) {
365                         PRINT_ERROR("Can't add trace_flag for target "
366                                 "driver %s", tgtt->name);
367                         goto out;
368                 }
369         }
370 #endif
371
372 out:
373         TRACE_EXIT_RES(retval);
374         return retval;
375 }
376
377 void scst_tgtt_sysfs_put(struct scst_tgt_template *tgtt)
378 {
379         TRACE_ENTRY();
380
381         if (tgtt->tgtt_kobj_initialized) {
382                 int rc;
383
384                 kobject_del(&tgtt->tgtt_kobj);
385                 kobject_put(&tgtt->tgtt_kobj);
386
387                 rc = wait_for_completion_timeout(&tgtt->tgtt_kobj_release_cmpl, HZ);
388                 if (rc == 0) {
389                         PRINT_INFO("Waiting for releasing sysfs entry "
390                                 "for target template %s...", tgtt->name);
391                         wait_for_completion(&tgtt->tgtt_kobj_release_cmpl);
392                         PRINT_INFO("Done waiting for releasing sysfs "
393                                 "entry for target template %s", tgtt->name);
394                 }
395         } else
396                 scst_tgtt_cleanup(tgtt);
397
398         TRACE_EXIT();
399         return;
400 }
401
402 /*
403  * Target directory implementation
404  */
405
406 static void scst_tgt_release(struct kobject *kobj)
407 {
408         struct scst_tgt *tgt;
409
410         TRACE_ENTRY();
411
412         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
413
414         /* Let's make lockdep happy */
415         up_write(&tgt->tgt_attr_rwsem);
416
417         scst_free_tgt(tgt);
418
419         TRACE_EXIT();
420         return;
421 }
422
423 static ssize_t scst_tgt_attr_show(struct kobject *kobj, struct attribute *attr,
424         char *buf)
425 {
426         int res;
427         struct kobj_attribute *kobj_attr;
428         struct scst_tgt *tgt;
429
430         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
431
432         if (down_read_trylock(&tgt->tgt_attr_rwsem) == 0) {
433                 res = -ENOENT;
434                 goto out;
435         }
436
437         kobj_attr = container_of(attr, struct kobj_attribute, attr);
438
439         res = kobj_attr->show(kobj, kobj_attr, buf);
440
441         up_read(&tgt->tgt_attr_rwsem);
442
443 out:
444         return res;
445 }
446
447 static ssize_t scst_tgt_attr_store(struct kobject *kobj,
448         struct attribute *attr, const char *buf, size_t count)
449 {
450         int res;
451         struct kobj_attribute *kobj_attr;
452         struct scst_tgt *tgt;
453
454         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
455
456         if (down_read_trylock(&tgt->tgt_attr_rwsem) == 0) {
457                 res = -ENOENT;
458                 goto out;
459         }
460
461         kobj_attr = container_of(attr, struct kobj_attribute, attr);
462
463         res = kobj_attr->store(kobj, kobj_attr, buf, count);
464
465         up_read(&tgt->tgt_attr_rwsem);
466
467 out:
468         return res;
469 }
470
471 static struct sysfs_ops scst_tgt_sysfs_ops = {
472         .show = scst_tgt_attr_show,
473         .store = scst_tgt_attr_store,
474 };
475
476 static struct kobj_type tgt_ktype = {
477         .sysfs_ops = &scst_tgt_sysfs_ops,
478         .release = scst_tgt_release,
479 };
480
481 static void scst_acg_release(struct kobject *kobj)
482 {
483         struct scst_acg *acg;
484
485         TRACE_ENTRY();
486
487         acg = container_of(kobj, struct scst_acg, acg_kobj);
488
489         scst_destroy_acg(acg);
490
491         TRACE_EXIT();
492         return;
493 }
494
495 static struct kobj_type acg_ktype = {
496         .sysfs_ops = &scst_sysfs_ops,
497         .release = scst_acg_release,
498 };
499
500 static struct kobj_attribute scst_luns_mgmt =
501         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
502                scst_luns_mgmt_store);
503
504 static struct kobj_attribute scst_acg_luns_mgmt =
505         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
506                scst_acg_luns_mgmt_store);
507
508 static struct kobj_attribute scst_acg_ini_mgmt =
509         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_acg_ini_mgmt_show,
510                scst_acg_ini_mgmt_store);
511
512 static struct kobj_attribute scst_ini_group_mgmt =
513         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_ini_group_mgmt_show,
514                scst_ini_group_mgmt_store);
515
516 static struct kobj_attribute scst_rel_tgt_id =
517         __ATTR(rel_tgt_id, S_IRUGO | S_IWUSR, scst_rel_tgt_id_show,
518                scst_rel_tgt_id_store);
519
520 static ssize_t scst_tgt_enable_show(struct kobject *kobj,
521         struct kobj_attribute *attr, char *buf)
522 {
523         struct scst_tgt *tgt;
524         int res;
525         bool enabled;
526
527         TRACE_ENTRY();
528
529         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
530
531         enabled = tgt->tgtt->is_target_enabled(tgt);
532
533         res = sprintf(buf, "%d\n", enabled ? 1 : 0);
534
535         TRACE_EXIT_RES(res);
536         return res;
537 }
538
539 static ssize_t scst_tgt_enable_store(struct kobject *kobj,
540         struct kobj_attribute *attr, const char *buf, size_t count)
541 {
542         int res;
543         struct scst_tgt *tgt;
544         bool enable;
545
546         TRACE_ENTRY();
547
548         if (buf == NULL) {
549                 PRINT_ERROR("%s: NULL buffer?", __func__);
550                 res = -EINVAL;
551                 goto out;
552         }
553
554         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
555
556         switch (buf[0]) {
557         case '0':
558                 enable = false;
559                 break;
560         case '1':
561                 if (tgt->rel_tgt_id == 0) {
562                         res = gen_relative_target_port_id(&tgt->rel_tgt_id);
563                         if (res)
564                                 goto out;
565                         PRINT_INFO("Using autogenerated rel ID %d for target "
566                                 "%s", tgt->rel_tgt_id, tgt->tgt_name);
567                 } else {
568                         if (!scst_is_relative_target_port_id_unique(
569                             tgt->rel_tgt_id, tgt)) {
570                                 PRINT_ERROR("Relative port id %d is not unique",
571                                         tgt->rel_tgt_id);
572                                         res = -EBADSLT;
573                                 goto out;
574                         }
575                 }
576                 enable = true;
577                 break;
578         default:
579                 PRINT_ERROR("%s: Requested action not understood: %s",
580                        __func__, buf);
581                 res = -EINVAL;
582                 goto out;
583         }
584
585         res = tgt->tgtt->enable_target(tgt, enable);
586         if (res == 0)
587                 res = count;
588
589 out:
590         TRACE_EXIT_RES(res);
591         return res;
592 }
593
594 static struct kobj_attribute tgt_enable_attr =
595         __ATTR(enabled, S_IRUGO | S_IWUSR,
596                scst_tgt_enable_show, scst_tgt_enable_store);
597
598 int scst_create_tgt_sysfs(struct scst_tgt *tgt)
599 {
600         int retval;
601         const struct attribute **pattr;
602
603         TRACE_ENTRY();
604
605         init_rwsem(&tgt->tgt_attr_rwsem);
606
607         tgt->tgt_kobj_initialized = 1;
608
609         retval = kobject_init_and_add(&tgt->tgt_kobj, &tgt_ktype,
610                         &tgt->tgtt->tgtt_kobj, tgt->tgt_name);
611         if (retval != 0) {
612                 PRINT_ERROR("Can't add tgt %s to sysfs", tgt->tgt_name);
613                 goto out;
614         }
615
616         /*
617          * In case of errors there's no need for additional cleanup, because
618          * it will be done by the _put function() called by the caller.
619          */
620
621         if ((tgt->tgtt->enable_target != NULL) &&
622             (tgt->tgtt->is_target_enabled != NULL)) {
623                 retval = sysfs_create_file(&tgt->tgt_kobj,
624                                 &tgt_enable_attr.attr);
625                 if (retval != 0) {
626                         PRINT_ERROR("Can't add attr %s to sysfs",
627                                 tgt_enable_attr.attr.name);
628                         goto out;
629                 }
630         }
631
632         tgt->tgt_sess_kobj = kobject_create_and_add("sessions", &tgt->tgt_kobj);
633         if (tgt->tgt_sess_kobj == NULL) {
634                 PRINT_ERROR("Can't create sess kobj for tgt %s", tgt->tgt_name);
635                 goto out_nomem;
636         }
637
638         tgt->tgt_luns_kobj = kobject_create_and_add("luns", &tgt->tgt_kobj);
639         if (tgt->tgt_luns_kobj == NULL) {
640                 PRINT_ERROR("Can't create luns kobj for tgt %s", tgt->tgt_name);
641                 goto out_nomem;
642         }
643
644         retval = sysfs_create_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
645         if (retval != 0) {
646                 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
647                         scst_luns_mgmt.attr.name, tgt->tgt_name);
648                 goto out;
649         }
650
651         tgt->tgt_ini_grp_kobj = kobject_create_and_add("ini_groups",
652                                         &tgt->tgt_kobj);
653         if (tgt->tgt_ini_grp_kobj == NULL) {
654                 PRINT_ERROR("Can't create ini_grp kobj for tgt %s",
655                         tgt->tgt_name);
656                 goto out_nomem;
657         }
658
659         retval = sysfs_create_file(tgt->tgt_ini_grp_kobj,
660                         &scst_ini_group_mgmt.attr);
661         if (retval != 0) {
662                 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
663                         scst_ini_group_mgmt.attr.name, tgt->tgt_name);
664                 goto out;
665         }
666
667         retval = sysfs_create_file(&tgt->tgt_kobj,
668                         &scst_rel_tgt_id.attr);
669         if (retval != 0) {
670                 PRINT_ERROR("Can't add attribute %s for tgt %s",
671                         scst_rel_tgt_id.attr.name, tgt->tgt_name);
672                 goto out;
673         }
674
675         pattr = tgt->tgtt->tgt_attrs;
676         if (pattr != NULL) {
677                 while (*pattr != NULL) {
678                         TRACE_DBG("Creating attr %s for tgt %s", (*pattr)->name,
679                                 tgt->tgt_name);
680                         retval = sysfs_create_file(&tgt->tgt_kobj, *pattr);
681                         if (retval != 0) {
682                                 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
683                                         (*pattr)->name, tgt->tgt_name);
684                                 goto out;
685                         }
686                         pattr++;
687                 }
688         }
689
690 out:
691         TRACE_EXIT_RES(retval);
692         return retval;
693
694 out_nomem:
695         retval = -ENOMEM;
696         goto out;
697 }
698
699 /*
700  * Must not be called under scst_mutex or there can be a deadlock with
701  * tgt_attr_rwsem
702  */
703 void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt)
704 {
705         if (tgt->tgt_kobj_initialized) {
706                 down_write(&tgt->tgt_attr_rwsem);
707                 tgt->tgt_kobj_put_prepared = 1;
708         }
709
710         return;
711 }
712
713 /*
714  * Must not be called under scst_mutex or there can be a deadlock with
715  * tgt_attr_rwsem
716  */
717 void scst_tgt_sysfs_put(struct scst_tgt *tgt)
718 {
719         if (tgt->tgt_kobj_initialized) {
720                 kobject_del(tgt->tgt_sess_kobj);
721                 kobject_put(tgt->tgt_sess_kobj);
722
723                 kobject_del(tgt->tgt_luns_kobj);
724                 kobject_put(tgt->tgt_luns_kobj);
725
726                 kobject_del(tgt->tgt_ini_grp_kobj);
727                 kobject_put(tgt->tgt_ini_grp_kobj);
728
729                 kobject_del(&tgt->tgt_kobj);
730
731                 if (!tgt->tgt_kobj_put_prepared)
732                         down_write(&tgt->tgt_attr_rwsem);
733                 kobject_put(&tgt->tgt_kobj);
734         } else
735                 scst_free_tgt(tgt);
736         return;
737 }
738
739 /*
740  * Devices directory implementation
741  */
742
743 ssize_t scst_device_sysfs_type_show(struct kobject *kobj,
744                             struct kobj_attribute *attr, char *buf)
745 {
746         int pos = 0;
747
748         struct scst_device *dev;
749
750         dev = container_of(kobj, struct scst_device, dev_kobj);
751
752         pos = sprintf(buf, "%d - %s\n", dev->type,
753                 (unsigned)dev->type > ARRAY_SIZE(scst_dev_handler_types) ?
754                       "unknown" : scst_dev_handler_types[dev->type]);
755
756         return pos;
757 }
758
759 static struct kobj_attribute device_type_attr =
760         __ATTR(type, S_IRUGO, scst_device_sysfs_type_show, NULL);
761
762 static struct attribute *scst_device_attrs[] = {
763         &device_type_attr.attr,
764         NULL,
765 };
766
767 static void scst_sysfs_device_release(struct kobject *kobj)
768 {
769         struct scst_device *dev;
770
771         TRACE_ENTRY();
772
773         dev = container_of(kobj, struct scst_device, dev_kobj);
774
775         /* Let's make lockdep happy */
776         up_write(&dev->dev_attr_rwsem);
777
778         scst_free_device(dev);
779
780         TRACE_EXIT();
781         return;
782 }
783
784 int scst_create_devt_dev_sysfs(struct scst_device *dev)
785 {
786         int retval = 0;
787         const struct attribute **pattr;
788
789         TRACE_ENTRY();
790
791         if (dev->handler == &scst_null_devtype)
792                 goto out;
793
794         sBUG_ON(!dev->handler->devt_kobj_initialized);
795
796         /*
797          * In case of errors there's no need for additional cleanup, because
798          * it will be done by the _put function() called by the caller.
799          */
800
801         retval = sysfs_create_link(&dev->dev_kobj,
802                         &dev->handler->devt_kobj, "handler");
803         if (retval != 0) {
804                 PRINT_ERROR("Can't create handler link for dev %s",
805                         dev->virt_name);
806                 goto out;
807         }
808
809         retval = sysfs_create_link(&dev->handler->devt_kobj,
810                         &dev->dev_kobj, dev->virt_name);
811         if (retval != 0) {
812                 PRINT_ERROR("Can't create handler link for dev %s",
813                         dev->virt_name);
814                 goto out;
815         }
816
817         pattr = dev->handler->dev_attrs;
818         if (pattr != NULL) {
819                 while (*pattr != NULL) {
820                         retval = sysfs_create_file(&dev->dev_kobj, *pattr);
821                         if (retval != 0) {
822                                 PRINT_ERROR("Can't add dev attr %s for dev %s",
823                                         (*pattr)->name, dev->virt_name);
824                                 goto out;
825                         }
826                         pattr++;
827                 }
828         }
829
830 out:
831         TRACE_EXIT_RES(retval);
832         return retval;
833 }
834
835 void scst_devt_dev_sysfs_put(struct scst_device *dev)
836 {
837         const struct attribute **pattr;
838
839         TRACE_ENTRY();
840
841         if (dev->handler == &scst_null_devtype)
842                 goto out;
843
844         sBUG_ON(!dev->handler->devt_kobj_initialized);
845
846         pattr = dev->handler->dev_attrs;
847         if (pattr != NULL) {
848                 while (*pattr != NULL) {
849                         sysfs_remove_file(&dev->dev_kobj, *pattr);
850                         pattr++;
851                 }
852         }
853
854         sysfs_remove_link(&dev->dev_kobj, "handler");
855         sysfs_remove_link(&dev->handler->devt_kobj, dev->virt_name);
856
857 out:
858         TRACE_EXIT();
859         return;
860 }
861
862 static ssize_t scst_dev_attr_show(struct kobject *kobj, struct attribute *attr,
863                          char *buf)
864 {
865         int res;
866         struct kobj_attribute *kobj_attr;
867         struct scst_device *dev;
868
869         dev = container_of(kobj, struct scst_device, dev_kobj);
870
871         if (down_read_trylock(&dev->dev_attr_rwsem) == 0) {
872                 res = -ENOENT;
873                 goto out;
874         }
875
876         kobj_attr = container_of(attr, struct kobj_attribute, attr);
877
878         res = kobj_attr->show(kobj, kobj_attr, buf);
879
880         up_read(&dev->dev_attr_rwsem);
881
882 out:
883         return res;
884 }
885
886 static ssize_t scst_dev_attr_store(struct kobject *kobj, struct attribute *attr,
887                           const char *buf, size_t count)
888 {
889         int res;
890         struct kobj_attribute *kobj_attr;
891         struct scst_device *dev;
892
893         dev = container_of(kobj, struct scst_device, dev_kobj);
894
895         if (down_read_trylock(&dev->dev_attr_rwsem) == 0) {
896                 res = -ENOENT;
897                 goto out;
898         }
899
900         kobj_attr = container_of(attr, struct kobj_attribute, attr);
901
902         res = kobj_attr->store(kobj, kobj_attr, buf, count);
903
904         up_read(&dev->dev_attr_rwsem);
905
906 out:
907         return res;
908 }
909
910 static struct sysfs_ops scst_dev_sysfs_ops = {
911         .show = scst_dev_attr_show,
912         .store = scst_dev_attr_store,
913 };
914
915 static struct kobj_type scst_device_ktype = {
916         .sysfs_ops = &scst_dev_sysfs_ops,
917         .release = scst_sysfs_device_release,
918         .default_attrs = scst_device_attrs,
919 };
920
921 int scst_create_device_sysfs(struct scst_device *dev)
922 {
923         int retval = 0;
924
925         TRACE_ENTRY();
926
927         init_rwsem(&dev->dev_attr_rwsem);
928
929         dev->dev_kobj_initialized = 1;
930
931         retval = kobject_init_and_add(&dev->dev_kobj, &scst_device_ktype,
932                                       scst_devices_kobj, dev->virt_name);
933         if (retval != 0) {
934                 PRINT_ERROR("Can't add device %s to sysfs", dev->virt_name);
935                 goto out;
936         }
937
938         /*
939          * In case of errors there's no need for additional cleanup, because
940          * it will be done by the _put function() called by the caller.
941          */
942
943         dev->dev_exp_kobj = kobject_create_and_add("exported",
944                                                    &dev->dev_kobj);
945         if (dev->dev_exp_kobj == NULL) {
946                 PRINT_ERROR("Can't create exported link for device %s",
947                         dev->virt_name);
948                 retval = -ENOMEM;
949                 goto out;
950         }
951
952         if (dev->scsi_dev != NULL) {
953                 retval = sysfs_create_link(&dev->dev_kobj,
954                         &dev->scsi_dev->sdev_dev.kobj, "scsi_device");
955                 if (retval != 0) {
956                         PRINT_ERROR("Can't create scsi_device link for dev %s",
957                                 dev->virt_name);
958                         goto out;
959                 }
960         }
961
962 out:
963         TRACE_EXIT_RES(retval);
964         return retval;
965 }
966
967 /*
968  * Must not be called under scst_mutex or there can be a deadlock with
969  * dev_attr_rwsem
970  */
971 void scst_device_sysfs_put(struct scst_device *dev)
972 {
973         TRACE_ENTRY();
974
975         if (dev->dev_kobj_initialized) {
976                 kobject_del(dev->dev_exp_kobj);
977                 kobject_put(dev->dev_exp_kobj);
978
979                 kobject_del(&dev->dev_kobj);
980
981                 down_write(&dev->dev_attr_rwsem);
982                 kobject_put(&dev->dev_kobj);
983         } else
984                 scst_free_device(dev);
985
986         TRACE_EXIT();
987         return;
988 }
989
990 /*
991  * Target sessions directory implementation
992  */
993
994 static ssize_t scst_sess_sysfs_commands_show(struct kobject *kobj,
995                             struct kobj_attribute *attr, char *buf)
996 {
997         struct scst_session *sess;
998
999         sess = container_of(kobj, struct scst_session, sess_kobj);
1000
1001         return sprintf(buf, "%i\n", atomic_read(&sess->sess_cmd_count));
1002 }
1003
1004 static struct kobj_attribute session_commands_attr =
1005         __ATTR(commands, S_IRUGO, scst_sess_sysfs_commands_show, NULL);
1006
1007 static ssize_t scst_sess_sysfs_active_commands_show(struct kobject *kobj,
1008                             struct kobj_attribute *attr, char *buf)
1009 {
1010         int res;
1011         struct scst_session *sess;
1012         int active_cmds = 0, t;
1013
1014         if (mutex_lock_interruptible(&scst_mutex) != 0) {
1015                 res = -EINTR;
1016                 goto out;
1017         }
1018
1019         sess = container_of(kobj, struct scst_session, sess_kobj);
1020
1021         for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
1022                 struct list_head *sess_tgt_dev_list_head =
1023                         &sess->sess_tgt_dev_list_hash[t];
1024                 struct scst_tgt_dev *tgt_dev;
1025                 list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
1026                                 sess_tgt_dev_list_entry) {
1027                         active_cmds += atomic_read(&tgt_dev->tgt_dev_cmd_count);
1028                 }
1029         }
1030
1031         mutex_unlock(&scst_mutex);
1032
1033         res = sprintf(buf, "%i\n", active_cmds);
1034
1035 out:
1036         return res;
1037 }
1038
1039 static struct kobj_attribute session_active_commands_attr =
1040         __ATTR(active_commands, S_IRUGO, scst_sess_sysfs_active_commands_show,
1041                 NULL);
1042
1043 static ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
1044                             struct kobj_attribute *attr, char *buf)
1045 {
1046         struct scst_session *sess;
1047
1048         sess = container_of(kobj, struct scst_session, sess_kobj);
1049
1050         return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
1051                 sess->initiator_name);
1052 }
1053
1054 static struct kobj_attribute session_initiator_name_attr =
1055         __ATTR(initiator_name, S_IRUGO, scst_sess_sysfs_initiator_name_show, NULL);
1056
1057 static struct attribute *scst_session_attrs[] = {
1058         &session_commands_attr.attr,
1059         &session_active_commands_attr.attr,
1060         &session_initiator_name_attr.attr,
1061         NULL,
1062 };
1063
1064 static void scst_sysfs_session_release(struct kobject *kobj)
1065 {
1066         struct scst_session *sess;
1067
1068         TRACE_ENTRY();
1069
1070         sess = container_of(kobj, struct scst_session, sess_kobj);
1071
1072         /* Let's make lockdep happy */
1073         up_write(&sess->sess_attr_rwsem);
1074
1075         scst_release_session(sess);
1076
1077         TRACE_EXIT();
1078         return;
1079 }
1080
1081 static ssize_t scst_sess_attr_show(struct kobject *kobj, struct attribute *attr,
1082                          char *buf)
1083 {
1084         int res;
1085         struct kobj_attribute *kobj_attr;
1086         struct scst_session *sess;
1087
1088         sess = container_of(kobj, struct scst_session, sess_kobj);
1089
1090         if (down_read_trylock(&sess->sess_attr_rwsem) == 0) {
1091                 res = -ENOENT;
1092                 goto out;
1093         }
1094
1095         kobj_attr = container_of(attr, struct kobj_attribute, attr);
1096
1097         res = kobj_attr->show(kobj, kobj_attr, buf);
1098
1099         up_read(&sess->sess_attr_rwsem);
1100
1101 out:
1102         return res;
1103 }
1104
1105 static ssize_t scst_sess_attr_store(struct kobject *kobj, struct attribute *attr,
1106                           const char *buf, size_t count)
1107 {
1108         int res;
1109         struct kobj_attribute *kobj_attr;
1110         struct scst_session *sess;
1111
1112         sess = container_of(kobj, struct scst_session, sess_kobj);
1113
1114         if (down_read_trylock(&sess->sess_attr_rwsem) == 0) {
1115                 res = -ENOENT;
1116                 goto out;
1117         }
1118
1119         kobj_attr = container_of(attr, struct kobj_attribute, attr);
1120
1121         res = kobj_attr->store(kobj, kobj_attr, buf, count);
1122
1123         up_read(&sess->sess_attr_rwsem);
1124
1125 out:
1126         return res;
1127 }
1128
1129 static struct sysfs_ops scst_sess_sysfs_ops = {
1130         .show = scst_sess_attr_show,
1131         .store = scst_sess_attr_store,
1132 };
1133
1134 static struct kobj_type scst_session_ktype = {
1135         .sysfs_ops = &scst_sess_sysfs_ops,
1136         .release = scst_sysfs_session_release,
1137         .default_attrs = scst_session_attrs,
1138 };
1139
1140 /* scst_mutex supposed to be locked */
1141 int scst_create_sess_sysfs(struct scst_session *sess)
1142 {
1143         int retval = 0;
1144         struct scst_session *s;
1145         const struct attribute **pattr;
1146         char *name = (char *)sess->initiator_name;
1147         int len = strlen(name) + 1, n = 1;
1148
1149         TRACE_ENTRY();
1150
1151 restart:
1152         list_for_each_entry(s, &sess->tgt->sess_list, sess_list_entry) {
1153                 if (!s->sess_kobj_initialized)
1154                         continue;
1155
1156                 if (strcmp(name, kobject_name(&s->sess_kobj)) == 0) {
1157                         if (s == sess)
1158                                 continue;
1159
1160                         TRACE_DBG("Dublicated session from the same initiator "
1161                                 "%s found", name);
1162
1163                         if (name == sess->initiator_name) {
1164                                 len = strlen(sess->initiator_name);
1165                                 len += 20;
1166                                 name = kmalloc(len, GFP_KERNEL);
1167                                 if (name == NULL) {
1168                                         PRINT_ERROR("Unable to allocate a "
1169                                                 "replacement name (size %d)",
1170                                                 len);
1171                                 }
1172                         }
1173
1174                         snprintf(name, len, "%s_%d", sess->initiator_name, n);
1175                         n++;
1176                         goto restart;
1177                 }
1178         }
1179
1180         init_rwsem(&sess->sess_attr_rwsem);
1181
1182         sess->sess_kobj_initialized = 1;
1183
1184         retval = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
1185                               sess->tgt->tgt_sess_kobj, name);
1186         if (retval != 0) {
1187                 PRINT_ERROR("Can't add session %s to sysfs", name);
1188                 goto out_free;
1189         }
1190
1191         /*
1192          * In case of errors there's no need for additional cleanup, because
1193          * it will be done by the _put function() called by the caller.
1194          */
1195
1196         pattr = sess->tgt->tgtt->sess_attrs;
1197         if (pattr != NULL) {
1198                 while (*pattr != NULL) {
1199                         retval = sysfs_create_file(&sess->sess_kobj, *pattr);
1200                         if (retval != 0) {
1201                                 PRINT_ERROR("Can't add sess attr %s for sess "
1202                                         "for initiator %s", (*pattr)->name,
1203                                         name);
1204                                 goto out_free;
1205                         }
1206                         pattr++;
1207                 }
1208         }
1209
1210         if (sess->acg == sess->tgt->default_acg)
1211                 retval = sysfs_create_link(&sess->sess_kobj,
1212                                 sess->tgt->tgt_luns_kobj, "luns");
1213         else
1214                 retval = sysfs_create_link(&sess->sess_kobj,
1215                                 sess->acg->luns_kobj, "luns");
1216
1217 out_free:
1218         if (name != sess->initiator_name)
1219                 kfree(name);
1220
1221         TRACE_EXIT_RES(retval);
1222         return retval;
1223 }
1224
1225 /*
1226  * Must not be called under scst_mutex or there can be a deadlock with
1227  * sess_attr_rwsem
1228  */
1229 void scst_sess_sysfs_put(struct scst_session *sess)
1230 {
1231         TRACE_ENTRY();
1232
1233         if (sess->sess_kobj_initialized) {
1234                 kobject_del(&sess->sess_kobj);
1235
1236                 down_write(&sess->sess_attr_rwsem);
1237                 kobject_put(&sess->sess_kobj);
1238         } else
1239                 scst_release_session(sess);
1240
1241         TRACE_EXIT();
1242         return;
1243 }
1244
1245 /*
1246  * Target luns directory implementation
1247  */
1248
1249 static void scst_acg_dev_release(struct kobject *kobj)
1250 {
1251         struct scst_acg_dev *acg_dev;
1252
1253         TRACE_ENTRY();
1254
1255         acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
1256
1257         scst_acg_dev_destroy(acg_dev);
1258
1259         TRACE_EXIT();
1260         return;
1261 }
1262
1263 static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
1264                                    struct kobj_attribute *attr,
1265                                    char *buf)
1266 {
1267         struct scst_acg_dev *acg_dev;
1268
1269         acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
1270
1271         if (acg_dev->rd_only || acg_dev->dev->rd_only)
1272                 return sprintf(buf, "%d\n%s\n", 1, SCST_SYSFS_KEY_MARK);
1273         else
1274                 return sprintf(buf, "%d\n", 0);
1275 }
1276
1277 static struct kobj_attribute lun_options_attr =
1278         __ATTR(read_only, S_IRUGO, scst_lun_rd_only_show, NULL);
1279
1280 static struct attribute *lun_attrs[] = {
1281         &lun_options_attr.attr,
1282         NULL,
1283 };
1284
1285 static struct kobj_type acg_dev_ktype = {
1286         .sysfs_ops = &scst_sysfs_ops,
1287         .release = scst_acg_dev_release,
1288         .default_attrs = lun_attrs,
1289 };
1290
1291 int scst_create_acg_dev_sysfs(struct scst_acg *acg, unsigned int virt_lun,
1292         struct kobject *parent)
1293 {
1294         int retval;
1295         struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
1296         char str[20];
1297
1298         TRACE_ENTRY();
1299
1300         list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
1301                             acg_dev_list_entry) {
1302                 if (acg_dev_tmp->lun == virt_lun) {
1303                         acg_dev = acg_dev_tmp;
1304                         break;
1305                 }
1306         }
1307         if (acg_dev == NULL) {
1308                 PRINT_ERROR("%s", "acg_dev lookup for kobject creation failed");
1309                 retval = -EINVAL;
1310                 goto out;
1311         }
1312
1313         snprintf(str, sizeof(str), "export%u",
1314                 acg_dev->dev->dev_exported_lun_num++);
1315
1316         kobject_get(&acg_dev->dev->dev_kobj);
1317
1318         acg_dev->acg_dev_kobj_initialized = 1;
1319
1320         retval = kobject_init_and_add(&acg_dev->acg_dev_kobj, &acg_dev_ktype,
1321                                       parent, "%u", virt_lun);
1322         if (retval != 0) {
1323                 PRINT_ERROR("Can't add acg %s to sysfs", acg->acg_name);
1324                 goto out;
1325         }
1326
1327         /*
1328          * In case of errors there's no need for additional cleanup, because
1329          * it will be done by the _put function() called by the caller.
1330          */
1331
1332         retval = sysfs_create_link(acg_dev->dev->dev_exp_kobj,
1333                                    &acg_dev->acg_dev_kobj, str);
1334         if (retval != 0) {
1335                 PRINT_ERROR("Can't create acg %s LUN link", acg->acg_name);
1336                 goto out;
1337         }
1338
1339         retval = sysfs_create_link(&acg_dev->acg_dev_kobj,
1340                         &acg_dev->dev->dev_kobj, "device");
1341         if (retval != 0) {
1342                 PRINT_ERROR("Can't create acg %s device link", acg->acg_name);
1343                 goto out;
1344         }
1345
1346 out:
1347         return retval;
1348 }
1349
1350 static ssize_t __scst_luns_mgmt_store(struct scst_acg *acg,
1351         struct kobject *kobj, const char *buf, size_t count)
1352 {
1353         int res, virt = 0, read_only = 0, action;
1354         char *buffer, *p, *e = NULL;
1355         unsigned int host, channel = 0, id = 0, lun = 0, virt_lun;
1356         struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
1357         struct scst_device *d, *dev = NULL;
1358
1359 #define SCST_LUN_ACTION_ADD     1
1360 #define SCST_LUN_ACTION_DEL     2
1361 #define SCST_LUN_ACTION_REPLACE 3
1362 #define SCST_LUN_ACTION_CLEAR   4
1363
1364         TRACE_ENTRY();
1365
1366         buffer = kzalloc(count+1, GFP_KERNEL);
1367         if (buffer == NULL) {
1368                 res = -ENOMEM;
1369                 goto out;
1370         }
1371
1372         memcpy(buffer, buf, count);
1373         buffer[count] = '\0';
1374         p = buffer;
1375
1376         p = buffer;
1377         if (p[strlen(p) - 1] == '\n')
1378                 p[strlen(p) - 1] = '\0';
1379         if (strncasecmp("add", p, 3) == 0) {
1380                 p += 3;
1381                 action = SCST_LUN_ACTION_ADD;
1382         } else if (strncasecmp("del", p, 3) == 0) {
1383                 p += 3;
1384                 action = SCST_LUN_ACTION_DEL;
1385         } else if (!strncasecmp("replace", p, 7)) {
1386                 p += 7;
1387                 action = SCST_LUN_ACTION_REPLACE;
1388         } else if (!strncasecmp("clear", p, 5)) {
1389                 p += 5;
1390                 action = SCST_LUN_ACTION_CLEAR;
1391         } else {
1392                 PRINT_ERROR("Unknown action \"%s\"", p);
1393                 res = -EINVAL;
1394                 goto out_free;
1395         }
1396
1397         res = scst_suspend_activity(true);
1398         if (res != 0)
1399                 goto out_free;
1400
1401         if (mutex_lock_interruptible(&scst_mutex) != 0) {
1402                 res = -EINTR;
1403                 goto out_free_resume;
1404         }
1405
1406         if (action != SCST_LUN_ACTION_CLEAR) {
1407                 if (!isspace(*p)) {
1408                         PRINT_ERROR("%s", "Syntax error");
1409                         res = -EINVAL;
1410                         goto out_free_up;
1411                 }
1412
1413                 while (isspace(*p) && *p != '\0')
1414                         p++;
1415                 e = p; /* save p */
1416                 host = simple_strtoul(p, &p, 0);
1417                 if (*p == ':') {
1418                         channel = simple_strtoul(p + 1, &p, 0);
1419                         id = simple_strtoul(p + 1, &p, 0);
1420                         lun = simple_strtoul(p + 1, &p, 0);
1421                         e = p;
1422                 } else {
1423                         virt++;
1424                         p = e; /* restore p */
1425                         while (!isspace(*e) && *e != '\0')
1426                                 e++;
1427                         *e = '\0';
1428                 }
1429
1430                 list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
1431                         if (virt) {
1432                                 if (d->virt_id && !strcmp(d->virt_name, p)) {
1433                                         dev = d;
1434                                         TRACE_DBG("Virt device %p (%s) found",
1435                                                   dev, p);
1436                                         break;
1437                                 }
1438                         } else {
1439                                 if (d->scsi_dev &&
1440                                     d->scsi_dev->host->host_no == host &&
1441                                     d->scsi_dev->channel == channel &&
1442                                     d->scsi_dev->id == id &&
1443                                     d->scsi_dev->lun == lun) {
1444                                         dev = d;
1445                                         TRACE_DBG("Dev %p (%d:%d:%d:%d) found",
1446                                                   dev, host, channel, id, lun);
1447                                         break;
1448                                 }
1449                         }
1450                 }
1451                 if (dev == NULL) {
1452                         if (virt) {
1453                                 PRINT_ERROR("Virt device '%s' not found", p);
1454                         } else {
1455                                 PRINT_ERROR("Device %d:%d:%d:%d not found",
1456                                             host, channel, id, lun);
1457                         }
1458                         res = -EINVAL;
1459                         goto out_free_up;
1460                 }
1461         }
1462
1463         switch (action) {
1464         case SCST_LUN_ACTION_ADD:
1465         case SCST_LUN_ACTION_REPLACE:
1466         {
1467                 bool dev_replaced = false;
1468
1469                 e++;
1470                 while (isspace(*e) && *e != '\0')
1471                         e++;
1472                 virt_lun = simple_strtoul(e, &e, 0);
1473
1474                 while (isspace(*e) && *e != '\0')
1475                         e++;
1476
1477                 while (1) {
1478                         char *pp;
1479                         unsigned long val;
1480                         char *param = scst_get_next_token_str(&e);
1481                         if (param == NULL)
1482                                 break;
1483
1484                         p = scst_get_next_lexem(&param);
1485                         if (*p == '\0') {
1486                                 PRINT_ERROR("Syntax error at %s (device %s)",
1487                                         param, dev->virt_name);
1488                                 res = -EINVAL;
1489                                 goto out_free_up;
1490                         }
1491
1492                         pp = scst_get_next_lexem(&param);
1493                         if (*pp == '\0') {
1494                                 PRINT_ERROR("Parameter %s value missed for device %s",
1495                                         p, dev->virt_name);
1496                                 res = -EINVAL;
1497                                 goto out_free_up;
1498                         }
1499
1500                         if (scst_get_next_lexem(&param)[0] != '\0') {
1501                                 PRINT_ERROR("Too many parameter's %s values (device %s)",
1502                                         p, dev->virt_name);
1503                                 res = -EINVAL;
1504                                 goto out_free_up;
1505                         }
1506
1507                         res = strict_strtoul(pp, 0, &val);
1508                         if (res != 0) {
1509                                 PRINT_ERROR("strict_strtoul() for %s failed: %d "
1510                                         "(device %s)", pp, res, dev->virt_name);
1511                                 goto out_free_up;
1512                         }
1513
1514                         if (!strcasecmp("read_only", p)) {
1515                                 read_only = val;
1516                                 TRACE_DBG("READ ONLY %d", read_only);
1517                         } else {
1518                                 PRINT_ERROR("Unknown parameter %s (device %s)",
1519                                         p, dev->virt_name);
1520                                 res = -EINVAL;
1521                                 goto out_free_up;
1522                         }
1523                 }
1524
1525                 acg_dev = NULL;
1526                 list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
1527                                     acg_dev_list_entry) {
1528                         if (acg_dev_tmp->lun == virt_lun) {
1529                                 acg_dev = acg_dev_tmp;
1530                                 break;
1531                         }
1532                 }
1533
1534                 if (acg_dev != NULL) {
1535                         if (action == SCST_LUN_ACTION_ADD) {
1536                                 PRINT_ERROR("virt lun %d already exists in "
1537                                         "group %s", virt_lun, acg->acg_name);
1538                                 res = -EEXIST;
1539                                 goto out_free_up;
1540                         } else {
1541                                 /* Replace */
1542                                 res = scst_acg_remove_dev(acg, acg_dev->dev,
1543                                                 false);
1544                                 if (res != 0)
1545                                         goto out_free_up;
1546
1547                                 dev_replaced = true;
1548                         }
1549                 }
1550
1551                 res = scst_acg_add_dev(acg, dev, virt_lun, read_only,
1552                                         !dev_replaced);
1553                 if (res != 0)
1554                         goto out_free_up;
1555
1556                 res = scst_create_acg_dev_sysfs(acg, virt_lun, kobj);
1557                 if (res != 0) {
1558                         PRINT_ERROR("%s", "Creation of acg_dev kobject failed");
1559                         goto out_remove_acg_dev;
1560                 }
1561
1562                 if (dev_replaced) {
1563                         struct scst_tgt_dev *tgt_dev;
1564
1565                         list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
1566                                 dev_tgt_dev_list_entry) {
1567                                 if ((tgt_dev->acg_dev->acg == acg) &&
1568                                     (tgt_dev->lun == virt_lun)) {
1569                                         TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
1570                                                 " on tgt_dev %p", tgt_dev);
1571                                         scst_gen_aen_or_ua(tgt_dev,
1572                                                 SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
1573                                 }
1574                         }
1575                 }
1576
1577                 break;
1578         }
1579         case SCST_LUN_ACTION_DEL:
1580                 res = scst_acg_remove_dev(acg, dev, true);
1581                 if (res != 0)
1582                         goto out_free_up;
1583                 break;
1584         case SCST_LUN_ACTION_CLEAR:
1585                 PRINT_INFO("Removed all devices from group %s",
1586                         acg->acg_name);
1587                 list_for_each_entry_safe(acg_dev, acg_dev_tmp,
1588                                          &acg->acg_dev_list,
1589                                          acg_dev_list_entry) {
1590                         res = scst_acg_remove_dev(acg, acg_dev->dev,
1591                                 list_is_last(&acg_dev->acg_dev_list_entry,
1592                                              &acg->acg_dev_list));
1593                         if (res)
1594                                 goto out_free_up;
1595                 }
1596                 break;
1597         }
1598
1599         res = count;
1600
1601 out_free_up:
1602         mutex_unlock(&scst_mutex);
1603
1604 out_free_resume:
1605         scst_resume_activity();
1606
1607 out_free:
1608         kfree(buffer);
1609
1610 out:
1611         TRACE_EXIT_RES(res);
1612         return res;
1613
1614 out_remove_acg_dev:
1615         scst_acg_remove_dev(acg, dev, true);
1616         goto out_free_up;
1617
1618 #undef SCST_LUN_ACTION_ADD
1619 #undef SCST_LUN_ACTION_DEL
1620 #undef SCST_LUN_ACTION_REPLACE
1621 #undef SCST_LUN_ACTION_CLEAR
1622 }
1623
1624 static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
1625                                    struct kobj_attribute *attr,
1626                                    char *buf)
1627 {
1628         static char *help = "Usage: echo \"add|del H:C:I:L lun [parameters]\" "
1629                                         ">mgmt\n"
1630                             "       echo \"add|del VNAME lun [parameters]\" "
1631                                         ">mgmt\n"
1632                             "       echo \"replace H:C:I:L lun [parameters]\" "
1633                                         ">mgmt\n"
1634                             "       echo \"replace VNAME lun [parameters]\" "
1635                                         ">mgmt\n"
1636                             "       echo \"clear\" >mgmt\n"
1637                             "\n"
1638                             "where parameters are one or more "
1639                             "param_name=value pairs separated by ';'\n"
1640                             "\nThe following parameters available: read_only.";
1641
1642         return sprintf(buf, help);
1643 }
1644
1645 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
1646                                     struct kobj_attribute *attr,
1647                                     const char *buf, size_t count)
1648 {
1649         int res;
1650         struct scst_acg *acg;
1651         struct scst_tgt *tgt;
1652
1653         tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
1654         acg = tgt->default_acg;
1655         res = __scst_luns_mgmt_store(acg, kobj, buf, count);
1656
1657         TRACE_EXIT_RES(res);
1658         return res;
1659 }
1660
1661 static int scst_create_acg_sysfs(struct scst_tgt *tgt,
1662         struct scst_acg *acg)
1663 {
1664         int retval = 0;
1665
1666         TRACE_ENTRY();
1667
1668         acg->acg_kobj_initialized = 1;
1669
1670         retval = kobject_init_and_add(&acg->acg_kobj, &acg_ktype,
1671                 tgt->tgt_ini_grp_kobj, acg->acg_name);
1672         if (retval != 0) {
1673                 PRINT_ERROR("Can't add acg '%s' to sysfs", acg->acg_name);
1674                 goto out;
1675         }
1676
1677         acg->luns_kobj = kobject_create_and_add("luns", &acg->acg_kobj);
1678         if (acg->luns_kobj == NULL) {
1679                 PRINT_ERROR("Can't create luns kobj for tgt %s",
1680                         tgt->tgt_name);
1681                 retval = -ENOMEM;
1682                 goto out;
1683         }
1684
1685         retval = sysfs_create_file(acg->luns_kobj, &scst_acg_luns_mgmt.attr);
1686         if (retval != 0) {
1687                 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
1688                         scst_acg_luns_mgmt.attr.name, tgt->tgt_name);
1689                 goto out;
1690         }
1691
1692         acg->initiators_kobj = kobject_create_and_add("initiators",
1693                 &acg->acg_kobj);
1694         if (acg->initiators_kobj == NULL) {
1695                 PRINT_ERROR("Can't create initiators kobj for tgt %s",
1696                         tgt->tgt_name);
1697                 retval = -ENOMEM;
1698                 goto out;
1699         }
1700
1701         retval = sysfs_create_file(acg->initiators_kobj,
1702                 &scst_acg_ini_mgmt.attr);
1703         if (retval != 0) {
1704                 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
1705                         scst_acg_ini_mgmt.attr.name, tgt->tgt_name);
1706                 goto out;
1707         }
1708 out:
1709         TRACE_EXIT_RES(retval);
1710         return retval;
1711 }
1712
1713 void scst_acg_sysfs_put(struct scst_acg *acg)
1714 {
1715         TRACE_ENTRY();
1716
1717         if (acg->acg_kobj_initialized) {
1718                 scst_clear_acg(acg);
1719
1720                 kobject_del(acg->luns_kobj);
1721                 kobject_put(acg->luns_kobj);
1722
1723                 kobject_del(acg->initiators_kobj);
1724                 kobject_put(acg->initiators_kobj);
1725
1726                 kobject_del(&acg->acg_kobj);
1727                 kobject_put(&acg->acg_kobj);
1728         } else
1729                 scst_destroy_acg(acg);
1730
1731         TRACE_EXIT();
1732         return;
1733 }
1734
1735 static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
1736         struct kobj_attribute *attr, char *buf)
1737 {
1738         static char *help = "Usage: echo \"create GROUP_NAME\" "
1739                                         ">mgmt\n"
1740                             "       echo \"del GROUP_NAME\" "
1741                                         ">mgmt\n";
1742
1743         return sprintf(buf, help);
1744 }
1745
1746 static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
1747         struct kobj_attribute *attr, const char *buf, size_t count)
1748 {
1749         int res, action;
1750         int len;
1751         char *name;
1752         char *buffer, *p, *e = NULL;
1753         struct scst_acg *a, *acg = NULL;
1754         struct scst_tgt *tgt;
1755
1756 #define SCST_INI_GROUP_ACTION_CREATE    1
1757 #define SCST_INI_GROUP_ACTION_DEL       2
1758
1759         TRACE_ENTRY();
1760
1761         tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
1762
1763         buffer = kzalloc(count+1, GFP_KERNEL);
1764         if (buffer == NULL) {
1765                 res = -ENOMEM;
1766                 goto out;
1767         }
1768
1769         memcpy(buffer, buf, count);
1770         buffer[count] = '\0';
1771         p = buffer;
1772
1773         p = buffer;
1774         if (p[strlen(p) - 1] == '\n')
1775                 p[strlen(p) - 1] = '\0';
1776         if (strncasecmp("create ", p, 7) == 0) {
1777                 p += 7;
1778                 action = SCST_INI_GROUP_ACTION_CREATE;
1779         } else if (strncasecmp("del ", p, 4) == 0) {
1780                 p += 4;
1781                 action = SCST_INI_GROUP_ACTION_DEL;
1782         } else {
1783                 PRINT_ERROR("Unknown action \"%s\"", p);
1784                 res = -EINVAL;
1785                 goto out_free;
1786         }
1787
1788         res = scst_suspend_activity(true);
1789         if (res != 0)
1790                 goto out_free;
1791
1792         if (mutex_lock_interruptible(&scst_mutex) != 0) {
1793                 res = -EINTR;
1794                 goto out_free_resume;
1795         }
1796
1797         while (isspace(*p) && *p != '\0')
1798                 p++;
1799         e = p;
1800         while (!isspace(*e) && *e != '\0')
1801                 e++;
1802         *e = '\0';
1803
1804         if (p[0] == '\0') {
1805                 PRINT_ERROR("%s", "Group name required");
1806                 res = -EINVAL;
1807                 goto out_free_up;
1808         }
1809
1810         list_for_each_entry(a, &tgt->acg_list, acg_list_entry) {
1811                 if (strcmp(a->acg_name, p) == 0) {
1812                         TRACE_DBG("group (acg) %p %s found",
1813                                   a, a->acg_name);
1814                         acg = a;
1815                         break;
1816                 }
1817         }
1818
1819         switch (action) {
1820         case SCST_INI_GROUP_ACTION_CREATE:
1821                 TRACE_DBG("Creating group '%s'", p);
1822                 if (acg != NULL) {
1823                         PRINT_ERROR("acg name %s exist", p);
1824                         res = -EINVAL;
1825                         goto out_free_up;
1826                 }
1827
1828                 len = strlen(p) + 1;
1829                 name = kmalloc(len, GFP_KERNEL);
1830                 if (name == NULL) {
1831                         PRINT_ERROR("%s", "Allocation of name failed");
1832                         res = -ENOMEM;
1833                         goto out_free_up;
1834                 }
1835                 strlcpy(name, p, len);
1836
1837                 acg = scst_alloc_add_acg(tgt, name);
1838                 kfree(name);
1839                 if (acg == NULL)
1840                         goto out_free_up;
1841
1842                 res = scst_create_acg_sysfs(tgt, acg);
1843                 if (res != 0)
1844                         goto out_free_acg;
1845                 break;
1846         case SCST_INI_GROUP_ACTION_DEL:
1847                 TRACE_DBG("Deleting group '%s'", p);
1848                 if (acg == NULL) {
1849                         PRINT_ERROR("Group %s not found", p);
1850                         res = -EINVAL;
1851                         goto out_free_up;
1852                 }
1853                 if (!scst_acg_sess_is_empty(acg)) {
1854                         PRINT_ERROR("Group %s is not empty", acg->acg_name);
1855                         res = -EBUSY;
1856                         goto out_free_up;
1857                 }
1858                 scst_acg_sysfs_put(acg);
1859                 break;
1860         }
1861
1862         res = count;
1863
1864 out_free_up:
1865         mutex_unlock(&scst_mutex);
1866
1867 out_free_resume:
1868         scst_resume_activity();
1869
1870 out_free:
1871         kfree(buffer);
1872
1873 out:
1874         TRACE_EXIT_RES(res);
1875         return res;
1876
1877 out_free_acg:
1878         scst_acg_sysfs_put(acg);
1879         goto out_free_up;
1880
1881 #undef SCST_LUN_ACTION_CREATE
1882 #undef SCST_LUN_ACTION_DEL
1883 }
1884
1885 static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
1886         struct kobj_attribute *attr, char *buf)
1887 {
1888         struct scst_tgt *tgt;
1889         int res;
1890
1891         TRACE_ENTRY();
1892
1893         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
1894
1895         res = sprintf(buf, "%d\n%s", tgt->rel_tgt_id,
1896                 (tgt->rel_tgt_id != 0) ? SCST_SYSFS_KEY_MARK "\n" : "");
1897
1898         TRACE_EXIT_RES(res);
1899         return res;
1900 }
1901
1902 static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
1903         struct kobj_attribute *attr, const char *buf, size_t count)
1904 {
1905         int res = 0;
1906         struct scst_tgt *tgt;
1907         unsigned long rel_tgt_id;
1908
1909         TRACE_ENTRY();
1910
1911         if (buf == NULL)
1912                 goto out_err;
1913
1914         tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
1915
1916         res = strict_strtoul(buf, 0, &rel_tgt_id);
1917         if (res != 0)
1918                 goto out_err;
1919
1920         TRACE_DBG("Try to set relative target port id %d",
1921                 (uint16_t)rel_tgt_id);
1922
1923         if (rel_tgt_id < SCST_MIN_REL_TGT_ID ||
1924             rel_tgt_id > SCST_MAX_REL_TGT_ID) {
1925                 if ((rel_tgt_id == 0) && !tgt->tgtt->is_target_enabled(tgt))
1926                         goto set;
1927
1928                 PRINT_ERROR("Invalid relative port id %d",
1929                         (uint16_t)rel_tgt_id);
1930                 res = -EINVAL;
1931                 goto out;
1932         }
1933
1934         if (tgt->tgtt->is_target_enabled(tgt) &&
1935             rel_tgt_id != tgt->rel_tgt_id) {
1936                 if (!scst_is_relative_target_port_id_unique(rel_tgt_id, tgt)) {
1937                         PRINT_ERROR("Relative port id %d is not unique",
1938                                 (uint16_t)rel_tgt_id);
1939                         res = -EBADSLT;
1940                         goto out;
1941                 }
1942         }
1943
1944 set:
1945         tgt->rel_tgt_id = (uint16_t)rel_tgt_id;
1946
1947         res = count;
1948
1949 out:
1950         TRACE_EXIT_RES(res);
1951         return res;
1952
1953 out_err:
1954         PRINT_ERROR("%s: Requested action not understood: %s", __func__, buf);
1955         res = -EINVAL;
1956         goto out;
1957 }
1958
1959 int scst_create_acn_sysfs(struct scst_acg *acg, struct scst_acn *acn)
1960 {
1961         int retval = 0;
1962         int len;
1963         struct kobj_attribute *attr = NULL;
1964
1965         TRACE_ENTRY();
1966
1967         acn->acn_attr = NULL;
1968
1969         attr = kzalloc(sizeof(struct kobj_attribute), GFP_KERNEL);
1970         if (attr == NULL) {
1971                 PRINT_ERROR("Unable to allocate attributes for initiator '%s'",
1972                         acn->name);
1973                 retval = -ENOMEM;
1974                 goto out;
1975         }
1976
1977         len = strlen(acn->name) + 1;
1978         attr->attr.name = kzalloc(len, GFP_KERNEL);
1979         if (attr->attr.name == NULL) {
1980                 PRINT_ERROR("Unable to allocate attributes for initiator '%s'",
1981                         acn->name);
1982                 retval = -ENOMEM;
1983                 goto out_free;
1984         }
1985         strlcpy((char *)attr->attr.name, acn->name, len);
1986
1987         attr->attr.owner = THIS_MODULE;
1988         attr->attr.mode = S_IRUGO;
1989         attr->show = scst_acn_file_show;
1990         attr->store = NULL;
1991
1992         retval = sysfs_create_file(acg->initiators_kobj, &attr->attr);
1993         if (retval != 0) {
1994                 PRINT_ERROR("Unable to create acn '%s' for group '%s'",
1995                         acn->name, acg->acg_name);
1996                 kfree(attr->attr.name);
1997                 goto out_free;
1998         }
1999
2000         acn->acn_attr = attr;
2001
2002 out:
2003         TRACE_EXIT_RES(retval);
2004         return retval;
2005
2006 out_free:
2007         kfree(attr);
2008         goto out;
2009 }
2010
2011 void scst_acn_sysfs_del(struct scst_acg *acg, struct scst_acn *acn,
2012         bool reassign)
2013 {
2014         TRACE_ENTRY();
2015
2016         if (acn->acn_attr != NULL) {
2017                 sysfs_remove_file(acg->initiators_kobj,
2018                         &acn->acn_attr->attr);
2019                 kfree(acn->acn_attr->attr.name);
2020                 kfree(acn->acn_attr);
2021         }
2022         scst_acg_remove_acn(acn);
2023         if (reassign)
2024                 scst_check_reassign_sessions();
2025
2026         TRACE_EXIT();
2027         return;
2028 }
2029
2030 static ssize_t scst_acn_file_show(struct kobject *kobj,
2031         struct kobj_attribute *attr, char *buf)
2032 {
2033         return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
2034                 attr->attr.name);
2035 }
2036
2037 static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
2038                                     struct kobj_attribute *attr,
2039                                     const char *buf, size_t count)
2040 {
2041         int res;
2042         struct scst_acg *acg;
2043
2044         acg = container_of(kobj->parent, struct scst_acg, acg_kobj);
2045         res = __scst_luns_mgmt_store(acg, kobj, buf, count);
2046
2047         TRACE_EXIT_RES(res);
2048         return res;
2049 }
2050
2051 static ssize_t scst_acg_ini_mgmt_show(struct kobject *kobj,
2052         struct kobj_attribute *attr, char *buf)
2053 {
2054         static char *help = "Usage: echo \"add INITIATOR_NAME\" "
2055                                         ">mgmt\n"
2056                             "       echo \"del INITIATOR_NAME\" "
2057                                         ">mgmt\n"
2058                             "       echo \"move INITIATOR_NAME DEST_GROUP_NAME\" "
2059                                         ">mgmt\n"
2060                             "       echo \"clear\" "
2061                                         ">mgmt\n";
2062
2063         return sprintf(buf, help);
2064 }
2065
2066 static ssize_t scst_acg_ini_mgmt_store(struct kobject *kobj,
2067         struct kobj_attribute *attr, const char *buf, size_t count)
2068 {
2069         int res, action;
2070         char *buffer, *p, *e = NULL;
2071         char *name = NULL, *group = NULL;
2072         struct scst_acg *acg = NULL, *acg_dest = NULL;
2073         struct scst_tgt *tgt = NULL;
2074         struct scst_acn *acn = NULL, *acn_tmp;
2075
2076 #define SCST_ACG_ACTION_INI_ADD         1
2077 #define SCST_ACG_ACTION_INI_DEL         2
2078 #define SCST_ACG_ACTION_INI_CLEAR       3
2079 #define SCST_ACG_ACTION_INI_MOVE        4
2080
2081         TRACE_ENTRY();
2082
2083         acg = container_of(kobj->parent, struct scst_acg, acg_kobj);
2084
2085         buffer = kzalloc(count+1, GFP_KERNEL);
2086         if (buffer == NULL) {
2087                 res = -ENOMEM;
2088                 goto out;
2089         }
2090
2091         memcpy(buffer, buf, count);
2092         buffer[count] = '\0';
2093         p = buffer;
2094
2095         p = buffer;
2096         if (p[strlen(p) - 1] == '\n')
2097                 p[strlen(p) - 1] = '\0';
2098
2099         if (strncasecmp("add", p, 3) == 0) {
2100                 p += 3;
2101                 action = SCST_ACG_ACTION_INI_ADD;
2102         } else if (strncasecmp("del", p, 3) == 0) {
2103                 p += 3;
2104                 action = SCST_ACG_ACTION_INI_DEL;
2105         } else if (strncasecmp("clear", p, 5) == 0) {
2106                 p += 5;
2107                 action = SCST_ACG_ACTION_INI_CLEAR;
2108         } else if (strncasecmp("move", p, 4) == 0) {
2109                 p += 4;
2110                 action = SCST_ACG_ACTION_INI_MOVE;
2111         } else {
2112                 PRINT_ERROR("Unknown action \"%s\"", p);
2113                 res = -EINVAL;
2114                 goto out_free;
2115         }
2116
2117         if (action != SCST_ACG_ACTION_INI_CLEAR)
2118                 if (!isspace(*p)) {
2119                         PRINT_ERROR("%s", "Syntax error");
2120                         res = -EINVAL;
2121                         goto out_free;
2122                 }
2123
2124         res = scst_suspend_activity(true);
2125         if (res != 0)
2126                 goto out_free;
2127
2128         if (mutex_lock_interruptible(&scst_mutex) != 0) {
2129                 res = -EINTR;
2130                 goto out_free_resume;
2131         }
2132
2133         if (action != SCST_ACG_ACTION_INI_CLEAR)
2134                 while (isspace(*p) && *p != '\0')
2135                         p++;
2136
2137         switch (action) {
2138         case SCST_ACG_ACTION_INI_ADD:
2139                 e = p;
2140                 while (!isspace(*e) && *e != '\0')
2141                         e++;
2142                 *e = '\0';
2143                 name = p;
2144
2145                 if (name[0] == '\0') {
2146                         PRINT_ERROR("%s", "Invalid initiator name");
2147                         res = -EINVAL;
2148                         goto out_free_up;
2149                 }
2150
2151                 res = scst_acg_add_name(acg, name);
2152                 if (res != 0)
2153                         goto out_free_up;
2154                 break;
2155         case SCST_ACG_ACTION_INI_DEL:
2156                 e = p;
2157                 while (!isspace(*e) && *e != '\0')
2158                         e++;
2159                 *e = '\0';
2160                 name = p;
2161
2162                 if (name[0] == '\0') {
2163                         PRINT_ERROR("%s", "Invalid initiator name");
2164                         res = -EINVAL;
2165                         goto out_free_up;
2166                 }
2167
2168                 acn = scst_acg_find_name(acg, name);
2169                 if (acn == NULL) {
2170                         PRINT_ERROR("Unable to find "
2171                                 "initiator '%s' in group '%s'",
2172                                 name, acg->acg_name);
2173                         res = -EINVAL;
2174                         goto out_free_up;
2175                 }
2176                 scst_acn_sysfs_del(acg, acn, true);
2177                 break;
2178         case SCST_ACG_ACTION_INI_CLEAR:
2179                 list_for_each_entry_safe(acn, acn_tmp, &acg->acn_list,
2180                                 acn_list_entry) {
2181                         scst_acn_sysfs_del(acg, acn, false);
2182                 }
2183                 scst_check_reassign_sessions();
2184                 break;
2185         case SCST_ACG_ACTION_INI_MOVE:
2186                 e = p;
2187                 while (!isspace(*e) && *e != '\0')
2188                         e++;
2189                 if (*e == '\0') {
2190                         PRINT_ERROR("%s", "Too few parameters");
2191                         res = -EINVAL;
2192                         goto out_free_up;
2193                 }
2194                 *e = '\0';
2195                 name = p;
2196
2197                 if (name[0] == '\0') {
2198                         PRINT_ERROR("%s", "Invalid initiator name");
2199                         res = -EINVAL;
2200                         goto out_free_up;
2201                 }
2202
2203                 e++;
2204                 p = e;
2205                 while (!isspace(*e) && *e != '\0')
2206                         e++;
2207                 *e = '\0';
2208                 group = p;
2209
2210                 if (group[0] == '\0') {
2211                         PRINT_ERROR("%s", "Invalid group name");
2212                         res = -EINVAL;
2213                         goto out_free_up;
2214                 }
2215
2216                 TRACE_DBG("Move initiator '%s' to group '%s'",
2217                         name, group);
2218
2219                 /*
2220                  * Better get tgt from hierarchy tgt_kobj -> tgt_ini_grp_kobj ->
2221                  * acg_kobj -> initiators_kobj than have direct pointer to tgt
2222                  * in struct acg and have a headache to care about its possible
2223                  * wrong dereference on the destruction time.
2224                  */
2225                 {
2226                         struct kobject *k;
2227
2228                         /* acg_kobj */
2229                         k = kobj->parent;
2230                         if (k == NULL) {
2231                                 res = -EINVAL;
2232                                 goto out_free_up;
2233                         }
2234                         /* tgt_ini_grp_kobj */
2235                         k = k->parent;
2236                         if (k == NULL) {
2237                                 res = -EINVAL;
2238                                 goto out_free_up;
2239                         }
2240                         /* tgt_kobj */
2241                         k = k->parent;
2242                         if (k == NULL) {
2243                                 res = -EINVAL;
2244                                 goto out_free_up;
2245                         }
2246
2247                         tgt = container_of(k, struct scst_tgt, tgt_kobj);
2248                 }
2249
2250                 acn = scst_acg_find_name(acg, name);
2251                 if (acn == NULL) {
2252                         PRINT_ERROR("Unable to find "
2253                                 "initiator '%s' in group '%s'",
2254                                 name, acg->acg_name);
2255                         res = -EINVAL;
2256                         goto out_free_up;
2257                 }
2258                 acg_dest = scst_tgt_find_acg(tgt, group);
2259                 if (acg_dest == NULL) {
2260                         PRINT_ERROR("Unable to find group '%s' in target '%s'",
2261                                 group, tgt->tgt_name);
2262                         res = -EINVAL;
2263                         goto out_free_up;
2264                 }
2265                 if (scst_acg_find_name(acg_dest, name) != NULL) {
2266                         PRINT_ERROR("Initiator '%s' already exists in group '%s'",
2267                                 name, acg_dest->acg_name);
2268                         res = -EEXIST;
2269                         goto out_free_up;
2270                 }
2271                 scst_acn_sysfs_del(acg, acn, false);
2272
2273                 res = scst_acg_add_name(acg_dest, name);
2274                 if (res != 0)
2275                         goto out_free_up;
2276                 break;
2277         }
2278
2279         res = count;
2280
2281 out_free_up:
2282         mutex_unlock(&scst_mutex);
2283
2284 out_free_resume:
2285         scst_resume_activity();
2286
2287 out_free:
2288         kfree(buffer);
2289
2290 out:
2291         TRACE_EXIT_RES(res);
2292         return res;
2293
2294 #undef SCST_ACG_ACTION_INI_ADD
2295 #undef SCST_ACG_ACTION_INI_DEL
2296 #undef SCST_ACG_ACTION_INI_CLEAR
2297 #undef SCST_ACG_ACTION_INI_MOVE
2298 }
2299
2300 /*
2301  * SGV directory implementation
2302  */
2303
2304 static struct kobj_attribute sgv_stat_attr =
2305         __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show,
2306                 sgv_sysfs_stat_reset);
2307
2308 static struct attribute *sgv_attrs[] = {
2309         &sgv_stat_attr.attr,
2310         NULL,
2311 };
2312
2313 static void sgv_kobj_release(struct kobject *kobj)
2314 {
2315         struct sgv_pool *pool;
2316
2317         TRACE_ENTRY();
2318
2319         pool = container_of(kobj, struct sgv_pool, sgv_kobj);
2320
2321         sgv_pool_destroy(pool);
2322
2323         TRACE_EXIT();
2324         return;
2325 }
2326
2327 static struct kobj_type sgv_pool_ktype = {
2328         .sysfs_ops = &scst_sysfs_ops,
2329         .release = sgv_kobj_release,
2330         .default_attrs = sgv_attrs,
2331 };
2332
2333 int scst_create_sgv_sysfs(struct sgv_pool *pool)
2334 {
2335         int retval;
2336
2337         TRACE_ENTRY();
2338
2339         pool->sgv_kobj_initialized = 1;
2340
2341         retval = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype,
2342                         scst_sgv_kobj, pool->name);
2343         if (retval != 0) {
2344                 PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name);
2345                 goto out;
2346         }
2347
2348 out:
2349         TRACE_EXIT_RES(retval);
2350         return retval;
2351 }
2352
2353 /* pool can be dead upon exit from this function! */
2354 void scst_sgv_sysfs_put(struct sgv_pool *pool)
2355 {
2356         if (pool->sgv_kobj_initialized) {
2357                 kobject_del(&pool->sgv_kobj);
2358                 kobject_put(&pool->sgv_kobj);
2359         } else
2360                 sgv_pool_destroy(pool);
2361         return;
2362 }
2363
2364 static struct kobj_attribute sgv_global_stat_attr =
2365         __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show,
2366                 sgv_sysfs_global_stat_reset);
2367
2368 static struct attribute *sgv_default_attrs[] = {
2369         &sgv_global_stat_attr.attr,
2370         NULL,
2371 };
2372
2373 static struct kobj_type sgv_ktype = {
2374         .sysfs_ops = &scst_sysfs_ops,
2375         .release = scst_sysfs_release,
2376         .default_attrs = sgv_default_attrs,
2377 };
2378
2379 /*
2380  * SCST sysfs root directory implementation
2381  */
2382
2383 static ssize_t scst_threads_show(struct kobject *kobj,
2384         struct kobj_attribute *attr, char *buf)
2385 {
2386         int count;
2387
2388         TRACE_ENTRY();
2389
2390         count = sprintf(buf, "%d\n", scst_global_threads_count());
2391
2392         TRACE_EXIT();
2393         return count;
2394 }
2395
2396 static ssize_t scst_threads_store(struct kobject *kobj,
2397         struct kobj_attribute *attr, const char *buf, size_t count)
2398 {
2399         int res;
2400         long oldtn, newtn, delta;
2401
2402         TRACE_ENTRY();
2403
2404         if (mutex_lock_interruptible(&scst_global_threads_mutex) != 0) {
2405                 res = -EINTR;
2406                 goto out;
2407         }
2408
2409         oldtn = scst_nr_global_threads;
2410
2411         res = strict_strtoul(buf, 0, &newtn);
2412         if (res != 0) {
2413                 PRINT_ERROR("strict_strtoul() for %s failed: %d ", buf, res);
2414                 goto out_up;
2415         }
2416
2417         delta = newtn - oldtn;
2418         if (delta < 0)
2419                 __scst_del_global_threads(-delta);
2420         else
2421                 __scst_add_global_threads(delta);
2422
2423         PRINT_INFO("Changed cmd threads num: old %ld, new %ld", oldtn, newtn);
2424
2425         res = count;
2426
2427 out_up:
2428         mutex_unlock(&scst_global_threads_mutex);
2429
2430 out:
2431         TRACE_EXIT_RES(res);
2432         return res;
2433 }
2434
2435 static ssize_t scst_setup_id_show(struct kobject *kobj,
2436         struct kobj_attribute *attr, char *buf)
2437 {
2438         int count;
2439
2440         TRACE_ENTRY();
2441
2442         count = sprintf(buf, "0x%x%s\n", scst_setup_id,
2443                 (scst_setup_id == 0) ? "" : SCST_SYSFS_KEY_MARK "\n");
2444
2445         TRACE_EXIT();
2446         return count;
2447 }
2448
2449 static ssize_t scst_setup_id_store(struct kobject *kobj,
2450         struct kobj_attribute *attr, const char *buf, size_t count)
2451 {
2452         int res;
2453         unsigned long val;
2454
2455         TRACE_ENTRY();
2456
2457         res = strict_strtoul(buf, 0, &val);
2458         if (res != 0) {
2459                 PRINT_ERROR("strict_strtoul() for %s failed: %d ", buf, res);
2460                 goto out;
2461         }
2462
2463         scst_setup_id = val;
2464         PRINT_INFO("Changed scst_setup_id to %x", scst_setup_id);
2465
2466         res = count;
2467
2468 out:
2469         TRACE_EXIT_RES(res);
2470         return res;
2471 }
2472
2473 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
2474
2475 static void scst_read_trace_tlb(const struct scst_trace_log *tbl, char *buf,
2476         unsigned long log_level, int *pos)
2477 {
2478         const struct scst_trace_log *t = tbl;
2479
2480         if (t == NULL)
2481                 goto out;
2482
2483         while (t->token) {
2484                 if (log_level & t->val) {
2485                         *pos += sprintf(&buf[*pos], "%s%s",
2486                                         (*pos == 0) ? "" : " | ",
2487                                         t->token);
2488                 }
2489                 t++;
2490         }
2491 out:
2492         return;
2493 }
2494
2495 static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
2496         unsigned long log_level, char *buf, const char *help)
2497 {
2498         int pos = 0;
2499
2500         scst_read_trace_tlb(scst_trace_tbl, buf, log_level, &pos);
2501         scst_read_trace_tlb(local_tbl, buf, log_level, &pos);
2502
2503         pos += sprintf(&buf[pos], "\n\n\nUsage:\n"
2504                 "       echo \"all|none|default\" >trace_level\n"
2505                 "       echo \"value DEC|0xHEX|0OCT\" >trace_level\n"
2506                 "       echo \"add|del TOKEN\" >trace_level\n"
2507                 "\nwhere TOKEN is one of [debug, function, line, pid,\n"
2508 #ifndef GENERATING_UPSTREAM_PATCH
2509                 "                      entryexit, buff, mem, sg, out_of_mem,\n"
2510 #else
2511                 "                      buff, mem, sg, out_of_mem,\n"
2512 #endif
2513                 "                      special, scsi, mgmt, minor,\n"
2514                 "                      mgmt_dbg, scsi_serializing,\n"
2515                 "                      retry, recv_bot, send_bot, recv_top,\n"
2516                 "                      send_top%s]", help != NULL ? help : "");
2517
2518         return pos;
2519 }
2520
2521 static ssize_t scst_main_trace_level_show(struct kobject *kobj,
2522         struct kobj_attribute *attr, char *buf)
2523 {
2524         return scst_trace_level_show(scst_local_trace_tbl, trace_flag,
2525                         buf, NULL);
2526 }
2527
2528 static int scst_write_trace(const char *buf, size_t length,
2529         unsigned long *log_level, unsigned long default_level,
2530         const char *name, const struct scst_trace_log *tbl)
2531 {
2532         int res = length;
2533         int action;
2534         unsigned long level = 0, oldlevel;
2535         char *buffer, *p, *e;
2536         const struct scst_trace_log *t;
2537
2538 #define SCST_TRACE_ACTION_ALL           1
2539 #define SCST_TRACE_ACTION_NONE          2
2540 #define SCST_TRACE_ACTION_DEFAULT       3
2541 #define SCST_TRACE_ACTION_ADD           4
2542 #define SCST_TRACE_ACTION_DEL           5
2543 #define SCST_TRACE_ACTION_VALUE         6
2544
2545         TRACE_ENTRY();
2546
2547         if ((buf == NULL) || (length == 0)) {
2548                 res = -EINVAL;
2549                 goto out;
2550         }
2551
2552         buffer = kmalloc(length+1, GFP_KERNEL);
2553         if (buffer == NULL) {
2554                 PRINT_ERROR("Unable to alloc intermediate buffer (size %zd)",
2555                         length+1);
2556                 res = -ENOMEM;
2557                 goto out;
2558         }
2559         memcpy(buffer, buf, length);
2560         buffer[length] = '\0';
2561
2562         p = buffer;
2563         if (!strncasecmp("all", p, 3)) {
2564                 action = SCST_TRACE_ACTION_ALL;
2565         } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
2566                 action = SCST_TRACE_ACTION_NONE;
2567         } else if (!strncasecmp("default", p, 7)) {
2568                 action = SCST_TRACE_ACTION_DEFAULT;
2569         } else if (!strncasecmp("add", p, 3)) {
2570                 p += 3;
2571                 action = SCST_TRACE_ACTION_ADD;
2572         } else if (!strncasecmp("del", p, 3)) {
2573                 p += 3;
2574                 action = SCST_TRACE_ACTION_DEL;
2575         } else if (!strncasecmp("value", p, 5)) {
2576                 p += 5;
2577                 action = SCST_TRACE_ACTION_VALUE;
2578         } else {
2579                 if (p[strlen(p) - 1] == '\n')
2580                         p[strlen(p) - 1] = '\0';
2581                 PRINT_ERROR("Unknown action \"%s\"", p);
2582                 res = -EINVAL;
2583                 goto out_free;
2584         }
2585
2586         switch (action) {
2587         case SCST_TRACE_ACTION_ADD:
2588         case SCST_TRACE_ACTION_DEL:
2589         case SCST_TRACE_ACTION_VALUE:
2590                 if (!isspace(*p)) {
2591                         PRINT_ERROR("%s", "Syntax error");
2592                         res = -EINVAL;
2593                         goto out_free;
2594                 }
2595         }
2596
2597         switch (action) {
2598         case SCST_TRACE_ACTION_ALL:
2599                 level = TRACE_ALL;
2600                 break;
2601         case SCST_TRACE_ACTION_DEFAULT:
2602                 level = default_level;
2603                 break;
2604         case SCST_TRACE_ACTION_NONE:
2605                 level = TRACE_NULL;
2606                 break;
2607         case SCST_TRACE_ACTION_ADD:
2608         case SCST_TRACE_ACTION_DEL:
2609                 while (isspace(*p) && *p != '\0')
2610                         p++;
2611                 e = p;
2612                 while (!isspace(*e) && *e != '\0')
2613                         e++;
2614                 *e = 0;
2615                 if (tbl) {
2616                         t = tbl;
2617                         while (t->token) {
2618                                 if (!strcasecmp(p, t->token)) {
2619                                         level = t->val;
2620                                         break;
2621                                 }
2622                                 t++;
2623                         }
2624                 }
2625                 if (level == 0) {
2626                         t = scst_trace_tbl;
2627                         while (t->token) {
2628                                 if (!strcasecmp(p, t->token)) {
2629                                         level = t->val;
2630                                         break;
2631                                 }
2632                                 t++;
2633                         }
2634                 }
2635                 if (level == 0) {
2636                         PRINT_ERROR("Unknown token \"%s\"", p);
2637                         res = -EINVAL;
2638                         goto out_free;
2639                 }
2640                 break;
2641         case SCST_TRACE_ACTION_VALUE:
2642                 while (isspace(*p) && *p != '\0')
2643                         p++;
2644                 res = strict_strtoul(p, 0, &level);
2645                 if (res != 0) {
2646                         PRINT_ERROR("Invalid trace value \"%s\"", p);
2647                         res = -EINVAL;
2648                         goto out_free;
2649                 }
2650                 break;
2651         }
2652
2653         oldlevel = *log_level;
2654
2655         switch (action) {
2656         case SCST_TRACE_ACTION_ADD:
2657                 *log_level |= level;
2658                 break;
2659         case SCST_TRACE_ACTION_DEL:
2660                 *log_level &= ~level;
2661                 break;
2662         default:
2663                 *log_level = level;
2664                 break;
2665         }
2666
2667         PRINT_INFO("Changed trace level for \"%s\": old 0x%08lx, new 0x%08lx",
2668                 name, oldlevel, *log_level);
2669
2670 out_free:
2671         kfree(buffer);
2672 out:
2673         TRACE_EXIT_RES(res);
2674         return res;
2675
2676 #undef SCST_TRACE_ACTION_ALL
2677 #undef SCST_TRACE_ACTION_NONE
2678 #undef SCST_TRACE_ACTION_DEFAULT
2679 #undef SCST_TRACE_ACTION_ADD
2680 #undef SCST_TRACE_ACTION_DEL
2681 #undef SCST_TRACE_ACTION_VALUE
2682 }
2683
2684 static ssize_t scst_main_trace_level_store(struct kobject *kobj,
2685         struct kobj_attribute *attr, const char *buf, size_t count)
2686 {
2687         int res;
2688
2689         TRACE_ENTRY();
2690
2691         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
2692                 res = -EINTR;
2693                 goto out;
2694         }
2695
2696         res = scst_write_trace(buf, count, &trace_flag,
2697                 SCST_DEFAULT_LOG_FLAGS, "scst", scst_local_trace_tbl);
2698
2699         mutex_unlock(&scst_log_mutex);
2700
2701 out:
2702         TRACE_EXIT_RES(res);
2703         return res;
2704 }
2705
2706 #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
2707
2708 static ssize_t scst_version_show(struct kobject *kobj,
2709                                  struct kobj_attribute *attr,
2710                                  char *buf)
2711 {
2712         TRACE_ENTRY();
2713
2714         sprintf(buf, "%s\n", SCST_VERSION_STRING);
2715
2716 #ifdef CONFIG_SCST_STRICT_SERIALIZING
2717         strcat(buf, "STRICT_SERIALIZING\n");
2718 #endif
2719
2720 #ifdef CONFIG_SCST_EXTRACHECKS
2721         strcat(buf, "EXTRACHECKS\n");
2722 #endif
2723
2724 #ifdef CONFIG_SCST_TRACING
2725         strcat(buf, "TRACING\n");
2726 #endif
2727
2728 #ifdef CONFIG_SCST_DEBUG
2729         strcat(buf, "DEBUG\n");
2730 #endif
2731
2732 #ifdef CONFIG_SCST_DEBUG_TM
2733         strcat(buf, "DEBUG_TM\n");
2734 #endif
2735
2736 #ifdef CONFIG_SCST_DEBUG_RETRY
2737         strcat(buf, "DEBUG_RETRY\n");
2738 #endif
2739
2740 #ifdef CONFIG_SCST_DEBUG_OOM
2741         strcat(buf, "DEBUG_OOM\n");
2742 #endif
2743
2744 #ifdef CONFIG_SCST_DEBUG_SN
2745         strcat(buf, "DEBUG_SN\n");
2746 #endif
2747
2748 #ifdef CONFIG_SCST_USE_EXPECTED_VALUES
2749         strcat(buf, "USE_EXPECTED_VALUES\n");
2750 #endif
2751
2752 #ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
2753         strcat(buf, "ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ\n");
2754 #endif
2755
2756 #ifdef CONFIG_SCST_STRICT_SECURITY
2757         strcat(buf, "SCST_STRICT_SECURITY\n");
2758 #endif
2759
2760         TRACE_EXIT();
2761         return strlen(buf);
2762 }
2763
2764 static struct kobj_attribute scst_threads_attr =
2765         __ATTR(threads, S_IRUGO | S_IWUSR, scst_threads_show,
2766                scst_threads_store);
2767
2768 static struct kobj_attribute scst_setup_id_attr =
2769         __ATTR(setup_id, S_IRUGO | S_IWUSR, scst_setup_id_show,
2770                scst_setup_id_store);
2771
2772 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
2773 static struct kobj_attribute scst_trace_level_attr =
2774         __ATTR(trace_level, S_IRUGO | S_IWUSR, scst_main_trace_level_show,
2775                scst_main_trace_level_store);
2776 #endif
2777
2778 static struct kobj_attribute scst_version_attr =
2779         __ATTR(version, S_IRUGO, scst_version_show, NULL);
2780
2781 static struct attribute *scst_sysfs_root_default_attrs[] = {
2782         &scst_threads_attr.attr,
2783         &scst_setup_id_attr.attr,
2784 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
2785         &scst_trace_level_attr.attr,
2786 #endif
2787         &scst_version_attr.attr,
2788         NULL,
2789 };
2790
2791 static void scst_sysfs_root_release(struct kobject *kobj)
2792 {
2793         complete_all(&scst_sysfs_root_release_completion);
2794 }
2795
2796 static ssize_t scst_show(struct kobject *kobj, struct attribute *attr,
2797                          char *buf)
2798 {
2799         struct kobj_attribute *kobj_attr;
2800         kobj_attr = container_of(attr, struct kobj_attribute, attr);
2801
2802         return kobj_attr->show(kobj, kobj_attr, buf);
2803 }
2804
2805 static ssize_t scst_store(struct kobject *kobj, struct attribute *attr,
2806                           const char *buf, size_t count)
2807 {
2808         struct kobj_attribute *kobj_attr;
2809         kobj_attr = container_of(attr, struct kobj_attribute, attr);
2810
2811         return kobj_attr->store(kobj, kobj_attr, buf, count);
2812 }
2813
2814 struct sysfs_ops scst_sysfs_ops = {
2815         .show = scst_show,
2816         .store = scst_store,
2817 };
2818
2819 static struct kobj_type scst_sysfs_root_ktype = {
2820         .sysfs_ops = &scst_sysfs_ops,
2821         .release = scst_sysfs_root_release,
2822         .default_attrs = scst_sysfs_root_default_attrs,
2823 };
2824
2825 static void scst_devt_free(struct kobject *kobj)
2826 {
2827         struct scst_dev_type *devt;
2828
2829         TRACE_ENTRY();
2830
2831         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
2832
2833         complete_all(&devt->devt_kobj_release_compl);
2834
2835         scst_devt_cleanup(devt);
2836
2837         TRACE_EXIT();
2838         return;
2839 }
2840
2841 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
2842
2843 static ssize_t scst_devt_trace_level_show(struct kobject *kobj,
2844         struct kobj_attribute *attr, char *buf)
2845 {
2846         struct scst_dev_type *devt;
2847
2848         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
2849
2850         return scst_trace_level_show(devt->trace_tbl,
2851                 devt->trace_flags ? *devt->trace_flags : 0, buf,
2852                 devt->trace_tbl_help);
2853 }
2854
2855 static ssize_t scst_devt_trace_level_store(struct kobject *kobj,
2856         struct kobj_attribute *attr, const char *buf, size_t count)
2857 {
2858         int res;
2859         struct scst_dev_type *devt;
2860
2861         TRACE_ENTRY();
2862
2863         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
2864
2865         if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
2866                 res = -EINTR;
2867                 goto out;
2868         }
2869
2870         res = scst_write_trace(buf, count, devt->trace_flags,
2871                 devt->default_trace_flags, devt->name, devt->trace_tbl);
2872
2873         mutex_unlock(&scst_log_mutex);
2874
2875 out:
2876         TRACE_EXIT_RES(res);
2877         return res;
2878 }
2879
2880 static struct kobj_attribute devt_trace_attr =
2881         __ATTR(trace_level, S_IRUGO | S_IWUSR,
2882                scst_devt_trace_level_show, scst_devt_trace_level_store);
2883
2884 #endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
2885
2886 static ssize_t scst_devt_type_show(struct kobject *kobj,
2887         struct kobj_attribute *attr, char *buf)
2888 {
2889         int pos;
2890         struct scst_dev_type *devt;
2891
2892         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
2893
2894         pos = sprintf(buf, "%d - %s\n", devt->type,
2895                 (unsigned)devt->type > ARRAY_SIZE(scst_dev_handler_types) ?
2896                         "unknown" : scst_dev_handler_types[devt->type]);
2897
2898         return pos;
2899 }
2900
2901 static struct kobj_attribute scst_devt_type_attr =
2902         __ATTR(type, S_IRUGO, scst_devt_type_show, NULL);
2903
2904 static struct attribute *scst_devt_default_attrs[] = {
2905         &scst_devt_type_attr.attr,
2906         NULL,
2907 };
2908
2909 static struct kobj_type scst_devt_ktype = {
2910         .sysfs_ops = &scst_sysfs_ops,
2911         .release = scst_devt_free,
2912         .default_attrs = scst_devt_default_attrs,
2913 };
2914
2915 static ssize_t scst_devt_mgmt_show(struct kobject *kobj,
2916         struct kobj_attribute *attr, char *buf)
2917 {
2918         char *help = "Usage: echo \"add_device device_name [parameters]\" "
2919                                 ">mgmt\n"
2920                      "       echo \"del_device device_name\" >mgmt\n"
2921                      "%s"
2922                      "\n"
2923                      "where parameters are one or more "
2924                      "param_name=value pairs separated by ';'\n"
2925                      "%s%s";
2926         struct scst_dev_type *devt;
2927
2928         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
2929
2930         if (devt->add_device_parameters_help != NULL)
2931                 return sprintf(buf, help,
2932                         (devt->mgmt_cmd_help) ? devt->mgmt_cmd_help : "",
2933                         "\nThe following parameters available: ",
2934                         devt->add_device_parameters_help);
2935         else
2936                 return sprintf(buf, help,
2937                         (devt->mgmt_cmd_help) ? devt->mgmt_cmd_help : "",
2938                         "", "");
2939 }
2940
2941 static ssize_t scst_devt_mgmt_store(struct kobject *kobj,
2942                                     struct kobj_attribute *attr,
2943                                     const char *buf, size_t count)
2944 {
2945         int res;
2946         char *buffer, *p, *pp, *device_name;
2947         struct scst_dev_type *devt;
2948
2949         TRACE_ENTRY();
2950
2951         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
2952
2953         buffer = kzalloc(count+1, GFP_KERNEL);
2954         if (buffer == NULL) {
2955                 res = -ENOMEM;
2956                 goto out;
2957         }
2958
2959         memcpy(buffer, buf, count);
2960         buffer[count] = '\0';
2961
2962         pp = buffer;
2963         if (pp[strlen(pp) - 1] == '\n')
2964                 pp[strlen(pp) - 1] = '\0';
2965
2966         p = scst_get_next_lexem(&pp);
2967
2968         if (strcasecmp("add_device", p) == 0) {
2969                 device_name = scst_get_next_lexem(&pp);
2970                 if (*device_name == '\0') {
2971                         PRINT_ERROR("%s", "Device name required");
2972                         res = -EINVAL;
2973                         goto out_free;
2974                 }
2975                 res = devt->add_device(device_name, pp);
2976         } else if (strcasecmp("del_device", p) == 0) {
2977                 device_name = scst_get_next_lexem(&pp);
2978                 if (*device_name == '\0') {
2979                         PRINT_ERROR("%s", "Device name required");
2980                         res = -EINVAL;
2981                         goto out_free;
2982                 }
2983
2984                 p = scst_get_next_lexem(&pp);
2985                 if (*p != '\0')
2986                         goto out_syntax_err;
2987
2988                 res = devt->del_device(device_name);
2989         } else if (devt->mgmt_cmd != NULL) {
2990                 scst_restore_token_str(p, pp);
2991                 res = devt->mgmt_cmd(buffer);
2992         } else {
2993                 PRINT_ERROR("Unknown action \"%s\"", p);
2994                 res = -EINVAL;
2995                 goto out_free;
2996         }
2997
2998         if (res == 0)
2999                 res = count;
3000
3001 out_free:
3002         kfree(buffer);
3003
3004 out:
3005         TRACE_EXIT_RES(res);
3006         return res;
3007
3008 out_syntax_err:
3009         PRINT_ERROR("Syntax error on \"%s\"", p);
3010         res = -EINVAL;
3011         goto out_free;
3012 }
3013
3014 static struct kobj_attribute scst_devt_mgmt =
3015         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_mgmt_show,
3016                scst_devt_mgmt_store);
3017
3018 static ssize_t scst_devt_pass_through_show(struct kobject *kobj,
3019         struct kobj_attribute *attr, char *buf)
3020 {
3021         return sprintf(buf, "1");
3022 }
3023
3024 static struct kobj_attribute scst_devt_pass_through =
3025         __ATTR(pass_through, S_IRUGO, scst_devt_pass_through_show, NULL);
3026
3027 static ssize_t scst_devt_pass_through_mgmt_show(struct kobject *kobj,
3028         struct kobj_attribute *attr, char *buf)
3029 {
3030         char *help = "Usage: echo \"assign H:C:I:L\" >mgmt\n"
3031                      "       echo \"unassign H:C:I:L\" >mgmt\n";
3032         return sprintf(buf, help);
3033 }
3034
3035 static ssize_t scst_devt_pass_through_mgmt_store(struct kobject *kobj,
3036         struct kobj_attribute *attr, const char *buf, size_t count)
3037 {
3038         int res;
3039         char *buffer, *p, *pp, *action;
3040         struct scst_dev_type *devt;
3041         unsigned long host, channel, id, lun;
3042         struct scst_device *d, *dev = NULL;
3043
3044         TRACE_ENTRY();
3045
3046         devt = container_of(kobj, struct scst_dev_type, devt_kobj);
3047
3048         buffer = kzalloc(count+1, GFP_KERNEL);
3049         if (buffer == NULL) {
3050                 res = -ENOMEM;
3051                 goto out;
3052         }
3053
3054         memcpy(buffer, buf, count);
3055         buffer[count] = '\0';
3056
3057         pp = buffer;
3058         if (pp[strlen(pp) - 1] == '\n')
3059                 pp[strlen(pp) - 1] = '\0';
3060
3061         action = scst_get_next_lexem(&pp);
3062         p = scst_get_next_lexem(&pp);
3063         if (*p == '\0') {
3064                 PRINT_ERROR("%s", "Device required");
3065                 res = -EINVAL;
3066                 goto out_free;
3067         }
3068
3069         ;
3070         if (*scst_get_next_lexem(&pp) != '\0') {
3071                 PRINT_ERROR("%s", "Too many parameters");
3072                 res = -EINVAL;
3073                 goto out_syntax_err;
3074         }
3075
3076         host = simple_strtoul(p, &p, 0);
3077         if ((host == ULONG_MAX) || (*p != ':'))
3078                 goto out_syntax_err;
3079         p++;
3080         channel = simple_strtoul(p, &p, 0);
3081         if ((channel == ULONG_MAX) || (*p != ':'))
3082                 goto out_syntax_err;
3083         p++;
3084         id = simple_strtoul(p, &p, 0);
3085         if ((channel == ULONG_MAX) || (*p != ':'))
3086                 goto out_syntax_err;
3087         p++;
3088         lun = simple_strtoul(p, &p, 0);
3089         if (lun == ULONG_MAX)
3090                 goto out_syntax_err;
3091
3092         TRACE_DBG("Dev %ld:%ld:%ld:%ld", host, channel, id, lun);
3093
3094         if (mutex_lock_interruptible(&scst_mutex) != 0) {
3095                 res = -EINTR;
3096                 goto out_free;
3097         }
3098
3099         list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
3100                 if ((d->virt_id == 0) &&
3101                     d->scsi_dev->host->host_no == host &&
3102                     d->scsi_dev->channel == channel &&
3103                     d->scsi_dev->id == id &&
3104                     d->scsi_dev->lun == lun) {
3105                         dev = d;
3106                         TRACE_DBG("Dev %p (%ld:%ld:%ld:%ld) found",
3107                                   dev, host, channel, id, lun);
3108                         break;
3109                 }
3110         }
3111         if (dev == NULL) {
3112                 PRINT_ERROR("Device %ld:%ld:%ld:%ld not found",
3113                                host, channel, id, lun);
3114                 res = -EINVAL;
3115                 goto out_unlock;
3116         }
3117
3118         if (dev->scsi_dev->type != devt->type) {
3119                 PRINT_ERROR("Type %d of device %s differs from type "
3120                         "%d of dev handler %s", dev->type,
3121                         dev->virt_name, devt->type, devt->name);
3122                 res = -EINVAL;
3123                 goto out_unlock;
3124         }
3125
3126         if (strcasecmp("assign", action) == 0)
3127                 res = scst_assign_dev_handler(dev, devt);
3128         else if (strcasecmp("deassign", action) == 0) {
3129                 if (dev->handler != devt) {
3130                         PRINT_ERROR("Device %s is not assigned to handler %s",
3131                                 dev->virt_name, devt->name);
3132                         res = -EINVAL;
3133                         goto out_unlock;
3134                 }
3135                 res = scst_assign_dev_handler(dev, &scst_null_devtype);
3136         } else {
3137                 PRINT_ERROR("Unknown action \"%s\"", action);
3138                 res = -EINVAL;
3139                 goto out_unlock;
3140         }
3141
3142         if (res == 0)
3143                 res = count;
3144
3145 out_unlock:
3146         mutex_unlock(&scst_mutex);
3147
3148 out_free:
3149         kfree(buffer);
3150
3151 out:
3152         TRACE_EXIT_RES(res);
3153         return res;
3154
3155 out_syntax_err:
3156         PRINT_ERROR("Syntax error on \"%s\"", p);
3157         res = -EINVAL;
3158         goto out_free;
3159 }
3160
3161 static struct kobj_attribute scst_devt_pass_through_mgmt =
3162         __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_pass_through_mgmt_show,
3163                scst_devt_pass_through_mgmt_store);
3164
3165 int scst_create_devt_sysfs(struct scst_dev_type *devt)
3166 {
3167         int retval;
3168         struct kobject *parent;
3169         const struct attribute **pattr;
3170
3171         TRACE_ENTRY();
3172
3173         init_completion(&devt->devt_kobj_release_compl);
3174
3175         if (devt->parent != NULL)
3176                 parent = &devt->parent->devt_kobj;
3177         else
3178                 parent = scst_handlers_kobj;
3179
3180         devt->devt_kobj_initialized = 1;
3181
3182         retval = kobject_init_and_add(&devt->devt_kobj, &scst_devt_ktype,
3183                         parent, devt->name);
3184         if (retval != 0) {
3185                 PRINT_ERROR("Can't add devt %s to sysfs", devt->name);
3186                 goto out;
3187         }
3188
3189         /*
3190          * In case of errors there's no need for additional cleanup, because
3191          * it will be done by the _put function() called by the caller.
3192          */
3193
3194         if (devt->add_device != NULL) {
3195                 retval = sysfs_create_file(&devt->devt_kobj,
3196                                 &scst_devt_mgmt.attr);
3197                 if (retval != 0) {
3198                         PRINT_ERROR("Can't add mgmt attr for dev handler %s",
3199                                 devt->name);
3200                         goto out;
3201                 }
3202         } else if (devt->pass_through) {
3203                 retval = sysfs_create_file(&devt->devt_kobj,
3204                                 &scst_devt_pass_through_mgmt.attr);
3205                 if (retval != 0) {
3206                         PRINT_ERROR("Can't add mgmt attr for dev handler %s",
3207                                 devt->name);
3208                         goto out;
3209                 }
3210
3211                 retval = sysfs_create_file(&devt->devt_kobj,
3212                                 &scst_devt_pass_through.attr);
3213                 if (retval != 0) {
3214                         PRINT_ERROR("Can't add pass_through attr for dev "
3215                                 "handler %s", devt->name);
3216                         goto out;
3217                 }
3218         }
3219
3220         pattr = devt->devt_attrs;
3221         if (pattr != NULL) {
3222                 while (*pattr != NULL) {
3223                         retval = sysfs_create_file(&devt->devt_kobj, *pattr);
3224                         if (retval != 0) {
3225                                 PRINT_ERROR("Can't add devt attr %s for dev "
3226                                         "handler %s", (*pattr)->name,
3227                                         devt->name);
3228                                 goto out;
3229                         }
3230                         pattr++;
3231                 }
3232         }
3233
3234 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
3235         if (devt->trace_flags != NULL) {
3236                 retval = sysfs_create_file(&devt->devt_kobj,
3237                                 &devt_trace_attr.attr);
3238                 if (retval != 0) {
3239                         PRINT_ERROR("Can't add devt trace_flag for dev "
3240                                 "handler %s", devt->name);
3241                         goto out;
3242                 }
3243         }
3244 #endif
3245
3246 out:
3247         TRACE_EXIT_RES(retval);
3248         return retval;
3249 }
3250
3251 void scst_devt_sysfs_put(struct scst_dev_type *devt)
3252 {
3253         TRACE_ENTRY();
3254
3255         if (devt->devt_kobj_initialized) {
3256                 int rc;
3257
3258                 kobject_del(&devt->devt_kobj);
3259                 kobject_put(&devt->devt_kobj);
3260
3261                 rc = wait_for_completion_timeout(&devt->devt_kobj_release_compl, HZ);
3262                 if (rc == 0) {
3263                         PRINT_INFO("Waiting for releasing sysfs entry "
3264                                 "for dev handler template %s...", devt->name);
3265                         wait_for_completion(&devt->devt_kobj_release_compl);
3266                         PRINT_INFO("Done waiting for releasing sysfs entry "
3267                                 "for dev handler template %s", devt->name);
3268                 }
3269         } else
3270                 scst_devt_cleanup(devt);
3271
3272         TRACE_EXIT();
3273         return;
3274 }
3275
3276 static DEFINE_MUTEX(scst_sysfs_user_info_mutex);
3277
3278 /* All protected by scst_sysfs_user_info_mutex */
3279 static LIST_HEAD(scst_sysfs_user_info_list);
3280 static uint32_t scst_sysfs_info_cur_cookie;
3281
3282 /* scst_sysfs_user_info_mutex supposed to be held */
3283 static struct scst_sysfs_user_info *scst_sysfs_user_find_info(uint32_t cookie)
3284 {
3285         struct scst_sysfs_user_info *info, *res = NULL;
3286
3287         TRACE_ENTRY();
3288
3289         list_for_each_entry(info, &scst_sysfs_user_info_list,
3290                         info_list_entry) {
3291                 if (info->info_cookie == cookie) {
3292                         res = info;
3293                         break;
3294                 }
3295         }
3296
3297         TRACE_EXIT_HRES(res);
3298         return res;
3299 }
3300
3301 struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie)
3302 {
3303         struct scst_sysfs_user_info *res = NULL;
3304
3305         TRACE_ENTRY();
3306
3307         mutex_lock(&scst_sysfs_user_info_mutex);
3308
3309         res = scst_sysfs_user_find_info(cookie);
3310         if (res != NULL) {
3311                 if (!res->info_being_executed)
3312                         res->info_being_executed = 1;
3313         }
3314
3315         mutex_unlock(&scst_sysfs_user_info_mutex);
3316
3317         TRACE_EXIT_HRES(res);
3318         return res;
3319 }
3320 EXPORT_SYMBOL(scst_sysfs_user_get_info);
3321
3322 int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info)
3323 {
3324         int res = 0;
3325         struct scst_sysfs_user_info *info;
3326
3327         TRACE_ENTRY();
3328
3329         info = kzalloc(sizeof(*info), GFP_KERNEL);
3330         if (info == NULL) {
3331                 PRINT_ERROR("Unable to allocate sysfs user info (size %d)",
3332                         sizeof(*info));
3333                 res = -ENOMEM;
3334                 goto out;
3335         }
3336
3337         mutex_lock(&scst_sysfs_user_info_mutex);
3338
3339         while ((info->info_cookie == 0) ||
3340                (scst_sysfs_user_find_info(info->info_cookie) != NULL))
3341                 info->info_cookie = scst_sysfs_info_cur_cookie++;
3342
3343         init_completion(&info->info_completion);
3344
3345         list_add_tail(&info->info_list_entry, &scst_sysfs_user_info_list);
3346         info->info_in_list = 1;
3347
3348         *out_info = info;
3349
3350         mutex_unlock(&scst_sysfs_user_info_mutex);
3351
3352 out:
3353         TRACE_EXIT_RES(res);
3354         return res;
3355 }
3356 EXPORT_SYMBOL(scst_sysfs_user_add_info);
3357
3358 void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info)
3359 {
3360         TRACE_ENTRY();
3361
3362         mutex_lock(&scst_sysfs_user_info_mutex);
3363
3364         if (info->info_in_list)
3365                 list_del(&info->info_list_entry);
3366
3367         mutex_unlock(&scst_sysfs_user_info_mutex);
3368
3369         kfree(info);
3370
3371         TRACE_EXIT();
3372         return;
3373 }
3374 EXPORT_SYMBOL(scst_sysfs_user_del_info);
3375
3376 static bool scst_sysfs_user_info_executing(struct scst_sysfs_user_info *info)
3377 {
3378         bool res;
3379
3380         TRACE_ENTRY();
3381
3382         mutex_lock(&scst_sysfs_user_info_mutex);
3383
3384         res = info->info_being_executed;
3385
3386         if (info->info_in_list) {
3387                 list_del(&info->info_list_entry);
3388                 info->info_in_list = 0;
3389         }
3390
3391         mutex_unlock(&scst_sysfs_user_info_mutex);
3392
3393         TRACE_EXIT_RES(res);
3394         return res;
3395 }
3396
3397 int scst_wait_info_completion(struct scst_sysfs_user_info *info,
3398         unsigned long timeout)
3399 {
3400         int res, rc;
3401
3402         TRACE_ENTRY();
3403
3404         TRACE_DBG("Waiting for info %p completion", info);
3405
3406         while (1) {
3407                 rc = wait_for_completion_interruptible_timeout(
3408                         &info->info_completion, timeout);
3409                 if (rc > 0) {
3410                         TRACE_DBG("Waiting for info %p finished with %d",
3411                                 info, rc);
3412                         break;
3413                 } else if (rc == 0) {
3414                         if (!scst_sysfs_user_info_executing(info)) {
3415                                 PRINT_ERROR("Timeout waiting for user "
3416                                         "space event %p", info);
3417                                 res = -EBUSY;
3418                                 goto out;
3419                         } else {
3420                                 /* Req is being executed in the kernel */
3421                                 TRACE_DBG("Keep waiting for info %p completion",
3422                                         info);
3423                                 wait_for_completion(&info->info_completion);
3424                                 break;
3425                         }
3426                 } else if (rc != -ERESTARTSYS) {
3427                                 res = rc;
3428                                 PRINT_ERROR("wait_for_completion() failed: %d",
3429                                         res);
3430                                 goto out;
3431                 } else {
3432                         TRACE_DBG("Waiting for info %p finished with %d, "
3433                                 "retrying", info, rc);
3434                 }
3435         }
3436
3437         TRACE_DBG("info %p, status %d", info, info->info_status);
3438         res = info->info_status;
3439
3440 out:
3441         TRACE_EXIT_RES(res);
3442         return res;
3443 }
3444 EXPORT_SYMBOL(scst_wait_info_completion);
3445
3446 int __init scst_sysfs_init(void)
3447 {
3448         int retval = 0;
3449
3450         TRACE_ENTRY();
3451
3452         retval = kobject_init_and_add(&scst_sysfs_root_kobj,
3453                         &scst_sysfs_root_ktype, kernel_kobj, "%s", "scst_tgt");
3454         if (retval != 0)
3455                 goto sysfs_root_add_error;
3456
3457         scst_targets_kobj = kobject_create_and_add("targets",
3458                                 &scst_sysfs_root_kobj);
3459         if (scst_targets_kobj == NULL)
3460                 goto targets_kobj_error;
3461
3462         scst_devices_kobj = kobject_create_and_add("devices",
3463                                 &scst_sysfs_root_kobj);
3464         if (scst_devices_kobj == NULL)
3465                 goto devices_kobj_error;
3466
3467         scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL);
3468         if (scst_sgv_kobj == NULL)
3469                 goto sgv_kobj_error;
3470
3471         retval = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype,
3472                         &scst_sysfs_root_kobj, "%s", "sgv");
3473         if (retval != 0)
3474                 goto sgv_kobj_add_error;
3475
3476         scst_handlers_kobj = kobject_create_and_add("handlers",
3477                                         &scst_sysfs_root_kobj);
3478         if (scst_handlers_kobj == NULL)
3479                 goto handlers_kobj_error;
3480
3481 out:
3482         TRACE_EXIT_RES(retval);
3483         return retval;
3484
3485 handlers_kobj_error:
3486         kobject_del(scst_sgv_kobj);
3487
3488 sgv_kobj_add_error:
3489         kobject_put(scst_sgv_kobj);
3490
3491 sgv_kobj_error:
3492         kobject_del(scst_devices_kobj);
3493         kobject_put(scst_devices_kobj);
3494
3495 devices_kobj_error:
3496         kobject_del(scst_targets_kobj);
3497         kobject_put(scst_targets_kobj);
3498
3499 targets_kobj_error:
3500         kobject_del(&scst_sysfs_root_kobj);
3501
3502 sysfs_root_add_error:
3503         kobject_put(&scst_sysfs_root_kobj);
3504
3505         if (retval == 0)
3506                 retval = -EINVAL;
3507         goto out;
3508 }
3509
3510 void scst_sysfs_cleanup(void)
3511 {
3512         TRACE_ENTRY();
3513
3514         PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
3515
3516         kobject_del(scst_sgv_kobj);
3517         kobject_put(scst_sgv_kobj);
3518
3519         kobject_del(scst_devices_kobj);
3520         kobject_put(scst_devices_kobj);
3521
3522         kobject_del(scst_targets_kobj);
3523         kobject_put(scst_targets_kobj);
3524
3525         kobject_del(scst_handlers_kobj);
3526         kobject_put(scst_handlers_kobj);
3527
3528         kobject_del(&scst_sysfs_root_kobj);
3529         kobject_put(&scst_sysfs_root_kobj);
3530
3531         wait_for_completion(&scst_sysfs_root_release_completion);
3532         /*
3533          * There is a race, when in the release() schedule happens just after
3534          * calling complete(), so if we exit and unload scst module immediately,
3535          * there will be oops there. So let's give it a chance to quit
3536          * gracefully. Unfortunately, current kobjects implementation
3537          * doesn't allow better ways to handle it.
3538          */
3539         msleep(3000);
3540
3541         PRINT_INFO("%s", "Exiting SCST sysfs hierarchy done");
3542
3543         TRACE_EXIT();
3544         return;
3545 }