diff options
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r-- | fs/ioctl.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c index 82d9c42b8bac..5612880fcbe7 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
16 | #include <linux/writeback.h> | 16 | #include <linux/writeback.h> |
17 | #include <linux/buffer_head.h> | 17 | #include <linux/buffer_head.h> |
18 | #include <linux/falloc.h> | ||
18 | 19 | ||
19 | #include <asm/ioctls.h> | 20 | #include <asm/ioctls.h> |
20 | 21 | ||
@@ -70,9 +71,7 @@ static int ioctl_fibmap(struct file *filp, int __user *p) | |||
70 | res = get_user(block, p); | 71 | res = get_user(block, p); |
71 | if (res) | 72 | if (res) |
72 | return res; | 73 | return res; |
73 | lock_kernel(); | ||
74 | res = mapping->a_ops->bmap(mapping, block); | 74 | res = mapping->a_ops->bmap(mapping, block); |
75 | unlock_kernel(); | ||
76 | return put_user(res, p); | 75 | return put_user(res, p); |
77 | } | 76 | } |
78 | 77 | ||
@@ -405,6 +404,37 @@ EXPORT_SYMBOL(generic_block_fiemap); | |||
405 | 404 | ||
406 | #endif /* CONFIG_BLOCK */ | 405 | #endif /* CONFIG_BLOCK */ |
407 | 406 | ||
407 | /* | ||
408 | * This provides compatibility with legacy XFS pre-allocation ioctls | ||
409 | * which predate the fallocate syscall. | ||
410 | * | ||
411 | * Only the l_start, l_len and l_whence fields of the 'struct space_resv' | ||
412 | * are used here, rest are ignored. | ||
413 | */ | ||
414 | int ioctl_preallocate(struct file *filp, void __user *argp) | ||
415 | { | ||
416 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
417 | struct space_resv sr; | ||
418 | |||
419 | if (copy_from_user(&sr, argp, sizeof(sr))) | ||
420 | return -EFAULT; | ||
421 | |||
422 | switch (sr.l_whence) { | ||
423 | case SEEK_SET: | ||
424 | break; | ||
425 | case SEEK_CUR: | ||
426 | sr.l_start += filp->f_pos; | ||
427 | break; | ||
428 | case SEEK_END: | ||
429 | sr.l_start += i_size_read(inode); | ||
430 | break; | ||
431 | default: | ||
432 | return -EINVAL; | ||
433 | } | ||
434 | |||
435 | return do_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len); | ||
436 | } | ||
437 | |||
408 | static int file_ioctl(struct file *filp, unsigned int cmd, | 438 | static int file_ioctl(struct file *filp, unsigned int cmd, |
409 | unsigned long arg) | 439 | unsigned long arg) |
410 | { | 440 | { |
@@ -414,12 +444,11 @@ static int file_ioctl(struct file *filp, unsigned int cmd, | |||
414 | switch (cmd) { | 444 | switch (cmd) { |
415 | case FIBMAP: | 445 | case FIBMAP: |
416 | return ioctl_fibmap(filp, p); | 446 | return ioctl_fibmap(filp, p); |
417 | case FS_IOC_FIEMAP: | ||
418 | return ioctl_fiemap(filp, arg); | ||
419 | case FIGETBSZ: | ||
420 | return put_user(inode->i_sb->s_blocksize, p); | ||
421 | case FIONREAD: | 447 | case FIONREAD: |
422 | return put_user(i_size_read(inode) - filp->f_pos, p); | 448 | return put_user(i_size_read(inode) - filp->f_pos, p); |
449 | case FS_IOC_RESVSP: | ||
450 | case FS_IOC_RESVSP64: | ||
451 | return ioctl_preallocate(filp, p); | ||
423 | } | 452 | } |
424 | 453 | ||
425 | return vfs_ioctl(filp, cmd, arg); | 454 | return vfs_ioctl(filp, cmd, arg); |
@@ -557,6 +586,16 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | |||
557 | error = ioctl_fsthaw(filp); | 586 | error = ioctl_fsthaw(filp); |
558 | break; | 587 | break; |
559 | 588 | ||
589 | case FS_IOC_FIEMAP: | ||
590 | return ioctl_fiemap(filp, arg); | ||
591 | |||
592 | case FIGETBSZ: | ||
593 | { | ||
594 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
595 | int __user *p = (int __user *)arg; | ||
596 | return put_user(inode->i_sb->s_blocksize, p); | ||
597 | } | ||
598 | |||
560 | default: | 599 | default: |
561 | if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) | 600 | if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) |
562 | error = file_ioctl(filp, cmd, arg); | 601 | error = file_ioctl(filp, cmd, arg); |