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.
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
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.
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>
27 #include "scst_priv.h"
30 static DEFINE_MUTEX(scst_sysfs_mutex);
32 static DECLARE_COMPLETION(scst_sysfs_root_release_completion);
34 static struct kobject scst_sysfs_root_kobj;
35 static struct kobject *scst_targets_kobj;
36 static struct kobject *scst_devices_kobj;
37 static struct kobject *scst_sgv_kobj;
38 static struct kobject *scst_handlers_kobj;
40 struct sysfs_ops scst_sysfs_ops;
41 EXPORT_SYMBOL(scst_sysfs_ops);
43 static const char *scst_dev_handler_types[] =
45 "Direct-access device (e.g., magnetic disk)",
46 "Sequential-access device (e.g., magnetic tape)",
49 "Write-once device (e.g., some optical disks)",
51 "Scanner device (obsolete)",
52 "Optical memory device (e.g., some optical disks)",
53 "Medium changer device (e.g., jukeboxes)",
54 "Communications device (obsolete)",
55 "Defined by ASC IT8 (Graphic arts pre-press devices)",
56 "Defined by ASC IT8 (Graphic arts pre-press devices)",
57 "Storage array controller device (e.g., RAID)",
58 "Enclosure services device",
59 "Simplified direct-access device (e.g., magnetic disk)",
60 "Optical card reader/writer device"
63 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
65 static DEFINE_MUTEX(scst_log_mutex);
67 static struct scst_trace_log scst_trace_tbl[] =
69 { TRACE_OUT_OF_MEM, "out_of_mem" },
70 { TRACE_MINOR, "minor" },
71 { TRACE_SG_OP, "sg" },
72 { TRACE_MEMORY, "mem" },
73 { TRACE_BUFF, "buff" },
74 #ifndef GENERATING_UPSTREAM_PATCH
75 { TRACE_ENTRYEXIT, "entryexit" },
78 { TRACE_LINE, "line" },
79 { TRACE_FUNCTION, "function" },
80 { TRACE_DEBUG, "debug" },
81 { TRACE_SPECIAL, "special" },
82 { TRACE_SCSI, "scsi" },
83 { TRACE_MGMT, "mgmt" },
84 { TRACE_MGMT_MINOR, "mgmt_minor" },
85 { TRACE_MGMT_DEBUG, "mgmt_dbg" },
89 static struct scst_trace_log scst_local_trace_tbl[] =
91 { TRACE_RTRY, "retry" },
92 { TRACE_SCSI_SERIALIZING, "scsi_serializing" },
93 { TRACE_RCV_BOT, "recv_bot" },
94 { TRACE_SND_BOT, "send_bot" },
95 { TRACE_RCV_TOP, "recv_top" },
96 { TRACE_SND_TOP, "send_top" },
100 static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
101 unsigned long log_level, char *buf, const char *help);
102 static int scst_write_trace(const char *buf, size_t length,
103 unsigned long *log_level, unsigned long default_level,
104 const char *name, const struct scst_trace_log *tbl);
106 #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
108 static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
109 struct kobj_attribute *attr,
111 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
112 struct kobj_attribute *attr,
113 const char *buf, size_t count);
115 static void scst_sysfs_release(struct kobject *kobj)
124 static void scst_tgtt_release(struct kobject *kobj)
126 struct scst_tgt_template *tgtt;
130 tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
132 complete_all(&tgtt->tgtt_kobj_release_cmpl);
134 scst_tgtt_cleanup(tgtt);
140 static struct kobj_type tgtt_ktype = {
141 .sysfs_ops = &scst_sysfs_ops,
142 .release = scst_tgtt_release,
145 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
147 static ssize_t scst_tgtt_trace_level_show(struct kobject *kobj,
148 struct kobj_attribute *attr, char *buf)
150 struct scst_tgt_template *tgtt;
152 tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
154 return scst_trace_level_show(tgtt->trace_tbl,
155 tgtt->trace_flags ? *tgtt->trace_flags : 0, buf,
156 tgtt->trace_tbl_help);
159 static ssize_t scst_tgtt_trace_level_store(struct kobject *kobj,
160 struct kobj_attribute *attr, const char *buf, size_t count)
163 struct scst_tgt_template *tgtt;
167 tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
169 if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
174 res = scst_write_trace(buf, count, tgtt->trace_flags,
175 tgtt->default_trace_flags, tgtt->name, tgtt->trace_tbl);
177 mutex_unlock(&scst_log_mutex);
184 static struct kobj_attribute tgtt_trace_attr =
185 __ATTR(trace_level, S_IRUGO | S_IWUSR,
186 scst_tgtt_trace_level_show, scst_tgtt_trace_level_store);
188 #endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
190 int scst_create_tgtt_sysfs(struct scst_tgt_template *tgtt)
193 const struct attribute **pattr;
197 init_completion(&tgtt->tgtt_kobj_release_cmpl);
199 tgtt->tgtt_kobj_initialized = 1;
201 retval = kobject_init_and_add(&tgtt->tgtt_kobj, &tgtt_ktype,
202 scst_targets_kobj, tgtt->name);
204 PRINT_ERROR("Can't add tgtt %s to sysfs", tgtt->name);
209 * In case of errors there's no need for additional cleanup, because
210 * it will be done by the _put function() called by the caller.
213 pattr = tgtt->tgtt_attrs;
215 while (*pattr != NULL) {
216 TRACE_DBG("Creating attr %s for target driver %s",
217 (*pattr)->name, tgtt->name);
218 retval = sysfs_create_file(&tgtt->tgtt_kobj, *pattr);
220 PRINT_ERROR("Can't add attr %s for target "
221 "driver %s", (*pattr)->name,
229 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
230 if (tgtt->trace_flags != NULL) {
231 retval = sysfs_create_file(&tgtt->tgtt_kobj,
232 &tgtt_trace_attr.attr);
234 PRINT_ERROR("Can't add trace_flag for target "
235 "driver %s", tgtt->name);
242 TRACE_EXIT_RES(retval);
246 void scst_tgtt_sysfs_put(struct scst_tgt_template *tgtt)
250 if (tgtt->tgtt_kobj_initialized) {
253 kobject_del(&tgtt->tgtt_kobj);
254 kobject_put(&tgtt->tgtt_kobj);
256 rc = wait_for_completion_timeout(&tgtt->tgtt_kobj_release_cmpl, HZ);
258 PRINT_INFO("Waiting for releasing sysfs entry "
259 "for target template %s...", tgtt->name);
260 wait_for_completion(&tgtt->tgtt_kobj_release_cmpl);
261 PRINT_INFO("Done waiting for releasing sysfs "
262 "entry for target template %s", tgtt->name);
265 scst_tgtt_cleanup(tgtt);
272 * Target directory implementation
275 static void scst_tgt_release(struct kobject *kobj)
277 struct scst_tgt *tgt;
281 tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
289 static struct kobj_type tgt_ktype = {
290 .sysfs_ops = &scst_sysfs_ops,
291 .release = scst_tgt_release,
294 static struct kobj_attribute scst_luns_mgmt =
295 __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
296 scst_luns_mgmt_store);
298 static ssize_t scst_tgt_enable_show(struct kobject *kobj,
299 struct kobj_attribute *attr, char *buf)
301 struct scst_tgt *tgt;
307 tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
309 enabled = tgt->tgtt->is_tgt_enabled(tgt);
311 res = sprintf(buf, "%d\n", enabled ? 1 : 0);
317 static ssize_t scst_tgt_enable_store(struct kobject *kobj,
318 struct kobj_attribute *attr, const char *buf, size_t count)
321 struct scst_tgt *tgt;
328 tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
330 res = tgt->tgtt->enable_tgt(tgt, buf, count);
337 PRINT_ERROR("%s: Requested action not understood: %s", __func__, buf);
342 static struct kobj_attribute tgt_enable_attr =
343 __ATTR(enabled, S_IRUGO | S_IWUSR,
344 scst_tgt_enable_show, scst_tgt_enable_store);
346 int scst_create_tgt_sysfs(struct scst_tgt *tgt)
349 const struct attribute **pattr;
353 tgt->tgt_kobj_initialized = 1;
355 retval = kobject_init_and_add(&tgt->tgt_kobj, &tgt_ktype,
356 &tgt->tgtt->tgtt_kobj, tgt->tgt_name);
358 PRINT_ERROR("Can't add tgt %s to sysfs", tgt->tgt_name);
363 * In case of errors there's no need for additional cleanup, because
364 * it will be done by the _put function() called by the caller.
367 if ((tgt->tgtt->enable_tgt != NULL) &&
368 (tgt->tgtt->is_tgt_enabled != NULL)) {
369 retval = sysfs_create_file(&tgt->tgt_kobj,
370 &tgt_enable_attr.attr);
372 PRINT_ERROR("Can't add attr %s to sysfs",
373 tgt_enable_attr.attr.name);
378 tgt->tgt_sess_kobj = kobject_create_and_add("sessions", &tgt->tgt_kobj);
379 if (tgt->tgt_sess_kobj == NULL) {
380 PRINT_ERROR("Can't create sess kobj for tgt %s", tgt->tgt_name);
384 tgt->tgt_luns_kobj = kobject_create_and_add("luns", &tgt->tgt_kobj);
385 if (tgt->tgt_luns_kobj == NULL) {
386 PRINT_ERROR("Can't create luns kobj for tgt %s", tgt->tgt_name);
390 retval = sysfs_create_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
392 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
393 scst_luns_mgmt.attr.name, tgt->tgt_name);
397 tgt->tgt_ini_grp_kobj = kobject_create_and_add("ini_group",
399 if (tgt->tgt_ini_grp_kobj == NULL) {
400 PRINT_ERROR("Can't create ini_grp kobj for tgt %s",
405 pattr = tgt->tgtt->tgt_attrs;
407 while (*pattr != NULL) {
408 TRACE_DBG("Creating attr %s for tgt %s", (*pattr)->name,
410 retval = sysfs_create_file(&tgt->tgt_kobj, *pattr);
412 PRINT_ERROR("Can't add tgt attr %s for tgt %s",
413 (*pattr)->name, tgt->tgt_name);
421 TRACE_EXIT_RES(retval);
429 void scst_tgt_sysfs_put(struct scst_tgt *tgt)
431 if (tgt->tgt_kobj_initialized) {
432 kobject_del(tgt->tgt_sess_kobj);
433 kobject_put(tgt->tgt_sess_kobj);
435 sysfs_remove_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
437 kobject_del(tgt->tgt_luns_kobj);
438 kobject_put(tgt->tgt_luns_kobj);
440 kobject_del(tgt->tgt_ini_grp_kobj);
441 kobject_put(tgt->tgt_ini_grp_kobj);
443 kobject_del(&tgt->tgt_kobj);
444 kobject_put(&tgt->tgt_kobj);
451 * Devices directory implementation
454 ssize_t scst_device_sysfs_type_show(struct kobject *kobj,
455 struct kobj_attribute *attr, char *buf)
459 struct scst_device *dev;
461 dev = container_of(kobj, struct scst_device, dev_kobj);
463 pos = sprintf(buf, "%d - %s\n", dev->type,
464 (unsigned)dev->type > ARRAY_SIZE(scst_dev_handler_types) ?
465 "unknown" : scst_dev_handler_types[dev->type]);
470 static struct kobj_attribute device_type_attr =
471 __ATTR(type, S_IRUGO, scst_device_sysfs_type_show, NULL);
473 static struct attribute *scst_device_attrs[] = {
474 &device_type_attr.attr,
478 static void scst_sysfs_device_release(struct kobject *kobj)
480 struct scst_device *dev;
484 dev = container_of(kobj, struct scst_device, dev_kobj);
486 scst_free_device(dev);
492 int scst_create_devt_dev_sysfs(struct scst_device *dev)
495 const struct attribute **pattr;
499 if (dev->handler == &scst_null_devtype)
502 sBUG_ON(!dev->handler->devt_kobj_initialized);
505 * In case of errors there's no need for additional cleanup, because
506 * it will be done by the _put function() called by the caller.
509 retval = sysfs_create_link(&dev->dev_kobj,
510 &dev->handler->devt_kobj, "handler");
512 PRINT_ERROR("Can't create handler link for dev %s",
517 pattr = dev->handler->dev_attrs;
519 while (*pattr != NULL) {
520 retval = sysfs_create_file(&dev->dev_kobj, *pattr);
522 PRINT_ERROR("Can't add dev attr %s for dev %s",
523 (*pattr)->name, dev->virt_name);
531 TRACE_EXIT_RES(retval);
535 void scst_devt_dev_sysfs_put(struct scst_device *dev)
537 const struct attribute **pattr;
541 if (dev->handler == &scst_null_devtype)
544 sBUG_ON(!dev->handler->devt_kobj_initialized);
546 pattr = dev->handler->dev_attrs;
548 while (*pattr != NULL) {
549 sysfs_remove_file(&dev->dev_kobj, *pattr);
554 sysfs_remove_link(&dev->dev_kobj, "handler");
561 static struct kobj_type scst_device_ktype = {
562 .sysfs_ops = &scst_sysfs_ops,
563 .release = scst_sysfs_device_release,
564 .default_attrs = scst_device_attrs,
567 int scst_create_device_sysfs(struct scst_device *dev)
573 dev->dev_kobj_initialized = 1;
575 retval = kobject_init_and_add(&dev->dev_kobj, &scst_device_ktype,
576 scst_devices_kobj, dev->virt_name);
578 PRINT_ERROR("Can't add device %s to sysfs", dev->virt_name);
583 * In case of errors there's no need for additional cleanup, because
584 * it will be done by the _put function() called by the caller.
587 dev->dev_exp_kobj = kobject_create_and_add("exported",
589 if (dev->dev_exp_kobj == NULL) {
590 PRINT_ERROR("Can't create exported link for device %s",
596 if (dev->scsi_dev != NULL) {
597 retval = sysfs_create_link(&dev->dev_kobj,
598 &dev->scsi_dev->sdev_dev.kobj, "scsi_device");
600 PRINT_ERROR("Can't create scsi_device link for dev %s",
607 TRACE_EXIT_RES(retval);
611 void scst_device_sysfs_put(struct scst_device *dev)
615 if (dev->dev_kobj_initialized) {
616 if (dev->dev_exp_kobj != NULL) {
617 kobject_del(dev->dev_exp_kobj);
618 kobject_put(dev->dev_exp_kobj);
620 kobject_del(&dev->dev_kobj);
621 kobject_put(&dev->dev_kobj);
623 scst_free_device(dev);
630 * Target sessions directory implementation
633 ssize_t scst_sess_sysfs_commands_show(struct kobject *kobj,
634 struct kobj_attribute *attr, char *buf)
636 struct scst_session *sess;
638 sess = container_of(kobj, struct scst_session, sess_kobj);
640 return sprintf(buf, "%i\n", atomic_read(&sess->sess_cmd_count));
643 static struct kobj_attribute session_commands_attr =
644 __ATTR(commands, S_IRUGO, scst_sess_sysfs_commands_show, NULL);
646 static struct attribute *scst_session_attrs[] = {
647 &session_commands_attr.attr,
651 static void scst_sysfs_session_release(struct kobject *kobj)
653 struct scst_session *sess;
657 sess = container_of(kobj, struct scst_session, sess_kobj);
659 scst_release_session(sess);
665 static struct kobj_type scst_session_ktype = {
666 .sysfs_ops = &scst_sysfs_ops,
667 .release = scst_sysfs_session_release,
668 .default_attrs = scst_session_attrs,
671 int scst_create_sess_sysfs(struct scst_session *sess)
674 const struct attribute **pattr;
678 sess->sess_kobj_initialized = 1;
680 retval = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
681 sess->tgt->tgt_sess_kobj, sess->initiator_name);
683 PRINT_ERROR("Can't add session %s to sysfs",
684 sess->initiator_name);
689 * In case of errors there's no need for additional cleanup, because
690 * it will be done by the _put function() called by the caller.
693 pattr = sess->tgt->tgtt->sess_attrs;
695 while (*pattr != NULL) {
696 retval = sysfs_create_file(&sess->sess_kobj, *pattr);
698 PRINT_ERROR("Can't add sess attr %s for sess "
699 "for initiator %s", (*pattr)->name,
700 sess->initiator_name);
708 TRACE_EXIT_RES(retval);
712 void scst_sess_sysfs_put(struct scst_session *sess)
716 if (sess->sess_kobj_initialized) {
717 kobject_del(&sess->sess_kobj);
718 kobject_put(&sess->sess_kobj);
720 scst_release_session(sess);
727 * Target luns directory implementation
730 static void scst_acg_dev_release(struct kobject *kobj)
732 struct scst_acg_dev *acg_dev;
736 acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
738 scst_acg_dev_destroy(acg_dev);
744 static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
745 struct kobj_attribute *attr,
748 struct scst_acg_dev *acg_dev;
750 acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
752 return sprintf(buf, "%d\n",
753 (acg_dev->rd_only || acg_dev->dev->rd_only) ? 1 : 0);
756 static struct kobj_attribute lun_options_attr =
757 __ATTR(read_only, S_IRUGO, scst_lun_rd_only_show, NULL);
759 static struct attribute *lun_attrs[] = {
760 &lun_options_attr.attr,
764 static struct kobj_type acg_dev_ktype = {
765 .sysfs_ops = &scst_sysfs_ops,
766 .release = scst_acg_dev_release,
767 .default_attrs = lun_attrs,
770 int scst_create_acg_dev_sysfs(struct scst_acg *acg, unsigned int virt_lun,
771 struct kobject *parent)
774 struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
779 list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
780 acg_dev_list_entry) {
781 if (acg_dev_tmp->lun == virt_lun) {
782 acg_dev = acg_dev_tmp;
786 if (acg_dev == NULL) {
787 PRINT_ERROR("%s", "acg_dev lookup for kobject creation failed");
792 snprintf(str, sizeof(str), "%u", acg_dev->dev->dev_exported_lun_num++);
794 acg_dev->acg_dev_kobj_initialized = 1;
796 retval = kobject_init_and_add(&acg_dev->acg_dev_kobj, &acg_dev_ktype,
797 parent, "%u", virt_lun);
799 PRINT_ERROR("Can't add acg %s to sysfs", acg->acg_name);
804 * In case of errors there's no need for additional cleanup, because
805 * it will be done by the _put function() called by the caller.
808 retval = sysfs_create_link(acg_dev->dev->dev_exp_kobj,
809 &acg_dev->acg_dev_kobj, str);
811 PRINT_ERROR("Can't create acg %s LUN link", acg->acg_name);
815 retval = sysfs_create_link(&acg_dev->acg_dev_kobj,
816 &acg_dev->dev->dev_kobj, "device");
818 PRINT_ERROR("Can't create acg %s device link", acg->acg_name);
826 static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
827 struct kobj_attribute *attr,
830 static char *help = "Usage: echo \"add|del H:C:I:L lun [READ_ONLY]\" "
832 " echo \"add|del VNAME lun [READ_ONLY]\" "
835 return sprintf(buf, help);
838 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
839 struct kobj_attribute *attr,
840 const char *buf, size_t count)
842 int res, virt = 0, read_only = 0, action;
843 char *buffer, *p, *e = NULL;
844 unsigned int host, channel = 0, id = 0, lun = 0, virt_lun;
845 struct scst_acg *acg;
846 struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
847 struct scst_device *d, *dev = NULL;
848 struct scst_tgt *tgt;
850 #define SCST_LUN_ACTION_ADD 1
851 #define SCST_LUN_ACTION_DEL 2
852 #define SCST_LUN_ACTION_REPLACE 3
856 tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
857 acg = tgt->default_acg;
859 buffer = kzalloc(count+1, GFP_KERNEL);
860 if (buffer == NULL) {
865 memcpy(buffer, buf, count);
866 buffer[count] = '\0';
870 if (p[strlen(p) - 1] == '\n')
871 p[strlen(p) - 1] = '\0';
872 if (strncasecmp("add", p, 3) == 0) {
874 action = SCST_LUN_ACTION_ADD;
875 } else if (strncasecmp("del", p, 3) == 0) {
877 action = SCST_LUN_ACTION_DEL;
878 } else if (!strncasecmp("replace", p, 7)) {
880 action = SCST_LUN_ACTION_REPLACE;
882 PRINT_ERROR("Unknown action \"%s\"", p);
888 PRINT_ERROR("%s", "Syntax error");
893 res = scst_suspend_activity(true);
897 if (mutex_lock_interruptible(&scst_mutex) != 0) {
899 goto out_free_resume;
902 while (isspace(*p) && *p != '\0')
905 host = simple_strtoul(p, &p, 0);
907 channel = simple_strtoul(p + 1, &p, 0);
908 id = simple_strtoul(p + 1, &p, 0);
909 lun = simple_strtoul(p + 1, &p, 0);
913 p = e; /* restore p */
914 while (!isspace(*e) && *e != '\0')
919 list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
921 if (d->virt_id && !strcmp(d->virt_name, p)) {
923 TRACE_DBG("Virt device %p (%s) found",
929 d->scsi_dev->host->host_no == host &&
930 d->scsi_dev->channel == channel &&
931 d->scsi_dev->id == id &&
932 d->scsi_dev->lun == lun) {
934 TRACE_DBG("Dev %p (%d:%d:%d:%d) found",
935 dev, host, channel, id, lun);
942 PRINT_ERROR("Virt device %s not found", p);
944 PRINT_ERROR("Device %d:%d:%d:%d not found",
945 host, channel, id, lun);
952 case SCST_LUN_ACTION_ADD:
953 case SCST_LUN_ACTION_REPLACE:
955 bool dev_replaced = false;
958 while (isspace(*e) && *e != '\0')
960 virt_lun = simple_strtoul(e, &e, 0);
962 while (isspace(*e) && *e != '\0')
966 if ((strncasecmp("READ_ONLY", e, 9) == 0) &&
967 (isspace(e[9]) || (e[9] == '\0')))
970 PRINT_ERROR("Unknown option \"%s\"", e);
977 list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
978 acg_dev_list_entry) {
979 if (acg_dev_tmp->lun == virt_lun) {
980 acg_dev = acg_dev_tmp;
985 if (acg_dev != NULL) {
986 if (action == SCST_LUN_ACTION_ADD) {
987 PRINT_ERROR("virt lun %d already exists in "
988 "group %s", virt_lun, acg->acg_name);
993 res = scst_acg_remove_dev(acg, acg_dev->dev,
1002 res = scst_acg_add_dev(acg, dev, virt_lun, read_only,
1007 res = scst_create_acg_dev_sysfs(acg, virt_lun, kobj);
1009 PRINT_ERROR("%s", "Creation of acg_dev kobject failed");
1010 goto out_remove_acg_dev;
1014 struct scst_tgt_dev *tgt_dev;
1016 list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
1017 dev_tgt_dev_list_entry) {
1018 if ((tgt_dev->acg_dev->acg == acg) &&
1019 (tgt_dev->lun == virt_lun)) {
1020 TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
1021 " on tgt_dev %p", tgt_dev);
1022 scst_gen_aen_or_ua(tgt_dev,
1023 SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
1030 case SCST_LUN_ACTION_DEL:
1031 res = scst_acg_remove_dev(acg, dev, true);
1040 mutex_unlock(&scst_mutex);
1043 scst_resume_activity();
1049 TRACE_EXIT_RES(res);
1053 scst_acg_remove_dev(acg, dev, true);
1056 #undef SCST_LUN_ACTION_ADD
1057 #undef SCST_LUN_ACTION_DEL
1058 #undef SCST_LUN_ACTION_REPLACE
1062 * SGV directory implementation
1065 static struct kobj_attribute sgv_stat_attr =
1066 __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show,
1067 sgv_sysfs_stat_reset);
1069 static struct attribute *sgv_attrs[] = {
1070 &sgv_stat_attr.attr,
1074 static void sgv_kobj_release(struct kobject *kobj)
1076 struct sgv_pool *pool;
1080 pool = container_of(kobj, struct sgv_pool, sgv_kobj);
1082 sgv_pool_destroy(pool);
1088 static struct kobj_type sgv_pool_ktype = {
1089 .sysfs_ops = &scst_sysfs_ops,
1090 .release = sgv_kobj_release,
1091 .default_attrs = sgv_attrs,
1094 int scst_create_sgv_sysfs(struct sgv_pool *pool)
1100 pool->sgv_kobj_initialized = 1;
1102 retval = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype,
1103 scst_sgv_kobj, pool->name);
1105 PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name);
1110 TRACE_EXIT_RES(retval);
1114 /* pool can be dead upon exit from this function! */
1115 void scst_sgv_sysfs_put(struct sgv_pool *pool)
1117 if (pool->sgv_kobj_initialized) {
1118 kobject_del(&pool->sgv_kobj);
1119 kobject_put(&pool->sgv_kobj);
1121 sgv_pool_destroy(pool);
1125 static struct kobj_attribute sgv_global_stat_attr =
1126 __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show,
1127 sgv_sysfs_global_stat_reset);
1129 static struct attribute *sgv_default_attrs[] = {
1130 &sgv_global_stat_attr.attr,
1134 static struct kobj_type sgv_ktype = {
1135 .sysfs_ops = &scst_sysfs_ops,
1136 .release = scst_sysfs_release,
1137 .default_attrs = sgv_default_attrs,
1141 * SCST sysfs root directory implementation
1144 static ssize_t scst_threads_show(struct kobject *kobj,
1145 struct kobj_attribute *attr, char *buf)
1151 count = sprintf(buf, "%d\n", scst_global_threads_count());
1157 static ssize_t scst_threads_store(struct kobject *kobj,
1158 struct kobj_attribute *attr, const char *buf, size_t count)
1161 int oldtn, newtn, delta;
1165 if (mutex_lock_interruptible(&scst_sysfs_mutex) != 0) {
1170 mutex_lock(&scst_global_threads_mutex);
1172 oldtn = scst_nr_global_threads;
1173 sscanf(buf, "%du", &newtn);
1176 PRINT_ERROR("Illegal threads num value %d", newtn);
1178 goto out_up_thr_free;
1180 delta = newtn - oldtn;
1182 __scst_del_global_threads(-delta);
1184 __scst_add_global_threads(delta);
1186 PRINT_INFO("Changed cmd threads num: old %d, new %d", oldtn, newtn);
1189 mutex_unlock(&scst_global_threads_mutex);
1191 mutex_unlock(&scst_sysfs_mutex);
1194 TRACE_EXIT_RES(res);
1198 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1200 static void scst_read_trace_tlb(const struct scst_trace_log *tbl, char *buf,
1201 unsigned long log_level, int *pos)
1203 const struct scst_trace_log *t = tbl;
1209 if (log_level & t->val) {
1210 *pos += sprintf(&buf[*pos], "%s%s",
1211 (*pos == 0) ? "" : " | ",
1220 static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
1221 unsigned long log_level, char *buf, const char *help)
1225 scst_read_trace_tlb(scst_trace_tbl, buf, log_level, &pos);
1226 scst_read_trace_tlb(local_tbl, buf, log_level, &pos);
1228 pos += sprintf(&buf[pos], "\n\n\nUsage:\n"
1229 " echo \"all|none|default\" >trace_level\n"
1230 " echo \"value DEC|0xHEX|0OCT\" >trace_level\n"
1231 " echo \"add|del TOKEN\" >trace_level\n"
1232 "\nwhere TOKEN is one of [debug, function, line, pid,\n"
1233 #ifndef GENERATING_UPSTREAM_PATCH
1234 " entryexit, buff, mem, sg, out_of_mem,\n"
1236 " buff, mem, sg, out_of_mem,\n"
1238 " special, scsi, mgmt, minor,\n"
1239 " mgmt_minor, mgmt_dbg, scsi_serializing,\n"
1240 " retry, recv_bot, send_bot, recv_top,\n"
1241 " send_top%s]", help != NULL ? help : "");
1246 static ssize_t scst_main_trace_level_show(struct kobject *kobj,
1247 struct kobj_attribute *attr, char *buf)
1249 return scst_trace_level_show(scst_local_trace_tbl, trace_flag,
1253 static int scst_write_trace(const char *buf, size_t length,
1254 unsigned long *log_level, unsigned long default_level,
1255 const char *name, const struct scst_trace_log *tbl)
1259 unsigned long level = 0, oldlevel;
1260 char *buffer, *p, *e;
1261 const struct scst_trace_log *t;
1263 #define SCST_TRACE_ACTION_ALL 1
1264 #define SCST_TRACE_ACTION_NONE 2
1265 #define SCST_TRACE_ACTION_DEFAULT 3
1266 #define SCST_TRACE_ACTION_ADD 4
1267 #define SCST_TRACE_ACTION_DEL 5
1268 #define SCST_TRACE_ACTION_VALUE 6
1272 if ((buf == NULL) || (length == 0)) {
1277 buffer = kmalloc(length+1, GFP_KERNEL);
1278 if (buffer == NULL) {
1279 PRINT_ERROR("Unable to alloc intermediate buffer (size %zd)",
1284 memcpy(buffer, buf, length);
1285 buffer[length] = '\0';
1288 if (!strncasecmp("all", p, 3)) {
1289 action = SCST_TRACE_ACTION_ALL;
1290 } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
1291 action = SCST_TRACE_ACTION_NONE;
1292 } else if (!strncasecmp("default", p, 7)) {
1293 action = SCST_TRACE_ACTION_DEFAULT;
1294 } else if (!strncasecmp("add", p, 3)) {
1296 action = SCST_TRACE_ACTION_ADD;
1297 } else if (!strncasecmp("del", p, 3)) {
1299 action = SCST_TRACE_ACTION_DEL;
1300 } else if (!strncasecmp("value", p, 5)) {
1302 action = SCST_TRACE_ACTION_VALUE;
1304 if (p[strlen(p) - 1] == '\n')
1305 p[strlen(p) - 1] = '\0';
1306 PRINT_ERROR("Unknown action \"%s\"", p);
1312 case SCST_TRACE_ACTION_ADD:
1313 case SCST_TRACE_ACTION_DEL:
1314 case SCST_TRACE_ACTION_VALUE:
1316 PRINT_ERROR("%s", "Syntax error");
1323 case SCST_TRACE_ACTION_ALL:
1326 case SCST_TRACE_ACTION_DEFAULT:
1327 level = default_level;
1329 case SCST_TRACE_ACTION_NONE:
1332 case SCST_TRACE_ACTION_ADD:
1333 case SCST_TRACE_ACTION_DEL:
1334 while (isspace(*p) && *p != '\0')
1337 while (!isspace(*e) && *e != '\0')
1343 if (!strcasecmp(p, t->token)) {
1353 if (!strcasecmp(p, t->token)) {
1361 PRINT_ERROR("Unknown token \"%s\"", p);
1366 case SCST_TRACE_ACTION_VALUE:
1367 while (isspace(*p) && *p != '\0')
1369 res = strict_strtoul(p, 0, &level);
1371 PRINT_ERROR("Invalud trace value \"%s\"", p);
1378 oldlevel = *log_level;
1381 case SCST_TRACE_ACTION_ADD:
1382 *log_level |= level;
1384 case SCST_TRACE_ACTION_DEL:
1385 *log_level &= ~level;
1392 PRINT_INFO("Changed trace level for \"%s\": old 0x%08lx, new 0x%08lx",
1393 name, oldlevel, *log_level);
1398 TRACE_EXIT_RES(res);
1401 #undef SCST_TRACE_ACTION_ALL
1402 #undef SCST_TRACE_ACTION_NONE
1403 #undef SCST_TRACE_ACTION_DEFAULT
1404 #undef SCST_TRACE_ACTION_ADD
1405 #undef SCST_TRACE_ACTION_DEL
1406 #undef SCST_TRACE_ACTION_VALUE
1409 static ssize_t scst_main_trace_level_store(struct kobject *kobj,
1410 struct kobj_attribute *attr, const char *buf, size_t count)
1416 if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
1421 res = scst_write_trace(buf, count, &trace_flag,
1422 SCST_DEFAULT_LOG_FLAGS, "scst", scst_local_trace_tbl);
1424 mutex_unlock(&scst_log_mutex);
1427 TRACE_EXIT_RES(res);
1431 #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
1433 static ssize_t scst_version_show(struct kobject *kobj,
1434 struct kobj_attribute *attr,
1439 sprintf(buf, "%s\n", SCST_VERSION_STRING);
1441 #ifdef CONFIG_SCST_STRICT_SERIALIZING
1442 strcat(buf, "Strict serializing enabled\n");
1445 #ifdef CONFIG_SCST_EXTRACHECKS
1446 strcat(buf, "EXTRACHECKS\n");
1449 #ifdef CONFIG_SCST_TRACING
1450 strcat(buf, "TRACING\n");
1453 #ifdef CONFIG_SCST_DEBUG
1454 strcat(buf, "DEBUG\n");
1457 #ifdef CONFIG_SCST_DEBUG_TM
1458 strcat(buf, "DEBUG_TM\n");
1461 #ifdef CONFIG_SCST_DEBUG_RETRY
1462 strcat(buf, "DEBUG_RETRY\n");
1465 #ifdef CONFIG_SCST_DEBUG_OOM
1466 strcat(buf, "DEBUG_OOM\n");
1469 #ifdef CONFIG_SCST_DEBUG_SN
1470 strcat(buf, "DEBUG_SN\n");
1473 #ifdef CONFIG_SCST_USE_EXPECTED_VALUES
1474 strcat(buf, "USE_EXPECTED_VALUES\n");
1477 #ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
1478 strcat(buf, "ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ\n");
1481 #ifdef CONFIG_SCST_STRICT_SECURITY
1482 strcat(buf, "SCST_STRICT_SECURITY\n");
1489 static struct kobj_attribute scst_threads_attr =
1490 __ATTR(threads, S_IRUGO | S_IWUSR, scst_threads_show,
1491 scst_threads_store);
1493 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1494 static struct kobj_attribute scst_trace_level_attr =
1495 __ATTR(trace_level, S_IRUGO | S_IWUSR, scst_main_trace_level_show,
1496 scst_main_trace_level_store);
1499 static struct kobj_attribute scst_version_attr =
1500 __ATTR(version, S_IRUGO, scst_version_show, NULL);
1502 static struct attribute *scst_sysfs_root_default_attrs[] = {
1503 &scst_threads_attr.attr,
1504 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1505 &scst_trace_level_attr.attr,
1507 &scst_version_attr.attr,
1511 static void scst_sysfs_root_release(struct kobject *kobj)
1513 complete_all(&scst_sysfs_root_release_completion);
1516 static ssize_t scst_show(struct kobject *kobj, struct attribute *attr,
1519 struct kobj_attribute *kobj_attr;
1520 kobj_attr = container_of(attr, struct kobj_attribute, attr);
1522 return kobj_attr->show(kobj, kobj_attr, buf);
1525 static ssize_t scst_store(struct kobject *kobj, struct attribute *attr,
1526 const char *buf, size_t count)
1528 struct kobj_attribute *kobj_attr;
1529 kobj_attr = container_of(attr, struct kobj_attribute, attr);
1531 return kobj_attr->store(kobj, kobj_attr, buf, count);
1534 struct sysfs_ops scst_sysfs_ops = {
1536 .store = scst_store,
1539 static struct kobj_type scst_sysfs_root_ktype = {
1540 .sysfs_ops = &scst_sysfs_ops,
1541 .release = scst_sysfs_root_release,
1542 .default_attrs = scst_sysfs_root_default_attrs,
1545 static void scst_devt_free(struct kobject *kobj)
1547 struct scst_dev_type *devt;
1551 devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1553 complete_all(&devt->devt_kobj_release_compl);
1555 scst_devt_cleanup(devt);
1561 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1563 static ssize_t scst_devt_trace_level_show(struct kobject *kobj,
1564 struct kobj_attribute *attr, char *buf)
1566 struct scst_dev_type *devt;
1568 devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1570 return scst_trace_level_show(devt->trace_tbl,
1571 devt->trace_flags ? *devt->trace_flags : 0, buf,
1572 devt->trace_tbl_help);
1575 static ssize_t scst_devt_trace_level_store(struct kobject *kobj,
1576 struct kobj_attribute *attr, const char *buf, size_t count)
1579 struct scst_dev_type *devt;
1583 devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1585 if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
1590 res = scst_write_trace(buf, count, devt->trace_flags,
1591 devt->default_trace_flags, devt->name, devt->trace_tbl);
1593 mutex_unlock(&scst_log_mutex);
1596 TRACE_EXIT_RES(res);
1600 static struct kobj_attribute devt_trace_attr =
1601 __ATTR(trace_level, S_IRUGO | S_IWUSR,
1602 scst_devt_trace_level_show, scst_devt_trace_level_store);
1604 #endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
1606 static ssize_t scst_devt_type_show(struct kobject *kobj,
1607 struct kobj_attribute *attr, char *buf)
1610 struct scst_dev_type *devt;
1612 devt = container_of(kobj, struct scst_dev_type, devt_kobj);
1614 pos = sprintf(buf, "%d - %s\n", devt->type,
1615 (unsigned)devt->type > ARRAY_SIZE(scst_dev_handler_types) ?
1616 "unknown" : scst_dev_handler_types[devt->type]);
1621 static struct kobj_attribute scst_devt_type_attr =
1622 __ATTR(type, S_IRUGO, scst_devt_type_show, NULL);
1624 static struct attribute *scst_devt_default_attrs[] = {
1625 &scst_devt_type_attr.attr,
1629 static struct kobj_type scst_devt_ktype = {
1630 .sysfs_ops = &scst_sysfs_ops,
1631 .release = scst_devt_free,
1632 .default_attrs = scst_devt_default_attrs,
1635 int scst_create_devt_sysfs(struct scst_dev_type *devt)
1638 struct kobject *parent;
1639 const struct attribute **pattr;
1643 init_completion(&devt->devt_kobj_release_compl);
1645 if (devt->parent != NULL)
1646 parent = &devt->parent->devt_kobj;
1648 parent = scst_handlers_kobj;
1650 devt->devt_kobj_initialized = 1;
1652 retval = kobject_init_and_add(&devt->devt_kobj, &scst_devt_ktype,
1653 parent, devt->name);
1655 PRINT_ERROR("Can't add devt %s to sysfs", devt->name);
1660 * In case of errors there's no need for additional cleanup, because
1661 * it will be done by the _put function() called by the caller.
1664 pattr = devt->devt_attrs;
1665 if (pattr != NULL) {
1666 while (*pattr != NULL) {
1667 retval = sysfs_create_file(&devt->devt_kobj, *pattr);
1669 PRINT_ERROR("Can't add devt attr %s for dev "
1670 "handler %s", (*pattr)->name,
1678 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
1679 if (devt->trace_flags != NULL) {
1680 retval = sysfs_create_file(&devt->devt_kobj,
1681 &devt_trace_attr.attr);
1683 PRINT_ERROR("Can't add devt trace_flag for dev "
1684 "handler %s", devt->name);
1691 TRACE_EXIT_RES(retval);
1695 void scst_devt_sysfs_put(struct scst_dev_type *devt)
1699 if (devt->devt_kobj_initialized) {
1702 kobject_del(&devt->devt_kobj);
1703 kobject_put(&devt->devt_kobj);
1705 rc = wait_for_completion_timeout(&devt->devt_kobj_release_compl, HZ);
1707 PRINT_INFO("Waiting for releasing sysfs entry "
1708 "for dev handler template %s...", devt->name);
1709 wait_for_completion(&devt->devt_kobj_release_compl);
1710 PRINT_INFO("Done waiting for releasing sysfs entry "
1711 "for dev handler template %s", devt->name);
1714 scst_devt_cleanup(devt);
1720 int __init scst_sysfs_init(void)
1726 retval = kobject_init_and_add(&scst_sysfs_root_kobj,
1727 &scst_sysfs_root_ktype, kernel_kobj, "%s", "scst_tgt");
1729 goto sysfs_root_add_error;
1731 scst_targets_kobj = kobject_create_and_add("targets",
1732 &scst_sysfs_root_kobj);
1733 if (scst_targets_kobj == NULL)
1734 goto targets_kobj_error;
1736 scst_devices_kobj = kobject_create_and_add("devices",
1737 &scst_sysfs_root_kobj);
1738 if (scst_devices_kobj == NULL)
1739 goto devices_kobj_error;
1741 scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL);
1742 if (scst_sgv_kobj == NULL)
1743 goto sgv_kobj_error;
1745 retval = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype,
1746 &scst_sysfs_root_kobj, "%s", "sgv");
1748 goto sgv_kobj_add_error;
1750 scst_handlers_kobj = kobject_create_and_add("handlers",
1751 &scst_sysfs_root_kobj);
1752 if (scst_handlers_kobj == NULL)
1753 goto handlers_kobj_error;
1756 TRACE_EXIT_RES(retval);
1759 handlers_kobj_error:
1760 kobject_del(scst_sgv_kobj);
1763 kobject_put(scst_sgv_kobj);
1766 kobject_del(scst_devices_kobj);
1767 kobject_put(scst_devices_kobj);
1770 kobject_del(scst_targets_kobj);
1771 kobject_put(scst_targets_kobj);
1774 kobject_del(&scst_sysfs_root_kobj);
1776 sysfs_root_add_error:
1777 kobject_put(&scst_sysfs_root_kobj);
1784 void __exit scst_sysfs_cleanup(void)
1788 PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
1790 kobject_del(scst_sgv_kobj);
1791 kobject_put(scst_sgv_kobj);
1793 kobject_del(scst_devices_kobj);
1794 kobject_put(scst_devices_kobj);
1796 kobject_del(scst_targets_kobj);
1797 kobject_put(scst_targets_kobj);
1799 kobject_del(scst_handlers_kobj);
1800 kobject_put(scst_handlers_kobj);
1802 kobject_del(&scst_sysfs_root_kobj);
1803 kobject_put(&scst_sysfs_root_kobj);
1805 wait_for_completion(&scst_sysfs_root_release_completion);
1807 PRINT_INFO("%s", "Exiting SCST sysfs hierarchy done");