]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.fixes/scsi-misc-git-update
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / scsi-misc-git-update
CommitLineData
2cb7cef9
BS
1From: James Bottomley <james.bottomley@hansenpartnership.com>
2Subject: SCSI misc fixes
3References: FATE#303485,FATE#303484
4
5This patch pulls in the latest patches from the scsi-misc tree.
6The functions are required by the various driver updates.
7
8Signed-off-by: Hannes Reinecke <hare@suse.de>
9
10---
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 +
28 lib/Makefile | 3
29 lib/string_helpers.c | 64 +++
30 19 files changed, 834 insertions(+), 87 deletions(-)
31
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.
36
37
38+Transport supplied functions
39+----------------------------
40+
41+The following functions are supplied by the FC-transport for use by LLDs.
42+
43+ fc_vport_create - create a vport
44+ fc_vport_terminate - detach and remove a vport
45+
46+Details:
47+
48+/**
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
52+ * the virtual port.
53+ *
54+ * Notes:
55+ * This routine assumes no locks are held on entry.
56+ */
57+struct fc_vport *
58+fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids)
59+
60+/**
61+ * fc_vport_terminate - Admin App or LLDD requests termination of a vport
62+ * @vport: fc_vport to be terminated
63+ *
64+ * Calls the LLDD vport_delete() function, then deallocates and removes
65+ * the vport from the shost and object tree.
66+ *
67+ * Notes:
68+ * This routine assumes no locks are held on entry.
69+ */
70+int
71+fc_vport_terminate(struct fc_vport *vport)
72+
73+
74 Credits
75 =======
76 The following people have contributed to this document:
77--- a/drivers/mmc/card/block.c
78+++ b/drivers/mmc/card/block.c
79@@ -29,6 +29,7 @@
80 #include <linux/blkdev.h>
81 #include <linux/mutex.h>
82 #include <linux/scatterlist.h>
83+#include <linux/string_helpers.h>
84
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;
89 int err;
90
91+ char cap_str[10];
92+
93 /*
94 * Check that the card supports the command class(es) we need.
95 */
96@@ -546,10 +549,11 @@ static int mmc_blk_probe(struct mmc_card
97 if (err)
98 goto out;
99
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)" : "");
108
109 mmc_set_drvdata(card, md);
110 add_disk(md->disk);
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
114 return NULL;
115 }
116
117- memset(rq->cmd, 0, BLK_MAX_CDB);
118 rq->cmd_len = COMMAND_SIZE(cmd);
119 rq->cmd[0] = cmd;
120
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
142 return NULL;
143 }
144
145- memset(rq->cmd, 0, BLK_MAX_CDB);
146-
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);
158 }
159 }
160 }
161--- a/drivers/scsi/scsi.c
162+++ b/drivers/scsi/scsi.c
163@@ -668,13 +668,14 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
164 goto out;
165 }
166
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))) {
171 /*
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
180+ * suspend state.
181 */
182
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
187 break;
188 case SDEV_QUIESCE:
189 case SDEV_BLOCK:
190+ case SDEV_CREATED_BLOCK:
191 /*
192 * If the devices is blocked we defer normal commands.
193 */
194@@ -2073,10 +2074,13 @@ scsi_device_set_state(struct scsi_device
195
196 switch (state) {
197 case SDEV_CREATED:
198- /* There are no legal states that come back to
199- * created. This is the manually initialised start
200- * state */
201- goto illegal;
202+ switch (oldstate) {
203+ case SDEV_CREATED_BLOCK:
204+ break;
205+ default:
206+ goto illegal;
207+ }
208+ break;
209
210 case SDEV_RUNNING:
211 switch (oldstate) {
212@@ -2114,8 +2118,17 @@ scsi_device_set_state(struct scsi_device
213
214 case SDEV_BLOCK:
215 switch (oldstate) {
216- case SDEV_CREATED:
217 case SDEV_RUNNING:
218+ case SDEV_CREATED_BLOCK:
219+ break;
220+ default:
221+ goto illegal;
222+ }
223+ break;
224+
225+ case SDEV_CREATED_BLOCK:
226+ switch (oldstate) {
227+ case SDEV_CREATED:
228 break;
229 default:
230 goto illegal;
231@@ -2403,8 +2416,12 @@ scsi_internal_device_block(struct scsi_d
232 int err = 0;
233
234 err = scsi_device_set_state(sdev, SDEV_BLOCK);
235- if (err)
236- return err;
237+ if (err) {
238+ err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK);
239+
240+ if (err)
241+ return err;
242+ }
243
244 /*
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.
248 */
249 err = scsi_device_set_state(sdev, SDEV_RUNNING);
250- if (err)
251- return err;
252+ if (err) {
253+ err = scsi_device_set_state(sdev, SDEV_CREATED);
254+
255+ if (err)
256+ return err;
257+ }
258
259 spin_lock_irqsave(q->queue_lock, flags);
260 blk_start_queue(q);
261--- a/drivers/scsi/scsi_netlink.c
262+++ b/drivers/scsi/scsi_netlink.c
263@@ -21,6 +21,7 @@
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>
270
271@@ -30,6 +31,39 @@
272 struct sock *scsi_nl_sock = NULL;
273 EXPORT_SYMBOL_GPL(scsi_nl_sock);
274
275+static DEFINE_SPINLOCK(scsi_nl_lock);
276+static struct list_head scsi_nl_drivers;
277+
278+static u32 scsi_nl_state;
279+#define STATE_EHANDLER_BSY 0x00000001
280+
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;
285+ int flags;
286+};
287+
288+/* flags values (bit flags) */
289+#define HANDLER_DELETING 0x1
290+
291+static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] =
292+ { {NULL, }, };
293+
294+
295+struct scsi_nl_drvr {
296+ struct list_head next;
297+ int (*dmsg_handler)(struct Scsi_Host *shost, void *payload,
298+ u32 len, u32 pid);
299+ void (*devt_handler)(struct notifier_block *nb,
300+ unsigned long event, void *notify_ptr);
301+ struct scsi_host_template *hostt;
302+ u64 vendor_id;
303+ unsigned int refcnt;
304+ int flags;
305+};
306+
307+
308
309 /**
310 * scsi_nl_rcv_msg - Receive message handler.
311@@ -45,8 +79,9 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
312 {
313 struct nlmsghdr *nlh;
314 struct scsi_nl_hdr *hdr;
315- uint32_t rlen;
316- int err;
317+ unsigned long flags;
318+ u32 rlen;
319+ int err, tport;
320
321 while (skb->len >= NLMSG_SPACE(0)) {
322 err = 0;
323@@ -65,7 +100,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
324
325 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
326 err = -EBADMSG;
327- return;
328+ goto next_msg;
329 }
330
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",
335 __func__);
336- return;
337+ goto next_msg;
338 }
339
340 /*
341- * We currently don't support anyone sending us a message
342+ * Deliver message to the appropriate transport
343 */
344+ spin_lock_irqsave(&scsi_nl_lock, flags);
345+
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--;
355+ } else
356+ err = -ENOENT;
357+
358+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
359
360 next_msg:
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)
364 {
365 struct netlink_notify *n = ptr;
366+ struct scsi_nl_drvr *driver;
367+ unsigned long flags;
368+ int tport;
369
370 if (n->protocol != NETLINK_SCSITRANSPORT)
371 return NOTIFY_DONE;
372
373+ spin_lock_irqsave(&scsi_nl_lock, flags);
374+ scsi_nl_state |= STATE_EHANDLER_BSY;
375+
376+ /*
377+ * Pass event on to any transports that may be listening
378+ */
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);
385+ }
386+ }
387+
388 /*
389- * Currently, we are not tracking PID's, etc. There is nothing
390- * to handle.
391+ * Pass event on to any drivers that may be listening
392 */
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);
399+ }
400+ }
401+
402+ scsi_nl_state &= ~STATE_EHANDLER_BSY;
403+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
404
405 return NOTIFY_DONE;
406 }
407@@ -128,7 +206,281 @@ static struct notifier_block scsi_netlin
408
409
410 /**
411- * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface
412+ * GENERIC SCSI transport receive and event handlers
413+ **/
414+
415+/**
416+ * scsi_generic_msg_handler - receive message handler for GENERIC transport
417+ * messages
418+ *
419+ * @skb: socket receive buffer
420+ *
421+ **/
422+static int
423+scsi_generic_msg_handler(struct sk_buff *skb)
424+{
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;
431+
432+ pid = NETLINK_CREDS(skb)->pid;
433+
434+ switch (snlh->msgtype) {
435+ case SCSI_NL_SHOST_VENDOR:
436+ {
437+ struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh);
438+
439+ /* Locate the driver that corresponds to the message */
440+ spin_lock_irqsave(&scsi_nl_lock, flags);
441+ match = 0;
442+ list_for_each_entry(driver, &scsi_nl_drivers, next) {
443+ if (driver->vendor_id == msg->vendor_id) {
444+ match = 1;
445+ break;
446+ }
447+ }
448+
449+ if ((!match) || (!driver->dmsg_handler)) {
450+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
451+ err = -ESRCH;
452+ goto rcv_exit;
453+ }
454+
455+ if (driver->flags & HANDLER_DELETING) {
456+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
457+ err = -ESHUTDOWN;
458+ goto rcv_exit;
459+ }
460+
461+ driver->refcnt++;
462+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
463+
464+
465+ /* if successful, scsi_host_lookup takes a shost reference */
466+ shost = scsi_host_lookup(msg->host_no);
467+ if (!shost) {
468+ err = -ENODEV;
469+ goto driver_exit;
470+ }
471+
472+ /* is this host owned by the vendor ? */
473+ if (shost->hostt != driver->hostt) {
474+ err = -EINVAL;
475+ goto vendormsg_put;
476+ }
477+
478+ /* pass message on to the driver */
479+ err = driver->dmsg_handler(shost, (void *)&msg[1],
480+ msg->vmsg_datalen, pid);
481+
482+vendormsg_put:
483+ /* release reference by scsi_host_lookup */
484+ scsi_host_put(shost);
485+
486+driver_exit:
487+ /* release our own reference on the registration object */
488+ spin_lock_irqsave(&scsi_nl_lock, flags);
489+ driver->refcnt--;
490+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
491+ break;
492+ }
493+
494+ default:
495+ err = -EBADR;
496+ break;
497+ }
498+
499+rcv_exit:
500+ if (err)
501+ printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n",
502+ __func__, snlh->msgtype, err);
503+ return err;
504+}
505+
506+
507+/**
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.
511+ *
512+ * @tport: transport registering handlers
513+ * @msg_handler: receive message handler callback
514+ * @event_handler: receive event handler callback
515+ **/
516+int
517+scsi_nl_add_transport(u8 tport,
518+ int (*msg_handler)(struct sk_buff *),
519+ void (*event_handler)(struct notifier_block *, unsigned long, void *))
520+{
521+ unsigned long flags;
522+ int err = 0;
523+
524+ if (tport >= SCSI_NL_MAX_TRANSPORTS)
525+ return -EINVAL;
526+
527+ spin_lock_irqsave(&scsi_nl_lock, flags);
528+
529+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
530+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
531+ msleep(1);
532+ spin_lock_irqsave(&scsi_nl_lock, flags);
533+ }
534+
535+ if (transports[tport].msg_handler || transports[tport].event_handler) {
536+ err = -EALREADY;
537+ goto register_out;
538+ }
539+
540+ transports[tport].msg_handler = msg_handler;
541+ transports[tport].event_handler = event_handler;
542+ transports[tport].flags = 0;
543+ transports[tport].refcnt = 0;
544+
545+register_out:
546+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
547+
548+ return err;
549+}
550+EXPORT_SYMBOL_GPL(scsi_nl_add_transport);
551+
552+
553+/**
554+ * scsi_nl_remove_transport -
555+ * Disable transport receiption of messages and events
556+ *
557+ * @tport: transport deregistering handlers
558+ *
559+ **/
560+void
561+scsi_nl_remove_transport(u8 tport)
562+{
563+ unsigned long flags;
564+
565+ spin_lock_irqsave(&scsi_nl_lock, flags);
566+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
567+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
568+ msleep(1);
569+ spin_lock_irqsave(&scsi_nl_lock, flags);
570+ }
571+
572+ if (tport < SCSI_NL_MAX_TRANSPORTS) {
573+ transports[tport].flags |= HANDLER_DELETING;
574+
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);
579+ }
580+ transports[tport].msg_handler = NULL;
581+ transports[tport].event_handler = NULL;
582+ transports[tport].flags = 0;
583+ }
584+
585+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
586+
587+ return;
588+}
589+EXPORT_SYMBOL_GPL(scsi_nl_remove_transport);
590+
591+
592+/**
593+ * scsi_nl_add_driver -
594+ * A driver is registering its interfaces for SCSI netlink messages
595+ *
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
601+ *
602+ * Returns:
603+ * 0 on Success
604+ * error result otherwise
605+ **/
606+int
607+scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt,
608+ int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload,
609+ u32 len, u32 pid),
610+ void (*nlevt_handler)(struct notifier_block *nb,
611+ unsigned long event, void *notify_ptr))
612+{
613+ struct scsi_nl_drvr *driver;
614+ unsigned long flags;
615+
616+ driver = kzalloc(sizeof(*driver), GFP_KERNEL);
617+ if (unlikely(!driver)) {
618+ printk(KERN_ERR "%s: allocation failure\n", __func__);
619+ return -ENOMEM;
620+ }
621+
622+ driver->dmsg_handler = nlmsg_handler;
623+ driver->devt_handler = nlevt_handler;
624+ driver->hostt = hostt;
625+ driver->vendor_id = vendor_id;
626+
627+ spin_lock_irqsave(&scsi_nl_lock, flags);
628+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
629+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
630+ msleep(1);
631+ spin_lock_irqsave(&scsi_nl_lock, flags);
632+ }
633+ list_add_tail(&driver->next, &scsi_nl_drivers);
634+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
635+
636+ return 0;
637+}
638+EXPORT_SYMBOL_GPL(scsi_nl_add_driver);
639+
640+
641+/**
642+ * scsi_nl_remove_driver -
643+ * An driver is unregistering with the SCSI netlink messages
644+ *
645+ * @vendor_id: The unique identification value for the driver.
646+ **/
647+void
648+scsi_nl_remove_driver(u64 vendor_id)
649+{
650+ struct scsi_nl_drvr *driver;
651+ unsigned long flags;
652+
653+ spin_lock_irqsave(&scsi_nl_lock, flags);
654+ if (scsi_nl_state & STATE_EHANDLER_BSY) {
655+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
656+ msleep(1);
657+ spin_lock_irqsave(&scsi_nl_lock, flags);
658+ }
659+
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);
667+ }
668+ list_del(&driver->next);
669+ kfree(driver);
670+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
671+ return;
672+ }
673+ }
674+
675+ spin_unlock_irqrestore(&scsi_nl_lock, flags);
676+
677+ printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n",
678+ __func__, (unsigned long long)vendor_id);
679+ return;
680+}
681+EXPORT_SYMBOL_GPL(scsi_nl_remove_driver);
682+
683+
684+/**
685+ * scsi_netlink_init - Called by SCSI subsystem to intialize
686+ * the SCSI transport netlink interface
687 *
688 **/
689 void
690@@ -136,6 +488,8 @@ scsi_netlink_init(void)
691 {
692 int error;
693
694+ INIT_LIST_HEAD(&scsi_nl_drivers);
695+
696 error = netlink_register_notifier(&scsi_netlink_notifier);
697 if (error) {
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",
701 __func__);
702 netlink_unregister_notifier(&scsi_netlink_notifier);
703+ return;
704 }
705
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);
709+ if (error)
710+ printk(KERN_ERR "%s: register of GENERIC transport handler"
711+ " failed - %d\n", __func__, error);
712 return;
713 }
714
715@@ -163,6 +524,8 @@ scsi_netlink_init(void)
716 void
717 scsi_netlink_exit(void)
718 {
719+ scsi_nl_remove_transport(SCSI_NL_TRANSPORT);
720+
721 if (scsi_nl_sock) {
722 netlink_kernel_release(scsi_nl_sock);
723 netlink_unregister_notifier(&scsi_netlink_notifier);
724@@ -172,3 +535,147 @@ scsi_netlink_exit(void)
725 }
726
727
728+/*
729+ * Exported Interfaces
730+ */
731+
732+/**
733+ * scsi_nl_send_transport_msg -
734+ * Generic function to send a single message from a SCSI transport to
735+ * a single process
736+ *
737+ * @pid: receiving pid
738+ * @hdr: message payload
739+ *
740+ **/
741+void
742+scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr)
743+{
744+ struct sk_buff *skb;
745+ struct nlmsghdr *nlh;
746+ const char *fn;
747+ char *datab;
748+ u32 len, skblen;
749+ int err;
750+
751+ if (!scsi_nl_sock) {
752+ err = -ENOENT;
753+ fn = "netlink socket";
754+ goto msg_fail;
755+ }
756+
757+ len = NLMSG_SPACE(hdr->msglen);
758+ skblen = NLMSG_SPACE(len);
759+
760+ skb = alloc_skb(skblen, GFP_KERNEL);
761+ if (!skb) {
762+ err = -ENOBUFS;
763+ fn = "alloc_skb";
764+ goto msg_fail;
765+ }
766+
767+ nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0);
768+ if (!nlh) {
769+ err = -ENOBUFS;
770+ fn = "nlmsg_put";
771+ goto msg_fail_skb;
772+ }
773+ datab = NLMSG_DATA(nlh);
774+ memcpy(datab, hdr, hdr->msglen);
775+
776+ err = nlmsg_unicast(scsi_nl_sock, skb, pid);
777+ if (err < 0) {
778+ fn = "nlmsg_unicast";
779+ /* nlmsg_unicast already kfree_skb'd */
780+ goto msg_fail;
781+ }
782+
783+ return;
784+
785+msg_fail_skb:
786+ kfree_skb(skb);
787+msg_fail:
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,
792+ fn, err);
793+ return;
794+}
795+EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg);
796+
797+
798+/**
799+ * scsi_nl_send_vendor_msg - called to send a shost vendor unique message
800+ * to a specific process id.
801+ *
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
807+ *
808+ * Returns:
809+ * 0 on succesful return
810+ * otherwise, failing error code
811+ *
812+ * Notes:
813+ * This routine assumes no locks are held on entry.
814+ */
815+int
816+scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id,
817+ char *data_buf, u32 data_len)
818+{
819+ struct sk_buff *skb;
820+ struct nlmsghdr *nlh;
821+ struct scsi_nl_host_vendor_msg *msg;
822+ u32 len, skblen;
823+ int err;
824+
825+ if (!scsi_nl_sock) {
826+ err = -ENOENT;
827+ goto send_vendor_fail;
828+ }
829+
830+ len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len);
831+ skblen = NLMSG_SPACE(len);
832+
833+ skb = alloc_skb(skblen, GFP_KERNEL);
834+ if (!skb) {
835+ err = -ENOBUFS;
836+ goto send_vendor_fail;
837+ }
838+
839+ nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
840+ skblen - sizeof(*nlh), 0);
841+ if (!nlh) {
842+ err = -ENOBUFS;
843+ goto send_vendor_fail_skb;
844+ }
845+ msg = NLMSG_DATA(nlh);
846+
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);
853+
854+ err = nlmsg_unicast(scsi_nl_sock, skb, pid);
855+ if (err)
856+ /* nlmsg_multicast already kfree_skb'd */
857+ goto send_vendor_fail;
858+
859+ return 0;
860+
861+send_vendor_fail_skb:
862+ kfree_skb(skb);
863+send_vendor_fail:
864+ printk(KERN_WARNING
865+ "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n",
866+ __func__, host_no, err);
867+ return err;
868+}
869+EXPORT_SYMBOL(scsi_nl_send_vendor_msg);
870+
871+
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)
877 {
878+ int ret;
879+
880 /*
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
884
885 /* set the device running here so that slave configure
886 * may do I/O */
887- scsi_device_set_state(sdev, SDEV_RUNNING);
888+ ret = scsi_device_set_state(sdev, SDEV_RUNNING);
889+ if (ret) {
890+ ret = scsi_device_set_state(sdev, SDEV_BLOCK);
891+
892+ if (ret) {
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;
897+ }
898+ }
899
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);
904
905 if (sdev->host->hostt->slave_configure) {
906- int ret = sdev->host->hostt->slave_configure(sdev);
907+ ret = sdev->host->hostt->slave_configure(sdev);
908 if (ret) {
909 /*
910 * if LLDD reports slave not present, don't clutter
911@@ -994,7 +1006,7 @@ static int scsi_probe_and_add_lun(struct
912 */
913 sdev = scsi_device_lookup_by_target(starget, lun);
914 if (sdev) {
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
921 kfree(lun_data);
922 out:
923 scsi_device_put(sdev);
924- if (sdev->sdev_state == SDEV_CREATED)
925+ if (scsi_device_created(sdev))
926 /*
927 * the sdev we used didn't appear in the report luns scan
928 */
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" },
936 };
937
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
941@@ -40,31 +40,7 @@
942
943 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
944 static void fc_vport_sched_delete(struct work_struct *work);
945-
946-/*
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.
949- *
950- * fc_vport_identifiers: This set of data contains all elements
951- * to uniquely identify and instantiate a FC virtual port.
952- *
953- * Notes:
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
958- * this field.
959- */
960-struct fc_vport_identifiers {
961- u64 node_name;
962- u64 port_name;
963- u32 roles;
964- bool disable;
965- enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
966- char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
967-};
968-
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);
973
974@@ -1760,7 +1736,7 @@ store_fc_host_vport_create(struct device
975 vid.disable = false; /* always enabled */
976
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;
981 }
982 static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
983@@ -3103,7 +3079,7 @@ fc_scsi_scan_rport(struct work_struct *w
984
985
986 /**
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.
994 */
995 static int
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)
999 {
1000 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1001@@ -3231,6 +3207,28 @@ delete_vport:
1002 return error;
1003 }
1004
1005+/**
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.
1011+ *
1012+ * Notes:
1013+ * This routine assumes no locks are held on entry.
1014+ */
1015+struct fc_vport *
1016+fc_vport_create(struct Scsi_Host *shost, int channel,
1017+ struct fc_vport_identifiers *ids)
1018+{
1019+ int stat;
1020+ struct fc_vport *vport;
1021+
1022+ stat = fc_vport_setup(shost, channel, &shost->shost_gendev,
1023+ ids, &vport);
1024+ return stat ? NULL : vport;
1025+}
1026+EXPORT_SYMBOL(fc_vport_create);
1027
1028 /**
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
1032@@ -47,6 +47,7 @@
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>
1038
1039 #include <scsi/scsi.h>
1040@@ -1436,27 +1437,21 @@ got_data:
1041 */
1042 sector_size = 512;
1043 }
1044+ blk_queue_hardsect_size(sdp->request_queue, sector_size);
1045+
1046 {
1047- /*
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)
1051- */
1052- int hard_sector = sector_size;
1053- sector_t sz = (sdkp->capacity/2) * (hard_sector/256);
1054- struct request_queue *queue = sdp->request_queue;
1055- sector_t mb = sz;
1056-
1057- blk_queue_hardsect_size(queue, hard_sector);
1058- /* avoid 64-bit division on 32-bit platforms */
1059- sector_div(sz, 625);
1060- mb -= sz - 974;
1061- sector_div(mb, 1950);
1062+ char cap_str_2[10], cap_str_10[10];
1063+ u64 sz = sdkp->capacity << ffz(~sector_size);
1064+
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));
1069
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);
1076 }
1077
1078 /* Rescale capacity to 512-byte units */
1079--- /dev/null
1080+++ b/include/linux/string_helpers.h
1081@@ -0,0 +1,16 @@
1082+#ifndef _LINUX_STRING_HELPERS_H_
1083+#define _LINUX_STRING_HELPERS_H_
1084+
1085+#include <linux/types.h>
1086+
1087+/* Descriptions of the types of units to
1088+ * print in */
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 */
1092+};
1093+
1094+int string_get_size(u64 size, enum string_size_units units,
1095+ char *buf, int len);
1096+
1097+#endif
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
1103 * user request */
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
1110+ * lld. */
1111+ SDEV_CREATED_BLOCK, /* same as above but for created devices */
1112 };
1113
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)
1118
1119+/*
1120+ * checks for positions of the SCSI state machine
1121+ */
1122 static inline int scsi_device_online(struct scsi_device *sdev)
1123 {
1124 return sdev->sdev_state != SDEV_OFFLINE;
1125 }
1126+static inline int scsi_device_blocked(struct scsi_device *sdev)
1127+{
1128+ return sdev->sdev_state == SDEV_BLOCK ||
1129+ sdev->sdev_state == SDEV_CREATED_BLOCK;
1130+}
1131+static inline int scsi_device_created(struct scsi_device *sdev)
1132+{
1133+ return sdev->sdev_state == SDEV_CREATED ||
1134+ sdev->sdev_state == SDEV_CREATED_BLOCK;
1135+}
1136
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
1141@@ -22,6 +22,9 @@
1142 #ifndef SCSI_NETLINK_H
1143 #define SCSI_NETLINK_H
1144
1145+#include <linux/netlink.h>
1146+
1147+
1148 /*
1149 * This file intended to be included by both kernel and user space
1150 */
1151@@ -55,7 +58,41 @@ struct scsi_nl_hdr {
1152 #define SCSI_NL_TRANSPORT_FC 1
1153 #define SCSI_NL_MAX_TRANSPORTS 2
1154
1155-/* scsi_nl_hdr->msgtype values are defined in each transport */
1156+/* Transport-based scsi_nl_hdr->msgtype values are defined in each transport */
1157+
1158+/*
1159+ * GENERIC SCSI scsi_nl_hdr->msgtype Values
1160+ */
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 */
1165+
1166+
1167+/*
1168+ * Message Structures :
1169+ */
1170+
1171+/* macro to round up message lengths to 8byte boundary */
1172+#define SCSI_NL_MSGALIGN(len) (((len) + 7) & ~7)
1173+
1174+
1175+/*
1176+ * SCSI HOST Vendor Unique messages :
1177+ * SCSI_NL_SHOST_VENDOR
1178+ *
1179+ * Note: The Vendor Unique message payload will begin directly after
1180+ * this structure, with the length of the payload per vmsg_datalen.
1181+ *
1182+ * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
1183+ * formatting requirements specified below
1184+ */
1185+struct scsi_nl_host_vendor_msg {
1186+ struct scsi_nl_hdr snlh; /* must be 1st element ! */
1187+ uint64_t vendor_id;
1188+ uint16_t host_no;
1189+ uint16_t vmsg_datalen;
1190+} __attribute__((aligned(sizeof(uint64_t))));
1191
1192
1193 /*
1194@@ -83,5 +120,28 @@ struct scsi_nl_hdr {
1195 }
1196
1197
1198+#ifdef __KERNEL__
1199+
1200+#include <scsi/scsi_host.h>
1201+
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);
1207+
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);
1214+
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);
1218+
1219+#endif /* __KERNEL__ */
1220+
1221 #endif /* SCSI_NETLINK_H */
1222
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)
1228
1229+/*
1230+ * fc_vport_identifiers: This set of data contains all elements
1231+ * to uniquely identify and instantiate a FC virtual port.
1232+ *
1233+ * Notes:
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
1238+ * this field.
1239+ */
1240+#define FC_VPORT_SYMBOLIC_NAMELEN 64
1241+struct fc_vport_identifiers {
1242+ u64 node_name;
1243+ u64 port_name;
1244+ u32 roles;
1245+ bool disable;
1246+ enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
1247+ char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
1248+};
1249
1250 /*
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.
1254 */
1255
1256-#define FC_VPORT_SYMBOLIC_NAMELEN 64
1257 struct fc_vport {
1258 /* Fixed Attributes */
1259
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
1263 */
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);
1267
1268 #endif /* SCSI_TRANSPORT_FC_H */
1269--- a/lib/Makefile
1270+++ b/lib/Makefile
1271@@ -19,7 +19,8 @@ lib-$(CONFIG_SMP) += cpumask.o
1272 lib-y += kobject.o kref.o klist.o
1273
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 \
1277+ string_helpers.o
1278
1279 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
1280 CFLAGS_kobject.o += -DDEBUG
1281--- /dev/null
1282+++ b/lib/string_helpers.c
1283@@ -0,0 +1,64 @@
1284+/*
1285+ * Helpers for formatting and printing strings
1286+ *
1287+ * Copyright 31 August 2008 James Bottomley
1288+ */
1289+#include <linux/kernel.h>
1290+#include <linux/math64.h>
1291+#include <linux/module.h>
1292+#include <linux/string_helpers.h>
1293+
1294+/**
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
1300+ *
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.
1304+ *
1305+ */
1306+int string_get_size(u64 size, const enum string_size_units units,
1307+ char *buf, int len)
1308+{
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,
1316+ };
1317+ const int divisor[] = {
1318+ [STRING_UNITS_10] = 1000,
1319+ [STRING_UNITS_2] = 1024,
1320+ };
1321+ int i, j;
1322+ u64 remainder = 0, sf_cap;
1323+ char tmp[8];
1324+
1325+ tmp[0] = '\0';
1326+
1327+ for (i = 0; size > divisor[units] && units_str[units][i]; i++)
1328+ remainder = do_div(size, divisor[units]);
1329+
1330+ sf_cap = size;
1331+ for (j = 0; sf_cap*10 < 1000; j++)
1332+ sf_cap *= 10;
1333+
1334+ if (j) {
1335+ remainder *= 1000;
1336+ do_div(remainder, divisor[units]);
1337+ snprintf(tmp, sizeof(tmp), ".%03lld",
1338+ (unsigned long long)remainder);
1339+ tmp[j+1] = '\0';
1340+ }
1341+
1342+ snprintf(buf, len, "%lld%s%s", (unsigned long long)size,
1343+ tmp, units_str[units][i]);
1344+
1345+ return 0;
1346+}
1347+EXPORT_SYMBOL(string_get_size);