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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
"Four reasonably small fixes to the core for scsi host allocation
failure paths.

The root problem is that we're not freeing the memory allocated by
dev_set_name(), which involves a rejig of may of the free on error
paths to do put_device() instead of kfree which, in turn, has several
other knock on ramifications and inspection turned up a few other
lurking bugs"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
scsi: core: Only put parent device if host state differs from SHOST_CREATED
scsi: core: Put .shost_dev in failure path if host state changes to RUNNING
scsi: core: Fix failure handling of scsi_add_host_with_dma()
scsi: core: Fix error handling of scsi_host_alloc()

+26 -21
+26 -21
drivers/scsi/hosts.c
··· 254 254 255 255 device_enable_async_suspend(&shost->shost_dev); 256 256 257 + get_device(&shost->shost_gendev); 257 258 error = device_add(&shost->shost_dev); 258 259 if (error) 259 260 goto out_del_gendev; 260 - 261 - get_device(&shost->shost_gendev); 262 261 263 262 if (shost->transportt->host_size) { 264 263 shost->shost_data = kzalloc(shost->transportt->host_size, ··· 277 278 278 279 if (!shost->work_q) { 279 280 error = -EINVAL; 280 - goto out_free_shost_data; 281 + goto out_del_dev; 281 282 } 282 283 } 283 284 284 285 error = scsi_sysfs_add_host(shost); 285 286 if (error) 286 - goto out_destroy_host; 287 + goto out_del_dev; 287 288 288 289 scsi_proc_host_add(shost); 289 290 scsi_autopm_put_host(shost); 290 291 return error; 291 292 292 - out_destroy_host: 293 - if (shost->work_q) 294 - destroy_workqueue(shost->work_q); 295 - out_free_shost_data: 296 - kfree(shost->shost_data); 293 + /* 294 + * Any host allocation in this function will be freed in 295 + * scsi_host_dev_release(). 296 + */ 297 297 out_del_dev: 298 298 device_del(&shost->shost_dev); 299 299 out_del_gendev: 300 + /* 301 + * Host state is SHOST_RUNNING so we have to explicitly release 302 + * ->shost_dev. 303 + */ 304 + put_device(&shost->shost_dev); 300 305 device_del(&shost->shost_gendev); 301 306 out_disable_runtime_pm: 302 307 device_disable_async_suspend(&shost->shost_gendev); 303 308 pm_runtime_disable(&shost->shost_gendev); 304 309 pm_runtime_set_suspended(&shost->shost_gendev); 305 310 pm_runtime_put_noidle(&shost->shost_gendev); 306 - scsi_mq_destroy_tags(shost); 307 311 fail: 308 312 return error; 309 313 } ··· 347 345 348 346 ida_simple_remove(&host_index_ida, shost->host_no); 349 347 350 - if (parent) 348 + if (shost->shost_state != SHOST_CREATED) 351 349 put_device(parent); 352 350 kfree(shost); 353 351 } ··· 390 388 mutex_init(&shost->scan_mutex); 391 389 392 390 index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL); 393 - if (index < 0) 394 - goto fail_kfree; 391 + if (index < 0) { 392 + kfree(shost); 393 + return NULL; 394 + } 395 395 shost->host_no = index; 396 396 397 397 shost->dma_channel = 0xff; ··· 485 481 shost_printk(KERN_WARNING, shost, 486 482 "error handler thread failed to spawn, error = %ld\n", 487 483 PTR_ERR(shost->ehandler)); 488 - goto fail_index_remove; 484 + goto fail; 489 485 } 490 486 491 487 shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d", ··· 494 490 if (!shost->tmf_work_q) { 495 491 shost_printk(KERN_WARNING, shost, 496 492 "failed to create tmf workq\n"); 497 - goto fail_kthread; 493 + goto fail; 498 494 } 499 495 scsi_proc_hostdir_add(shost->hostt); 500 496 return shost; 497 + fail: 498 + /* 499 + * Host state is still SHOST_CREATED and that is enough to release 500 + * ->shost_gendev. scsi_host_dev_release() will free 501 + * dev_name(&shost->shost_dev). 502 + */ 503 + put_device(&shost->shost_gendev); 501 504 502 - fail_kthread: 503 - kthread_stop(shost->ehandler); 504 - fail_index_remove: 505 - ida_simple_remove(&host_index_ida, shost->host_no); 506 - fail_kfree: 507 - kfree(shost); 508 505 return NULL; 509 506 } 510 507 EXPORT_SYMBOL(scsi_host_alloc);