--- linux/drivers/block/scsi_ioctl.c 2003-05-31 13:50:04.000000000 +1000 +++ linux/drivers/block/scsi_ioctl.c2570dpg2 2003-05-31 14:13:15.000000000 +1000 @@ -82,7 +82,7 @@ static int sg_get_version(int *p) { - static int sg_version_num = 30527; + static int sg_version_num = 30729; /* version 3.7.* to distinguish */ return put_user(sg_version_num, p); } @@ -143,7 +143,7 @@ struct sg_io_hdr *uptr) { unsigned long start_time; - int reading, writing; + int reading, writing, dio; struct sg_io_hdr hdr; struct request *rq; struct bio *bio; @@ -163,11 +163,14 @@ */ if (hdr.iovec_count) return -EOPNOTSUPP; + if (hdr.flags & SG_FLAG_MMAP_IO) + return -EOPNOTSUPP; if (hdr.dxfer_len > (q->max_sectors << 9)) return -EIO; reading = writing = 0; + dio = 0; buffer = NULL; bio = NULL; if (hdr.dxfer_len) { @@ -194,10 +197,12 @@ bio = bio_map_user(bdev, (unsigned long) hdr.dxferp, hdr.dxfer_len, reading); - /* - * if bio setup failed, fall back to slow approach - */ - if (!bio) { + if (bio) + dio = 1; + else { + /* + * if bio setup failed, fall back to slow approach + */ buffer = kmalloc(bytes, q->bounce_gfp | GFP_USER); if (!buffer) return -ENOMEM; @@ -206,8 +211,11 @@ if (copy_from_user(buffer, hdr.dxferp, hdr.dxfer_len)) goto out_buffer; + if (bytes > hdr.dxfer_len) + memset((char *)buffer + hdr.dxfer_len, + 0, bytes - hdr.dxfer_len); } else - memset(buffer, 0, hdr.dxfer_len); + memset(buffer, 0, bytes); } } @@ -257,11 +265,13 @@ hdr.status = rq->errors; hdr.masked_status = (hdr.status >> 1) & 0x1f; hdr.msg_status = 0; - hdr.host_status = 0; + hdr.host_status = 0; /* "lost nexus" error could go here */ hdr.driver_status = 0; hdr.info = 0; if (hdr.masked_status || hdr.host_status || hdr.driver_status) hdr.info |= SG_INFO_CHECK; + if (dio && (hdr.flags & SG_FLAG_DIRECT_IO)) + hdr.info |= SG_INFO_DIRECT_IO; hdr.resid = rq->data_len; hdr.duration = ((jiffies - start_time) * 1000) / HZ; hdr.sb_len_wr = 0; @@ -286,7 +296,7 @@ kfree(buffer); } - /* may not have succeeded, but output values written to control + /* may not have succeeded, but output status written to control * structure (struct sg_io_hdr). */ return 0; out_request: