GNU Linux-libre 5.10.219-gnu1
[releases.git] / drivers / scsi / iscsi_boot_sysfs.c
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
17 MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>");
18 MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information");
19 MODULE_LICENSE("GPL");
20 /*
21  * The kobject and attribute structures.
22  */
23 struct 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  */
32 static 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
50 static const struct sysfs_ops iscsi_boot_attr_ops = {
51         .show = iscsi_boot_show_attribute,
52 };
53
54 static 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
64 static 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)               \
70 static 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 */
76 iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX);
77 iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS);
78 iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR);
79 iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT);
80 iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN);
81 iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE);
82 iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC);
83 iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME);
84 iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME);
85 iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET);
86 iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name,
87                    ISCSI_BOOT_TGT_REV_CHAP_NAME);
88 iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret,
89                    ISCSI_BOOT_TGT_REV_CHAP_SECRET);
90
91 static 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
107 static 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
152 static 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 */
158 iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
159 iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
160 iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
161 iscsi_boot_rd_attr(eth_prefix, prefix-len, ISCSI_BOOT_ETH_PREFIX_LEN);
162 iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
163 iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
164 iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
165 iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS);
166 iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns,
167                    ISCSI_BOOT_ETH_SECONDARY_DNS);
168 iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP);
169 iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN);
170 iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC);
171 iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME);
172
173 static 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
190 static 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
238 static 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 */
244 iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX);
245 iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS);
246 iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER);
247 iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER);
248 iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server,
249                    ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
250 iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server,
251                    ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
252 iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME);
253
254 static 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
265 static 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
296 static 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 */
302 iscsi_boot_rd_attr(acpitbl_signature, signature, ISCSI_BOOT_ACPITBL_SIGNATURE);
303 iscsi_boot_rd_attr(acpitbl_oem_id, oem_id, ISCSI_BOOT_ACPITBL_OEM_ID);
304 iscsi_boot_rd_attr(acpitbl_oem_table_id, oem_table_id,
305                    ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
306
307 static 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
314 static 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
332 static struct attribute_group iscsi_boot_acpitbl_attr_group = {
333         .attrs = acpitbl_attrs,
334         .is_visible = iscsi_boot_acpitbl_attr_is_visible,
335 };
336
337 static struct iscsi_boot_kobj *
338 iscsi_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
382 static 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  */
401 struct iscsi_boot_kobj *
402 iscsi_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 }
412 EXPORT_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  */
426 struct iscsi_boot_kobj *
427 iscsi_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 }
438 EXPORT_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  */
452 struct iscsi_boot_kobj *
453 iscsi_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 }
464 EXPORT_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  */
478 struct iscsi_boot_kobj *
479 iscsi_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 }
490 EXPORT_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  */
496 struct 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 }
513 EXPORT_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  */
519 struct 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 }
532 EXPORT_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  */
540 void 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 }
554 EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);