Commit ba4ee30c6c797de148dcc7254cf6d531aba71d9b
Committed by
Konrad Rzeszutek Wilk
1 parent
1303a35bfe
Exists in
master
and in
7 other branches
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
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 |