From: Douglas Gilbert <dougg@torque.net>
To: linux-scsi@vger.kernel.org
Subject: [PATCH] SG_IO ioctl for block devices
Date: Wed, 04 Dec 2002 23:22:46 +1100 [thread overview]
Message-ID: <3DEDF396.1040600@torque.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 1809 bytes --]
I have been playing around with the SG_IO ioctl() that
recently appeared in drivers/block/scsi_ioctl.c .
First a warning: using sg's write()/read() interface is
a dangerous thing to do to anything other than an sg device
(especially a disk). The utilities in sg3_utils (and sg_utils)
took the precaution of sending a "sg" ioctl and assumed if
it worked then the file descriptor referred to a sg device.
Now _all_ block devices respond to the ioctl()s I chose :-(
IMO sg's write()/read() interface is still useful for
queuing and high speed applications. However for the
great majority of cases the SG_IO ioctl is sufficient.
It turns out that sg3_utils version 1.01 doesn't scribble
on disks (as outlined above), more by luck than good
management. Several things fail (e.g. sg_logs) that can
easily be fixed while sg_inq and sg_dd work. [sg_dd
works because it treats /dev/sda as a normal file
rather than a sg device.] I will release sg3_utils
version 1.02 shortly.
The error processing of the SG_IO ioctl() is broken as
far as I can determine. My attached patch drives output
values to 0 (their inert values) and rescues the scsi
status value from the scsi_request structure. Notice
the hack in drivers/scsi/scsi_lib.c to stop the
gratuitous clearing of req->errors. The sense buffer
is not conveyed into struct request and there seems to
be no code in scsi_lib.c to do that.
To keep the block SG_IO consistent with sg's version,
I removed the EIO errno conditions. CHECK CONDITION
does not (necessarily) indicate an error. Witness the
code fix around lk 2.4.18 to correctly handle
RECOVERED_ERROR. So a return value of zero implies
that a consistent set of values has been written
back into the sg_io_hdr instance (and the application
best check them).
The patch is against lk 2.5.50bk3
Doug Gilbert
[-- Attachment #2: 2550bk3_blk_sgio.diff --]
[-- Type: text/plain, Size: 2875 bytes --]
--- linux/drivers/block/scsi_ioctl.c 2002-11-29 09:27:35.000000000 +1100
+++ linux/drivers/block/scsi_ioctl.c2550sgio1 2002-12-04 21:14:53.000000000 +1100
@@ -126,7 +126,7 @@
struct sg_io_hdr *uptr)
{
unsigned long uaddr, start_time;
- int err, reading, writing, nr_sectors;
+ int reading, writing, nr_sectors;
struct sg_io_hdr hdr;
struct request *rq;
struct bio *bio;
@@ -265,26 +265,36 @@
start_time = jiffies;
- /*
- * return -EIO if we didn't transfer all data, caller can look at
- * residual count to find out how much did succeed
+ /* ignore return value. All information is passed back to caller
+ * (if he doesn't check that is his problem).
+ * N.B. a non-zero SCSI status is _not_ necessarily an error.
*/
- err = blk_do_rq(q, bdev, rq);
- if (rq->data_len > 0)
- err = -EIO;
+ blk_do_rq(q, bdev, rq);
if (bio) {
bio_unmap_user(bio, reading);
bio_put(bio);
}
- hdr.status = rq->errors;
+ /* write to all output members */
+ hdr.status = rq->errors;
+ hdr.masked_status = (hdr.status >> 1) & 0x1f;
+ hdr.msg_status = 0;
+ hdr.host_status = 0;
+ hdr.driver_status = 0;
+ hdr.info = 0;
+ if (hdr.masked_status || hdr.host_status || hdr.driver_status)
+ hdr.info |= SG_INFO_CHECK;
hdr.resid = rq->data_len;
hdr.duration = (jiffies - start_time) * (1000 / HZ);
+ hdr.sb_len_wr = 0;
if (rq->sense_len && hdr.sbp) {
- if (!copy_to_user(hdr.sbp,rq->sense, rq->sense_len))
- hdr.sb_len_wr = rq->sense_len;
+ int len = (hdr.mx_sb_len < rq->sense_len) ?
+ hdr.mx_sb_len : rq->sense_len;
+
+ if (!copy_to_user(hdr.sbp, rq->sense, len))
+ hdr.sb_len_wr = len;
}
blk_put_request(rq);
@@ -297,8 +307,9 @@
kfree(buffer);
}
-
- return err;
+ /* may not have succeeded, but output values written to control
+ * structure (struct sg_io_hdr). */
+ return 0;
}
#define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ)
--- linux/drivers/scsi/scsi_lib.c 2002-12-04 10:21:16.000000000 +1100
+++ linux/drivers/scsi/scsi_lib.c2550bk3sgio1 2002-12-04 21:14:20.000000000 +1100
@@ -441,6 +441,7 @@
int this_count = SCpnt->bufflen >> 9;
request_queue_t *q = &SCpnt->device->request_queue;
struct request *req = SCpnt->request;
+ int clear_errors = 1;
/*
* We must do one of several things here:
@@ -481,9 +482,12 @@
}
if (blk_pc_request(req)) {
- req->errors = result & 0xff;
+ req->errors = (driver_byte(result) & DRIVER_SENSE) ?
+ (CHECK_CONDITION << 1) : (result & 0xff);
if (!result)
req->data_len -= SCpnt->bufflen;
+ else
+ clear_errors = 0;
}
/*
@@ -504,7 +508,8 @@
req->nr_sectors, good_sectors));
SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n ", SCpnt->use_sg));
- req->errors = 0;
+ if (clear_errors)
+ req->errors = 0;
/*
* If multiple sectors are requested in one buffer, then
* they will have been finished off by the first command.
reply other threads:[~2002-12-04 12:21 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=3DEDF396.1040600@torque.net \
--to=dougg@torque.net \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.