Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: Use ida for host number management

Update the SCSI hosts module to use ida to manage its host_no index
instead of an atomic integer. This means that the SCSI host number will
now be reclaimable.

Use the ida "simple" mechanism, since there should be no need for a
separate spin lock current usage. Ida was chosen over idr because the
hosts module already has its own instance and locking mechanisms that
aren't easily changed.

Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Lee Duncan <lduncan@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Lee Duncan and committed by
Martin K. Petersen
126a4fe0 d92ca9d3

+14 -8
+14 -8
drivers/scsi/hosts.c
··· 33 33 #include <linux/transport_class.h> 34 34 #include <linux/platform_device.h> 35 35 #include <linux/pm_runtime.h> 36 - 36 + #include <linux/idr.h> 37 37 #include <scsi/scsi_device.h> 38 38 #include <scsi/scsi_host.h> 39 39 #include <scsi/scsi_transport.h> ··· 42 42 #include "scsi_logging.h" 43 43 44 44 45 - static atomic_t scsi_host_next_hn = ATOMIC_INIT(0); /* host_no for next new host */ 45 + static DEFINE_IDA(host_index_ida); 46 46 47 47 48 48 static void scsi_host_cls_release(struct device *dev) ··· 355 355 356 356 kfree(shost->shost_data); 357 357 358 + ida_simple_remove(&host_index_ida, shost->host_no); 359 + 358 360 if (parent) 359 361 put_device(parent); 360 362 kfree(shost); ··· 390 388 { 391 389 struct Scsi_Host *shost; 392 390 gfp_t gfp_mask = GFP_KERNEL; 391 + int index; 393 392 394 393 if (sht->unchecked_isa_dma && privsize) 395 394 gfp_mask |= __GFP_DMA; ··· 409 406 init_waitqueue_head(&shost->host_wait); 410 407 mutex_init(&shost->scan_mutex); 411 408 412 - /* 413 - * subtract one because we increment first then return, but we need to 414 - * know what the next host number was before increment 415 - */ 416 - shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1; 409 + index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL); 410 + if (index < 0) 411 + goto fail_kfree; 412 + shost->host_no = index; 413 + 417 414 shost->dma_channel = 0xff; 418 415 419 416 /* These three are default values which can be overridden */ ··· 498 495 shost_printk(KERN_WARNING, shost, 499 496 "error handler thread failed to spawn, error = %ld\n", 500 497 PTR_ERR(shost->ehandler)); 501 - goto fail_kfree; 498 + goto fail_index_remove; 502 499 } 503 500 504 501 shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d", ··· 514 511 515 512 fail_kthread: 516 513 kthread_stop(shost->ehandler); 514 + fail_index_remove: 515 + ida_simple_remove(&host_index_ida, shost->host_no); 517 516 fail_kfree: 518 517 kfree(shost); 519 518 return NULL; ··· 611 606 void scsi_exit_hosts(void) 612 607 { 613 608 class_unregister(&shost_class); 609 + ida_destroy(&host_index_ida); 614 610 } 615 611 616 612 int scsi_is_host_device(const struct device *dev)