Commit 865e9146 authored by Christoph Hellwig's avatar Christoph Hellwig

[PATCH] cleanup code for /proc add/remove single device

two new helpers in scsi_scan.c: scsi_add_single_device and
scsi_remove_single_device that do all hard work.  Thanks to
beeing in scsi_scan.c and using proper helpers they're a lot
smaller and cleaner.
parent 64ac28dd
......@@ -521,6 +521,8 @@ static inline void scsi_proc_host_rm(struct Scsi_Host *);
extern struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *,
uint, uint, uint);
extern void scsi_free_sdev(struct scsi_device *);
extern int scsi_add_single_device(uint, uint, uint, uint);
extern int scsi_remove_single_device(uint, uint, uint, uint);
/*
* Prototypes for functions in constants.c
......
......@@ -399,11 +399,8 @@ static void scsi_dump_status(int level)
static int proc_scsi_gen_write(struct file * file, const char * buf,
unsigned long length, void *data)
{
Scsi_Device *sdev;
struct Scsi_Host *shost;
char *p;
int host, channel, id, lun;
char * buffer;
char *buffer, *p;
int err;
if (!buf || length>PAGE_SIZE)
......@@ -529,35 +526,9 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
id = simple_strtoul(p + 1, &p, 0);
lun = simple_strtoul(p + 1, &p, 0);
printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel,
id, lun);
for (shost = scsi_host_get_next(NULL); shost;
shost = scsi_host_get_next(shost)) {
if (shost->host_no == host) {
break;
}
}
err = -ENXIO;
if (!shost)
goto out;
for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
if ((sdev->channel == channel
&& sdev->id == id
&& sdev->lun == lun)) {
break;
}
}
err = -ENOSYS;
if (sdev)
goto out; /* We do not yet support unplugging */
scan_scsis(shost, 1, channel, id, lun);
err = scsi_add_single_device(host, channel, id, lun);
if (err >= 0)
err = length;
goto out;
}
/*
* Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
* with "0 1 2 3" replaced by your "Host Channel Id Lun".
......@@ -569,7 +540,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
* hardware and thoroughly confuse the SCSI subsystem.
*
*/
else if (!strncmp("remove-single-device", buffer + 5, 20)) {
} else if (!strncmp("remove-single-device", buffer + 5, 20)) {
p = buffer + 26;
host = simple_strtoul(p, &p, 0);
......@@ -577,39 +548,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
id = simple_strtoul(p + 1, &p, 0);
lun = simple_strtoul(p + 1, &p, 0);
for (shost = scsi_host_get_next(NULL); shost;
shost = scsi_host_get_next(shost)) {
if (shost->host_no == host) {
break;
}
}
err = -ENODEV;
if (!shost)
goto out;
for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
if ((sdev->channel == channel
&& sdev->id == id
&& sdev->lun == lun)) {
break;
}
}
if (sdev == NULL)
goto out; /* there is no such device attached */
err = -EBUSY;
if (sdev->access_count)
goto out;
scsi_detach_device(sdev);
if (sdev->attached == 0) {
devfs_unregister (sdev->de);
scsi_free_sdev(sdev);
err = 0;
}
err = scsi_remove_single_device(host, channel, id, lun);
}
out:
......
......@@ -1862,6 +1862,69 @@ static int scsi_report_lun_scan(Scsi_Device *sdevscan)
}
int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
{
struct scsi_device *sdevscan, *sdev;
struct Scsi_Host *shost;
int error = -ENODEV;
shost = scsi_host_hn_get(host);
if (!shost)
return -ENODEV;
sdev = scsi_find_device(shost, channel, id, lun);
if (!sdev)
goto out;
error = -ENOMEM;
sdevscan = scsi_alloc_sdev(shost, channel, id, lun);
if (!sdevscan)
goto out;
sdevscan->scsi_level = scsi_find_scsi_level(channel, id, shost);
error = scsi_probe_and_add_lun(sdevscan, &sdev, NULL);
scsi_free_sdev(sdevscan);
error = -ENODEV;
if (error != SCSI_SCAN_LUN_PRESENT)
goto out;
scsi_attach_device(sdev);
error = 0;
out:
scsi_host_put(shost);
return error;
}
int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
{
struct scsi_device *sdev;
struct Scsi_Host *shost;
int error = -ENODEV;
shost = scsi_host_hn_get(host);
if (!shost)
return -ENODEV;
sdev = scsi_find_device(shost, channel, id, lun);
if (!sdev)
goto out;
error = -EBUSY;
if (sdev->access_count)
goto out;
scsi_detach_device(sdev);
if (sdev->attached)
goto out;
devfs_unregister(sdev->de);
scsi_free_sdev(sdev);
error = 0;
out:
scsi_host_put(shost);
return error;
}
/**
* scsi_scan_target - scan a target id, possibly including all LUNs on the
* target.
......
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