linux/drivers/scsi/iscsi_boot_sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Export the iSCSI boot info to userland via sysfs.
   4 *
   5 * Copyright (C) 2010 Red Hat, Inc.  All rights reserved.
   6 * Copyright (C) 2010 Mike Christie
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/string.h>
  11#include <linux/slab.h>
  12#include <linux/sysfs.h>
  13#include <linux/capability.h>
  14#include <linux/iscsi_boot_sysfs.h>
  15
  16
  17MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>");
  18MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information");
  19MODULE_LICENSE("GPL");
  20/*
  21 * The kobject and attribute structures.
  22 */
  23struct iscsi_boot_attr {
  24        struct attribute attr;
  25        int type;
  26        ssize_t (*show) (void *data, int type, char *buf);
  27};
  28
  29/*
  30 * The routine called for all sysfs attributes.
  31 */
  32static ssize_t iscsi_boot_show_attribute(struct kobject *kobj,
  33                                         struct attribute *attr, char *buf)
  34{
  35        struct iscsi_boot_kobj *boot_kobj =
  36                        container_of(kobj, struct iscsi_boot_kobj, kobj);
  37        struct iscsi_boot_attr *boot_attr =
  38                        container_of(attr, struct iscsi_boot_attr, attr);
  39        ssize_t ret = -EIO;
  40        char *str = buf;
  41
  42        if (!capable(CAP_SYS_ADMIN))
  43                return -EACCES;
  44
  45        if (boot_kobj->show)
  46                ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str);
  47        return ret;
  48}
  49
  50static const struct sysfs_ops iscsi_boot_attr_ops = {
  51        .show = iscsi_boot_show_attribute,
  52};
  53
  54static void iscsi_boot_kobj_release(struct kobject *kobj)
  55{
  56        struct iscsi_boot_kobj *boot_kobj =
  57                        container_of(kobj, struct iscsi_boot_kobj, kobj);
  58
  59        if (boot_kobj->release)
  60                boot_kobj->release(boot_kobj->data);
  61        kfree(boot_kobj);
  62}
  63
  64static struct kobj_type iscsi_boot_ktype = {
  65        .release = iscsi_boot_kobj_release,
  66        .sysfs_ops = &iscsi_boot_attr_ops,
  67};
  68
  69#define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type)               \
  70static struct iscsi_boot_attr iscsi_boot_attr_##fnname = {      \
  71        .attr   = { .name = __stringify(sysfs_name), .mode = 0444 },    \
  72        .type   = attr_type,                                            \
  73}
  74
  75/* Target attrs */
  76iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX);
  77iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS);
  78iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR);
  79iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT);
  80iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN);
  81iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE);
  82iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC);
  83iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME);
  84iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME);
  85iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET);
  86iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name,
  87                   ISCSI_BOOT_TGT_REV_CHAP_NAME);
  88iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret,
  89                   ISCSI_BOOT_TGT_REV_CHAP_SECRET);
  90
  91static struct attribute *target_attrs[] = {
  92        &iscsi_boot_attr_tgt_index.attr,
  93        &iscsi_boot_attr_tgt_flags.attr,
  94        &iscsi_boot_attr_tgt_ip.attr,
  95        &iscsi_boot_attr_tgt_port.attr,
  96        &iscsi_boot_attr_tgt_lun.attr,
  97        &iscsi_boot_attr_tgt_chap.attr,
  98        &iscsi_boot_attr_tgt_nic.attr,
  99        &iscsi_boot_attr_tgt_name.attr,
 100        &iscsi_boot_attr_tgt_chap_name.attr,
 101        &iscsi_boot_attr_tgt_chap_secret.attr,
 102        &iscsi_boot_attr_tgt_chap_rev_name.attr,
 103        &iscsi_boot_attr_tgt_chap_rev_secret.attr,
 104        NULL
 105};
 106
 107static umode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj,
 108                                             struct attribute *attr, int i)
 109{
 110        struct iscsi_boot_kobj *boot_kobj =
 111                        container_of(kobj, struct iscsi_boot_kobj, kobj);
 112
 113        if (attr ==  &iscsi_boot_attr_tgt_index.attr)
 114                return boot_kobj->is_visible(boot_kobj->data,
 115                                             ISCSI_BOOT_TGT_INDEX);
 116        else if (attr == &iscsi_boot_attr_tgt_flags.attr)
 117                return boot_kobj->is_visible(boot_kobj->data,
 118                                             ISCSI_BOOT_TGT_FLAGS);
 119        else if (attr == &iscsi_boot_attr_tgt_ip.attr)
 120                return boot_kobj->is_visible(boot_kobj->data,
 121                                              ISCSI_BOOT_TGT_IP_ADDR);
 122        else if (attr == &iscsi_boot_attr_tgt_port.attr)
 123                return boot_kobj->is_visible(boot_kobj->data,
 124                                              ISCSI_BOOT_TGT_PORT);
 125        else if (attr == &iscsi_boot_attr_tgt_lun.attr)
 126                return boot_kobj->is_visible(boot_kobj->data,
 127                                              ISCSI_BOOT_TGT_LUN);
 128        else if (attr == &iscsi_boot_attr_tgt_chap.attr)
 129                return boot_kobj->is_visible(boot_kobj->data,
 130                                             ISCSI_BOOT_TGT_CHAP_TYPE);
 131        else if (attr == &iscsi_boot_attr_tgt_nic.attr)
 132                return boot_kobj->is_visible(boot_kobj->data,
 133                                             ISCSI_BOOT_TGT_NIC_ASSOC);
 134        else if (attr == &iscsi_boot_attr_tgt_name.attr)
 135                return boot_kobj->is_visible(boot_kobj->data,
 136                                             ISCSI_BOOT_TGT_NAME);
 137        else if (attr == &iscsi_boot_attr_tgt_chap_name.attr)
 138                return boot_kobj->is_visible(boot_kobj->data,
 139                                             ISCSI_BOOT_TGT_CHAP_NAME);
 140        else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr)
 141                return boot_kobj->is_visible(boot_kobj->data,
 142                                             ISCSI_BOOT_TGT_CHAP_SECRET);
 143        else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr)
 144                return boot_kobj->is_visible(boot_kobj->data,
 145                                             ISCSI_BOOT_TGT_REV_CHAP_NAME);
 146        else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr)
 147                return boot_kobj->is_visible(boot_kobj->data,
 148                                             ISCSI_BOOT_TGT_REV_CHAP_SECRET);
 149        return 0;
 150}
 151
 152static struct attribute_group iscsi_boot_target_attr_group = {
 153        .attrs = target_attrs,
 154        .is_visible = iscsi_boot_tgt_attr_is_visible,
 155};
 156
 157/* Ethernet attrs */
 158iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
 159iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
 160iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
 161iscsi_boot_rd_attr(eth_prefix, prefix-len, ISCSI_BOOT_ETH_PREFIX_LEN);
 162iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
 163iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
 164iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
 165iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS);
 166iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns,
 167                   ISCSI_BOOT_ETH_SECONDARY_DNS);
 168iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP);
 169iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN);
 170iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC);
 171iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME);
 172
 173static struct attribute *ethernet_attrs[] = {
 174        &iscsi_boot_attr_eth_index.attr,
 175        &iscsi_boot_attr_eth_flags.attr,
 176        &iscsi_boot_attr_eth_ip.attr,
 177        &iscsi_boot_attr_eth_prefix.attr,
 178        &iscsi_boot_attr_eth_subnet.attr,
 179        &iscsi_boot_attr_eth_origin.attr,
 180        &iscsi_boot_attr_eth_gateway.attr,
 181        &iscsi_boot_attr_eth_primary_dns.attr,
 182        &iscsi_boot_attr_eth_secondary_dns.attr,
 183        &iscsi_boot_attr_eth_dhcp.attr,
 184        &iscsi_boot_attr_eth_vlan.attr,
 185        &iscsi_boot_attr_eth_mac.attr,
 186        &iscsi_boot_attr_eth_hostname.attr,
 187        NULL
 188};
 189
 190static umode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj,
 191                                             struct attribute *attr, int i)
 192{
 193        struct iscsi_boot_kobj *boot_kobj =
 194                        container_of(kobj, struct iscsi_boot_kobj, kobj);
 195
 196        if (attr ==  &iscsi_boot_attr_eth_index.attr)
 197                return boot_kobj->is_visible(boot_kobj->data,
 198                                             ISCSI_BOOT_ETH_INDEX);
 199        else if (attr ==  &iscsi_boot_attr_eth_flags.attr)
 200                return boot_kobj->is_visible(boot_kobj->data,
 201                                             ISCSI_BOOT_ETH_FLAGS);
 202        else if (attr ==  &iscsi_boot_attr_eth_ip.attr)
 203                return boot_kobj->is_visible(boot_kobj->data,
 204                                             ISCSI_BOOT_ETH_IP_ADDR);
 205        else if (attr ==  &iscsi_boot_attr_eth_prefix.attr)
 206                return boot_kobj->is_visible(boot_kobj->data,
 207                                             ISCSI_BOOT_ETH_PREFIX_LEN);
 208        else if (attr ==  &iscsi_boot_attr_eth_subnet.attr)
 209                return boot_kobj->is_visible(boot_kobj->data,
 210                                             ISCSI_BOOT_ETH_SUBNET_MASK);
 211        else if (attr ==  &iscsi_boot_attr_eth_origin.attr)
 212                return boot_kobj->is_visible(boot_kobj->data,
 213                                             ISCSI_BOOT_ETH_ORIGIN);
 214        else if (attr ==  &iscsi_boot_attr_eth_gateway.attr)
 215                return boot_kobj->is_visible(boot_kobj->data,
 216                                             ISCSI_BOOT_ETH_GATEWAY);
 217        else if (attr ==  &iscsi_boot_attr_eth_primary_dns.attr)
 218                return boot_kobj->is_visible(boot_kobj->data,
 219                                             ISCSI_BOOT_ETH_PRIMARY_DNS);
 220        else if (attr ==  &iscsi_boot_attr_eth_secondary_dns.attr)
 221                return boot_kobj->is_visible(boot_kobj->data,
 222                                             ISCSI_BOOT_ETH_SECONDARY_DNS);
 223        else if (attr ==  &iscsi_boot_attr_eth_dhcp.attr)
 224                return boot_kobj->is_visible(boot_kobj->data,
 225                                             ISCSI_BOOT_ETH_DHCP);
 226        else if (attr ==  &iscsi_boot_attr_eth_vlan.attr)
 227                return boot_kobj->is_visible(boot_kobj->data,
 228                                             ISCSI_BOOT_ETH_VLAN);
 229        else if (attr ==  &iscsi_boot_attr_eth_mac.attr)
 230                return boot_kobj->is_visible(boot_kobj->data,
 231                                             ISCSI_BOOT_ETH_MAC);
 232        else if (attr ==  &iscsi_boot_attr_eth_hostname.attr)
 233                return boot_kobj->is_visible(boot_kobj->data,
 234                                             ISCSI_BOOT_ETH_HOSTNAME);
 235        return 0;
 236}
 237
 238static struct attribute_group iscsi_boot_ethernet_attr_group = {
 239        .attrs = ethernet_attrs,
 240        .is_visible = iscsi_boot_eth_attr_is_visible,
 241};
 242
 243/* Initiator attrs */
 244iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX);
 245iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS);
 246iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER);
 247iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER);
 248iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server,
 249                   ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
 250iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server,
 251                   ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
 252iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME);
 253
 254static struct attribute *initiator_attrs[] = {
 255        &iscsi_boot_attr_ini_index.attr,
 256        &iscsi_boot_attr_ini_flags.attr,
 257        &iscsi_boot_attr_ini_isns.attr,
 258        &iscsi_boot_attr_ini_slp.attr,
 259        &iscsi_boot_attr_ini_primary_radius.attr,
 260        &iscsi_boot_attr_ini_secondary_radius.attr,
 261        &iscsi_boot_attr_ini_name.attr,
 262        NULL
 263};
 264
 265static umode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj,
 266                                             struct attribute *attr, int i)
 267{
 268        struct iscsi_boot_kobj *boot_kobj =
 269                        container_of(kobj, struct iscsi_boot_kobj, kobj);
 270
 271        if (attr ==  &iscsi_boot_attr_ini_index.attr)
 272                return boot_kobj->is_visible(boot_kobj->data,
 273                                             ISCSI_BOOT_INI_INDEX);
 274        if (attr ==  &iscsi_boot_attr_ini_flags.attr)
 275                return boot_kobj->is_visible(boot_kobj->data,
 276                                             ISCSI_BOOT_INI_FLAGS);
 277        if (attr ==  &iscsi_boot_attr_ini_isns.attr)
 278                return boot_kobj->is_visible(boot_kobj->data,
 279                                             ISCSI_BOOT_INI_ISNS_SERVER);
 280        if (attr ==  &iscsi_boot_attr_ini_slp.attr)
 281                return boot_kobj->is_visible(boot_kobj->data,
 282                                             ISCSI_BOOT_INI_SLP_SERVER);
 283        if (attr ==  &iscsi_boot_attr_ini_primary_radius.attr)
 284                return boot_kobj->is_visible(boot_kobj->data,
 285                                             ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
 286        if (attr ==  &iscsi_boot_attr_ini_secondary_radius.attr)
 287                return boot_kobj->is_visible(boot_kobj->data,
 288                                             ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
 289        if (attr ==  &iscsi_boot_attr_ini_name.attr)
 290                return boot_kobj->is_visible(boot_kobj->data,
 291                                             ISCSI_BOOT_INI_INITIATOR_NAME);
 292
 293        return 0;
 294}
 295
 296static struct attribute_group iscsi_boot_initiator_attr_group = {
 297        .attrs = initiator_attrs,
 298        .is_visible = iscsi_boot_ini_attr_is_visible,
 299};
 300
 301/* iBFT ACPI Table attributes */
 302iscsi_boot_rd_attr(acpitbl_signature, signature, ISCSI_BOOT_ACPITBL_SIGNATURE);
 303iscsi_boot_rd_attr(acpitbl_oem_id, oem_id, ISCSI_BOOT_ACPITBL_OEM_ID);
 304iscsi_boot_rd_attr(acpitbl_oem_table_id, oem_table_id,
 305                   ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
 306
 307static struct attribute *acpitbl_attrs[] = {
 308        &iscsi_boot_attr_acpitbl_signature.attr,
 309        &iscsi_boot_attr_acpitbl_oem_id.attr,
 310        &iscsi_boot_attr_acpitbl_oem_table_id.attr,
 311        NULL
 312};
 313
 314static umode_t iscsi_boot_acpitbl_attr_is_visible(struct kobject *kobj,
 315                                             struct attribute *attr, int i)
 316{
 317        struct iscsi_boot_kobj *boot_kobj =
 318                        container_of(kobj, struct iscsi_boot_kobj, kobj);
 319
 320        if (attr ==  &iscsi_boot_attr_acpitbl_signature.attr)
 321                return boot_kobj->is_visible(boot_kobj->data,
 322                                             ISCSI_BOOT_ACPITBL_SIGNATURE);
 323        if (attr ==  &iscsi_boot_attr_acpitbl_oem_id.attr)
 324                return boot_kobj->is_visible(boot_kobj->data,
 325                                             ISCSI_BOOT_ACPITBL_OEM_ID);
 326        if (attr ==  &iscsi_boot_attr_acpitbl_oem_table_id.attr)
 327                return boot_kobj->is_visible(boot_kobj->data,
 328                                             ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
 329        return 0;
 330}
 331
 332static struct attribute_group iscsi_boot_acpitbl_attr_group = {
 333        .attrs = acpitbl_attrs,
 334        .is_visible = iscsi_boot_acpitbl_attr_is_visible,
 335};
 336
 337static struct iscsi_boot_kobj *
 338iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
 339                       struct attribute_group *attr_group,
 340                       const char *name, int index, void *data,
 341                       ssize_t (*show) (void *data, int type, char *buf),
 342                       umode_t (*is_visible) (void *data, int type),
 343                       void (*release) (void *data))
 344{
 345        struct iscsi_boot_kobj *boot_kobj;
 346
 347        boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL);
 348        if (!boot_kobj)
 349                return NULL;
 350        INIT_LIST_HEAD(&boot_kobj->list);
 351
 352        boot_kobj->kobj.kset = boot_kset->kset;
 353        if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
 354                                 NULL, name, index)) {
 355                kobject_put(&boot_kobj->kobj);
 356                return NULL;
 357        }
 358        boot_kobj->data = data;
 359        boot_kobj->show = show;
 360        boot_kobj->is_visible = is_visible;
 361        boot_kobj->release = release;
 362
 363        if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
 364                /*
 365                 * We do not want to free this because the caller
 366                 * will assume that since the creation call failed
 367                 * the boot kobj was not setup and the normal release
 368                 * path is not being run.
 369                 */
 370                boot_kobj->release = NULL;
 371                kobject_put(&boot_kobj->kobj);
 372                return NULL;
 373        }
 374        boot_kobj->attr_group = attr_group;
 375
 376        kobject_uevent(&boot_kobj->kobj, KOBJ_ADD);
 377        /* Nothing broke so lets add it to the list. */
 378        list_add_tail(&boot_kobj->list, &boot_kset->kobj_list);
 379        return boot_kobj;
 380}
 381
 382static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
 383{
 384        list_del(&boot_kobj->list);
 385        sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group);
 386        kobject_put(&boot_kobj->kobj);
 387}
 388
 389/**
 390 * iscsi_boot_create_target() - create boot target sysfs dir
 391 * @boot_kset: boot kset
 392 * @index: the target id
 393 * @data: driver specific data for target
 394 * @show: attr show function
 395 * @is_visible: attr visibility function
 396 * @release: release function
 397 *
 398 * Note: The boot sysfs lib will free the data passed in for the caller
 399 * when all refs to the target kobject have been released.
 400 */
 401struct iscsi_boot_kobj *
 402iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
 403                         void *data,
 404                         ssize_t (*show) (void *data, int type, char *buf),
 405                         umode_t (*is_visible) (void *data, int type),
 406                         void (*release) (void *data))
 407{
 408        return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
 409                                      "target%d", index, data, show, is_visible,
 410                                      release);
 411}
 412EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
 413
 414/**
 415 * iscsi_boot_create_initiator() - create boot initiator sysfs dir
 416 * @boot_kset: boot kset
 417 * @index: the initiator id
 418 * @data: driver specific data
 419 * @show: attr show function
 420 * @is_visible: attr visibility function
 421 * @release: release function
 422 *
 423 * Note: The boot sysfs lib will free the data passed in for the caller
 424 * when all refs to the initiator kobject have been released.
 425 */
 426struct iscsi_boot_kobj *
 427iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
 428                            void *data,
 429                            ssize_t (*show) (void *data, int type, char *buf),
 430                            umode_t (*is_visible) (void *data, int type),
 431                            void (*release) (void *data))
 432{
 433        return iscsi_boot_create_kobj(boot_kset,
 434                                      &iscsi_boot_initiator_attr_group,
 435                                      "initiator", index, data, show,
 436                                      is_visible, release);
 437}
 438EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
 439
 440/**
 441 * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir
 442 * @boot_kset: boot kset
 443 * @index: the ethernet device id
 444 * @data: driver specific data
 445 * @show: attr show function
 446 * @is_visible: attr visibility function
 447 * @release: release function
 448 *
 449 * Note: The boot sysfs lib will free the data passed in for the caller
 450 * when all refs to the ethernet kobject have been released.
 451 */
 452struct iscsi_boot_kobj *
 453iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
 454                           void *data,
 455                           ssize_t (*show) (void *data, int type, char *buf),
 456                           umode_t (*is_visible) (void *data, int type),
 457                           void (*release) (void *data))
 458{
 459        return iscsi_boot_create_kobj(boot_kset,
 460                                      &iscsi_boot_ethernet_attr_group,
 461                                      "ethernet%d", index, data, show,
 462                                      is_visible, release);
 463}
 464EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
 465
 466/**
 467 * iscsi_boot_create_acpitbl() - create boot acpi table sysfs dir
 468 * @boot_kset: boot kset
 469 * @index: not used
 470 * @data: driver specific data
 471 * @show: attr show function
 472 * @is_visible: attr visibility function
 473 * @release: release function
 474 *
 475 * Note: The boot sysfs lib will free the data passed in for the caller
 476 * when all refs to the acpitbl kobject have been released.
 477 */
 478struct iscsi_boot_kobj *
 479iscsi_boot_create_acpitbl(struct iscsi_boot_kset *boot_kset, int index,
 480                           void *data,
 481                           ssize_t (*show)(void *data, int type, char *buf),
 482                           umode_t (*is_visible)(void *data, int type),
 483                           void (*release)(void *data))
 484{
 485        return iscsi_boot_create_kobj(boot_kset,
 486                                      &iscsi_boot_acpitbl_attr_group,
 487                                      "acpi_header", index, data, show,
 488                                      is_visible, release);
 489}
 490EXPORT_SYMBOL_GPL(iscsi_boot_create_acpitbl);
 491
 492/**
 493 * iscsi_boot_create_kset() - creates root sysfs tree
 494 * @set_name: name of root dir
 495 */
 496struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name)
 497{
 498        struct iscsi_boot_kset *boot_kset;
 499
 500        boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL);
 501        if (!boot_kset)
 502                return NULL;
 503
 504        boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj);
 505        if (!boot_kset->kset) {
 506                kfree(boot_kset);
 507                return NULL;
 508        }
 509
 510        INIT_LIST_HEAD(&boot_kset->kobj_list);
 511        return boot_kset;
 512}
 513EXPORT_SYMBOL_GPL(iscsi_boot_create_kset);
 514
 515/**
 516 * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host
 517 * @hostno: host number of scsi host
 518 */
 519struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno)
 520{
 521        struct iscsi_boot_kset *boot_kset;
 522        char *set_name;
 523
 524        set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno);
 525        if (!set_name)
 526                return NULL;
 527
 528        boot_kset = iscsi_boot_create_kset(set_name);
 529        kfree(set_name);
 530        return boot_kset;
 531}
 532EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset);
 533
 534/**
 535 * iscsi_boot_destroy_kset() - destroy kset and kobjects under it
 536 * @boot_kset: boot kset
 537 *
 538 * This will remove the kset and kobjects and attrs under it.
 539 */
 540void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
 541{
 542        struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
 543
 544        if (!boot_kset)
 545                return;
 546
 547        list_for_each_entry_safe(boot_kobj, tmp_kobj,
 548                                 &boot_kset->kobj_list, list)
 549                iscsi_boot_remove_kobj(boot_kobj);
 550
 551        kset_unregister(boot_kset->kset);
 552        kfree(boot_kset);
 553}
 554EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
 555