Commit a17430ad authored by Christoph Hellwig's avatar Christoph Hellwig

[PATCH] rationalize allocation and freeing of struct scsi_device

Currently allocation and freeing of struct scsi_device is a mess.
We have two nice functions in scsi_scan.c (scsi_allocate_sdev/
scsi_free_sdev) that are the right interfaces to deal with it, so I moved
them to scsi and made them non-static.  I've changed all functions
allocation freeing them to use it.
parent 3e880ac5
...@@ -669,6 +669,67 @@ void __init scsi_host_init(void) ...@@ -669,6 +669,67 @@ void __init scsi_host_init(void)
} }
} }
/*
* Function: scsi_get_host_dev()
*
* Purpose: Create a Scsi_Device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: The Scsi_Device or NULL
*
* Notes:
* Attach a single Scsi_Device to the Scsi_Host - this should
* be made to look like a "pseudo-device" that points to the
* HA itself. For the moment, we include it at the head of
* the host_queue itself - I don't think we want to show this
* to the HA in select_queue_depths(), as this would probably confuse
* matters.
*
* Note - this device is not accessible from any high-level
* drivers (including generics), which is probably not
* optimal. We can add hooks later to attach
*/
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0);
if (sdev) {
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
goto fail;
sdev->borken = 0;
}
return sdev;
fail:
kfree(sdev);
return NULL;
}
/*
* Function: scsi_free_host_dev()
*
* Purpose: Free a scsi_device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: Nothing
*
* Notes:
*/
void scsi_free_host_dev(struct scsi_device *sdev)
{
BUG_ON(sdev->id != sdev->host->this_id);
scsi_free_sdev(sdev);
}
void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev) void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev)
{ {
unsigned long flags; unsigned long flags;
......
...@@ -155,7 +155,6 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = ...@@ -155,7 +155,6 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
"Enclosure ", "Enclosure ",
}; };
static char * scsi_null_device_strs = "nullnullnullnull";
static const char * const spaces = " "; /* 16 of them */ static const char * const spaces = " "; /* 16 of them */
static unsigned scsi_default_dev_flags; static unsigned scsi_default_dev_flags;
...@@ -2251,95 +2250,3 @@ static void __exit exit_scsi(void) ...@@ -2251,95 +2250,3 @@ static void __exit exit_scsi(void)
module_init(init_scsi); module_init(init_scsi);
module_exit(exit_scsi); module_exit(exit_scsi);
/*
* Function: scsi_get_host_dev()
*
* Purpose: Create a Scsi_Device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: The Scsi_Device or NULL
*
* Notes:
*/
Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt)
{
Scsi_Device * SDpnt;
/*
* Attach a single Scsi_Device to the Scsi_Host - this should
* be made to look like a "pseudo-device" that points to the
* HA itself. For the moment, we include it at the head of
* the host_queue itself - I don't think we want to show this
* to the HA in select_queue_depths(), as this would probably confuse
* matters.
* Note - this device is not accessible from any high-level
* drivers (including generics), which is probably not
* optimal. We can add hooks later to attach
*/
SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device),
GFP_ATOMIC);
if(SDpnt == NULL)
return NULL;
memset(SDpnt, 0, sizeof(Scsi_Device));
SDpnt->vendor = scsi_null_device_strs;
SDpnt->model = scsi_null_device_strs;
SDpnt->rev = scsi_null_device_strs;
SDpnt->host = SHpnt;
SDpnt->id = SHpnt->this_id;
SDpnt->type = -1;
SDpnt->new_queue_depth = 1;
scsi_build_commandblocks(SDpnt);
if(SDpnt->current_queue_depth == 0) {
kfree(SDpnt);
return NULL;
}
scsi_initialize_queue(SDpnt, SHpnt);
SDpnt->online = TRUE;
/*
* Initialize the object that we will use to wait for command blocks.
*/
init_waitqueue_head(&SDpnt->scpnt_wait);
return SDpnt;
}
/*
* Function: scsi_free_host_dev()
*
* Purpose: Create a Scsi_Device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: Nothing
*
* Notes:
*/
void scsi_free_host_dev(Scsi_Device * SDpnt)
{
if( (unsigned char) SDpnt->id != (unsigned char) SDpnt->host->this_id )
{
panic("Attempt to delete wrong device\n");
}
blk_cleanup_queue(&SDpnt->request_queue);
/*
* We only have a single SCpnt attached to this device. Free
* it now.
*/
scsi_release_commandblocks(SDpnt);
if (SDpnt->inquiry)
kfree(SDpnt->inquiry);
kfree(SDpnt);
}
...@@ -519,6 +519,13 @@ static inline void scsi_proc_host_add(struct Scsi_Host *); ...@@ -519,6 +519,13 @@ static inline void scsi_proc_host_add(struct Scsi_Host *);
static inline void scsi_proc_host_rm(struct Scsi_Host *); static inline void scsi_proc_host_rm(struct Scsi_Host *);
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
/*
* Prototypes for functions in scsi_scan.c
*/
extern struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *,
uint, uint, uint);
extern void scsi_free_sdev(struct scsi_device *);
/* /*
* Prototypes for functions in constants.c * Prototypes for functions in constants.c
* Some of these used to live in constants.h * Some of these used to live in constants.h
......
...@@ -607,26 +607,10 @@ static int proc_scsi_gen_write(struct file * file, const char * buf, ...@@ -607,26 +607,10 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
if (sdev->attached == 0) { if (sdev->attached == 0) {
devfs_unregister (sdev->de); devfs_unregister (sdev->de);
scsi_free_sdev(sdev);
/* Now we can remove the device structure */
if (sdev->next != NULL)
sdev->next->prev = sdev->prev;
if (sdev->prev != NULL)
sdev->prev->next = sdev->next;
if (shost->host_queue == sdev) {
shost->host_queue = sdev->next;
}
blk_cleanup_queue(&sdev->request_queue);
if (sdev->inquiry)
kfree(sdev->inquiry);
kfree((char *) sdev);
} else {
goto out;
}
err = 0; err = 0;
} }
}
out: out:
free_page((unsigned long)buffer); free_page((unsigned long)buffer);
......
...@@ -465,12 +465,12 @@ static void scsi_initialize_merge_fn(struct scsi_device *sd) ...@@ -465,12 +465,12 @@ static void scsi_initialize_merge_fn(struct scsi_device *sd)
* Return value: * Return value:
* Scsi_Device pointer, or NULL on failure. * Scsi_Device pointer, or NULL on failure.
**/ **/
static Scsi_Device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel,
uint id, uint lun) uint id, uint lun)
{ {
Scsi_Device *sdev; struct scsi_device *sdev;
sdev = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), GFP_ATOMIC); sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC);
if (sdev == NULL) if (sdev == NULL)
printk(ALLOC_FAILURE_MSG, __FUNCTION__); printk(ALLOC_FAILURE_MSG, __FUNCTION__);
else { else {
...@@ -522,7 +522,7 @@ static Scsi_Device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, ...@@ -522,7 +522,7 @@ static Scsi_Device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel,
* Undo the actions in scsi_alloc_sdev, including removing @sdev from * Undo the actions in scsi_alloc_sdev, including removing @sdev from
* the list, and freeing @sdev. * the list, and freeing @sdev.
**/ **/
static void scsi_free_sdev(Scsi_Device *sdev) void scsi_free_sdev(struct scsi_device *sdev)
{ {
if (sdev->prev != NULL) if (sdev->prev != NULL)
sdev->prev->next = sdev->next; sdev->prev->next = sdev->next;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment