aboutsummaryrefslogtreecommitdiffstats
path: root/block/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/ioctl.c')
-rw-r--r--block/ioctl.c173
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
204static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, 204int __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
268int 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}
284EXPORT_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 */
227EXPORT_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 */
290int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, 233int 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}
370EXPORT_SYMBOL_GPL(blkdev_ioctl); 375EXPORT_SYMBOL_GPL(blkdev_ioctl);