From: Christoph Hellwig <hch@lst.de>
To: axboe@suse.de
Cc: linux-scsi@vger.kernel.org
Subject: [RFC] generic scsi ioctls for character devices
Date: Fri, 23 May 2003 10:33:41 +0200 [thread overview]
Message-ID: <20030523103341.A30181@lst.de> (raw)
add a scsi_cmd_ioctl variant that works for character devices that have
a gendisk/queue. It's a bit ugly because the fs/bio.c wants a struct
block_device * for each bio so we have to fake one up. The codepathes
scsi_cmd_ioctl uses only ever looks into it's ->bd_queue though..
--- 1.26/drivers/block/scsi_ioctl.c Wed May 14 12:22:25 2003
+++ edited/drivers/block/scsi_ioctl.c Fri May 16 23:08:01 2003
@@ -45,13 +45,12 @@
#define SCSI_SENSE_BUFFERSIZE 64
#endif
-static int blk_do_rq(request_queue_t *q, struct block_device *bdev,
- struct request *rq)
+static int blk_do_rq(struct gendisk *disk, struct request *rq)
{
DECLARE_COMPLETION(wait);
int err = 0;
- rq->rq_disk = bdev->bd_disk;
+ rq->rq_disk = disk;
/*
* we need an extra reference to the request, so we can look at
@@ -62,8 +61,8 @@
rq->flags |= REQ_NOMERGE;
rq->waiting = &wait;
drive_stat_acct(rq, rq->nr_sectors, 1);
- elv_add_request(q, rq, 1, 1);
- generic_unplug_device(q);
+ elv_add_request(disk->queue, rq, 1, 1);
+ generic_unplug_device(disk->queue);
wait_for_completion(&wait);
if (rq->errors)
@@ -80,12 +79,12 @@
return put_user(sg_version_num, p);
}
-static int scsi_get_idlun(request_queue_t *q, int *p)
+static int scsi_get_idlun(int *p)
{
return put_user(0, p);
}
-static int scsi_get_bus(request_queue_t *q, int *p)
+static int scsi_get_bus(int *p)
{
return put_user(0, p);
}
@@ -124,14 +123,15 @@
* will always return that we are ATAPI even for a real SCSI drive, I'm not
* so sure this is worth doing anything about (why would you care??)
*/
-static int sg_emulated_host(request_queue_t *q, int *p)
+static int sg_emulated_host(int *p)
{
return put_user(1, p);
}
-static int sg_io(request_queue_t *q, struct block_device *bdev,
- struct sg_io_hdr *uptr)
+static int sg_io(struct gendisk *disk, struct sg_io_hdr *uptr,
+ struct block_device *bdev)
{
+ struct request_queue *q = disk->queue;
unsigned long uaddr, start_time;
int reading, writing, nr_sectors;
struct sg_io_hdr hdr;
@@ -251,7 +251,7 @@
* (if he doesn't check that is his problem).
* N.B. a non-zero SCSI status is _not_ necessarily an error.
*/
- blk_do_rq(q, bdev, rq);
+ blk_do_rq(disk, rq);
if (bio)
bio_unmap_user(bio, reading);
@@ -299,8 +299,7 @@
#define READ_DEFECT_DATA_TIMEOUT (60 * HZ )
#define OMAX_SB_LEN 16 /* For backward compatibility */
-static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
- Scsi_Ioctl_Command *sic)
+static int sg_scsi_ioctl(struct gendisk *disk, struct scsi_ioctl_command *sic)
{
struct request *rq;
int err, in_len, out_len, bytes, opcode, cmdlen;
@@ -320,14 +319,14 @@
bytes = max(in_len, out_len);
if (bytes) {
- buffer = kmalloc(bytes, q->bounce_gfp | GFP_USER);
+ buffer = kmalloc(bytes, disk->queue->bounce_gfp | GFP_USER);
if (!buffer)
return -ENOMEM;
memset(buffer, 0, bytes);
}
- rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT);
+ rq = blk_get_request(disk->queue, in_len ? WRITE : READ, __GFP_WAIT);
cmdlen = COMMAND_SIZE(opcode);
@@ -372,7 +371,7 @@
rq->data_len = bytes;
rq->flags |= REQ_BLOCK_PC;
- blk_do_rq(q, bdev, rq);
+ blk_do_rq(disk, rq);
err = rq->errors & 0xff; /* only 8 bit SCSI status */
if (err) {
if (rq->sense_len && rq->sense) {
@@ -392,77 +391,98 @@
return err;
}
-int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
+static int tray_ioctl(struct gendisk *disk, int close)
{
- request_queue_t *q;
- struct request *rq;
- int close = 0, err;
+ struct request *rq = blk_get_request(disk->queue, WRITE, __GFP_WAIT);
+ int error;
+
+ rq->flags = REQ_BLOCK_PC;
+ rq->data = NULL;
+ rq->data_len = 0;
+ rq->timeout = BLK_DEFAULT_TIMEOUT;
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->cmd[0] = GPCMD_START_STOP_UNIT;
+ rq->cmd[4] = 0x02 + (close != 0);
+ rq->cmd_len = 6;
+ error = blk_do_rq(disk, rq);
+ blk_put_request(rq);
+
+ return error;
+}
- q = bdev_get_queue(bdev);
- if (!q)
- return -ENXIO;
+static int __scsi_cmd_ioctl(struct block_device *bdev,
+ unsigned int cmd, unsigned long arg)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ struct request_queue *q = disk->queue;
switch (cmd) {
- /*
- * new sgv3 interface
- */
- case SG_GET_VERSION_NUM:
- return sg_get_version((int *) arg);
- case SCSI_IOCTL_GET_IDLUN:
- return scsi_get_idlun(q, (int *) arg);
- case SCSI_IOCTL_GET_BUS_NUMBER:
- return scsi_get_bus(q, (int *) arg);
- case SG_SET_TIMEOUT:
- return sg_set_timeout(q, (int *) arg);
- case SG_GET_TIMEOUT:
- return sg_get_timeout(q);
- case SG_GET_RESERVED_SIZE:
- return sg_get_reserved_size(q, (int *) arg);
- case SG_SET_RESERVED_SIZE:
- return sg_set_reserved_size(q, (int *) arg);
- case SG_EMULATED_HOST:
- return sg_emulated_host(q, (int *) arg);
- case SG_IO:
- err = bd_claim(bdev, current);
- if (err)
- break;
- err = sg_io(q, bdev, (struct sg_io_hdr *) arg);
- bd_release(bdev);
- break;
- /*
- * old junk scsi send command ioctl
- */
- case SCSI_IOCTL_SEND_COMMAND:
- if (!arg)
- return -EINVAL;
-
- err = bd_claim(bdev, current);
- if (err)
- break;
- err = sg_scsi_ioctl(q, bdev, (Scsi_Ioctl_Command *)arg);
+ /*
+ * new sgv3 interface
+ */
+ case SG_GET_VERSION_NUM:
+ return sg_get_version((int *) arg);
+ case SCSI_IOCTL_GET_IDLUN:
+ return scsi_get_idlun((int *) arg);
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ return scsi_get_bus((int *) arg);
+ case SG_SET_TIMEOUT:
+ return sg_set_timeout(q, (int *) arg);
+ case SG_GET_TIMEOUT:
+ return sg_get_timeout(q);
+ case SG_GET_RESERVED_SIZE:
+ return sg_get_reserved_size(q, (int *) arg);
+ case SG_SET_RESERVED_SIZE:
+ return sg_set_reserved_size(q, (int *) arg);
+ case SG_EMULATED_HOST:
+ return sg_emulated_host((int *) arg);
+ case SG_IO:
+ return sg_io(disk, (struct sg_io_hdr *)arg, bdev);
+ /*
+ * old junk scsi send command ioctl
+ */
+ case SCSI_IOCTL_SEND_COMMAND:
+ return sg_scsi_ioctl(disk, (struct scsi_ioctl_command *)arg);
+ /*
+ * CDROM ioctls.
+ */
+ case CDROMCLOSETRAY:
+ return tray_ioctl(disk, 1);
+ case CDROMEJECT:
+ return tray_ioctl(disk, 0);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
+{
+ int error;
+
+ switch (cmd) {
+ case SG_IO:
+ case SCSI_IOCTL_SEND_COMMAND:
+ error = bd_claim(bdev, current);
+ if (!error) {
+ error = __scsi_cmd_ioctl(bdev, cmd, arg);
bd_release(bdev);
- break;
- case CDROMCLOSETRAY:
- close = 1;
- case CDROMEJECT:
- rq = blk_get_request(q, WRITE, __GFP_WAIT);
- rq->flags = REQ_BLOCK_PC;
- rq->data = NULL;
- rq->data_len = 0;
- rq->timeout = BLK_DEFAULT_TIMEOUT;
- memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->cmd[0] = GPCMD_START_STOP_UNIT;
- rq->cmd[4] = 0x02 + (close != 0);
- rq->cmd_len = 6;
- err = blk_do_rq(q, bdev, rq);
- blk_put_request(rq);
- break;
- default:
- err = -ENOTTY;
+ }
+
+ return error;
}
- blk_put_queue(q);
- return err;
+ return __scsi_cmd_ioctl(bdev, cmd, arg);
+}
+
+int scsi_cmd_ioctl_chrdev(struct gendisk *disk, unsigned int cmd, unsigned long arg)
+{
+ struct block_device fake_bdev;
+
+ memset(&fake_bdev, 0x0e, sizeof(fake_bdev));
+ fake_bdev.bd_disk = disk;
+
+ return __scsi_cmd_ioctl(&fake_bdev, cmd, arg);
}
EXPORT_SYMBOL(scsi_cmd_ioctl);
reply other threads:[~2003-05-23 8:20 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20030523103341.A30181@lst.de \
--to=hch@lst.de \
--cc=axboe@suse.de \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox