aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2011-07-25 14:48:40 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 10:36:00 -0400
commit8d07913dbe79568eafe5bb73806a08aac294d4e6 (patch)
tree125b845b1157dbe44640f83bfdfe36c187d061a9
parent2bab08fc770ccd6c56859371356a4a905e8c0bd4 (diff)
[SCSI] iscsi class: add iface representation
A iscsi host can have multiple interfaces. This patch adds a new iface iscsi class for this. It exports the network settings now, and will be extended to also export iscsi initiator port settings like the isid and initiator name for drivers that can support multiple initiator ports. Based on patch from Lalit Chandivade. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c189
-rw-r--r--include/scsi/iscsi_if.h21
-rw-r--r--include/scsi/scsi_transport_iscsi.h26
3 files changed, 233 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 212a8d846748..4d5e64f429e7 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -270,6 +270,185 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
270} 270}
271EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint); 271EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
272 272
273/*
274 * Interface to display network param to sysfs
275 */
276
277static void iscsi_iface_release(struct device *dev)
278{
279 struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
280 struct device *parent = iface->dev.parent;
281
282 kfree(iface);
283 put_device(parent);
284}
285
286
287static struct class iscsi_iface_class = {
288 .name = "iscsi_iface",
289 .dev_release = iscsi_iface_release,
290};
291
292#define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \
293struct device_attribute dev_attr_##_prefix##_##_name = \
294 __ATTR(_name, _mode, _show, _store)
295
296/* iface attrs show */
297#define iscsi_iface_attr_show(type, name, param_type, param) \
298static ssize_t \
299show_##type##_##name(struct device *dev, struct device_attribute *attr, \
300 char *buf) \
301{ \
302 struct iscsi_iface *iface = iscsi_dev_to_iface(dev); \
303 struct iscsi_transport *t = iface->transport; \
304 return t->get_iface_param(iface, param_type, param, buf); \
305} \
306
307#define iscsi_iface_net_attr(type, name, param) \
308 iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param) \
309static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
310
311/* generic read only ipvi4 attribute */
312iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
313iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
314iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
315iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
316
317/* generic read only ipv6 attribute */
318iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
319iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL);
320iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
321iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
322 ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
323iscsi_iface_net_attr(ipv6_iface, linklocal_autocfg,
324 ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
325
326/* common read only iface attribute */
327iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
328iscsi_iface_net_attr(iface, vlan, ISCSI_NET_PARAM_VLAN_ID);
329
330static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
331 struct attribute *attr, int i)
332{
333 struct device *dev = container_of(kobj, struct device, kobj);
334 struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
335 struct iscsi_transport *t = iface->transport;
336
337 if (attr == &dev_attr_iface_enabled.attr)
338 return (t->iface_param_mask & ISCSI_NET_IFACE_ENABLE) ?
339 S_IRUGO : 0;
340 else if (attr == &dev_attr_iface_vlan.attr)
341 return (t->iface_param_mask & ISCSI_NET_VLAN_ID) ? S_IRUGO : 0;
342
343 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
344 if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
345 return (t->iface_param_mask & ISCSI_NET_IPV4_ADDR) ?
346 S_IRUGO : 0;
347 else if (attr == &dev_attr_ipv4_iface_gateway.attr)
348 return (t->iface_param_mask & ISCSI_NET_IPV4_GW) ?
349 S_IRUGO : 0;
350 else if (attr == &dev_attr_ipv4_iface_subnet.attr)
351 return (t->iface_param_mask & ISCSI_NET_IPV4_SUBNET) ?
352 S_IRUGO : 0;
353 else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
354 return (t->iface_param_mask & ISCSI_NET_IPV4_BOOTPROTO) ?
355 S_IRUGO : 0;
356 } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
357 if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
358 return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR) ?
359 S_IRUGO : 0;
360 else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
361 return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL) ?
362 S_IRUGO : 0;
363 else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
364 return (t->iface_param_mask & ISCSI_NET_IPV6_ROUTER) ?
365 S_IRUGO : 0;
366 else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
367 return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR_AUTOCFG) ?
368 S_IRUGO : 0;
369 else if (attr == &dev_attr_ipv6_iface_linklocal_autocfg.attr)
370 return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG) ?
371 S_IRUGO : 0;
372 }
373
374 return 0;
375}
376
377static struct attribute *iscsi_iface_attrs[] = {
378 &dev_attr_iface_enabled.attr,
379 &dev_attr_iface_vlan.attr,
380 &dev_attr_ipv4_iface_ipaddress.attr,
381 &dev_attr_ipv4_iface_gateway.attr,
382 &dev_attr_ipv4_iface_subnet.attr,
383 &dev_attr_ipv4_iface_bootproto.attr,
384 &dev_attr_ipv6_iface_ipaddress.attr,
385 &dev_attr_ipv6_iface_link_local_addr.attr,
386 &dev_attr_ipv6_iface_router_addr.attr,
387 &dev_attr_ipv6_iface_ipaddr_autocfg.attr,
388 &dev_attr_ipv6_iface_linklocal_autocfg.attr,
389 NULL,
390};
391
392static struct attribute_group iscsi_iface_group = {
393 .attrs = iscsi_iface_attrs,
394 .is_visible = iscsi_iface_attr_is_visible,
395};
396
397struct iscsi_iface *
398iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
399 uint32_t iface_type, uint32_t iface_num, int dd_size)
400{
401 struct iscsi_iface *iface;
402 int err;
403
404 iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
405 if (!iface)
406 return NULL;
407
408 iface->transport = transport;
409 iface->iface_type = iface_type;
410 iface->iface_num = iface_num;
411 iface->dev.release = iscsi_iface_release;
412 iface->dev.class = &iscsi_iface_class;
413 /* parent reference released in iscsi_iface_release */
414 iface->dev.parent = get_device(&shost->shost_gendev);
415 if (iface_type == ISCSI_IFACE_TYPE_IPV4)
416 dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
417 iface_num);
418 else
419 dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
420 iface_num);
421
422 err = device_register(&iface->dev);
423 if (err)
424 goto free_iface;
425
426 err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
427 if (err)
428 goto unreg_iface;
429
430 if (dd_size)
431 iface->dd_data = &iface[1];
432 return iface;
433
434unreg_iface:
435 device_unregister(&iface->dev);
436 return NULL;
437
438free_iface:
439 put_device(iface->dev.parent);
440 kfree(iface);
441 return NULL;
442}
443EXPORT_SYMBOL_GPL(iscsi_create_iface);
444
445void iscsi_destroy_iface(struct iscsi_iface *iface)
446{
447 sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
448 device_unregister(&iface->dev);
449}
450EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
451
273static int iscsi_setup_host(struct transport_container *tc, struct device *dev, 452static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
274 struct device *cdev) 453 struct device *cdev)
275{ 454{
@@ -2175,6 +2354,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
2175 2354
2176 BUG_ON(count > ISCSI_SESSION_ATTRS); 2355 BUG_ON(count > ISCSI_SESSION_ATTRS);
2177 priv->session_attrs[count] = NULL; 2356 priv->session_attrs[count] = NULL;
2357 count = 0;
2178 2358
2179 spin_lock_irqsave(&iscsi_transport_lock, flags); 2359 spin_lock_irqsave(&iscsi_transport_lock, flags);
2180 list_add(&priv->list, &iscsi_transports); 2360 list_add(&priv->list, &iscsi_transports);
@@ -2237,10 +2417,14 @@ static __init int iscsi_transport_init(void)
2237 if (err) 2417 if (err)
2238 goto unregister_transport_class; 2418 goto unregister_transport_class;
2239 2419
2240 err = transport_class_register(&iscsi_host_class); 2420 err = class_register(&iscsi_iface_class);
2241 if (err) 2421 if (err)
2242 goto unregister_endpoint_class; 2422 goto unregister_endpoint_class;
2243 2423
2424 err = transport_class_register(&iscsi_host_class);
2425 if (err)
2426 goto unregister_iface_class;
2427
2244 err = transport_class_register(&iscsi_connection_class); 2428 err = transport_class_register(&iscsi_connection_class);
2245 if (err) 2429 if (err)
2246 goto unregister_host_class; 2430 goto unregister_host_class;
@@ -2270,6 +2454,8 @@ unregister_conn_class:
2270 transport_class_unregister(&iscsi_connection_class); 2454 transport_class_unregister(&iscsi_connection_class);
2271unregister_host_class: 2455unregister_host_class:
2272 transport_class_unregister(&iscsi_host_class); 2456 transport_class_unregister(&iscsi_host_class);
2457unregister_iface_class:
2458 class_unregister(&iscsi_iface_class);
2273unregister_endpoint_class: 2459unregister_endpoint_class:
2274 class_unregister(&iscsi_endpoint_class); 2460 class_unregister(&iscsi_endpoint_class);
2275unregister_transport_class: 2461unregister_transport_class:
@@ -2285,6 +2471,7 @@ static void __exit iscsi_transport_exit(void)
2285 transport_class_unregister(&iscsi_session_class); 2471 transport_class_unregister(&iscsi_session_class);
2286 transport_class_unregister(&iscsi_host_class); 2472 transport_class_unregister(&iscsi_host_class);
2287 class_unregister(&iscsi_endpoint_class); 2473 class_unregister(&iscsi_endpoint_class);
2474 class_unregister(&iscsi_iface_class);
2288 class_unregister(&iscsi_transport_class); 2475 class_unregister(&iscsi_transport_class);
2289} 2476}
2290 2477
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index e93831e87878..a563753d578b 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -296,10 +296,27 @@ enum iscsi_net_param {
296 ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG = 11, 296 ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG = 11,
297 ISCSI_NET_PARAM_IFACE_ENABLE = 12, 297 ISCSI_NET_PARAM_IFACE_ENABLE = 12,
298 ISCSI_NET_PARAM_VLAN_ID = 13, 298 ISCSI_NET_PARAM_VLAN_ID = 13,
299 ISCSI_NET_IFACE_TYPE = 14, 299 ISCSI_NET_PARAM_IFACE_TYPE = 14,
300 ISCSI_NET_IFACE_NAME = 15, 300 ISCSI_NET_PARAM_IFACE_NAME = 15,
301}; 301};
302 302
303#define ISCSI_NET_IPV4_ADDR (1ULL << ISCSI_NET_PARAM_IPV4_ADDR)
304#define ISCSI_NET_IPV4_SUBNET (1ULL << ISCSI_NET_PARAM_IPV4_SUBNET)
305#define ISCSI_NET_IPV4_GW (1ULL << ISCSI_NET_PARAM_IPV4_GW)
306#define ISCSI_NET_IPV4_BOOTPROTO (1ULL << ISCSI_NET_PARAM_IPV4_BOOTPROTO)
307#define ISCSI_NET_MAC (1ULL << ISCSI_NET_PARAM_MAC)
308#define ISCSI_NET_IPV6_LINKLOCAL (1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL)
309#define ISCSI_NET_IPV6_ADDR (1ULL << ISCSI_NET_PARAM_IPV6_ADDR)
310#define ISCSI_NET_IPV6_ROUTER (1ULL << ISCSI_NET_PARAM_IPV6_ROUTER)
311#define ISCSI_NET_IPV6_ADDR_AUTOCFG \
312 (1ULL << ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG)
313#define ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG \
314 (1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG)
315#define ISCSI_NET_IPV6_ROUTER_AUTOCFG \
316 (1ULL << ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG)
317#define ISCSI_NET_IFACE_ENABLE (1ULL << ISCSI_NET_PARAM_IFACE_ENABLE)
318#define ISCSI_NET_VLAN_ID (1ULL << ISCSI_NET_PARAM_VLAN_ID)
319
303/* 320/*
304 * Common error codes 321 * Common error codes
305 */ 322 */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 9fcce7cd3673..e1f210a173a5 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -37,6 +37,7 @@ struct iscsi_cls_conn;
37struct iscsi_conn; 37struct iscsi_conn;
38struct iscsi_task; 38struct iscsi_task;
39struct sockaddr; 39struct sockaddr;
40struct iscsi_iface;
40 41
41/** 42/**
42 * struct iscsi_transport - iSCSI Transport template 43 * struct iscsi_transport - iSCSI Transport template
@@ -87,6 +88,8 @@ struct iscsi_transport {
87 /* LLD sets this to indicate what values it can export to sysfs */ 88 /* LLD sets this to indicate what values it can export to sysfs */
88 uint64_t param_mask; 89 uint64_t param_mask;
89 uint64_t host_param_mask; 90 uint64_t host_param_mask;
91 uint64_t iface_param_mask;
92
90 struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep, 93 struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
91 uint16_t cmds_max, uint16_t qdepth, 94 uint16_t cmds_max, uint16_t qdepth,
92 uint32_t sn); 95 uint32_t sn);
@@ -138,6 +141,9 @@ struct iscsi_transport {
138 uint32_t enable, struct sockaddr *dst_addr); 141 uint32_t enable, struct sockaddr *dst_addr);
139 int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params); 142 int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
140 int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count); 143 int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count);
144 int (*get_iface_param) (struct iscsi_iface *iface,
145 enum iscsi_param_type param_type,
146 int param, char *buf);
141}; 147};
142 148
143/* 149/*
@@ -229,6 +235,20 @@ struct iscsi_endpoint {
229 struct iscsi_cls_conn *conn; 235 struct iscsi_cls_conn *conn;
230}; 236};
231 237
238struct iscsi_iface {
239 struct device dev;
240 struct iscsi_transport *transport;
241 uint32_t iface_type; /* IPv4 or IPv6 */
242 uint32_t iface_num; /* iface number, 0 - n */
243 void *dd_data; /* LLD private data */
244};
245
246#define iscsi_dev_to_iface(_dev) \
247 container_of(_dev, struct iscsi_iface, dev)
248
249#define iscsi_iface_to_shost(_iface) \
250 dev_to_shost(_iface->dev.parent)
251
232/* 252/*
233 * session and connection functions that can be used by HW iSCSI LLDs 253 * session and connection functions that can be used by HW iSCSI LLDs
234 */ 254 */
@@ -262,5 +282,11 @@ extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
262extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep); 282extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
263extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle); 283extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
264extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd); 284extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
285extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost,
286 struct iscsi_transport *t,
287 uint32_t iface_type,
288 uint32_t iface_num, int dd_size);
289extern void iscsi_destroy_iface(struct iscsi_iface *iface);
290extern struct iscsi_iface *iscsi_lookup_iface(int handle);
265 291
266#endif 292#endif