GNU Linux-libre 6.9.1-gnu
[releases.git] / block / ioctl.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/capability.h>
3 #include <linux/compat.h>
4 #include <linux/blkdev.h>
5 #include <linux/export.h>
6 #include <linux/gfp.h>
7 #include <linux/blkpg.h>
8 #include <linux/hdreg.h>
9 #include <linux/backing-dev.h>
10 #include <linux/fs.h>
11 #include <linux/blktrace_api.h>
12 #include <linux/pr.h>
13 #include <linux/uaccess.h>
14 #include "blk.h"
15
16 static int blkpg_do_ioctl(struct block_device *bdev,
17                           struct blkpg_partition __user *upart, int op)
18 {
19         struct gendisk *disk = bdev->bd_disk;
20         struct blkpg_partition p;
21         sector_t start, length, capacity, end;
22
23         if (!capable(CAP_SYS_ADMIN))
24                 return -EACCES;
25         if (copy_from_user(&p, upart, sizeof(struct blkpg_partition)))
26                 return -EFAULT;
27         if (bdev_is_partition(bdev))
28                 return -EINVAL;
29
30         if (p.pno <= 0)
31                 return -EINVAL;
32
33         if (op == BLKPG_DEL_PARTITION)
34                 return bdev_del_partition(disk, p.pno);
35
36         if (p.start < 0 || p.length <= 0 || p.start + p.length < 0)
37                 return -EINVAL;
38         /* Check that the partition is aligned to the block size */
39         if (!IS_ALIGNED(p.start | p.length, bdev_logical_block_size(bdev)))
40                 return -EINVAL;
41
42         start = p.start >> SECTOR_SHIFT;
43         length = p.length >> SECTOR_SHIFT;
44         capacity = get_capacity(disk);
45
46         if (check_add_overflow(start, length, &end))
47                 return -EINVAL;
48
49         if (start >= capacity || end > capacity)
50                 return -EINVAL;
51
52         switch (op) {
53         case BLKPG_ADD_PARTITION:
54                 return bdev_add_partition(disk, p.pno, start, length);
55         case BLKPG_RESIZE_PARTITION:
56                 return bdev_resize_partition(disk, p.pno, start, length);
57         default:
58                 return -EINVAL;
59         }
60 }
61
62 static int blkpg_ioctl(struct block_device *bdev,
63                        struct blkpg_ioctl_arg __user *arg)
64 {
65         struct blkpg_partition __user *udata;
66         int op;
67
68         if (get_user(op, &arg->op) || get_user(udata, &arg->data))
69                 return -EFAULT;
70
71         return blkpg_do_ioctl(bdev, udata, op);
72 }
73
74 #ifdef CONFIG_COMPAT
75 struct compat_blkpg_ioctl_arg {
76         compat_int_t op;
77         compat_int_t flags;
78         compat_int_t datalen;
79         compat_caddr_t data;
80 };
81
82 static int compat_blkpg_ioctl(struct block_device *bdev,
83                               struct compat_blkpg_ioctl_arg __user *arg)
84 {
85         compat_caddr_t udata;
86         int op;
87
88         if (get_user(op, &arg->op) || get_user(udata, &arg->data))
89                 return -EFAULT;
90
91         return blkpg_do_ioctl(bdev, compat_ptr(udata), op);
92 }
93 #endif
94
95 static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
96                 unsigned long arg)
97 {
98         uint64_t range[2];
99         uint64_t start, len, end;
100         struct inode *inode = bdev->bd_inode;
101         int err;
102
103         if (!(mode & BLK_OPEN_WRITE))
104                 return -EBADF;
105
106         if (!bdev_max_discard_sectors(bdev))
107                 return -EOPNOTSUPP;
108
109         if (copy_from_user(range, (void __user *)arg, sizeof(range)))
110                 return -EFAULT;
111
112         start = range[0];
113         len = range[1];
114
115         if (start & 511)
116                 return -EINVAL;
117         if (len & 511)
118                 return -EINVAL;
119
120         if (check_add_overflow(start, len, &end) ||
121             end > bdev_nr_bytes(bdev))
122                 return -EINVAL;
123
124         filemap_invalidate_lock(inode->i_mapping);
125         err = truncate_bdev_range(bdev, mode, start, start + len - 1);
126         if (err)
127                 goto fail;
128         err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL);
129 fail:
130         filemap_invalidate_unlock(inode->i_mapping);
131         return err;
132 }
133
134 static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
135                 void __user *argp)
136 {
137         uint64_t start, len;
138         uint64_t range[2];
139         int err;
140
141         if (!(mode & BLK_OPEN_WRITE))
142                 return -EBADF;
143         if (!bdev_max_secure_erase_sectors(bdev))
144                 return -EOPNOTSUPP;
145         if (copy_from_user(range, argp, sizeof(range)))
146                 return -EFAULT;
147
148         start = range[0];
149         len = range[1];
150         if ((start & 511) || (len & 511))
151                 return -EINVAL;
152         if (start + len > bdev_nr_bytes(bdev))
153                 return -EINVAL;
154
155         filemap_invalidate_lock(bdev->bd_inode->i_mapping);
156         err = truncate_bdev_range(bdev, mode, start, start + len - 1);
157         if (!err)
158                 err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
159                                                 GFP_KERNEL);
160         filemap_invalidate_unlock(bdev->bd_inode->i_mapping);
161         return err;
162 }
163
164
165 static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode,
166                 unsigned long arg)
167 {
168         uint64_t range[2];
169         uint64_t start, end, len;
170         struct inode *inode = bdev->bd_inode;
171         int err;
172
173         if (!(mode & BLK_OPEN_WRITE))
174                 return -EBADF;
175
176         if (copy_from_user(range, (void __user *)arg, sizeof(range)))
177                 return -EFAULT;
178
179         start = range[0];
180         len = range[1];
181         end = start + len - 1;
182
183         if (start & 511)
184                 return -EINVAL;
185         if (len & 511)
186                 return -EINVAL;
187         if (end >= (uint64_t)bdev_nr_bytes(bdev))
188                 return -EINVAL;
189         if (end < start)
190                 return -EINVAL;
191
192         /* Invalidate the page cache, including dirty pages */
193         filemap_invalidate_lock(inode->i_mapping);
194         err = truncate_bdev_range(bdev, mode, start, end);
195         if (err)
196                 goto fail;
197
198         err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL,
199                                    BLKDEV_ZERO_NOUNMAP);
200
201 fail:
202         filemap_invalidate_unlock(inode->i_mapping);
203         return err;
204 }
205
206 static int put_ushort(unsigned short __user *argp, unsigned short val)
207 {
208         return put_user(val, argp);
209 }
210
211 static int put_int(int __user *argp, int val)
212 {
213         return put_user(val, argp);
214 }
215
216 static int put_uint(unsigned int __user *argp, unsigned int val)
217 {
218         return put_user(val, argp);
219 }
220
221 static int put_long(long __user *argp, long val)
222 {
223         return put_user(val, argp);
224 }
225
226 static int put_ulong(unsigned long __user *argp, unsigned long val)
227 {
228         return put_user(val, argp);
229 }
230
231 static int put_u64(u64 __user *argp, u64 val)
232 {
233         return put_user(val, argp);
234 }
235
236 #ifdef CONFIG_COMPAT
237 static int compat_put_long(compat_long_t __user *argp, long val)
238 {
239         return put_user(val, argp);
240 }
241
242 static int compat_put_ulong(compat_ulong_t __user *argp, compat_ulong_t val)
243 {
244         return put_user(val, argp);
245 }
246 #endif
247
248 #ifdef CONFIG_COMPAT
249 /*
250  * This is the equivalent of compat_ptr_ioctl(), to be used by block
251  * drivers that implement only commands that are completely compatible
252  * between 32-bit and 64-bit user space
253  */
254 int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode,
255                         unsigned cmd, unsigned long arg)
256 {
257         struct gendisk *disk = bdev->bd_disk;
258
259         if (disk->fops->ioctl)
260                 return disk->fops->ioctl(bdev, mode, cmd,
261                                          (unsigned long)compat_ptr(arg));
262
263         return -ENOIOCTLCMD;
264 }
265 EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
266 #endif
267
268 static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode)
269 {
270         /* no sense to make reservations for partitions */
271         if (bdev_is_partition(bdev))
272                 return false;
273
274         if (capable(CAP_SYS_ADMIN))
275                 return true;
276         /*
277          * Only allow unprivileged reservations if the file descriptor is open
278          * for writing.
279          */
280         return mode & BLK_OPEN_WRITE;
281 }
282
283 static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode,
284                 struct pr_registration __user *arg)
285 {
286         const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
287         struct pr_registration reg;
288
289         if (!blkdev_pr_allowed(bdev, mode))
290                 return -EPERM;
291         if (!ops || !ops->pr_register)
292                 return -EOPNOTSUPP;
293         if (copy_from_user(&reg, arg, sizeof(reg)))
294                 return -EFAULT;
295
296         if (reg.flags & ~PR_FL_IGNORE_KEY)
297                 return -EOPNOTSUPP;
298         return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
299 }
300
301 static int blkdev_pr_reserve(struct block_device *bdev, blk_mode_t mode,
302                 struct pr_reservation __user *arg)
303 {
304         const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
305         struct pr_reservation rsv;
306
307         if (!blkdev_pr_allowed(bdev, mode))
308                 return -EPERM;
309         if (!ops || !ops->pr_reserve)
310                 return -EOPNOTSUPP;
311         if (copy_from_user(&rsv, arg, sizeof(rsv)))
312                 return -EFAULT;
313
314         if (rsv.flags & ~PR_FL_IGNORE_KEY)
315                 return -EOPNOTSUPP;
316         return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags);
317 }
318
319 static int blkdev_pr_release(struct block_device *bdev, blk_mode_t mode,
320                 struct pr_reservation __user *arg)
321 {
322         const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
323         struct pr_reservation rsv;
324
325         if (!blkdev_pr_allowed(bdev, mode))
326                 return -EPERM;
327         if (!ops || !ops->pr_release)
328                 return -EOPNOTSUPP;
329         if (copy_from_user(&rsv, arg, sizeof(rsv)))
330                 return -EFAULT;
331
332         if (rsv.flags)
333                 return -EOPNOTSUPP;
334         return ops->pr_release(bdev, rsv.key, rsv.type);
335 }
336
337 static int blkdev_pr_preempt(struct block_device *bdev, blk_mode_t mode,
338                 struct pr_preempt __user *arg, bool abort)
339 {
340         const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
341         struct pr_preempt p;
342
343         if (!blkdev_pr_allowed(bdev, mode))
344                 return -EPERM;
345         if (!ops || !ops->pr_preempt)
346                 return -EOPNOTSUPP;
347         if (copy_from_user(&p, arg, sizeof(p)))
348                 return -EFAULT;
349
350         if (p.flags)
351                 return -EOPNOTSUPP;
352         return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort);
353 }
354
355 static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode,
356                 struct pr_clear __user *arg)
357 {
358         const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
359         struct pr_clear c;
360
361         if (!blkdev_pr_allowed(bdev, mode))
362                 return -EPERM;
363         if (!ops || !ops->pr_clear)
364                 return -EOPNOTSUPP;
365         if (copy_from_user(&c, arg, sizeof(c)))
366                 return -EFAULT;
367
368         if (c.flags)
369                 return -EOPNOTSUPP;
370         return ops->pr_clear(bdev, c.key);
371 }
372
373 static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd,
374                 unsigned long arg)
375 {
376         if (!capable(CAP_SYS_ADMIN))
377                 return -EACCES;
378
379         mutex_lock(&bdev->bd_holder_lock);
380         if (bdev->bd_holder_ops && bdev->bd_holder_ops->sync)
381                 bdev->bd_holder_ops->sync(bdev);
382         else {
383                 mutex_unlock(&bdev->bd_holder_lock);
384                 sync_blockdev(bdev);
385         }
386
387         invalidate_bdev(bdev);
388         return 0;
389 }
390
391 static int blkdev_roset(struct block_device *bdev, unsigned cmd,
392                 unsigned long arg)
393 {
394         int ret, n;
395
396         if (!capable(CAP_SYS_ADMIN))
397                 return -EACCES;
398
399         if (get_user(n, (int __user *)arg))
400                 return -EFAULT;
401         if (bdev->bd_disk->fops->set_read_only) {
402                 ret = bdev->bd_disk->fops->set_read_only(bdev, n);
403                 if (ret)
404                         return ret;
405         }
406         bdev->bd_read_only = n;
407         return 0;
408 }
409
410 static int blkdev_getgeo(struct block_device *bdev,
411                 struct hd_geometry __user *argp)
412 {
413         struct gendisk *disk = bdev->bd_disk;
414         struct hd_geometry geo;
415         int ret;
416
417         if (!argp)
418                 return -EINVAL;
419         if (!disk->fops->getgeo)
420                 return -ENOTTY;
421
422         /*
423          * We need to set the startsect first, the driver may
424          * want to override it.
425          */
426         memset(&geo, 0, sizeof(geo));
427         geo.start = get_start_sect(bdev);
428         ret = disk->fops->getgeo(bdev, &geo);
429         if (ret)
430                 return ret;
431         if (copy_to_user(argp, &geo, sizeof(geo)))
432                 return -EFAULT;
433         return 0;
434 }
435
436 #ifdef CONFIG_COMPAT
437 struct compat_hd_geometry {
438         unsigned char heads;
439         unsigned char sectors;
440         unsigned short cylinders;
441         u32 start;
442 };
443
444 static int compat_hdio_getgeo(struct block_device *bdev,
445                               struct compat_hd_geometry __user *ugeo)
446 {
447         struct gendisk *disk = bdev->bd_disk;
448         struct hd_geometry geo;
449         int ret;
450
451         if (!ugeo)
452                 return -EINVAL;
453         if (!disk->fops->getgeo)
454                 return -ENOTTY;
455
456         memset(&geo, 0, sizeof(geo));
457         /*
458          * We need to set the startsect first, the driver may
459          * want to override it.
460          */
461         geo.start = get_start_sect(bdev);
462         ret = disk->fops->getgeo(bdev, &geo);
463         if (ret)
464                 return ret;
465
466         ret = copy_to_user(ugeo, &geo, 4);
467         ret |= put_user(geo.start, &ugeo->start);
468         if (ret)
469                 ret = -EFAULT;
470
471         return ret;
472 }
473 #endif
474
475 /* set the logical block size */
476 static int blkdev_bszset(struct block_device *bdev, blk_mode_t mode,
477                 int __user *argp)
478 {
479         int ret, n;
480         struct file *file;
481
482         if (!capable(CAP_SYS_ADMIN))
483                 return -EACCES;
484         if (!argp)
485                 return -EINVAL;
486         if (get_user(n, argp))
487                 return -EFAULT;
488
489         if (mode & BLK_OPEN_EXCL)
490                 return set_blocksize(bdev, n);
491
492         file = bdev_file_open_by_dev(bdev->bd_dev, mode, &bdev, NULL);
493         if (IS_ERR(file))
494                 return -EBUSY;
495         ret = set_blocksize(bdev, n);
496         fput(file);
497         return ret;
498 }
499
500 /*
501  * Common commands that are handled the same way on native and compat
502  * user space. Note the separate arg/argp parameters that are needed
503  * to deal with the compat_ptr() conversion.
504  */
505 static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
506                                unsigned int cmd, unsigned long arg,
507                                void __user *argp)
508 {
509         unsigned int max_sectors;
510
511         switch (cmd) {
512         case BLKFLSBUF:
513                 return blkdev_flushbuf(bdev, cmd, arg);
514         case BLKROSET:
515                 return blkdev_roset(bdev, cmd, arg);
516         case BLKDISCARD:
517                 return blk_ioctl_discard(bdev, mode, arg);
518         case BLKSECDISCARD:
519                 return blk_ioctl_secure_erase(bdev, mode, argp);
520         case BLKZEROOUT:
521                 return blk_ioctl_zeroout(bdev, mode, arg);
522         case BLKGETDISKSEQ:
523                 return put_u64(argp, bdev->bd_disk->diskseq);
524         case BLKREPORTZONE:
525                 return blkdev_report_zones_ioctl(bdev, cmd, arg);
526         case BLKRESETZONE:
527         case BLKOPENZONE:
528         case BLKCLOSEZONE:
529         case BLKFINISHZONE:
530                 return blkdev_zone_mgmt_ioctl(bdev, mode, cmd, arg);
531         case BLKGETZONESZ:
532                 return put_uint(argp, bdev_zone_sectors(bdev));
533         case BLKGETNRZONES:
534                 return put_uint(argp, bdev_nr_zones(bdev));
535         case BLKROGET:
536                 return put_int(argp, bdev_read_only(bdev) != 0);
537         case BLKSSZGET: /* get block device logical block size */
538                 return put_int(argp, bdev_logical_block_size(bdev));
539         case BLKPBSZGET: /* get block device physical block size */
540                 return put_uint(argp, bdev_physical_block_size(bdev));
541         case BLKIOMIN:
542                 return put_uint(argp, bdev_io_min(bdev));
543         case BLKIOOPT:
544                 return put_uint(argp, bdev_io_opt(bdev));
545         case BLKALIGNOFF:
546                 return put_int(argp, bdev_alignment_offset(bdev));
547         case BLKDISCARDZEROES:
548                 return put_uint(argp, 0);
549         case BLKSECTGET:
550                 max_sectors = min_t(unsigned int, USHRT_MAX,
551                                     queue_max_sectors(bdev_get_queue(bdev)));
552                 return put_ushort(argp, max_sectors);
553         case BLKROTATIONAL:
554                 return put_ushort(argp, !bdev_nonrot(bdev));
555         case BLKRASET:
556         case BLKFRASET:
557                 if(!capable(CAP_SYS_ADMIN))
558                         return -EACCES;
559                 bdev->bd_disk->bdi->ra_pages = (arg * 512) / PAGE_SIZE;
560                 return 0;
561         case BLKRRPART:
562                 if (!capable(CAP_SYS_ADMIN))
563                         return -EACCES;
564                 if (bdev_is_partition(bdev))
565                         return -EINVAL;
566                 return disk_scan_partitions(bdev->bd_disk,
567                                 mode | BLK_OPEN_STRICT_SCAN);
568         case BLKTRACESTART:
569         case BLKTRACESTOP:
570         case BLKTRACETEARDOWN:
571                 return blk_trace_ioctl(bdev, cmd, argp);
572         case IOC_PR_REGISTER:
573                 return blkdev_pr_register(bdev, mode, argp);
574         case IOC_PR_RESERVE:
575                 return blkdev_pr_reserve(bdev, mode, argp);
576         case IOC_PR_RELEASE:
577                 return blkdev_pr_release(bdev, mode, argp);
578         case IOC_PR_PREEMPT:
579                 return blkdev_pr_preempt(bdev, mode, argp, false);
580         case IOC_PR_PREEMPT_ABORT:
581                 return blkdev_pr_preempt(bdev, mode, argp, true);
582         case IOC_PR_CLEAR:
583                 return blkdev_pr_clear(bdev, mode, argp);
584         default:
585                 return -ENOIOCTLCMD;
586         }
587 }
588
589 /*
590  * Always keep this in sync with compat_blkdev_ioctl()
591  * to handle all incompatible commands in both functions.
592  *
593  * New commands must be compatible and go into blkdev_common_ioctl
594  */
595 long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
596 {
597         struct block_device *bdev = I_BDEV(file->f_mapping->host);
598         void __user *argp = (void __user *)arg;
599         blk_mode_t mode = file_to_blk_mode(file);
600         int ret;
601
602         switch (cmd) {
603         /* These need separate implementations for the data structure */
604         case HDIO_GETGEO:
605                 return blkdev_getgeo(bdev, argp);
606         case BLKPG:
607                 return blkpg_ioctl(bdev, argp);
608
609         /* Compat mode returns 32-bit data instead of 'long' */
610         case BLKRAGET:
611         case BLKFRAGET:
612                 if (!argp)
613                         return -EINVAL;
614                 return put_long(argp,
615                         (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512);
616         case BLKGETSIZE:
617                 if (bdev_nr_sectors(bdev) > ~0UL)
618                         return -EFBIG;
619                 return put_ulong(argp, bdev_nr_sectors(bdev));
620
621         /* The data is compatible, but the command number is different */
622         case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */
623                 return put_int(argp, block_size(bdev));
624         case BLKBSZSET:
625                 return blkdev_bszset(bdev, mode, argp);
626         case BLKGETSIZE64:
627                 return put_u64(argp, bdev_nr_bytes(bdev));
628
629         /* Incompatible alignment on i386 */
630         case BLKTRACESETUP:
631                 return blk_trace_ioctl(bdev, cmd, argp);
632         default:
633                 break;
634         }
635
636         ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
637         if (ret != -ENOIOCTLCMD)
638                 return ret;
639
640         if (!bdev->bd_disk->fops->ioctl)
641                 return -ENOTTY;
642         return bdev->bd_disk->fops->ioctl(bdev, mode, cmd, arg);
643 }
644
645 #ifdef CONFIG_COMPAT
646
647 #define BLKBSZGET_32            _IOR(0x12, 112, int)
648 #define BLKBSZSET_32            _IOW(0x12, 113, int)
649 #define BLKGETSIZE64_32         _IOR(0x12, 114, int)
650
651 /* Most of the generic ioctls are handled in the normal fallback path.
652    This assumes the blkdev's low level compat_ioctl always returns
653    ENOIOCTLCMD for unknown ioctls. */
654 long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
655 {
656         int ret;
657         void __user *argp = compat_ptr(arg);
658         struct block_device *bdev = I_BDEV(file->f_mapping->host);
659         struct gendisk *disk = bdev->bd_disk;
660         blk_mode_t mode = file_to_blk_mode(file);
661
662         switch (cmd) {
663         /* These need separate implementations for the data structure */
664         case HDIO_GETGEO:
665                 return compat_hdio_getgeo(bdev, argp);
666         case BLKPG:
667                 return compat_blkpg_ioctl(bdev, argp);
668
669         /* Compat mode returns 32-bit data instead of 'long' */
670         case BLKRAGET:
671         case BLKFRAGET:
672                 if (!argp)
673                         return -EINVAL;
674                 return compat_put_long(argp,
675                         (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512);
676         case BLKGETSIZE:
677                 if (bdev_nr_sectors(bdev) > ~(compat_ulong_t)0)
678                         return -EFBIG;
679                 return compat_put_ulong(argp, bdev_nr_sectors(bdev));
680
681         /* The data is compatible, but the command number is different */
682         case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
683                 return put_int(argp, bdev_logical_block_size(bdev));
684         case BLKBSZSET_32:
685                 return blkdev_bszset(bdev, mode, argp);
686         case BLKGETSIZE64_32:
687                 return put_u64(argp, bdev_nr_bytes(bdev));
688
689         /* Incompatible alignment on i386 */
690         case BLKTRACESETUP32:
691                 return blk_trace_ioctl(bdev, cmd, argp);
692         default:
693                 break;
694         }
695
696         ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
697         if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
698                 ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
699
700         return ret;
701 }
702 #endif