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