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