Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Export the iSCSI boot info to userland via sysfs.
0004  *
0005  * Copyright (C) 2010 Red Hat, Inc.  All rights reserved.
0006  * Copyright (C) 2010 Mike Christie
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/string.h>
0011 #include <linux/slab.h>
0012 #include <linux/sysfs.h>
0013 #include <linux/capability.h>
0014 #include <linux/iscsi_boot_sysfs.h>
0015 
0016 
0017 MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>");
0018 MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information");
0019 MODULE_LICENSE("GPL");
0020 /*
0021  * The kobject and attribute structures.
0022  */
0023 struct iscsi_boot_attr {
0024     struct attribute attr;
0025     int type;
0026     ssize_t (*show) (void *data, int type, char *buf);
0027 };
0028 
0029 /*
0030  * The routine called for all sysfs attributes.
0031  */
0032 static ssize_t iscsi_boot_show_attribute(struct kobject *kobj,
0033                      struct attribute *attr, char *buf)
0034 {
0035     struct iscsi_boot_kobj *boot_kobj =
0036             container_of(kobj, struct iscsi_boot_kobj, kobj);
0037     struct iscsi_boot_attr *boot_attr =
0038             container_of(attr, struct iscsi_boot_attr, attr);
0039     ssize_t ret = -EIO;
0040     char *str = buf;
0041 
0042     if (!capable(CAP_SYS_ADMIN))
0043         return -EACCES;
0044 
0045     if (boot_kobj->show)
0046         ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str);
0047     return ret;
0048 }
0049 
0050 static const struct sysfs_ops iscsi_boot_attr_ops = {
0051     .show = iscsi_boot_show_attribute,
0052 };
0053 
0054 static void iscsi_boot_kobj_release(struct kobject *kobj)
0055 {
0056     struct iscsi_boot_kobj *boot_kobj =
0057             container_of(kobj, struct iscsi_boot_kobj, kobj);
0058 
0059     if (boot_kobj->release)
0060         boot_kobj->release(boot_kobj->data);
0061     kfree(boot_kobj);
0062 }
0063 
0064 static struct kobj_type iscsi_boot_ktype = {
0065     .release = iscsi_boot_kobj_release,
0066     .sysfs_ops = &iscsi_boot_attr_ops,
0067 };
0068 
0069 #define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type)       \
0070 static struct iscsi_boot_attr iscsi_boot_attr_##fnname = {  \
0071     .attr   = { .name = __stringify(sysfs_name), .mode = 0444 },    \
0072     .type   = attr_type,                        \
0073 }
0074 
0075 /* Target attrs */
0076 iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX);
0077 iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS);
0078 iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR);
0079 iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT);
0080 iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN);
0081 iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE);
0082 iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC);
0083 iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME);
0084 iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME);
0085 iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET);
0086 iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name,
0087            ISCSI_BOOT_TGT_REV_CHAP_NAME);
0088 iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret,
0089            ISCSI_BOOT_TGT_REV_CHAP_SECRET);
0090 
0091 static struct attribute *target_attrs[] = {
0092     &iscsi_boot_attr_tgt_index.attr,
0093     &iscsi_boot_attr_tgt_flags.attr,
0094     &iscsi_boot_attr_tgt_ip.attr,
0095     &iscsi_boot_attr_tgt_port.attr,
0096     &iscsi_boot_attr_tgt_lun.attr,
0097     &iscsi_boot_attr_tgt_chap.attr,
0098     &iscsi_boot_attr_tgt_nic.attr,
0099     &iscsi_boot_attr_tgt_name.attr,
0100     &iscsi_boot_attr_tgt_chap_name.attr,
0101     &iscsi_boot_attr_tgt_chap_secret.attr,
0102     &iscsi_boot_attr_tgt_chap_rev_name.attr,
0103     &iscsi_boot_attr_tgt_chap_rev_secret.attr,
0104     NULL
0105 };
0106 
0107 static umode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj,
0108                          struct attribute *attr, int i)
0109 {
0110     struct iscsi_boot_kobj *boot_kobj =
0111             container_of(kobj, struct iscsi_boot_kobj, kobj);
0112 
0113     if (attr ==  &iscsi_boot_attr_tgt_index.attr)
0114         return boot_kobj->is_visible(boot_kobj->data,
0115                          ISCSI_BOOT_TGT_INDEX);
0116     else if (attr == &iscsi_boot_attr_tgt_flags.attr)
0117         return boot_kobj->is_visible(boot_kobj->data,
0118                          ISCSI_BOOT_TGT_FLAGS);
0119     else if (attr == &iscsi_boot_attr_tgt_ip.attr)
0120         return boot_kobj->is_visible(boot_kobj->data,
0121                           ISCSI_BOOT_TGT_IP_ADDR);
0122     else if (attr == &iscsi_boot_attr_tgt_port.attr)
0123         return boot_kobj->is_visible(boot_kobj->data,
0124                           ISCSI_BOOT_TGT_PORT);
0125     else if (attr == &iscsi_boot_attr_tgt_lun.attr)
0126         return boot_kobj->is_visible(boot_kobj->data,
0127                           ISCSI_BOOT_TGT_LUN);
0128     else if (attr == &iscsi_boot_attr_tgt_chap.attr)
0129         return boot_kobj->is_visible(boot_kobj->data,
0130                          ISCSI_BOOT_TGT_CHAP_TYPE);
0131     else if (attr == &iscsi_boot_attr_tgt_nic.attr)
0132         return boot_kobj->is_visible(boot_kobj->data,
0133                          ISCSI_BOOT_TGT_NIC_ASSOC);
0134     else if (attr == &iscsi_boot_attr_tgt_name.attr)
0135         return boot_kobj->is_visible(boot_kobj->data,
0136                          ISCSI_BOOT_TGT_NAME);
0137     else if (attr == &iscsi_boot_attr_tgt_chap_name.attr)
0138         return boot_kobj->is_visible(boot_kobj->data,
0139                          ISCSI_BOOT_TGT_CHAP_NAME);
0140     else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr)
0141         return boot_kobj->is_visible(boot_kobj->data,
0142                          ISCSI_BOOT_TGT_CHAP_SECRET);
0143     else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr)
0144         return boot_kobj->is_visible(boot_kobj->data,
0145                          ISCSI_BOOT_TGT_REV_CHAP_NAME);
0146     else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr)
0147         return boot_kobj->is_visible(boot_kobj->data,
0148                          ISCSI_BOOT_TGT_REV_CHAP_SECRET);
0149     return 0;
0150 }
0151 
0152 static struct attribute_group iscsi_boot_target_attr_group = {
0153     .attrs = target_attrs,
0154     .is_visible = iscsi_boot_tgt_attr_is_visible,
0155 };
0156 
0157 /* Ethernet attrs */
0158 iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
0159 iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
0160 iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
0161 iscsi_boot_rd_attr(eth_prefix, prefix-len, ISCSI_BOOT_ETH_PREFIX_LEN);
0162 iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
0163 iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
0164 iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
0165 iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS);
0166 iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns,
0167            ISCSI_BOOT_ETH_SECONDARY_DNS);
0168 iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP);
0169 iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN);
0170 iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC);
0171 iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME);
0172 
0173 static struct attribute *ethernet_attrs[] = {
0174     &iscsi_boot_attr_eth_index.attr,
0175     &iscsi_boot_attr_eth_flags.attr,
0176     &iscsi_boot_attr_eth_ip.attr,
0177     &iscsi_boot_attr_eth_prefix.attr,
0178     &iscsi_boot_attr_eth_subnet.attr,
0179     &iscsi_boot_attr_eth_origin.attr,
0180     &iscsi_boot_attr_eth_gateway.attr,
0181     &iscsi_boot_attr_eth_primary_dns.attr,
0182     &iscsi_boot_attr_eth_secondary_dns.attr,
0183     &iscsi_boot_attr_eth_dhcp.attr,
0184     &iscsi_boot_attr_eth_vlan.attr,
0185     &iscsi_boot_attr_eth_mac.attr,
0186     &iscsi_boot_attr_eth_hostname.attr,
0187     NULL
0188 };
0189 
0190 static umode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj,
0191                          struct attribute *attr, int i)
0192 {
0193     struct iscsi_boot_kobj *boot_kobj =
0194             container_of(kobj, struct iscsi_boot_kobj, kobj);
0195 
0196     if (attr ==  &iscsi_boot_attr_eth_index.attr)
0197         return boot_kobj->is_visible(boot_kobj->data,
0198                          ISCSI_BOOT_ETH_INDEX);
0199     else if (attr ==  &iscsi_boot_attr_eth_flags.attr)
0200         return boot_kobj->is_visible(boot_kobj->data,
0201                          ISCSI_BOOT_ETH_FLAGS);
0202     else if (attr ==  &iscsi_boot_attr_eth_ip.attr)
0203         return boot_kobj->is_visible(boot_kobj->data,
0204                          ISCSI_BOOT_ETH_IP_ADDR);
0205     else if (attr ==  &iscsi_boot_attr_eth_prefix.attr)
0206         return boot_kobj->is_visible(boot_kobj->data,
0207                          ISCSI_BOOT_ETH_PREFIX_LEN);
0208     else if (attr ==  &iscsi_boot_attr_eth_subnet.attr)
0209         return boot_kobj->is_visible(boot_kobj->data,
0210                          ISCSI_BOOT_ETH_SUBNET_MASK);
0211     else if (attr ==  &iscsi_boot_attr_eth_origin.attr)
0212         return boot_kobj->is_visible(boot_kobj->data,
0213                          ISCSI_BOOT_ETH_ORIGIN);
0214     else if (attr ==  &iscsi_boot_attr_eth_gateway.attr)
0215         return boot_kobj->is_visible(boot_kobj->data,
0216                          ISCSI_BOOT_ETH_GATEWAY);
0217     else if (attr ==  &iscsi_boot_attr_eth_primary_dns.attr)
0218         return boot_kobj->is_visible(boot_kobj->data,
0219                          ISCSI_BOOT_ETH_PRIMARY_DNS);
0220     else if (attr ==  &iscsi_boot_attr_eth_secondary_dns.attr)
0221         return boot_kobj->is_visible(boot_kobj->data,
0222                          ISCSI_BOOT_ETH_SECONDARY_DNS);
0223     else if (attr ==  &iscsi_boot_attr_eth_dhcp.attr)
0224         return boot_kobj->is_visible(boot_kobj->data,
0225                          ISCSI_BOOT_ETH_DHCP);
0226     else if (attr ==  &iscsi_boot_attr_eth_vlan.attr)
0227         return boot_kobj->is_visible(boot_kobj->data,
0228                          ISCSI_BOOT_ETH_VLAN);
0229     else if (attr ==  &iscsi_boot_attr_eth_mac.attr)
0230         return boot_kobj->is_visible(boot_kobj->data,
0231                          ISCSI_BOOT_ETH_MAC);
0232     else if (attr ==  &iscsi_boot_attr_eth_hostname.attr)
0233         return boot_kobj->is_visible(boot_kobj->data,
0234                          ISCSI_BOOT_ETH_HOSTNAME);
0235     return 0;
0236 }
0237 
0238 static struct attribute_group iscsi_boot_ethernet_attr_group = {
0239     .attrs = ethernet_attrs,
0240     .is_visible = iscsi_boot_eth_attr_is_visible,
0241 };
0242 
0243 /* Initiator attrs */
0244 iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX);
0245 iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS);
0246 iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER);
0247 iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER);
0248 iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server,
0249            ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
0250 iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server,
0251            ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
0252 iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME);
0253 
0254 static struct attribute *initiator_attrs[] = {
0255     &iscsi_boot_attr_ini_index.attr,
0256     &iscsi_boot_attr_ini_flags.attr,
0257     &iscsi_boot_attr_ini_isns.attr,
0258     &iscsi_boot_attr_ini_slp.attr,
0259     &iscsi_boot_attr_ini_primary_radius.attr,
0260     &iscsi_boot_attr_ini_secondary_radius.attr,
0261     &iscsi_boot_attr_ini_name.attr,
0262     NULL
0263 };
0264 
0265 static umode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj,
0266                          struct attribute *attr, int i)
0267 {
0268     struct iscsi_boot_kobj *boot_kobj =
0269             container_of(kobj, struct iscsi_boot_kobj, kobj);
0270 
0271     if (attr ==  &iscsi_boot_attr_ini_index.attr)
0272         return boot_kobj->is_visible(boot_kobj->data,
0273                          ISCSI_BOOT_INI_INDEX);
0274     if (attr ==  &iscsi_boot_attr_ini_flags.attr)
0275         return boot_kobj->is_visible(boot_kobj->data,
0276                          ISCSI_BOOT_INI_FLAGS);
0277     if (attr ==  &iscsi_boot_attr_ini_isns.attr)
0278         return boot_kobj->is_visible(boot_kobj->data,
0279                          ISCSI_BOOT_INI_ISNS_SERVER);
0280     if (attr ==  &iscsi_boot_attr_ini_slp.attr)
0281         return boot_kobj->is_visible(boot_kobj->data,
0282                          ISCSI_BOOT_INI_SLP_SERVER);
0283     if (attr ==  &iscsi_boot_attr_ini_primary_radius.attr)
0284         return boot_kobj->is_visible(boot_kobj->data,
0285                          ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
0286     if (attr ==  &iscsi_boot_attr_ini_secondary_radius.attr)
0287         return boot_kobj->is_visible(boot_kobj->data,
0288                          ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
0289     if (attr ==  &iscsi_boot_attr_ini_name.attr)
0290         return boot_kobj->is_visible(boot_kobj->data,
0291                          ISCSI_BOOT_INI_INITIATOR_NAME);
0292 
0293     return 0;
0294 }
0295 
0296 static struct attribute_group iscsi_boot_initiator_attr_group = {
0297     .attrs = initiator_attrs,
0298     .is_visible = iscsi_boot_ini_attr_is_visible,
0299 };
0300 
0301 /* iBFT ACPI Table attributes */
0302 iscsi_boot_rd_attr(acpitbl_signature, signature, ISCSI_BOOT_ACPITBL_SIGNATURE);
0303 iscsi_boot_rd_attr(acpitbl_oem_id, oem_id, ISCSI_BOOT_ACPITBL_OEM_ID);
0304 iscsi_boot_rd_attr(acpitbl_oem_table_id, oem_table_id,
0305            ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
0306 
0307 static struct attribute *acpitbl_attrs[] = {
0308     &iscsi_boot_attr_acpitbl_signature.attr,
0309     &iscsi_boot_attr_acpitbl_oem_id.attr,
0310     &iscsi_boot_attr_acpitbl_oem_table_id.attr,
0311     NULL
0312 };
0313 
0314 static umode_t iscsi_boot_acpitbl_attr_is_visible(struct kobject *kobj,
0315                          struct attribute *attr, int i)
0316 {
0317     struct iscsi_boot_kobj *boot_kobj =
0318             container_of(kobj, struct iscsi_boot_kobj, kobj);
0319 
0320     if (attr ==  &iscsi_boot_attr_acpitbl_signature.attr)
0321         return boot_kobj->is_visible(boot_kobj->data,
0322                          ISCSI_BOOT_ACPITBL_SIGNATURE);
0323     if (attr ==  &iscsi_boot_attr_acpitbl_oem_id.attr)
0324         return boot_kobj->is_visible(boot_kobj->data,
0325                          ISCSI_BOOT_ACPITBL_OEM_ID);
0326     if (attr ==  &iscsi_boot_attr_acpitbl_oem_table_id.attr)
0327         return boot_kobj->is_visible(boot_kobj->data,
0328                          ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
0329     return 0;
0330 }
0331 
0332 static struct attribute_group iscsi_boot_acpitbl_attr_group = {
0333     .attrs = acpitbl_attrs,
0334     .is_visible = iscsi_boot_acpitbl_attr_is_visible,
0335 };
0336 
0337 static struct iscsi_boot_kobj *
0338 iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
0339                struct attribute_group *attr_group,
0340                const char *name, int index, void *data,
0341                ssize_t (*show) (void *data, int type, char *buf),
0342                umode_t (*is_visible) (void *data, int type),
0343                void (*release) (void *data))
0344 {
0345     struct iscsi_boot_kobj *boot_kobj;
0346 
0347     boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL);
0348     if (!boot_kobj)
0349         return NULL;
0350     INIT_LIST_HEAD(&boot_kobj->list);
0351 
0352     boot_kobj->kobj.kset = boot_kset->kset;
0353     if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
0354                  NULL, name, index)) {
0355         kobject_put(&boot_kobj->kobj);
0356         return NULL;
0357     }
0358     boot_kobj->data = data;
0359     boot_kobj->show = show;
0360     boot_kobj->is_visible = is_visible;
0361     boot_kobj->release = release;
0362 
0363     if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
0364         /*
0365          * We do not want to free this because the caller
0366          * will assume that since the creation call failed
0367          * the boot kobj was not setup and the normal release
0368          * path is not being run.
0369          */
0370         boot_kobj->release = NULL;
0371         kobject_put(&boot_kobj->kobj);
0372         return NULL;
0373     }
0374     boot_kobj->attr_group = attr_group;
0375 
0376     kobject_uevent(&boot_kobj->kobj, KOBJ_ADD);
0377     /* Nothing broke so lets add it to the list. */
0378     list_add_tail(&boot_kobj->list, &boot_kset->kobj_list);
0379     return boot_kobj;
0380 }
0381 
0382 static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
0383 {
0384     list_del(&boot_kobj->list);
0385     sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group);
0386     kobject_put(&boot_kobj->kobj);
0387 }
0388 
0389 /**
0390  * iscsi_boot_create_target() - create boot target sysfs dir
0391  * @boot_kset: boot kset
0392  * @index: the target id
0393  * @data: driver specific data for target
0394  * @show: attr show function
0395  * @is_visible: attr visibility function
0396  * @release: release function
0397  *
0398  * Note: The boot sysfs lib will free the data passed in for the caller
0399  * when all refs to the target kobject have been released.
0400  */
0401 struct iscsi_boot_kobj *
0402 iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
0403              void *data,
0404              ssize_t (*show) (void *data, int type, char *buf),
0405              umode_t (*is_visible) (void *data, int type),
0406              void (*release) (void *data))
0407 {
0408     return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
0409                       "target%d", index, data, show, is_visible,
0410                       release);
0411 }
0412 EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
0413 
0414 /**
0415  * iscsi_boot_create_initiator() - create boot initiator sysfs dir
0416  * @boot_kset: boot kset
0417  * @index: the initiator id
0418  * @data: driver specific data
0419  * @show: attr show function
0420  * @is_visible: attr visibility function
0421  * @release: release function
0422  *
0423  * Note: The boot sysfs lib will free the data passed in for the caller
0424  * when all refs to the initiator kobject have been released.
0425  */
0426 struct iscsi_boot_kobj *
0427 iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
0428                 void *data,
0429                 ssize_t (*show) (void *data, int type, char *buf),
0430                 umode_t (*is_visible) (void *data, int type),
0431                 void (*release) (void *data))
0432 {
0433     return iscsi_boot_create_kobj(boot_kset,
0434                       &iscsi_boot_initiator_attr_group,
0435                       "initiator", index, data, show,
0436                       is_visible, release);
0437 }
0438 EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
0439 
0440 /**
0441  * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir
0442  * @boot_kset: boot kset
0443  * @index: the ethernet device id
0444  * @data: driver specific data
0445  * @show: attr show function
0446  * @is_visible: attr visibility function
0447  * @release: release function
0448  *
0449  * Note: The boot sysfs lib will free the data passed in for the caller
0450  * when all refs to the ethernet kobject have been released.
0451  */
0452 struct iscsi_boot_kobj *
0453 iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
0454                void *data,
0455                ssize_t (*show) (void *data, int type, char *buf),
0456                umode_t (*is_visible) (void *data, int type),
0457                void (*release) (void *data))
0458 {
0459     return iscsi_boot_create_kobj(boot_kset,
0460                       &iscsi_boot_ethernet_attr_group,
0461                       "ethernet%d", index, data, show,
0462                       is_visible, release);
0463 }
0464 EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
0465 
0466 /**
0467  * iscsi_boot_create_acpitbl() - create boot acpi table sysfs dir
0468  * @boot_kset: boot kset
0469  * @index: not used
0470  * @data: driver specific data
0471  * @show: attr show function
0472  * @is_visible: attr visibility function
0473  * @release: release function
0474  *
0475  * Note: The boot sysfs lib will free the data passed in for the caller
0476  * when all refs to the acpitbl kobject have been released.
0477  */
0478 struct iscsi_boot_kobj *
0479 iscsi_boot_create_acpitbl(struct iscsi_boot_kset *boot_kset, int index,
0480                void *data,
0481                ssize_t (*show)(void *data, int type, char *buf),
0482                umode_t (*is_visible)(void *data, int type),
0483                void (*release)(void *data))
0484 {
0485     return iscsi_boot_create_kobj(boot_kset,
0486                       &iscsi_boot_acpitbl_attr_group,
0487                       "acpi_header", index, data, show,
0488                       is_visible, release);
0489 }
0490 EXPORT_SYMBOL_GPL(iscsi_boot_create_acpitbl);
0491 
0492 /**
0493  * iscsi_boot_create_kset() - creates root sysfs tree
0494  * @set_name: name of root dir
0495  */
0496 struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name)
0497 {
0498     struct iscsi_boot_kset *boot_kset;
0499 
0500     boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL);
0501     if (!boot_kset)
0502         return NULL;
0503 
0504     boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj);
0505     if (!boot_kset->kset) {
0506         kfree(boot_kset);
0507         return NULL;
0508     }
0509 
0510     INIT_LIST_HEAD(&boot_kset->kobj_list);
0511     return boot_kset;
0512 }
0513 EXPORT_SYMBOL_GPL(iscsi_boot_create_kset);
0514 
0515 /**
0516  * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host
0517  * @hostno: host number of scsi host
0518  */
0519 struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno)
0520 {
0521     struct iscsi_boot_kset *boot_kset;
0522     char *set_name;
0523 
0524     set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno);
0525     if (!set_name)
0526         return NULL;
0527 
0528     boot_kset = iscsi_boot_create_kset(set_name);
0529     kfree(set_name);
0530     return boot_kset;
0531 }
0532 EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset);
0533 
0534 /**
0535  * iscsi_boot_destroy_kset() - destroy kset and kobjects under it
0536  * @boot_kset: boot kset
0537  *
0538  * This will remove the kset and kobjects and attrs under it.
0539  */
0540 void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
0541 {
0542     struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
0543 
0544     if (!boot_kset)
0545         return;
0546 
0547     list_for_each_entry_safe(boot_kobj, tmp_kobj,
0548                  &boot_kset->kobj_list, list)
0549         iscsi_boot_remove_kobj(boot_kobj);
0550 
0551     kset_unregister(boot_kset->kset);
0552     kfree(boot_kset);
0553 }
0554 EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);