aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-03-22 11:52:04 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-04-13 11:13:15 -0400
commit21b2f0c803adaf00fce1b606c50b49ae8b106773 (patch)
tree1acc834df309041ed0c5681f4bd222fd3e113900
parent765fcab23d0a79ed7aab8da79766f5873d936f1b (diff)
[SCSI] unify SCSI_IOCTL_SEND_COMMAND implementations
We currently have two implementations of this obsolete ioctl, one in the block layer and one in the scsi code. Both of them have drawbacks. This patch kills the scsi layer version after updating the block version with the missing bits: - argument checking - use scatterlist I/O - set number of retries based on the submitted command This is the last user of non-S/G I/O except for the gdth driver, so getting this in ASAP and through the scsi tree would be nie to kill the non-S/G I/O path. Jens, what do you think about adding a check for non-S/G I/O in the midlayer? Thanks to Or Gerlitz for testing this patch. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--block/scsi_ioctl.c101
-rw-r--r--drivers/scsi/scsi_ioctl.c176
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--include/linux/blkdev.h4
-rw-r--r--include/scsi/scsi_ioctl.h2
5 files changed, 78 insertions, 207 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 24f7af9d0abc..b33eda26e205 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -350,16 +350,51 @@ out:
350 return ret; 350 return ret;
351} 351}
352 352
353/**
354 * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
355 * @file: file this ioctl operates on (optional)
356 * @q: request queue to send scsi commands down
357 * @disk: gendisk to operate on (option)
358 * @sic: userspace structure describing the command to perform
359 *
360 * Send down the scsi command described by @sic to the device below
361 * the request queue @q. If @file is non-NULL it's used to perform
362 * fine-grained permission checks that allow users to send down
363 * non-destructive SCSI commands. If the caller has a struct gendisk
364 * available it should be passed in as @disk to allow the low level
365 * driver to use the information contained in it. A non-NULL @disk
366 * is only allowed if the caller knows that the low level driver doesn't
367 * need it (e.g. in the scsi subsystem).
368 *
369 * Notes:
370 * - This interface is deprecated - users should use the SG_IO
371 * interface instead, as this is a more flexible approach to
372 * performing SCSI commands on a device.
373 * - The SCSI command length is determined by examining the 1st byte
374 * of the given command. There is no way to override this.
375 * - Data transfers are limited to PAGE_SIZE
376 * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
377 * accommodate the sense buffer when an error occurs.
378 * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
379 * old code will not be surprised.
380 * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
381 * a negative return and the Unix error code in 'errno'.
382 * If the SCSI command succeeds then 0 is returned.
383 * Positive numbers returned are the compacted SCSI error codes (4
384 * bytes in one int) where the lowest byte is the SCSI status.
385 */
353#define OMAX_SB_LEN 16 /* For backward compatibility */ 386#define OMAX_SB_LEN 16 /* For backward compatibility */
354 387int sg_scsi_ioctl(struct file *file, struct request_queue *q,
355static int sg_scsi_ioctl(struct file *file, request_queue_t *q, 388 struct gendisk *disk, struct scsi_ioctl_command __user *sic)
356 struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
357{ 389{
358 struct request *rq; 390 struct request *rq;
359 int err; 391 int err;
360 unsigned int in_len, out_len, bytes, opcode, cmdlen; 392 unsigned int in_len, out_len, bytes, opcode, cmdlen;
361 char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; 393 char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
362 394
395 if (!sic)
396 return -EINVAL;
397
363 /* 398 /*
364 * get in an out lengths, verify they don't exceed a page worth of data 399 * get in an out lengths, verify they don't exceed a page worth of data
365 */ 400 */
@@ -393,45 +428,53 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
393 if (copy_from_user(rq->cmd, sic->data, cmdlen)) 428 if (copy_from_user(rq->cmd, sic->data, cmdlen))
394 goto error; 429 goto error;
395 430
396 if (copy_from_user(buffer, sic->data + cmdlen, in_len)) 431 if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
397 goto error; 432 goto error;
398 433
399 err = verify_command(file, rq->cmd); 434 err = verify_command(file, rq->cmd);
400 if (err) 435 if (err)
401 goto error; 436 goto error;
402 437
438 /* default. possible overriden later */
439 rq->retries = 5;
440
403 switch (opcode) { 441 switch (opcode) {
404 case SEND_DIAGNOSTIC: 442 case SEND_DIAGNOSTIC:
405 case FORMAT_UNIT: 443 case FORMAT_UNIT:
406 rq->timeout = FORMAT_UNIT_TIMEOUT; 444 rq->timeout = FORMAT_UNIT_TIMEOUT;
407 break; 445 rq->retries = 1;
408 case START_STOP: 446 break;
409 rq->timeout = START_STOP_TIMEOUT; 447 case START_STOP:
410 break; 448 rq->timeout = START_STOP_TIMEOUT;
411 case MOVE_MEDIUM: 449 break;
412 rq->timeout = MOVE_MEDIUM_TIMEOUT; 450 case MOVE_MEDIUM:
413 break; 451 rq->timeout = MOVE_MEDIUM_TIMEOUT;
414 case READ_ELEMENT_STATUS: 452 break;
415 rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; 453 case READ_ELEMENT_STATUS:
416 break; 454 rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
417 case READ_DEFECT_DATA: 455 break;
418 rq->timeout = READ_DEFECT_DATA_TIMEOUT; 456 case READ_DEFECT_DATA:
419 break; 457 rq->timeout = READ_DEFECT_DATA_TIMEOUT;
420 default: 458 rq->retries = 1;
421 rq->timeout = BLK_DEFAULT_TIMEOUT; 459 break;
422 break; 460 default:
461 rq->timeout = BLK_DEFAULT_TIMEOUT;
462 break;
463 }
464
465 if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) {
466 err = DRIVER_ERROR << 24;
467 goto out;
423 } 468 }
424 469
425 memset(sense, 0, sizeof(sense)); 470 memset(sense, 0, sizeof(sense));
426 rq->sense = sense; 471 rq->sense = sense;
427 rq->sense_len = 0; 472 rq->sense_len = 0;
428
429 rq->data = buffer;
430 rq->data_len = bytes;
431 rq->flags |= REQ_BLOCK_PC; 473 rq->flags |= REQ_BLOCK_PC;
432 rq->retries = 0;
433 474
434 blk_execute_rq(q, bd_disk, rq, 0); 475 blk_execute_rq(q, disk, rq, 0);
476
477out:
435 err = rq->errors & 0xff; /* only 8 bit SCSI status */ 478 err = rq->errors & 0xff; /* only 8 bit SCSI status */
436 if (err) { 479 if (err) {
437 if (rq->sense_len && rq->sense) { 480 if (rq->sense_len && rq->sense) {
@@ -450,7 +493,7 @@ error:
450 blk_put_request(rq); 493 blk_put_request(rq);
451 return err; 494 return err;
452} 495}
453 496EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
454 497
455/* Send basic block requests */ 498/* Send basic block requests */
456static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data) 499static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data)
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 36e930066649..a89aff61d3d8 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -158,180 +158,6 @@ int scsi_set_medium_removal(struct scsi_device *sdev, char state)
158EXPORT_SYMBOL(scsi_set_medium_removal); 158EXPORT_SYMBOL(scsi_set_medium_removal);
159 159
160/* 160/*
161 * This interface is deprecated - users should use the scsi generic (sg)
162 * interface instead, as this is a more flexible approach to performing
163 * generic SCSI commands on a device.
164 *
165 * The structure that we are passed should look like:
166 *
167 * struct sdata {
168 * unsigned int inlen; [i] Length of data to be written to device
169 * unsigned int outlen; [i] Length of data to be read from device
170 * unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12).
171 * [o] Data read from device starts here.
172 * [o] On error, sense buffer starts here.
173 * unsigned char wdata[y]; [i] Data written to device starts here.
174 * };
175 * Notes:
176 * - The SCSI command length is determined by examining the 1st byte
177 * of the given command. There is no way to override this.
178 * - Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha).
179 * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
180 * accommodate the sense buffer when an error occurs.
181 * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
182 * old code will not be surprised.
183 * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
184 * a negative return and the Unix error code in 'errno'.
185 * If the SCSI command succeeds then 0 is returned.
186 * Positive numbers returned are the compacted SCSI error codes (4
187 * bytes in one int) where the lowest byte is the SCSI status.
188 * See the drivers/scsi/scsi.h file for more information on this.
189 *
190 */
191#define OMAX_SB_LEN 16 /* Old sense buffer length */
192
193int scsi_ioctl_send_command(struct scsi_device *sdev,
194 struct scsi_ioctl_command __user *sic)
195{
196 char *buf;
197 unsigned char cmd[MAX_COMMAND_SIZE];
198 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
199 char __user *cmd_in;
200 unsigned char opcode;
201 unsigned int inlen, outlen, cmdlen;
202 unsigned int needed, buf_needed;
203 int timeout, retries, result;
204 int data_direction;
205 gfp_t gfp_mask = GFP_KERNEL;
206
207 if (!sic)
208 return -EINVAL;
209
210 if (sdev->host->unchecked_isa_dma)
211 gfp_mask |= GFP_DMA;
212
213 /*
214 * Verify that we can read at least this much.
215 */
216 if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
217 return -EFAULT;
218
219 if(__get_user(inlen, &sic->inlen))
220 return -EFAULT;
221
222 if(__get_user(outlen, &sic->outlen))
223 return -EFAULT;
224
225 /*
226 * We do not transfer more than MAX_BUF with this interface.
227 * If the user needs to transfer more data than this, they
228 * should use scsi_generics (sg) instead.
229 */
230 if (inlen > MAX_BUF)
231 return -EINVAL;
232 if (outlen > MAX_BUF)
233 return -EINVAL;
234
235 cmd_in = sic->data;
236 if(get_user(opcode, cmd_in))
237 return -EFAULT;
238
239 needed = buf_needed = (inlen > outlen ? inlen : outlen);
240 if (buf_needed) {
241 buf_needed = (buf_needed + 511) & ~511;
242 if (buf_needed > MAX_BUF)
243 buf_needed = MAX_BUF;
244 buf = kzalloc(buf_needed, gfp_mask);
245 if (!buf)
246 return -ENOMEM;
247 if (inlen == 0) {
248 data_direction = DMA_FROM_DEVICE;
249 } else if (outlen == 0 ) {
250 data_direction = DMA_TO_DEVICE;
251 } else {
252 /*
253 * Can this ever happen?
254 */
255 data_direction = DMA_BIDIRECTIONAL;
256 }
257
258 } else {
259 buf = NULL;
260 data_direction = DMA_NONE;
261 }
262
263 /*
264 * Obtain the command from the user's address space.
265 */
266 cmdlen = COMMAND_SIZE(opcode);
267
268 result = -EFAULT;
269
270 if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen))
271 goto error;
272
273 if(__copy_from_user(cmd, cmd_in, cmdlen))
274 goto error;
275
276 /*
277 * Obtain the data to be sent to the device (if any).
278 */
279
280 if(inlen && copy_from_user(buf, cmd_in + cmdlen, inlen))
281 goto error;
282
283 switch (opcode) {
284 case SEND_DIAGNOSTIC:
285 case FORMAT_UNIT:
286 timeout = FORMAT_UNIT_TIMEOUT;
287 retries = 1;
288 break;
289 case START_STOP:
290 timeout = START_STOP_TIMEOUT;
291 retries = NORMAL_RETRIES;
292 break;
293 case MOVE_MEDIUM:
294 timeout = MOVE_MEDIUM_TIMEOUT;
295 retries = NORMAL_RETRIES;
296 break;
297 case READ_ELEMENT_STATUS:
298 timeout = READ_ELEMENT_STATUS_TIMEOUT;
299 retries = NORMAL_RETRIES;
300 break;
301 case READ_DEFECT_DATA:
302 timeout = READ_DEFECT_DATA_TIMEOUT;
303 retries = 1;
304 break;
305 default:
306 timeout = IOCTL_NORMAL_TIMEOUT;
307 retries = NORMAL_RETRIES;
308 break;
309 }
310
311 result = scsi_execute(sdev, cmd, data_direction, buf, needed,
312 sense, timeout, retries, 0);
313
314 /*
315 * If there was an error condition, pass the info back to the user.
316 */
317 if (result) {
318 int sb_len = sizeof(*sense);
319
320 sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
321 if (copy_to_user(cmd_in, sense, sb_len))
322 result = -EFAULT;
323 } else {
324 if (outlen && copy_to_user(cmd_in, buf, outlen))
325 result = -EFAULT;
326 }
327
328error:
329 kfree(buf);
330 return result;
331}
332EXPORT_SYMBOL(scsi_ioctl_send_command);
333
334/*
335 * The scsi_ioctl_get_pci() function places into arg the value 161 * The scsi_ioctl_get_pci() function places into arg the value
336 * pci_dev::slot_name (8 characters) for the PCI device (if any). 162 * pci_dev::slot_name (8 characters) for the PCI device (if any).
337 * Returns: 0 on success 163 * Returns: 0 on success
@@ -409,7 +235,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
409 case SCSI_IOCTL_SEND_COMMAND: 235 case SCSI_IOCTL_SEND_COMMAND:
410 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 236 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
411 return -EACCES; 237 return -EACCES;
412 return scsi_ioctl_send_command(sdev, arg); 238 return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg);
413 case SCSI_IOCTL_DOORLOCK: 239 case SCSI_IOCTL_DOORLOCK:
414 return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); 240 return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
415 case SCSI_IOCTL_DOORUNLOCK: 241 case SCSI_IOCTL_DOORUNLOCK:
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7405d0df95db..fcf9243dfa7d 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1044,7 +1044,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
1044 if (!sg_allow_access(opcode, sdp->device->type)) 1044 if (!sg_allow_access(opcode, sdp->device->type))
1045 return -EPERM; 1045 return -EPERM;
1046 } 1046 }
1047 return scsi_ioctl_send_command(sdp->device, p); 1047 return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
1048 case SG_SET_DEBUG: 1048 case SG_SET_DEBUG:
1049 result = get_user(val, ip); 1049 result = get_user(val, ip);
1050 if (result) 1050 if (result)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d0cac8b58de7..59e1259b1c40 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -17,6 +17,8 @@
17 17
18#include <asm/scatterlist.h> 18#include <asm/scatterlist.h>
19 19
20struct scsi_ioctl_command;
21
20struct request_queue; 22struct request_queue;
21typedef struct request_queue request_queue_t; 23typedef struct request_queue request_queue_t;
22struct elevator_queue; 24struct elevator_queue;
@@ -611,6 +613,8 @@ extern void blk_plug_device(request_queue_t *);
611extern int blk_remove_plug(request_queue_t *); 613extern int blk_remove_plug(request_queue_t *);
612extern void blk_recount_segments(request_queue_t *, struct bio *); 614extern void blk_recount_segments(request_queue_t *, struct bio *);
613extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *); 615extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
616extern int sg_scsi_ioctl(struct file *, struct request_queue *,
617 struct gendisk *, struct scsi_ioctl_command __user *);
614extern void blk_start_queue(request_queue_t *q); 618extern void blk_start_queue(request_queue_t *q);
615extern void blk_stop_queue(request_queue_t *q); 619extern void blk_stop_queue(request_queue_t *q);
616extern void blk_sync_queue(struct request_queue *q); 620extern void blk_sync_queue(struct request_queue *q);
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index d4be4d92d586..edb9525386da 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -41,8 +41,6 @@ typedef struct scsi_fctargaddress {
41} Scsi_FCTargAddress; 41} Scsi_FCTargAddress;
42 42
43extern int scsi_ioctl(struct scsi_device *, int, void __user *); 43extern int scsi_ioctl(struct scsi_device *, int, void __user *);
44extern int scsi_ioctl_send_command(struct scsi_device *,
45 struct scsi_ioctl_command __user *);
46extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, 44extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
47 void __user *arg, struct file *filp); 45 void __user *arg, struct file *filp);
48 46