diff options
Diffstat (limited to 'block/ioctl.c')
-rw-r--r-- | block/ioctl.c | 173 |
1 files changed, 89 insertions, 84 deletions
diff --git a/block/ioctl.c b/block/ioctl.c index 38bee321e1fa..c832d639b6e2 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -201,97 +201,41 @@ static int put_u64(unsigned long arg, u64 val) | |||
201 | return put_user(val, (u64 __user *)arg); | 201 | return put_user(val, (u64 __user *)arg); |
202 | } | 202 | } |
203 | 203 | ||
204 | static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, | 204 | int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, |
205 | unsigned cmd, unsigned long arg) | 205 | unsigned cmd, unsigned long arg) |
206 | { | ||
207 | struct backing_dev_info *bdi; | ||
208 | int ret, n; | ||
209 | |||
210 | switch (cmd) { | ||
211 | case BLKRAGET: | ||
212 | case BLKFRAGET: | ||
213 | if (!arg) | ||
214 | return -EINVAL; | ||
215 | bdi = blk_get_backing_dev_info(bdev); | ||
216 | if (bdi == NULL) | ||
217 | return -ENOTTY; | ||
218 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); | ||
219 | case BLKROGET: | ||
220 | return put_int(arg, bdev_read_only(bdev) != 0); | ||
221 | case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ | ||
222 | return put_int(arg, block_size(bdev)); | ||
223 | case BLKSSZGET: /* get block device hardware sector size */ | ||
224 | return put_int(arg, bdev_hardsect_size(bdev)); | ||
225 | case BLKSECTGET: | ||
226 | return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); | ||
227 | case BLKRASET: | ||
228 | case BLKFRASET: | ||
229 | if(!capable(CAP_SYS_ADMIN)) | ||
230 | return -EACCES; | ||
231 | bdi = blk_get_backing_dev_info(bdev); | ||
232 | if (bdi == NULL) | ||
233 | return -ENOTTY; | ||
234 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | ||
235 | return 0; | ||
236 | case BLKBSZSET: | ||
237 | /* set the logical block size */ | ||
238 | if (!capable(CAP_SYS_ADMIN)) | ||
239 | return -EACCES; | ||
240 | if (!arg) | ||
241 | return -EINVAL; | ||
242 | if (get_user(n, (int __user *) arg)) | ||
243 | return -EFAULT; | ||
244 | if (bd_claim(bdev, file) < 0) | ||
245 | return -EBUSY; | ||
246 | ret = set_blocksize(bdev, n); | ||
247 | bd_release(bdev); | ||
248 | return ret; | ||
249 | case BLKPG: | ||
250 | return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); | ||
251 | case BLKRRPART: | ||
252 | return blkdev_reread_part(bdev); | ||
253 | case BLKGETSIZE: | ||
254 | if ((bdev->bd_inode->i_size >> 9) > ~0UL) | ||
255 | return -EFBIG; | ||
256 | return put_ulong(arg, bdev->bd_inode->i_size >> 9); | ||
257 | case BLKGETSIZE64: | ||
258 | return put_u64(arg, bdev->bd_inode->i_size); | ||
259 | case BLKTRACESTART: | ||
260 | case BLKTRACESTOP: | ||
261 | case BLKTRACESETUP: | ||
262 | case BLKTRACETEARDOWN: | ||
263 | return blk_trace_ioctl(bdev, cmd, (char __user *) arg); | ||
264 | } | ||
265 | return -ENOIOCTLCMD; | ||
266 | } | ||
267 | |||
268 | int blkdev_driver_ioctl(struct inode *inode, struct file *file, | ||
269 | struct gendisk *disk, unsigned cmd, unsigned long arg) | ||
270 | { | 206 | { |
207 | struct gendisk *disk = bdev->bd_disk; | ||
271 | int ret; | 208 | int ret; |
272 | if (disk->fops->unlocked_ioctl) | ||
273 | return disk->fops->unlocked_ioctl(file, cmd, arg); | ||
274 | 209 | ||
275 | if (disk->fops->ioctl) { | 210 | if (disk->fops->ioctl) |
211 | return disk->fops->ioctl(bdev, mode, cmd, arg); | ||
212 | |||
213 | if (disk->fops->locked_ioctl) { | ||
276 | lock_kernel(); | 214 | lock_kernel(); |
277 | ret = disk->fops->ioctl(inode, file, cmd, arg); | 215 | ret = disk->fops->locked_ioctl(bdev, mode, cmd, arg); |
278 | unlock_kernel(); | 216 | unlock_kernel(); |
279 | return ret; | 217 | return ret; |
280 | } | 218 | } |
281 | 219 | ||
282 | return -ENOTTY; | 220 | return -ENOTTY; |
283 | } | 221 | } |
284 | EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); | 222 | /* |
223 | * For the record: _GPL here is only because somebody decided to slap it | ||
224 | * on the previous export. Sheer idiocy, since it wasn't copyrightable | ||
225 | * at all and could be open-coded without any exports by anybody who cares. | ||
226 | */ | ||
227 | EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); | ||
285 | 228 | ||
286 | /* | 229 | /* |
287 | * always keep this in sync with compat_blkdev_ioctl() and | 230 | * always keep this in sync with compat_blkdev_ioctl() and |
288 | * compat_blkdev_locked_ioctl() | 231 | * compat_blkdev_locked_ioctl() |
289 | */ | 232 | */ |
290 | int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | 233 | int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, |
291 | unsigned long arg) | 234 | unsigned long arg) |
292 | { | 235 | { |
293 | struct block_device *bdev = inode->i_bdev; | ||
294 | struct gendisk *disk = bdev->bd_disk; | 236 | struct gendisk *disk = bdev->bd_disk; |
237 | struct backing_dev_info *bdi; | ||
238 | loff_t size; | ||
295 | int ret, n; | 239 | int ret, n; |
296 | 240 | ||
297 | switch(cmd) { | 241 | switch(cmd) { |
@@ -299,7 +243,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
299 | if (!capable(CAP_SYS_ADMIN)) | 243 | if (!capable(CAP_SYS_ADMIN)) |
300 | return -EACCES; | 244 | return -EACCES; |
301 | 245 | ||
302 | ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); | 246 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
303 | /* -EINVAL to handle old uncorrected drivers */ | 247 | /* -EINVAL to handle old uncorrected drivers */ |
304 | if (ret != -EINVAL && ret != -ENOTTY) | 248 | if (ret != -EINVAL && ret != -ENOTTY) |
305 | return ret; | 249 | return ret; |
@@ -311,7 +255,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
311 | return 0; | 255 | return 0; |
312 | 256 | ||
313 | case BLKROSET: | 257 | case BLKROSET: |
314 | ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); | 258 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
315 | /* -EINVAL to handle old uncorrected drivers */ | 259 | /* -EINVAL to handle old uncorrected drivers */ |
316 | if (ret != -EINVAL && ret != -ENOTTY) | 260 | if (ret != -EINVAL && ret != -ENOTTY) |
317 | return ret; | 261 | return ret; |
@@ -327,7 +271,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
327 | case BLKDISCARD: { | 271 | case BLKDISCARD: { |
328 | uint64_t range[2]; | 272 | uint64_t range[2]; |
329 | 273 | ||
330 | if (!(file->f_mode & FMODE_WRITE)) | 274 | if (!(mode & FMODE_WRITE)) |
331 | return -EBADF; | 275 | return -EBADF; |
332 | 276 | ||
333 | if (copy_from_user(range, (void __user *)arg, sizeof(range))) | 277 | if (copy_from_user(range, (void __user *)arg, sizeof(range))) |
@@ -357,14 +301,75 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
357 | return -EFAULT; | 301 | return -EFAULT; |
358 | return 0; | 302 | return 0; |
359 | } | 303 | } |
360 | } | 304 | case BLKRAGET: |
361 | 305 | case BLKFRAGET: | |
362 | lock_kernel(); | 306 | if (!arg) |
363 | ret = blkdev_locked_ioctl(file, bdev, cmd, arg); | 307 | return -EINVAL; |
364 | unlock_kernel(); | 308 | bdi = blk_get_backing_dev_info(bdev); |
365 | if (ret != -ENOIOCTLCMD) | 309 | if (bdi == NULL) |
310 | return -ENOTTY; | ||
311 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); | ||
312 | case BLKROGET: | ||
313 | return put_int(arg, bdev_read_only(bdev) != 0); | ||
314 | case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ | ||
315 | return put_int(arg, block_size(bdev)); | ||
316 | case BLKSSZGET: /* get block device hardware sector size */ | ||
317 | return put_int(arg, bdev_hardsect_size(bdev)); | ||
318 | case BLKSECTGET: | ||
319 | return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); | ||
320 | case BLKRASET: | ||
321 | case BLKFRASET: | ||
322 | if(!capable(CAP_SYS_ADMIN)) | ||
323 | return -EACCES; | ||
324 | bdi = blk_get_backing_dev_info(bdev); | ||
325 | if (bdi == NULL) | ||
326 | return -ENOTTY; | ||
327 | lock_kernel(); | ||
328 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | ||
329 | unlock_kernel(); | ||
330 | return 0; | ||
331 | case BLKBSZSET: | ||
332 | /* set the logical block size */ | ||
333 | if (!capable(CAP_SYS_ADMIN)) | ||
334 | return -EACCES; | ||
335 | if (!arg) | ||
336 | return -EINVAL; | ||
337 | if (get_user(n, (int __user *) arg)) | ||
338 | return -EFAULT; | ||
339 | if (!(mode & FMODE_EXCL) && bd_claim(bdev, &bdev) < 0) | ||
340 | return -EBUSY; | ||
341 | ret = set_blocksize(bdev, n); | ||
342 | if (!(mode & FMODE_EXCL)) | ||
343 | bd_release(bdev); | ||
366 | return ret; | 344 | return ret; |
367 | 345 | case BLKPG: | |
368 | return blkdev_driver_ioctl(inode, file, disk, cmd, arg); | 346 | lock_kernel(); |
347 | ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); | ||
348 | unlock_kernel(); | ||
349 | break; | ||
350 | case BLKRRPART: | ||
351 | lock_kernel(); | ||
352 | ret = blkdev_reread_part(bdev); | ||
353 | unlock_kernel(); | ||
354 | break; | ||
355 | case BLKGETSIZE: | ||
356 | size = bdev->bd_inode->i_size; | ||
357 | if ((size >> 9) > ~0UL) | ||
358 | return -EFBIG; | ||
359 | return put_ulong(arg, size >> 9); | ||
360 | case BLKGETSIZE64: | ||
361 | return put_u64(arg, bdev->bd_inode->i_size); | ||
362 | case BLKTRACESTART: | ||
363 | case BLKTRACESTOP: | ||
364 | case BLKTRACESETUP: | ||
365 | case BLKTRACETEARDOWN: | ||
366 | lock_kernel(); | ||
367 | ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg); | ||
368 | unlock_kernel(); | ||
369 | break; | ||
370 | default: | ||
371 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); | ||
372 | } | ||
373 | return ret; | ||
369 | } | 374 | } |
370 | EXPORT_SYMBOL_GPL(blkdev_ioctl); | 375 | EXPORT_SYMBOL_GPL(blkdev_ioctl); |