1 From: James Bottomley <james.bottomley@hansenpartnership.com>
2 Subject: SCSI misc fixes
3 References: FATE#303485,FATE#303484
5 This patch pulls in the latest patches from the scsi-misc tree.
6 The functions are required by the various driver updates.
8 Signed-off-by: Hannes Reinecke <hare@suse.de>
11 Documentation/scsi/scsi_fc_transport.txt | 36 +
12 drivers/mmc/card/block.c | 10
13 drivers/scsi/device_handler/scsi_dh_emc.c | 1
14 drivers/scsi/device_handler/scsi_dh_hp_sw.c | 2
15 drivers/scsi/device_handler/scsi_dh_rdac.c | 2
16 drivers/scsi/libiscsi.c | 2
17 drivers/scsi/scsi.c | 13
18 drivers/scsi/scsi_lib.c | 39 +-
19 drivers/scsi/scsi_netlink.c | 523 +++++++++++++++++++++++++++-
20 drivers/scsi/scsi_scan.c | 20 -
21 drivers/scsi/scsi_sysfs.c | 1
22 drivers/scsi/scsi_transport_fc.c | 54 +-
23 drivers/scsi/sd.c | 29 -
24 include/linux/string_helpers.h | 16
25 include/scsi/scsi_device.h | 21 -
26 include/scsi/scsi_netlink.h | 62 +++
27 include/scsi/scsi_transport_fc.h | 23 +
29 lib/string_helpers.c | 64 +++
30 19 files changed, 834 insertions(+), 87 deletions(-)
32 --- a/Documentation/scsi/scsi_fc_transport.txt
33 +++ b/Documentation/scsi/scsi_fc_transport.txt
34 @@ -436,6 +436,42 @@ Other:
35 was updated to remove all vports for the fc_host as well.
38 +Transport supplied functions
39 +----------------------------
41 +The following functions are supplied by the FC-transport for use by LLDs.
43 + fc_vport_create - create a vport
44 + fc_vport_terminate - detach and remove a vport
49 + * fc_vport_create - Admin App or LLDD requests creation of a vport
50 + * @shost: scsi host the virtual port is connected to.
51 + * @ids: The world wide names, FC4 port roles, etc for
55 + * This routine assumes no locks are held on entry.
58 +fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids)
61 + * fc_vport_terminate - Admin App or LLDD requests termination of a vport
62 + * @vport: fc_vport to be terminated
64 + * Calls the LLDD vport_delete() function, then deallocates and removes
65 + * the vport from the shost and object tree.
68 + * This routine assumes no locks are held on entry.
71 +fc_vport_terminate(struct fc_vport *vport)
76 The following people have contributed to this document:
77 --- a/drivers/mmc/card/block.c
78 +++ b/drivers/mmc/card/block.c
80 #include <linux/blkdev.h>
81 #include <linux/mutex.h>
82 #include <linux/scatterlist.h>
83 +#include <linux/string_helpers.h>
85 #include <linux/mmc/card.h>
86 #include <linux/mmc/host.h>
87 @@ -532,6 +533,8 @@ static int mmc_blk_probe(struct mmc_card
88 struct mmc_blk_data *md;
94 * Check that the card supports the command class(es) we need.
96 @@ -546,10 +549,11 @@ static int mmc_blk_probe(struct mmc_card
100 - printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
101 + string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
102 + cap_str, sizeof(cap_str));
103 + printk(KERN_INFO "%s: %s %s %s %s\n",
104 md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
105 - (unsigned long long)(get_capacity(md->disk) >> 1),
106 - md->read_only ? "(ro)" : "");
107 + cap_str, md->read_only ? "(ro)" : "");
109 mmc_set_drvdata(card, md);
111 --- a/drivers/scsi/device_handler/scsi_dh_emc.c
112 +++ b/drivers/scsi/device_handler/scsi_dh_emc.c
113 @@ -278,7 +278,6 @@ static struct request *get_req(struct sc
117 - memset(rq->cmd, 0, BLK_MAX_CDB);
118 rq->cmd_len = COMMAND_SIZE(cmd);
121 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
122 +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
123 @@ -114,7 +114,6 @@ static int hp_sw_tur(struct scsi_device
124 req->cmd_type = REQ_TYPE_BLOCK_PC;
125 req->cmd_flags |= REQ_FAILFAST;
126 req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
127 - memset(req->cmd, 0, MAX_COMMAND_SIZE);
128 req->cmd[0] = TEST_UNIT_READY;
129 req->timeout = HP_SW_TIMEOUT;
130 req->sense = h->sense;
131 @@ -207,7 +206,6 @@ static int hp_sw_start_stop(struct scsi_
132 req->cmd_type = REQ_TYPE_BLOCK_PC;
133 req->cmd_flags |= REQ_FAILFAST;
134 req->cmd_len = COMMAND_SIZE(START_STOP);
135 - memset(req->cmd, 0, MAX_COMMAND_SIZE);
136 req->cmd[0] = START_STOP;
137 req->cmd[4] = 1; /* Start spin cycle */
138 req->timeout = HP_SW_TIMEOUT;
139 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c
140 +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
141 @@ -225,8 +225,6 @@ static struct request *get_rdac_req(stru
145 - memset(rq->cmd, 0, BLK_MAX_CDB);
147 rq->cmd_type = REQ_TYPE_BLOCK_PC;
148 rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
149 rq->retries = RDAC_RETRIES;
150 --- a/drivers/scsi/libiscsi.c
151 +++ b/drivers/scsi/libiscsi.c
152 @@ -1456,7 +1456,7 @@ static void fail_all_commands(struct isc
153 if (lun == task->sc->device->lun || lun == -1) {
154 debug_scsi("failing in progress sc %p itt 0x%x\n",
155 task->sc, task->itt);
156 - fail_command(conn, task, DID_BUS_BUSY << 16);
157 + fail_command(conn, task, error << 16);
161 --- a/drivers/scsi/scsi.c
162 +++ b/drivers/scsi/scsi.c
163 @@ -668,13 +668,14 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
167 - /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */
168 - if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) {
169 + /* Check to see if the scsi lld made this device blocked. */
170 + if (unlikely(scsi_device_blocked(cmd->device))) {
172 - * in SDEV_BLOCK, the command is just put back on the device
173 - * queue. The suspend state has already blocked the queue so
174 - * future requests should not occur until the device
175 - * transitions out of the suspend state.
176 + * in blocked state, the command is just put back on
177 + * the device queue. The suspend state has already
178 + * blocked the queue so future requests should not
179 + * occur until the device transitions out of the
183 scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
184 --- a/drivers/scsi/scsi_lib.c
185 +++ b/drivers/scsi/scsi_lib.c
186 @@ -1250,6 +1250,7 @@ int scsi_prep_state_check(struct scsi_de
190 + case SDEV_CREATED_BLOCK:
192 * If the devices is blocked we defer normal commands.
194 @@ -2073,10 +2074,13 @@ scsi_device_set_state(struct scsi_device
198 - /* There are no legal states that come back to
199 - * created. This is the manually initialised start
202 + switch (oldstate) {
203 + case SDEV_CREATED_BLOCK:
212 @@ -2114,8 +2118,17 @@ scsi_device_set_state(struct scsi_device
218 + case SDEV_CREATED_BLOCK:
225 + case SDEV_CREATED_BLOCK:
226 + switch (oldstate) {
231 @@ -2403,8 +2416,12 @@ scsi_internal_device_block(struct scsi_d
234 err = scsi_device_set_state(sdev, SDEV_BLOCK);
238 + err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK);
245 * The device has transitioned to SDEV_BLOCK. Stop the
246 @@ -2447,8 +2464,12 @@ scsi_internal_device_unblock(struct scsi
247 * and goose the device queue if successful.
249 err = scsi_device_set_state(sdev, SDEV_RUNNING);
253 + err = scsi_device_set_state(sdev, SDEV_CREATED);
259 spin_lock_irqsave(q->queue_lock, flags);
261 --- a/drivers/scsi/scsi_netlink.c
262 +++ b/drivers/scsi/scsi_netlink.c
264 #include <linux/time.h>
265 #include <linux/jiffies.h>
266 #include <linux/security.h>
267 +#include <linux/delay.h>
268 #include <net/sock.h>
269 #include <net/netlink.h>
272 struct sock *scsi_nl_sock = NULL;
273 EXPORT_SYMBOL_GPL(scsi_nl_sock);
275 +static DEFINE_SPINLOCK(scsi_nl_lock);
276 +static struct list_head scsi_nl_drivers;
278 +static u32 scsi_nl_state;
279 +#define STATE_EHANDLER_BSY 0x00000001
281 +struct scsi_nl_transport {
282 + int (*msg_handler)(struct sk_buff *);
283 + void (*event_handler)(struct notifier_block *, unsigned long, void *);
284 + unsigned int refcnt;
288 +/* flags values (bit flags) */
289 +#define HANDLER_DELETING 0x1
291 +static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] =
295 +struct scsi_nl_drvr {
296 + struct list_head next;
297 + int (*dmsg_handler)(struct Scsi_Host *shost, void *payload,
299 + void (*devt_handler)(struct notifier_block *nb,
300 + unsigned long event, void *notify_ptr);
301 + struct scsi_host_template *hostt;
303 + unsigned int refcnt;
310 * scsi_nl_rcv_msg - Receive message handler.
311 @@ -45,8 +79,9 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
313 struct nlmsghdr *nlh;
314 struct scsi_nl_hdr *hdr;
317 + unsigned long flags;
321 while (skb->len >= NLMSG_SPACE(0)) {
323 @@ -65,7 +100,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
325 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
331 hdr = NLMSG_DATA(nlh);
332 @@ -83,12 +118,27 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
333 if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
334 printk(KERN_WARNING "%s: discarding partial message\n",
341 - * We currently don't support anyone sending us a message
342 + * Deliver message to the appropriate transport
344 + spin_lock_irqsave(&scsi_nl_lock, flags);
346 + tport = hdr->transport;
347 + if ((tport < SCSI_NL_MAX_TRANSPORTS) &&
348 + !(transports[tport].flags & HANDLER_DELETING) &&
349 + (transports[tport].msg_handler)) {
350 + transports[tport].refcnt++;
351 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
352 + err = transports[tport].msg_handler(skb);
353 + spin_lock_irqsave(&scsi_nl_lock, flags);
354 + transports[tport].refcnt--;
358 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
361 if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
362 @@ -110,14 +160,42 @@ static int
363 scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr)
365 struct netlink_notify *n = ptr;
366 + struct scsi_nl_drvr *driver;
367 + unsigned long flags;
370 if (n->protocol != NETLINK_SCSITRANSPORT)
373 + spin_lock_irqsave(&scsi_nl_lock, flags);
374 + scsi_nl_state |= STATE_EHANDLER_BSY;
377 + * Pass event on to any transports that may be listening
379 + for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) {
380 + if (!(transports[tport].flags & HANDLER_DELETING) &&
381 + (transports[tport].event_handler)) {
382 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
383 + transports[tport].event_handler(this, event, ptr);
384 + spin_lock_irqsave(&scsi_nl_lock, flags);
389 - * Currently, we are not tracking PID's, etc. There is nothing
391 + * Pass event on to any drivers that may be listening
393 + list_for_each_entry(driver, &scsi_nl_drivers, next) {
394 + if (!(driver->flags & HANDLER_DELETING) &&
395 + (driver->devt_handler)) {
396 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
397 + driver->devt_handler(this, event, ptr);
398 + spin_lock_irqsave(&scsi_nl_lock, flags);
402 + scsi_nl_state &= ~STATE_EHANDLER_BSY;
403 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
407 @@ -128,7 +206,281 @@ static struct notifier_block scsi_netlin
411 - * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface
412 + * GENERIC SCSI transport receive and event handlers
416 + * scsi_generic_msg_handler - receive message handler for GENERIC transport
419 + * @skb: socket receive buffer
423 +scsi_generic_msg_handler(struct sk_buff *skb)
425 + struct nlmsghdr *nlh = nlmsg_hdr(skb);
426 + struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh);
427 + struct scsi_nl_drvr *driver;
428 + struct Scsi_Host *shost;
429 + unsigned long flags;
430 + int err = 0, match, pid;
432 + pid = NETLINK_CREDS(skb)->pid;
434 + switch (snlh->msgtype) {
435 + case SCSI_NL_SHOST_VENDOR:
437 + struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh);
439 + /* Locate the driver that corresponds to the message */
440 + spin_lock_irqsave(&scsi_nl_lock, flags);
442 + list_for_each_entry(driver, &scsi_nl_drivers, next) {
443 + if (driver->vendor_id == msg->vendor_id) {
449 + if ((!match) || (!driver->dmsg_handler)) {
450 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
455 + if (driver->flags & HANDLER_DELETING) {
456 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
462 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
465 + /* if successful, scsi_host_lookup takes a shost reference */
466 + shost = scsi_host_lookup(msg->host_no);
472 + /* is this host owned by the vendor ? */
473 + if (shost->hostt != driver->hostt) {
475 + goto vendormsg_put;
478 + /* pass message on to the driver */
479 + err = driver->dmsg_handler(shost, (void *)&msg[1],
480 + msg->vmsg_datalen, pid);
483 + /* release reference by scsi_host_lookup */
484 + scsi_host_put(shost);
487 + /* release our own reference on the registration object */
488 + spin_lock_irqsave(&scsi_nl_lock, flags);
490 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
501 + printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n",
502 + __func__, snlh->msgtype, err);
508 + * scsi_nl_add_transport -
509 + * Registers message and event handlers for a transport. Enables
510 + * receipt of netlink messages and events to a transport.
512 + * @tport: transport registering handlers
513 + * @msg_handler: receive message handler callback
514 + * @event_handler: receive event handler callback
517 +scsi_nl_add_transport(u8 tport,
518 + int (*msg_handler)(struct sk_buff *),
519 + void (*event_handler)(struct notifier_block *, unsigned long, void *))
521 + unsigned long flags;
524 + if (tport >= SCSI_NL_MAX_TRANSPORTS)
527 + spin_lock_irqsave(&scsi_nl_lock, flags);
529 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
530 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
532 + spin_lock_irqsave(&scsi_nl_lock, flags);
535 + if (transports[tport].msg_handler || transports[tport].event_handler) {
540 + transports[tport].msg_handler = msg_handler;
541 + transports[tport].event_handler = event_handler;
542 + transports[tport].flags = 0;
543 + transports[tport].refcnt = 0;
546 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
550 +EXPORT_SYMBOL_GPL(scsi_nl_add_transport);
554 + * scsi_nl_remove_transport -
555 + * Disable transport receiption of messages and events
557 + * @tport: transport deregistering handlers
561 +scsi_nl_remove_transport(u8 tport)
563 + unsigned long flags;
565 + spin_lock_irqsave(&scsi_nl_lock, flags);
566 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
567 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
569 + spin_lock_irqsave(&scsi_nl_lock, flags);
572 + if (tport < SCSI_NL_MAX_TRANSPORTS) {
573 + transports[tport].flags |= HANDLER_DELETING;
575 + while (transports[tport].refcnt != 0) {
576 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
577 + schedule_timeout_uninterruptible(HZ/4);
578 + spin_lock_irqsave(&scsi_nl_lock, flags);
580 + transports[tport].msg_handler = NULL;
581 + transports[tport].event_handler = NULL;
582 + transports[tport].flags = 0;
585 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
589 +EXPORT_SYMBOL_GPL(scsi_nl_remove_transport);
593 + * scsi_nl_add_driver -
594 + * A driver is registering its interfaces for SCSI netlink messages
596 + * @vendor_id: A unique identification value for the driver.
597 + * @hostt: address of the driver's host template. Used
598 + * to verify an shost is bound to the driver
599 + * @nlmsg_handler: receive message handler callback
600 + * @nlevt_handler: receive event handler callback
604 + * error result otherwise
607 +scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt,
608 + int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload,
610 + void (*nlevt_handler)(struct notifier_block *nb,
611 + unsigned long event, void *notify_ptr))
613 + struct scsi_nl_drvr *driver;
614 + unsigned long flags;
616 + driver = kzalloc(sizeof(*driver), GFP_KERNEL);
617 + if (unlikely(!driver)) {
618 + printk(KERN_ERR "%s: allocation failure\n", __func__);
622 + driver->dmsg_handler = nlmsg_handler;
623 + driver->devt_handler = nlevt_handler;
624 + driver->hostt = hostt;
625 + driver->vendor_id = vendor_id;
627 + spin_lock_irqsave(&scsi_nl_lock, flags);
628 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
629 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
631 + spin_lock_irqsave(&scsi_nl_lock, flags);
633 + list_add_tail(&driver->next, &scsi_nl_drivers);
634 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
638 +EXPORT_SYMBOL_GPL(scsi_nl_add_driver);
642 + * scsi_nl_remove_driver -
643 + * An driver is unregistering with the SCSI netlink messages
645 + * @vendor_id: The unique identification value for the driver.
648 +scsi_nl_remove_driver(u64 vendor_id)
650 + struct scsi_nl_drvr *driver;
651 + unsigned long flags;
653 + spin_lock_irqsave(&scsi_nl_lock, flags);
654 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
655 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
657 + spin_lock_irqsave(&scsi_nl_lock, flags);
660 + list_for_each_entry(driver, &scsi_nl_drivers, next) {
661 + if (driver->vendor_id == vendor_id) {
662 + driver->flags |= HANDLER_DELETING;
663 + while (driver->refcnt != 0) {
664 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
665 + schedule_timeout_uninterruptible(HZ/4);
666 + spin_lock_irqsave(&scsi_nl_lock, flags);
668 + list_del(&driver->next);
670 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
675 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
677 + printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n",
678 + __func__, (unsigned long long)vendor_id);
681 +EXPORT_SYMBOL_GPL(scsi_nl_remove_driver);
685 + * scsi_netlink_init - Called by SCSI subsystem to intialize
686 + * the SCSI transport netlink interface
690 @@ -136,6 +488,8 @@ scsi_netlink_init(void)
694 + INIT_LIST_HEAD(&scsi_nl_drivers);
696 error = netlink_register_notifier(&scsi_netlink_notifier);
698 printk(KERN_ERR "%s: register of event handler failed - %d\n",
699 @@ -150,8 +504,15 @@ scsi_netlink_init(void)
700 printk(KERN_ERR "%s: register of recieve handler failed\n",
702 netlink_unregister_notifier(&scsi_netlink_notifier);
706 + /* Register the entry points for the generic SCSI transport */
707 + error = scsi_nl_add_transport(SCSI_NL_TRANSPORT,
708 + scsi_generic_msg_handler, NULL);
710 + printk(KERN_ERR "%s: register of GENERIC transport handler"
711 + " failed - %d\n", __func__, error);
715 @@ -163,6 +524,8 @@ scsi_netlink_init(void)
717 scsi_netlink_exit(void)
719 + scsi_nl_remove_transport(SCSI_NL_TRANSPORT);
722 netlink_kernel_release(scsi_nl_sock);
723 netlink_unregister_notifier(&scsi_netlink_notifier);
724 @@ -172,3 +535,147 @@ scsi_netlink_exit(void)
729 + * Exported Interfaces
733 + * scsi_nl_send_transport_msg -
734 + * Generic function to send a single message from a SCSI transport to
737 + * @pid: receiving pid
738 + * @hdr: message payload
742 +scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr)
744 + struct sk_buff *skb;
745 + struct nlmsghdr *nlh;
751 + if (!scsi_nl_sock) {
753 + fn = "netlink socket";
757 + len = NLMSG_SPACE(hdr->msglen);
758 + skblen = NLMSG_SPACE(len);
760 + skb = alloc_skb(skblen, GFP_KERNEL);
767 + nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0);
773 + datab = NLMSG_DATA(nlh);
774 + memcpy(datab, hdr, hdr->msglen);
776 + err = nlmsg_unicast(scsi_nl_sock, skb, pid);
778 + fn = "nlmsg_unicast";
779 + /* nlmsg_unicast already kfree_skb'd */
788 + printk(KERN_WARNING
789 + "%s: Dropped Message : pid %d Transport %d, msgtype x%x, "
790 + "msglen %d: %s : err %d\n",
791 + __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen,
795 +EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg);
799 + * scsi_nl_send_vendor_msg - called to send a shost vendor unique message
800 + * to a specific process id.
802 + * @pid: process id of the receiver
803 + * @host_no: host # sending the message
804 + * @vendor_id: unique identifier for the driver's vendor
805 + * @data_len: amount, in bytes, of vendor unique payload data
806 + * @data_buf: pointer to vendor unique data buffer
809 + * 0 on succesful return
810 + * otherwise, failing error code
813 + * This routine assumes no locks are held on entry.
816 +scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id,
817 + char *data_buf, u32 data_len)
819 + struct sk_buff *skb;
820 + struct nlmsghdr *nlh;
821 + struct scsi_nl_host_vendor_msg *msg;
825 + if (!scsi_nl_sock) {
827 + goto send_vendor_fail;
830 + len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len);
831 + skblen = NLMSG_SPACE(len);
833 + skb = alloc_skb(skblen, GFP_KERNEL);
836 + goto send_vendor_fail;
839 + nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
840 + skblen - sizeof(*nlh), 0);
843 + goto send_vendor_fail_skb;
845 + msg = NLMSG_DATA(nlh);
847 + INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT,
848 + SCSI_NL_SHOST_VENDOR, len);
849 + msg->vendor_id = vendor_id;
850 + msg->host_no = host_no;
851 + msg->vmsg_datalen = data_len; /* bytes */
852 + memcpy(&msg[1], data_buf, data_len);
854 + err = nlmsg_unicast(scsi_nl_sock, skb, pid);
856 + /* nlmsg_multicast already kfree_skb'd */
857 + goto send_vendor_fail;
861 +send_vendor_fail_skb:
864 + printk(KERN_WARNING
865 + "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n",
866 + __func__, host_no, err);
869 +EXPORT_SYMBOL(scsi_nl_send_vendor_msg);
872 --- a/drivers/scsi/scsi_scan.c
873 +++ b/drivers/scsi/scsi_scan.c
874 @@ -730,6 +730,8 @@ static int scsi_probe_lun(struct scsi_de
875 static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
876 int *bflags, int async)
881 * XXX do not save the inquiry, since it can change underneath us,
882 * save just vendor/model/rev.
883 @@ -885,7 +887,17 @@ static int scsi_add_lun(struct scsi_devi
885 /* set the device running here so that slave configure
887 - scsi_device_set_state(sdev, SDEV_RUNNING);
888 + ret = scsi_device_set_state(sdev, SDEV_RUNNING);
890 + ret = scsi_device_set_state(sdev, SDEV_BLOCK);
893 + sdev_printk(KERN_ERR, sdev,
894 + "in wrong state %s to complete scan\n",
895 + scsi_device_state_name(sdev->sdev_state));
896 + return SCSI_SCAN_NO_RESPONSE;
900 if (*bflags & BLIST_MS_192_BYTES_FOR_3F)
901 sdev->use_192_bytes_for_3f = 1;
902 @@ -899,7 +911,7 @@ static int scsi_add_lun(struct scsi_devi
903 transport_configure_device(&sdev->sdev_gendev);
905 if (sdev->host->hostt->slave_configure) {
906 - int ret = sdev->host->hostt->slave_configure(sdev);
907 + ret = sdev->host->hostt->slave_configure(sdev);
910 * if LLDD reports slave not present, don't clutter
911 @@ -994,7 +1006,7 @@ static int scsi_probe_and_add_lun(struct
913 sdev = scsi_device_lookup_by_target(starget, lun);
915 - if (rescan || sdev->sdev_state != SDEV_CREATED) {
916 + if (rescan || !scsi_device_created(sdev)) {
917 SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
918 "scsi scan: device exists on %s\n",
919 sdev->sdev_gendev.bus_id));
920 @@ -1467,7 +1479,7 @@ static int scsi_report_lun_scan(struct s
923 scsi_device_put(sdev);
924 - if (sdev->sdev_state == SDEV_CREATED)
925 + if (scsi_device_created(sdev))
927 * the sdev we used didn't appear in the report luns scan
929 --- a/drivers/scsi/scsi_sysfs.c
930 +++ b/drivers/scsi/scsi_sysfs.c
931 @@ -34,6 +34,7 @@ static const struct {
932 { SDEV_QUIESCE, "quiesce" },
933 { SDEV_OFFLINE, "offline" },
934 { SDEV_BLOCK, "blocked" },
935 + { SDEV_CREATED_BLOCK, "created-blocked" },
938 const char *scsi_device_state_name(enum scsi_device_state state)
939 --- a/drivers/scsi/scsi_transport_fc.c
940 +++ b/drivers/scsi/scsi_transport_fc.c
943 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
944 static void fc_vport_sched_delete(struct work_struct *work);
947 - * This is a temporary carrier for creating a vport. It will eventually
948 - * be replaced by a real message definition for sgio or netlink.
950 - * fc_vport_identifiers: This set of data contains all elements
951 - * to uniquely identify and instantiate a FC virtual port.
954 - * symbolic_name: The driver is to append the symbolic_name string data
955 - * to the symbolic_node_name data that it generates by default.
956 - * the resulting combination should then be registered with the switch.
957 - * It is expected that things like Xen may stuff a VM title into
960 -struct fc_vport_identifiers {
965 - enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
966 - char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
969 -static int fc_vport_create(struct Scsi_Host *shost, int channel,
970 +static int fc_vport_setup(struct Scsi_Host *shost, int channel,
971 struct device *pdev, struct fc_vport_identifiers *ids,
972 struct fc_vport **vport);
974 @@ -1760,7 +1736,7 @@ store_fc_host_vport_create(struct device
975 vid.disable = false; /* always enabled */
977 /* we only allow support on Channel 0 !!! */
978 - stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
979 + stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport);
980 return stat ? stat : count;
982 static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
983 @@ -3103,7 +3079,7 @@ fc_scsi_scan_rport(struct work_struct *w
987 - * fc_vport_create - allocates and creates a FC virtual port.
988 + * fc_vport_setup - allocates and creates a FC virtual port.
989 * @shost: scsi host the virtual port is connected to.
990 * @channel: Channel on shost port connected to.
991 * @pdev: parent device for vport
992 @@ -3118,7 +3094,7 @@ fc_scsi_scan_rport(struct work_struct *w
993 * This routine assumes no locks are held on entry.
996 -fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
997 +fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
998 struct fc_vport_identifiers *ids, struct fc_vport **ret_vport)
1000 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1001 @@ -3231,6 +3207,28 @@ delete_vport:
1006 + * fc_vport_create - Admin App or LLDD requests creation of a vport
1007 + * @shost: scsi host the virtual port is connected to.
1008 + * @channel: channel on shost port connected to.
1009 + * @ids: The world wide names, FC4 port roles, etc for
1010 + * the virtual port.
1013 + * This routine assumes no locks are held on entry.
1016 +fc_vport_create(struct Scsi_Host *shost, int channel,
1017 + struct fc_vport_identifiers *ids)
1020 + struct fc_vport *vport;
1022 + stat = fc_vport_setup(shost, channel, &shost->shost_gendev,
1024 + return stat ? NULL : vport;
1026 +EXPORT_SYMBOL(fc_vport_create);
1029 * fc_vport_terminate - Admin App or LLDD requests termination of a vport
1030 --- a/drivers/scsi/sd.c
1031 +++ b/drivers/scsi/sd.c
1033 #include <linux/blkpg.h>
1034 #include <linux/delay.h>
1035 #include <linux/mutex.h>
1036 +#include <linux/string_helpers.h>
1037 #include <asm/uaccess.h>
1039 #include <scsi/scsi.h>
1040 @@ -1436,27 +1437,21 @@ got_data:
1044 + blk_queue_hardsect_size(sdp->request_queue, sector_size);
1048 - * The msdos fs needs to know the hardware sector size
1049 - * So I have created this table. See ll_rw_blk.c
1050 - * Jacques Gelinas (Jacques@solucorp.qc.ca)
1052 - int hard_sector = sector_size;
1053 - sector_t sz = (sdkp->capacity/2) * (hard_sector/256);
1054 - struct request_queue *queue = sdp->request_queue;
1057 - blk_queue_hardsect_size(queue, hard_sector);
1058 - /* avoid 64-bit division on 32-bit platforms */
1059 - sector_div(sz, 625);
1061 - sector_div(mb, 1950);
1062 + char cap_str_2[10], cap_str_10[10];
1063 + u64 sz = sdkp->capacity << ffz(~sector_size);
1065 + string_get_size(sz, STRING_UNITS_2, cap_str_2,
1066 + sizeof(cap_str_2));
1067 + string_get_size(sz, STRING_UNITS_10, cap_str_10,
1068 + sizeof(cap_str_10));
1070 sd_printk(KERN_NOTICE, sdkp,
1071 - "%llu %d-byte hardware sectors (%llu MB)\n",
1072 + "%llu %d-byte hardware sectors: (%s/%s)\n",
1073 (unsigned long long)sdkp->capacity,
1074 - hard_sector, (unsigned long long)mb);
1075 + sector_size, cap_str_10, cap_str_2);
1078 /* Rescale capacity to 512-byte units */
1080 +++ b/include/linux/string_helpers.h
1082 +#ifndef _LINUX_STRING_HELPERS_H_
1083 +#define _LINUX_STRING_HELPERS_H_
1085 +#include <linux/types.h>
1087 +/* Descriptions of the types of units to
1089 +enum string_size_units {
1090 + STRING_UNITS_10, /* use powers of 10^3 (standard SI) */
1091 + STRING_UNITS_2, /* use binary powers of 2^10 */
1094 +int string_get_size(u64 size, enum string_size_units units,
1095 + char *buf, int len);
1098 --- a/include/scsi/scsi_device.h
1099 +++ b/include/scsi/scsi_device.h
1100 @@ -42,9 +42,11 @@ enum scsi_device_state {
1101 * originate in the mid-layer) */
1102 SDEV_OFFLINE, /* Device offlined (by error handling or
1104 - SDEV_BLOCK, /* Device blocked by scsi lld. No scsi
1105 - * commands from user or midlayer should be issued
1106 - * to the scsi lld. */
1107 + SDEV_BLOCK, /* Device blocked by scsi lld. No
1108 + * scsi commands from user or midlayer
1109 + * should be issued to the scsi
1111 + SDEV_CREATED_BLOCK, /* same as above but for created devices */
1114 enum scsi_device_event {
1115 @@ -384,10 +386,23 @@ static inline unsigned int sdev_id(struc
1116 #define scmd_id(scmd) sdev_id((scmd)->device)
1117 #define scmd_channel(scmd) sdev_channel((scmd)->device)
1120 + * checks for positions of the SCSI state machine
1122 static inline int scsi_device_online(struct scsi_device *sdev)
1124 return sdev->sdev_state != SDEV_OFFLINE;
1126 +static inline int scsi_device_blocked(struct scsi_device *sdev)
1128 + return sdev->sdev_state == SDEV_BLOCK ||
1129 + sdev->sdev_state == SDEV_CREATED_BLOCK;
1131 +static inline int scsi_device_created(struct scsi_device *sdev)
1133 + return sdev->sdev_state == SDEV_CREATED ||
1134 + sdev->sdev_state == SDEV_CREATED_BLOCK;
1137 /* accessor functions for the SCSI parameters */
1138 static inline int scsi_device_sync(struct scsi_device *sdev)
1139 --- a/include/scsi/scsi_netlink.h
1140 +++ b/include/scsi/scsi_netlink.h
1142 #ifndef SCSI_NETLINK_H
1143 #define SCSI_NETLINK_H
1145 +#include <linux/netlink.h>
1149 * This file intended to be included by both kernel and user space
1151 @@ -55,7 +58,41 @@ struct scsi_nl_hdr {
1152 #define SCSI_NL_TRANSPORT_FC 1
1153 #define SCSI_NL_MAX_TRANSPORTS 2
1155 -/* scsi_nl_hdr->msgtype values are defined in each transport */
1156 +/* Transport-based scsi_nl_hdr->msgtype values are defined in each transport */
1159 + * GENERIC SCSI scsi_nl_hdr->msgtype Values
1161 + /* kernel -> user */
1162 +#define SCSI_NL_SHOST_VENDOR 0x0001
1163 + /* user -> kernel */
1164 +/* SCSI_NL_SHOST_VENDOR msgtype is kernel->user and user->kernel */
1168 + * Message Structures :
1171 +/* macro to round up message lengths to 8byte boundary */
1172 +#define SCSI_NL_MSGALIGN(len) (((len) + 7) & ~7)
1176 + * SCSI HOST Vendor Unique messages :
1177 + * SCSI_NL_SHOST_VENDOR
1179 + * Note: The Vendor Unique message payload will begin directly after
1180 + * this structure, with the length of the payload per vmsg_datalen.
1182 + * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
1183 + * formatting requirements specified below
1185 +struct scsi_nl_host_vendor_msg {
1186 + struct scsi_nl_hdr snlh; /* must be 1st element ! */
1187 + uint64_t vendor_id;
1189 + uint16_t vmsg_datalen;
1190 +} __attribute__((aligned(sizeof(uint64_t))));
1194 @@ -83,5 +120,28 @@ struct scsi_nl_hdr {
1200 +#include <scsi/scsi_host.h>
1202 +/* Exported Kernel Interfaces */
1203 +int scsi_nl_add_transport(u8 tport,
1204 + int (*msg_handler)(struct sk_buff *),
1205 + void (*event_handler)(struct notifier_block *, unsigned long, void *));
1206 +void scsi_nl_remove_transport(u8 tport);
1208 +int scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt,
1209 + int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload,
1210 + u32 len, u32 pid),
1211 + void (*nlevt_handler)(struct notifier_block *nb,
1212 + unsigned long event, void *notify_ptr));
1213 +void scsi_nl_remove_driver(u64 vendor_id);
1215 +void scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr);
1216 +int scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id,
1217 + char *data_buf, u32 data_len);
1219 +#endif /* __KERNEL__ */
1221 #endif /* SCSI_NETLINK_H */
1223 --- a/include/scsi/scsi_transport_fc.h
1224 +++ b/include/scsi/scsi_transport_fc.h
1225 @@ -167,6 +167,26 @@ enum fc_tgtid_binding_type {
1226 struct device_attribute dev_attr_vport_##_name = \
1227 __ATTR(_name,_mode,_show,_store)
1230 + * fc_vport_identifiers: This set of data contains all elements
1231 + * to uniquely identify and instantiate a FC virtual port.
1234 + * symbolic_name: The driver is to append the symbolic_name string data
1235 + * to the symbolic_node_name data that it generates by default.
1236 + * the resulting combination should then be registered with the switch.
1237 + * It is expected that things like Xen may stuff a VM title into
1240 +#define FC_VPORT_SYMBOLIC_NAMELEN 64
1241 +struct fc_vport_identifiers {
1246 + enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
1247 + char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
1251 * FC Virtual Port Attributes
1252 @@ -197,7 +217,6 @@ struct device_attribute dev_attr_vport_#
1253 * managed by the transport w/o driver interaction.
1256 -#define FC_VPORT_SYMBOLIC_NAMELEN 64
1258 /* Fixed Attributes */
1260 @@ -732,6 +751,8 @@ void fc_host_post_vendor_event(struct Sc
1261 * be sure to read the Vendor Type and ID formatting requirements
1262 * specified in scsi_netlink.h
1264 +struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
1265 + struct fc_vport_identifiers *);
1266 int fc_vport_terminate(struct fc_vport *vport);
1268 #endif /* SCSI_TRANSPORT_FC_H */
1271 @@ -19,7 +19,8 @@ lib-$(CONFIG_SMP) += cpumask.o
1272 lib-y += kobject.o kref.o klist.o
1274 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
1275 - bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o
1276 + bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
1279 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
1280 CFLAGS_kobject.o += -DDEBUG
1282 +++ b/lib/string_helpers.c
1285 + * Helpers for formatting and printing strings
1287 + * Copyright 31 August 2008 James Bottomley
1289 +#include <linux/kernel.h>
1290 +#include <linux/math64.h>
1291 +#include <linux/module.h>
1292 +#include <linux/string_helpers.h>
1295 + * string_get_size - get the size in the specified units
1296 + * @size: The size to be converted
1297 + * @units: units to use (powers of 1000 or 1024)
1298 + * @buf: buffer to format to
1299 + * @len: length of buffer
1301 + * This function returns a string formatted to 3 significant figures
1302 + * giving the size in the required units. Returns 0 on success or
1303 + * error on failure. @buf is always zero terminated.
1306 +int string_get_size(u64 size, const enum string_size_units units,
1307 + char *buf, int len)
1309 + const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB",
1310 + "EB", "ZB", "YB", NULL};
1311 + const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB",
1312 + "EiB", "ZiB", "YiB", NULL };
1313 + const char **units_str[] = {
1314 + [STRING_UNITS_10] = units_10,
1315 + [STRING_UNITS_2] = units_2,
1317 + const int divisor[] = {
1318 + [STRING_UNITS_10] = 1000,
1319 + [STRING_UNITS_2] = 1024,
1322 + u64 remainder = 0, sf_cap;
1327 + for (i = 0; size > divisor[units] && units_str[units][i]; i++)
1328 + remainder = do_div(size, divisor[units]);
1331 + for (j = 0; sf_cap*10 < 1000; j++)
1335 + remainder *= 1000;
1336 + do_div(remainder, divisor[units]);
1337 + snprintf(tmp, sizeof(tmp), ".%03lld",
1338 + (unsigned long long)remainder);
1342 + snprintf(buf, len, "%lld%s%s", (unsigned long long)size,
1343 + tmp, units_str[units][i]);
1347 +EXPORT_SYMBOL(string_get_size);