]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - block/ioctl.c
block: don't depend on consecutive minor space
[mirror_ubuntu-zesty-kernel.git] / block / ioctl.c
CommitLineData
c59ede7b 1#include <linux/capability.h>
1da177e4
LT
2#include <linux/blkdev.h>
3#include <linux/blkpg.h>
a885c8c4 4#include <linux/hdreg.h>
1da177e4
LT
5#include <linux/backing-dev.h>
6#include <linux/buffer_head.h>
7#include <linux/smp_lock.h>
2056a782 8#include <linux/blktrace_api.h>
1da177e4
LT
9#include <asm/uaccess.h>
10
11static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg)
12{
13 struct block_device *bdevp;
14 struct gendisk *disk;
15 struct blkpg_ioctl_arg a;
16 struct blkpg_partition p;
17 long long start, length;
cf771cb5 18 int partno;
1da177e4 19 int i;
04ebd4ae 20 int err;
1da177e4
LT
21
22 if (!capable(CAP_SYS_ADMIN))
23 return -EACCES;
24 if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
25 return -EFAULT;
26 if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
27 return -EFAULT;
28 disk = bdev->bd_disk;
29 if (bdev != bdev->bd_contains)
30 return -EINVAL;
cf771cb5 31 partno = p.pno;
f331c029 32 if (partno <= 0 || partno > disk_max_parts(disk))
1da177e4
LT
33 return -EINVAL;
34 switch (a.op) {
35 case BLKPG_ADD_PARTITION:
36 start = p.start >> 9;
37 length = p.length >> 9;
38 /* check for fit in a hd_struct */
39 if (sizeof(sector_t) == sizeof(long) &&
40 sizeof(long long) > sizeof(long)) {
41 long pstart = start, plength = length;
42 if (pstart != start || plength != length
43 || pstart < 0 || plength < 0)
44 return -EINVAL;
45 }
88e34126 46
c039e313 47 mutex_lock(&bdev->bd_mutex);
88e34126 48
1da177e4 49 /* overlap? */
f331c029 50 for (i = 0; i < disk_max_parts(disk); i++) {
1da177e4
LT
51 struct hd_struct *s = disk->part[i];
52
53 if (!s)
54 continue;
55 if (!(start+length <= s->start_sect ||
56 start >= s->start_sect + s->nr_sects)) {
c039e313 57 mutex_unlock(&bdev->bd_mutex);
1da177e4
LT
58 return -EBUSY;
59 }
60 }
61 /* all seems OK */
cf771cb5
TH
62 err = add_partition(disk, partno, start, length,
63 ADDPART_FLAG_NONE);
c039e313 64 mutex_unlock(&bdev->bd_mutex);
04ebd4ae 65 return err;
1da177e4 66 case BLKPG_DEL_PARTITION:
cf771cb5 67 if (!disk->part[partno - 1])
1da177e4 68 return -ENXIO;
cf771cb5 69 bdevp = bdget_disk(disk, partno);
1da177e4
LT
70 if (!bdevp)
71 return -ENOMEM;
2e7b651d 72 mutex_lock(&bdevp->bd_mutex);
1da177e4 73 if (bdevp->bd_openers) {
c039e313 74 mutex_unlock(&bdevp->bd_mutex);
1da177e4
LT
75 bdput(bdevp);
76 return -EBUSY;
77 }
78 /* all seems OK */
79 fsync_bdev(bdevp);
f98393a6 80 invalidate_bdev(bdevp);
1da177e4 81
6d740cd5 82 mutex_lock_nested(&bdev->bd_mutex, 1);
cf771cb5 83 delete_partition(disk, partno);
c039e313
AV
84 mutex_unlock(&bdev->bd_mutex);
85 mutex_unlock(&bdevp->bd_mutex);
1da177e4
LT
86 bdput(bdevp);
87
88 return 0;
89 default:
90 return -EINVAL;
91 }
92}
93
94static int blkdev_reread_part(struct block_device *bdev)
95{
96 struct gendisk *disk = bdev->bd_disk;
97 int res;
98
f331c029 99 if (!disk_max_parts(disk) || bdev != bdev->bd_contains)
1da177e4
LT
100 return -EINVAL;
101 if (!capable(CAP_SYS_ADMIN))
102 return -EACCES;
c039e313 103 if (!mutex_trylock(&bdev->bd_mutex))
1da177e4
LT
104 return -EBUSY;
105 res = rescan_partitions(disk, bdev);
c039e313 106 mutex_unlock(&bdev->bd_mutex);
1da177e4
LT
107 return res;
108}
109
d30a2605
DW
110static void blk_ioc_discard_endio(struct bio *bio, int err)
111{
112 if (err) {
113 if (err == -EOPNOTSUPP)
114 set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
115 clear_bit(BIO_UPTODATE, &bio->bi_flags);
116 }
117 complete(bio->bi_private);
118}
119
120static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
121 uint64_t len)
122{
123 struct request_queue *q = bdev_get_queue(bdev);
124 int ret = 0;
125
126 if (start & 511)
127 return -EINVAL;
128 if (len & 511)
129 return -EINVAL;
130 start >>= 9;
131 len >>= 9;
132
133 if (start + len > (bdev->bd_inode->i_size >> 9))
134 return -EINVAL;
135
136 if (!q->prepare_discard_fn)
137 return -EOPNOTSUPP;
138
139 while (len && !ret) {
140 DECLARE_COMPLETION_ONSTACK(wait);
141 struct bio *bio;
142
143 bio = bio_alloc(GFP_KERNEL, 0);
144 if (!bio)
145 return -ENOMEM;
146
147 bio->bi_end_io = blk_ioc_discard_endio;
148 bio->bi_bdev = bdev;
149 bio->bi_private = &wait;
150 bio->bi_sector = start;
151
152 if (len > q->max_hw_sectors) {
153 bio->bi_size = q->max_hw_sectors << 9;
154 len -= q->max_hw_sectors;
155 start += q->max_hw_sectors;
156 } else {
157 bio->bi_size = len << 9;
158 len = 0;
159 }
e17fc0a1 160 submit_bio(DISCARD_NOBARRIER, bio);
d30a2605
DW
161
162 wait_for_completion(&wait);
163
164 if (bio_flagged(bio, BIO_EOPNOTSUPP))
165 ret = -EOPNOTSUPP;
166 else if (!bio_flagged(bio, BIO_UPTODATE))
167 ret = -EIO;
168 bio_put(bio);
169 }
170 return ret;
171}
172
1da177e4
LT
173static int put_ushort(unsigned long arg, unsigned short val)
174{
175 return put_user(val, (unsigned short __user *)arg);
176}
177
178static int put_int(unsigned long arg, int val)
179{
180 return put_user(val, (int __user *)arg);
181}
182
183static int put_long(unsigned long arg, long val)
184{
185 return put_user(val, (long __user *)arg);
186}
187
188static int put_ulong(unsigned long arg, unsigned long val)
189{
190 return put_user(val, (unsigned long __user *)arg);
191}
192
193static int put_u64(unsigned long arg, u64 val)
194{
195 return put_user(val, (u64 __user *)arg);
196}
197
bb93e3a5
AB
198static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
199 unsigned cmd, unsigned long arg)
1da177e4 200{
1da177e4
LT
201 struct backing_dev_info *bdi;
202 int ret, n;
203
204 switch (cmd) {
205 case BLKRAGET:
206 case BLKFRAGET:
207 if (!arg)
208 return -EINVAL;
209 bdi = blk_get_backing_dev_info(bdev);
210 if (bdi == NULL)
211 return -ENOTTY;
212 return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
213 case BLKROGET:
214 return put_int(arg, bdev_read_only(bdev) != 0);
215 case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */
216 return put_int(arg, block_size(bdev));
217 case BLKSSZGET: /* get block device hardware sector size */
218 return put_int(arg, bdev_hardsect_size(bdev));
219 case BLKSECTGET:
220 return put_ushort(arg, bdev_get_queue(bdev)->max_sectors);
221 case BLKRASET:
222 case BLKFRASET:
223 if(!capable(CAP_SYS_ADMIN))
224 return -EACCES;
225 bdi = blk_get_backing_dev_info(bdev);
226 if (bdi == NULL)
227 return -ENOTTY;
228 bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
229 return 0;
230 case BLKBSZSET:
231 /* set the logical block size */
232 if (!capable(CAP_SYS_ADMIN))
233 return -EACCES;
234 if (!arg)
235 return -EINVAL;
236 if (get_user(n, (int __user *) arg))
237 return -EFAULT;
238 if (bd_claim(bdev, file) < 0)
239 return -EBUSY;
240 ret = set_blocksize(bdev, n);
241 bd_release(bdev);
242 return ret;
243 case BLKPG:
244 return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);
245 case BLKRRPART:
246 return blkdev_reread_part(bdev);
247 case BLKGETSIZE:
248 if ((bdev->bd_inode->i_size >> 9) > ~0UL)
249 return -EFBIG;
250 return put_ulong(arg, bdev->bd_inode->i_size >> 9);
251 case BLKGETSIZE64:
252 return put_u64(arg, bdev->bd_inode->i_size);
2056a782
JA
253 case BLKTRACESTART:
254 case BLKTRACESTOP:
255 case BLKTRACESETUP:
256 case BLKTRACETEARDOWN:
257 return blk_trace_ioctl(bdev, cmd, (char __user *) arg);
bb93e3a5
AB
258 }
259 return -ENOIOCTLCMD;
260}
261
7006f6ec
AK
262int blkdev_driver_ioctl(struct inode *inode, struct file *file,
263 struct gendisk *disk, unsigned cmd, unsigned long arg)
bb93e3a5
AB
264{
265 int ret;
266 if (disk->fops->unlocked_ioctl)
267 return disk->fops->unlocked_ioctl(file, cmd, arg);
268
269 if (disk->fops->ioctl) {
270 lock_kernel();
271 ret = disk->fops->ioctl(inode, file, cmd, arg);
272 unlock_kernel();
273 return ret;
274 }
275
276 return -ENOTTY;
277}
7006f6ec 278EXPORT_SYMBOL_GPL(blkdev_driver_ioctl);
bb93e3a5 279
f58c4c0a
AB
280/*
281 * always keep this in sync with compat_blkdev_ioctl() and
282 * compat_blkdev_locked_ioctl()
283 */
bb93e3a5
AB
284int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
285 unsigned long arg)
286{
287 struct block_device *bdev = inode->i_bdev;
288 struct gendisk *disk = bdev->bd_disk;
289 int ret, n;
290
291 switch(cmd) {
1da177e4
LT
292 case BLKFLSBUF:
293 if (!capable(CAP_SYS_ADMIN))
294 return -EACCES;
bb93e3a5
AB
295
296 ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
297 /* -EINVAL to handle old uncorrected drivers */
298 if (ret != -EINVAL && ret != -ENOTTY)
299 return ret;
300
301 lock_kernel();
1da177e4 302 fsync_bdev(bdev);
f98393a6 303 invalidate_bdev(bdev);
bb93e3a5 304 unlock_kernel();
1da177e4 305 return 0;
bb93e3a5 306
1da177e4 307 case BLKROSET:
bb93e3a5
AB
308 ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
309 /* -EINVAL to handle old uncorrected drivers */
310 if (ret != -EINVAL && ret != -ENOTTY)
311 return ret;
1da177e4
LT
312 if (!capable(CAP_SYS_ADMIN))
313 return -EACCES;
314 if (get_user(n, (int __user *)(arg)))
315 return -EFAULT;
bb93e3a5 316 lock_kernel();
1da177e4 317 set_device_ro(bdev, n);
bb93e3a5 318 unlock_kernel();
1da177e4 319 return 0;
d30a2605
DW
320
321 case BLKDISCARD: {
322 uint64_t range[2];
323
324 if (!(file->f_mode & FMODE_WRITE))
325 return -EBADF;
326
327 if (copy_from_user(range, (void __user *)arg, sizeof(range)))
328 return -EFAULT;
329
330 return blk_ioctl_discard(bdev, range[0], range[1]);
331 }
332
a885c8c4
CH
333 case HDIO_GETGEO: {
334 struct hd_geometry geo;
335
336 if (!arg)
337 return -EINVAL;
338 if (!disk->fops->getgeo)
339 return -ENOTTY;
340
341 /*
342 * We need to set the startsect first, the driver may
343 * want to override it.
344 */
345 geo.start = get_start_sect(bdev);
346 ret = disk->fops->getgeo(bdev, &geo);
347 if (ret)
348 return ret;
349 if (copy_to_user((struct hd_geometry __user *)arg, &geo,
350 sizeof(geo)))
351 return -EFAULT;
352 return 0;
353 }
1da177e4 354 }
bb93e3a5
AB
355
356 lock_kernel();
357 ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
358 unlock_kernel();
359 if (ret != -ENOIOCTLCMD)
360 return ret;
361
362 return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
1da177e4 363}
68f66feb 364EXPORT_SYMBOL_GPL(blkdev_ioctl);