Commit ba4ee30c6c797de148dcc7254cf6d531aba71d9b

Authored by Mike Christie
Committed by Konrad Rzeszutek Wilk
1 parent 1303a35bfe

ibft: separate ibft parsing from sysfs interface

Not all iscsi drivers support ibft. For drivers like be2iscsi
that do not but are bootable through a vendor firmware specific
format/process this patch moves the sysfs interface from the ibft code
to a lib module. This then allows userspace tools to search for iscsi boot
info in a common place and in a common format.

ibft iscsi boot info is exported in the same place as it was
before: /sys/firmware/ibft.

vendor/fw boot info gets export in /sys/firmware/iscsi_bootX, where X is the
scsi host number of the HBA. Underneath these parent dirs, the
target, ethernet, and initiator dirs are the same as they were before.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Konrad Rzeszutek Wilk <konrad@kernel.org>
Signed-off-by: Peter Jones <pjones@redhat.com>

Showing 4 changed files with 613 additions and 0 deletions Side-by-side Diff

drivers/firmware/Kconfig
... ... @@ -122,6 +122,14 @@
122 122 is necessary for iSCSI Boot Firmware Table Attributes module to work
123 123 properly.
124 124  
  125 +config ISCSI_BOOT_SYSFS
  126 + tristate "iSCSI Boot Sysfs Interface"
  127 + default n
  128 + help
  129 + This option enables support for exposing iSCSI boot information
  130 + via sysfs to userspace. If you wish to export this information,
  131 + say Y. Otherwise, say N.
  132 +
125 133 config ISCSI_IBFT
126 134 tristate "iSCSI Boot Firmware Table Attributes module"
127 135 depends on ISCSI_IBFT_FIND
drivers/firmware/Makefile
... ... @@ -10,5 +10,6 @@
10 10 obj-$(CONFIG_DMIID) += dmi-id.o
11 11 obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
12 12 obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
  13 +obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o
13 14 obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
drivers/firmware/iscsi_boot_sysfs.c
  1 +/*
  2 + * Export the iSCSI boot info to userland via sysfs.
  3 + *
  4 + * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
  5 + * Copyright (C) 2010 Mike Christie
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License v2.0 as published by
  9 + * the Free Software Foundation
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + */
  16 +
  17 +#include <linux/module.h>
  18 +#include <linux/string.h>
  19 +#include <linux/slab.h>
  20 +#include <linux/sysfs.h>
  21 +#include <linux/capability.h>
  22 +#include <linux/iscsi_boot_sysfs.h>
  23 +
  24 +
  25 +MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>");
  26 +MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information");
  27 +MODULE_LICENSE("GPL");
  28 +/*
  29 + * The kobject and attribute structures.
  30 + */
  31 +struct iscsi_boot_attr {
  32 + struct attribute attr;
  33 + int type;
  34 + ssize_t (*show) (void *data, int type, char *buf);
  35 +};
  36 +
  37 +/*
  38 + * The routine called for all sysfs attributes.
  39 + */
  40 +static ssize_t iscsi_boot_show_attribute(struct kobject *kobj,
  41 + struct attribute *attr, char *buf)
  42 +{
  43 + struct iscsi_boot_kobj *boot_kobj =
  44 + container_of(kobj, struct iscsi_boot_kobj, kobj);
  45 + struct iscsi_boot_attr *boot_attr =
  46 + container_of(attr, struct iscsi_boot_attr, attr);
  47 + ssize_t ret = -EIO;
  48 + char *str = buf;
  49 +
  50 + if (!capable(CAP_SYS_ADMIN))
  51 + return -EACCES;
  52 +
  53 + if (boot_kobj->show)
  54 + ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str);
  55 + return ret;
  56 +}
  57 +
  58 +static const struct sysfs_ops iscsi_boot_attr_ops = {
  59 + .show = iscsi_boot_show_attribute,
  60 +};
  61 +
  62 +static void iscsi_boot_kobj_release(struct kobject *kobj)
  63 +{
  64 + struct iscsi_boot_kobj *boot_kobj =
  65 + container_of(kobj, struct iscsi_boot_kobj, kobj);
  66 +
  67 + kfree(boot_kobj->data);
  68 + kfree(boot_kobj);
  69 +}
  70 +
  71 +static struct kobj_type iscsi_boot_ktype = {
  72 + .release = iscsi_boot_kobj_release,
  73 + .sysfs_ops = &iscsi_boot_attr_ops,
  74 +};
  75 +
  76 +#define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type) \
  77 +static struct iscsi_boot_attr iscsi_boot_attr_##fnname = { \
  78 + .attr = { .name = __stringify(sysfs_name), .mode = 0444 }, \
  79 + .type = attr_type, \
  80 +}
  81 +
  82 +/* Target attrs */
  83 +iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX);
  84 +iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS);
  85 +iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR);
  86 +iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT);
  87 +iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN);
  88 +iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE);
  89 +iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC);
  90 +iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME);
  91 +iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME);
  92 +iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET);
  93 +iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name,
  94 + ISCSI_BOOT_TGT_REV_CHAP_NAME);
  95 +iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret,
  96 + ISCSI_BOOT_TGT_REV_CHAP_SECRET);
  97 +
  98 +static struct attribute *target_attrs[] = {
  99 + &iscsi_boot_attr_tgt_index.attr,
  100 + &iscsi_boot_attr_tgt_flags.attr,
  101 + &iscsi_boot_attr_tgt_ip.attr,
  102 + &iscsi_boot_attr_tgt_port.attr,
  103 + &iscsi_boot_attr_tgt_lun.attr,
  104 + &iscsi_boot_attr_tgt_chap.attr,
  105 + &iscsi_boot_attr_tgt_nic.attr,
  106 + &iscsi_boot_attr_tgt_name.attr,
  107 + &iscsi_boot_attr_tgt_chap_name.attr,
  108 + &iscsi_boot_attr_tgt_chap_secret.attr,
  109 + &iscsi_boot_attr_tgt_chap_rev_name.attr,
  110 + &iscsi_boot_attr_tgt_chap_rev_secret.attr,
  111 + NULL
  112 +};
  113 +
  114 +static mode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj,
  115 + struct attribute *attr, int i)
  116 +{
  117 + struct iscsi_boot_kobj *boot_kobj =
  118 + container_of(kobj, struct iscsi_boot_kobj, kobj);
  119 +
  120 + if (attr == &iscsi_boot_attr_tgt_index.attr)
  121 + return boot_kobj->is_visible(boot_kobj->data,
  122 + ISCSI_BOOT_TGT_INDEX);
  123 + else if (attr == &iscsi_boot_attr_tgt_flags.attr)
  124 + return boot_kobj->is_visible(boot_kobj->data,
  125 + ISCSI_BOOT_TGT_FLAGS);
  126 + else if (attr == &iscsi_boot_attr_tgt_ip.attr)
  127 + return boot_kobj->is_visible(boot_kobj->data,
  128 + ISCSI_BOOT_TGT_IP_ADDR);
  129 + else if (attr == &iscsi_boot_attr_tgt_port.attr)
  130 + return boot_kobj->is_visible(boot_kobj->data,
  131 + ISCSI_BOOT_TGT_PORT);
  132 + else if (attr == &iscsi_boot_attr_tgt_lun.attr)
  133 + return boot_kobj->is_visible(boot_kobj->data,
  134 + ISCSI_BOOT_TGT_LUN);
  135 + else if (attr == &iscsi_boot_attr_tgt_chap.attr)
  136 + return boot_kobj->is_visible(boot_kobj->data,
  137 + ISCSI_BOOT_TGT_CHAP_TYPE);
  138 + else if (attr == &iscsi_boot_attr_tgt_nic.attr)
  139 + return boot_kobj->is_visible(boot_kobj->data,
  140 + ISCSI_BOOT_TGT_NIC_ASSOC);
  141 + else if (attr == &iscsi_boot_attr_tgt_name.attr)
  142 + return boot_kobj->is_visible(boot_kobj->data,
  143 + ISCSI_BOOT_TGT_NAME);
  144 + else if (attr == &iscsi_boot_attr_tgt_chap_name.attr)
  145 + return boot_kobj->is_visible(boot_kobj->data,
  146 + ISCSI_BOOT_TGT_CHAP_NAME);
  147 + else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr)
  148 + return boot_kobj->is_visible(boot_kobj->data,
  149 + ISCSI_BOOT_TGT_CHAP_SECRET);
  150 + else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr)
  151 + return boot_kobj->is_visible(boot_kobj->data,
  152 + ISCSI_BOOT_TGT_REV_CHAP_NAME);
  153 + else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr)
  154 + return boot_kobj->is_visible(boot_kobj->data,
  155 + ISCSI_BOOT_TGT_REV_CHAP_SECRET);
  156 + return 0;
  157 +}
  158 +
  159 +static struct attribute_group iscsi_boot_target_attr_group = {
  160 + .attrs = target_attrs,
  161 + .is_visible = iscsi_boot_tgt_attr_is_visible,
  162 +};
  163 +
  164 +/* Ethernet attrs */
  165 +iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
  166 +iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
  167 +iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
  168 +iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
  169 +iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
  170 +iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
  171 +iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS);
  172 +iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns,
  173 + ISCSI_BOOT_ETH_SECONDARY_DNS);
  174 +iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP);
  175 +iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN);
  176 +iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC);
  177 +iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME);
  178 +
  179 +static struct attribute *ethernet_attrs[] = {
  180 + &iscsi_boot_attr_eth_index.attr,
  181 + &iscsi_boot_attr_eth_flags.attr,
  182 + &iscsi_boot_attr_eth_ip.attr,
  183 + &iscsi_boot_attr_eth_subnet.attr,
  184 + &iscsi_boot_attr_eth_origin.attr,
  185 + &iscsi_boot_attr_eth_gateway.attr,
  186 + &iscsi_boot_attr_eth_primary_dns.attr,
  187 + &iscsi_boot_attr_eth_secondary_dns.attr,
  188 + &iscsi_boot_attr_eth_dhcp.attr,
  189 + &iscsi_boot_attr_eth_vlan.attr,
  190 + &iscsi_boot_attr_eth_mac.attr,
  191 + &iscsi_boot_attr_eth_hostname.attr,
  192 + NULL
  193 +};
  194 +
  195 +static mode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj,
  196 + struct attribute *attr, int i)
  197 +{
  198 + struct iscsi_boot_kobj *boot_kobj =
  199 + container_of(kobj, struct iscsi_boot_kobj, kobj);
  200 +
  201 + if (attr == &iscsi_boot_attr_eth_index.attr)
  202 + return boot_kobj->is_visible(boot_kobj->data,
  203 + ISCSI_BOOT_ETH_INDEX);
  204 + else if (attr == &iscsi_boot_attr_eth_flags.attr)
  205 + return boot_kobj->is_visible(boot_kobj->data,
  206 + ISCSI_BOOT_ETH_FLAGS);
  207 + else if (attr == &iscsi_boot_attr_eth_ip.attr)
  208 + return boot_kobj->is_visible(boot_kobj->data,
  209 + ISCSI_BOOT_ETH_IP_ADDR);
  210 + else if (attr == &iscsi_boot_attr_eth_subnet.attr)
  211 + return boot_kobj->is_visible(boot_kobj->data,
  212 + ISCSI_BOOT_ETH_SUBNET_MASK);
  213 + else if (attr == &iscsi_boot_attr_eth_origin.attr)
  214 + return boot_kobj->is_visible(boot_kobj->data,
  215 + ISCSI_BOOT_ETH_ORIGIN);
  216 + else if (attr == &iscsi_boot_attr_eth_gateway.attr)
  217 + return boot_kobj->is_visible(boot_kobj->data,
  218 + ISCSI_BOOT_ETH_GATEWAY);
  219 + else if (attr == &iscsi_boot_attr_eth_primary_dns.attr)
  220 + return boot_kobj->is_visible(boot_kobj->data,
  221 + ISCSI_BOOT_ETH_PRIMARY_DNS);
  222 + else if (attr == &iscsi_boot_attr_eth_secondary_dns.attr)
  223 + return boot_kobj->is_visible(boot_kobj->data,
  224 + ISCSI_BOOT_ETH_SECONDARY_DNS);
  225 + else if (attr == &iscsi_boot_attr_eth_dhcp.attr)
  226 + return boot_kobj->is_visible(boot_kobj->data,
  227 + ISCSI_BOOT_ETH_DHCP);
  228 + else if (attr == &iscsi_boot_attr_eth_vlan.attr)
  229 + return boot_kobj->is_visible(boot_kobj->data,
  230 + ISCSI_BOOT_ETH_VLAN);
  231 + else if (attr == &iscsi_boot_attr_eth_mac.attr)
  232 + return boot_kobj->is_visible(boot_kobj->data,
  233 + ISCSI_BOOT_ETH_MAC);
  234 + else if (attr == &iscsi_boot_attr_eth_hostname.attr)
  235 + return boot_kobj->is_visible(boot_kobj->data,
  236 + ISCSI_BOOT_ETH_HOSTNAME);
  237 + return 0;
  238 +}
  239 +
  240 +static struct attribute_group iscsi_boot_ethernet_attr_group = {
  241 + .attrs = ethernet_attrs,
  242 + .is_visible = iscsi_boot_eth_attr_is_visible,
  243 +};
  244 +
  245 +/* Initiator attrs */
  246 +iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX);
  247 +iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS);
  248 +iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER);
  249 +iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER);
  250 +iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server,
  251 + ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
  252 +iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server,
  253 + ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
  254 +iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME);
  255 +
  256 +static struct attribute *initiator_attrs[] = {
  257 + &iscsi_boot_attr_ini_index.attr,
  258 + &iscsi_boot_attr_ini_flags.attr,
  259 + &iscsi_boot_attr_ini_isns.attr,
  260 + &iscsi_boot_attr_ini_slp.attr,
  261 + &iscsi_boot_attr_ini_primary_radius.attr,
  262 + &iscsi_boot_attr_ini_secondary_radius.attr,
  263 + &iscsi_boot_attr_ini_name.attr,
  264 + NULL
  265 +};
  266 +
  267 +static mode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj,
  268 + struct attribute *attr, int i)
  269 +{
  270 + struct iscsi_boot_kobj *boot_kobj =
  271 + container_of(kobj, struct iscsi_boot_kobj, kobj);
  272 +
  273 + if (attr == &iscsi_boot_attr_ini_index.attr)
  274 + return boot_kobj->is_visible(boot_kobj->data,
  275 + ISCSI_BOOT_INI_INDEX);
  276 + if (attr == &iscsi_boot_attr_ini_flags.attr)
  277 + return boot_kobj->is_visible(boot_kobj->data,
  278 + ISCSI_BOOT_INI_FLAGS);
  279 + if (attr == &iscsi_boot_attr_ini_isns.attr)
  280 + return boot_kobj->is_visible(boot_kobj->data,
  281 + ISCSI_BOOT_INI_ISNS_SERVER);
  282 + if (attr == &iscsi_boot_attr_ini_slp.attr)
  283 + return boot_kobj->is_visible(boot_kobj->data,
  284 + ISCSI_BOOT_INI_SLP_SERVER);
  285 + if (attr == &iscsi_boot_attr_ini_primary_radius.attr)
  286 + return boot_kobj->is_visible(boot_kobj->data,
  287 + ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
  288 + if (attr == &iscsi_boot_attr_ini_secondary_radius.attr)
  289 + return boot_kobj->is_visible(boot_kobj->data,
  290 + ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
  291 + if (attr == &iscsi_boot_attr_ini_name.attr)
  292 + return boot_kobj->is_visible(boot_kobj->data,
  293 + ISCSI_BOOT_INI_INITIATOR_NAME);
  294 +
  295 + return 0;
  296 +}
  297 +
  298 +static struct attribute_group iscsi_boot_initiator_attr_group = {
  299 + .attrs = initiator_attrs,
  300 + .is_visible = iscsi_boot_ini_attr_is_visible,
  301 +};
  302 +
  303 +static struct iscsi_boot_kobj *
  304 +iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
  305 + struct attribute_group *attr_group,
  306 + const char *name, int index, void *data,
  307 + ssize_t (*show) (void *data, int type, char *buf),
  308 + mode_t (*is_visible) (void *data, int type))
  309 +{
  310 + struct iscsi_boot_kobj *boot_kobj;
  311 +
  312 + boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL);
  313 + if (!boot_kobj)
  314 + return NULL;
  315 + INIT_LIST_HEAD(&boot_kobj->list);
  316 +
  317 + boot_kobj->kobj.kset = boot_kset->kset;
  318 + if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
  319 + NULL, name, index)) {
  320 + kfree(boot_kobj);
  321 + return NULL;
  322 + }
  323 + boot_kobj->data = data;
  324 + boot_kobj->show = show;
  325 + boot_kobj->is_visible = is_visible;
  326 +
  327 + if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
  328 + /*
  329 + * We do not want to free this because the caller
  330 + * will assume that since the creation call failed
  331 + * the boot kobj was not setup and the normal release
  332 + * path is not being run.
  333 + */
  334 + boot_kobj->data = NULL;
  335 + kobject_put(&boot_kobj->kobj);
  336 + return NULL;
  337 + }
  338 + boot_kobj->attr_group = attr_group;
  339 +
  340 + kobject_uevent(&boot_kobj->kobj, KOBJ_ADD);
  341 + /* Nothing broke so lets add it to the list. */
  342 + list_add_tail(&boot_kobj->list, &boot_kset->kobj_list);
  343 + return boot_kobj;
  344 +}
  345 +
  346 +static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
  347 +{
  348 + list_del(&boot_kobj->list);
  349 + sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group);
  350 + kobject_put(&boot_kobj->kobj);
  351 +}
  352 +
  353 +/**
  354 + * iscsi_boot_create_target() - create boot target sysfs dir
  355 + * @boot_kset: boot kset
  356 + * @index: the target id
  357 + * @data: driver specific data for target
  358 + * @show: attr show function
  359 + * @is_visible: attr visibility function
  360 + *
  361 + * Note: The boot sysfs lib will free the data passed in for the caller
  362 + * when all refs to the target kobject have been released.
  363 + */
  364 +struct iscsi_boot_kobj *
  365 +iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
  366 + void *data,
  367 + ssize_t (*show) (void *data, int type, char *buf),
  368 + mode_t (*is_visible) (void *data, int type))
  369 +{
  370 + return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
  371 + "target%d", index, data, show, is_visible);
  372 +}
  373 +EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
  374 +
  375 +/**
  376 + * iscsi_boot_create_initiator() - create boot initiator sysfs dir
  377 + * @boot_kset: boot kset
  378 + * @index: the initiator id
  379 + * @data: driver specific data
  380 + * @show: attr show function
  381 + * @is_visible: attr visibility function
  382 + *
  383 + * Note: The boot sysfs lib will free the data passed in for the caller
  384 + * when all refs to the initiator kobject have been released.
  385 + */
  386 +struct iscsi_boot_kobj *
  387 +iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
  388 + void *data,
  389 + ssize_t (*show) (void *data, int type, char *buf),
  390 + mode_t (*is_visible) (void *data, int type))
  391 +{
  392 + return iscsi_boot_create_kobj(boot_kset,
  393 + &iscsi_boot_initiator_attr_group,
  394 + "initiator", index, data, show,
  395 + is_visible);
  396 +}
  397 +EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
  398 +
  399 +/**
  400 + * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir
  401 + * @boot_kset: boot kset
  402 + * @index: the ethernet device id
  403 + * @data: driver specific data
  404 + * @show: attr show function
  405 + * @is_visible: attr visibility function
  406 + *
  407 + * Note: The boot sysfs lib will free the data passed in for the caller
  408 + * when all refs to the ethernet kobject have been released.
  409 + */
  410 +struct iscsi_boot_kobj *
  411 +iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
  412 + void *data,
  413 + ssize_t (*show) (void *data, int type, char *buf),
  414 + mode_t (*is_visible) (void *data, int type))
  415 +{
  416 + return iscsi_boot_create_kobj(boot_kset,
  417 + &iscsi_boot_ethernet_attr_group,
  418 + "ethernet%d", index, data, show,
  419 + is_visible);
  420 +}
  421 +EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
  422 +
  423 +/**
  424 + * iscsi_boot_create_kset() - creates root sysfs tree
  425 + * @set_name: name of root dir
  426 + */
  427 +struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name)
  428 +{
  429 + struct iscsi_boot_kset *boot_kset;
  430 +
  431 + boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL);
  432 + if (!boot_kset)
  433 + return NULL;
  434 +
  435 + boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj);
  436 + if (!boot_kset->kset) {
  437 + kfree(boot_kset);
  438 + return NULL;
  439 + }
  440 +
  441 + INIT_LIST_HEAD(&boot_kset->kobj_list);
  442 + return boot_kset;
  443 +}
  444 +EXPORT_SYMBOL_GPL(iscsi_boot_create_kset);
  445 +
  446 +/**
  447 + * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host
  448 + * @hostno: host number of scsi host
  449 + */
  450 +struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno)
  451 +{
  452 + struct iscsi_boot_kset *boot_kset;
  453 + char *set_name;
  454 +
  455 + set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno);
  456 + if (!set_name)
  457 + return NULL;
  458 +
  459 + boot_kset = iscsi_boot_create_kset(set_name);
  460 + kfree(set_name);
  461 + return boot_kset;
  462 +}
  463 +EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset);
  464 +
  465 +/**
  466 + * iscsi_boot_destroy_kset() - destroy kset and kobjects under it
  467 + * @boot_kset: boot kset
  468 + *
  469 + * This will remove the kset and kobjects and attrs under it.
  470 + */
  471 +void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
  472 +{
  473 + struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
  474 +
  475 + list_for_each_entry_safe(boot_kobj, tmp_kobj,
  476 + &boot_kset->kobj_list, list)
  477 + iscsi_boot_remove_kobj(boot_kobj);
  478 +
  479 + kset_unregister(boot_kset->kset);
  480 +}
  481 +EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
include/linux/iscsi_boot_sysfs.h
  1 +/*
  2 + * Export the iSCSI boot info to userland via sysfs.
  3 + *
  4 + * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
  5 + * Copyright (C) 2010 Mike Christie
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License v2.0 as published by
  9 + * the Free Software Foundation
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + */
  16 +#ifndef _ISCSI_BOOT_SYSFS_
  17 +#define _ISCSI_BOOT_SYSFS_
  18 +
  19 +/*
  20 + * The text attributes names for each of the kobjects.
  21 +*/
  22 +enum iscsi_boot_eth_properties_enum {
  23 + ISCSI_BOOT_ETH_INDEX,
  24 + ISCSI_BOOT_ETH_FLAGS,
  25 + ISCSI_BOOT_ETH_IP_ADDR,
  26 + ISCSI_BOOT_ETH_SUBNET_MASK,
  27 + ISCSI_BOOT_ETH_ORIGIN,
  28 + ISCSI_BOOT_ETH_GATEWAY,
  29 + ISCSI_BOOT_ETH_PRIMARY_DNS,
  30 + ISCSI_BOOT_ETH_SECONDARY_DNS,
  31 + ISCSI_BOOT_ETH_DHCP,
  32 + ISCSI_BOOT_ETH_VLAN,
  33 + ISCSI_BOOT_ETH_MAC,
  34 + /* eth_pci_bdf - this is replaced by link to the device itself. */
  35 + ISCSI_BOOT_ETH_HOSTNAME,
  36 + ISCSI_BOOT_ETH_END_MARKER,
  37 +};
  38 +
  39 +enum iscsi_boot_tgt_properties_enum {
  40 + ISCSI_BOOT_TGT_INDEX,
  41 + ISCSI_BOOT_TGT_FLAGS,
  42 + ISCSI_BOOT_TGT_IP_ADDR,
  43 + ISCSI_BOOT_TGT_PORT,
  44 + ISCSI_BOOT_TGT_LUN,
  45 + ISCSI_BOOT_TGT_CHAP_TYPE,
  46 + ISCSI_BOOT_TGT_NIC_ASSOC,
  47 + ISCSI_BOOT_TGT_NAME,
  48 + ISCSI_BOOT_TGT_CHAP_NAME,
  49 + ISCSI_BOOT_TGT_CHAP_SECRET,
  50 + ISCSI_BOOT_TGT_REV_CHAP_NAME,
  51 + ISCSI_BOOT_TGT_REV_CHAP_SECRET,
  52 + ISCSI_BOOT_TGT_END_MARKER,
  53 +};
  54 +
  55 +enum iscsi_boot_initiator_properties_enum {
  56 + ISCSI_BOOT_INI_INDEX,
  57 + ISCSI_BOOT_INI_FLAGS,
  58 + ISCSI_BOOT_INI_ISNS_SERVER,
  59 + ISCSI_BOOT_INI_SLP_SERVER,
  60 + ISCSI_BOOT_INI_PRI_RADIUS_SERVER,
  61 + ISCSI_BOOT_INI_SEC_RADIUS_SERVER,
  62 + ISCSI_BOOT_INI_INITIATOR_NAME,
  63 + ISCSI_BOOT_INI_END_MARKER,
  64 +};
  65 +
  66 +struct attribute_group;
  67 +
  68 +struct iscsi_boot_kobj {
  69 + struct kobject kobj;
  70 + struct attribute_group *attr_group;
  71 + struct list_head list;
  72 +
  73 + /*
  74 + * Pointer to store driver specific info. If set this will
  75 + * be freed for the LLD when the kobj release function is called.
  76 + */
  77 + void *data;
  78 + /*
  79 + * Driver specific show function.
  80 + *
  81 + * The enum of the type. This can be any value of the above
  82 + * properties.
  83 + */
  84 + ssize_t (*show) (void *data, int type, char *buf);
  85 +
  86 + /*
  87 + * Drivers specific visibility function.
  88 + * The function should return if they the attr should be readable
  89 + * writable or should not be shown.
  90 + *
  91 + * The enum of the type. This can be any value of the above
  92 + * properties.
  93 + */
  94 + mode_t (*is_visible) (void *data, int type);
  95 +};
  96 +
  97 +struct iscsi_boot_kset {
  98 + struct list_head kobj_list;
  99 + struct kset *kset;
  100 +};
  101 +
  102 +struct iscsi_boot_kobj *
  103 +iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
  104 + void *data,
  105 + ssize_t (*show) (void *data, int type, char *buf),
  106 + mode_t (*is_visible) (void *data, int type));
  107 +
  108 +struct iscsi_boot_kobj *
  109 +iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
  110 + void *data,
  111 + ssize_t (*show) (void *data, int type, char *buf),
  112 + mode_t (*is_visible) (void *data, int type));
  113 +struct iscsi_boot_kobj *
  114 +iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
  115 + void *data,
  116 + ssize_t (*show) (void *data, int type, char *buf),
  117 + mode_t (*is_visible) (void *data, int type));
  118 +
  119 +struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name);
  120 +struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno);
  121 +void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset);
  122 +
  123 +#endif