diff options
Diffstat (limited to 'fs/nilfs2/ioctl.c')
| -rw-r--r-- | fs/nilfs2/ioctl.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index f2469ba6246b..41d6743d303c 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -698,6 +698,63 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, | |||
| 698 | return 0; | 698 | return 0; |
| 699 | } | 699 | } |
| 700 | 700 | ||
| 701 | static int nilfs_ioctl_resize(struct inode *inode, struct file *filp, | ||
| 702 | void __user *argp) | ||
| 703 | { | ||
| 704 | __u64 newsize; | ||
| 705 | int ret = -EPERM; | ||
| 706 | |||
| 707 | if (!capable(CAP_SYS_ADMIN)) | ||
| 708 | goto out; | ||
| 709 | |||
| 710 | ret = mnt_want_write(filp->f_path.mnt); | ||
| 711 | if (ret) | ||
| 712 | goto out; | ||
| 713 | |||
| 714 | ret = -EFAULT; | ||
| 715 | if (copy_from_user(&newsize, argp, sizeof(newsize))) | ||
| 716 | goto out_drop_write; | ||
| 717 | |||
| 718 | ret = nilfs_resize_fs(inode->i_sb, newsize); | ||
| 719 | |||
| 720 | out_drop_write: | ||
| 721 | mnt_drop_write(filp->f_path.mnt); | ||
| 722 | out: | ||
| 723 | return ret; | ||
| 724 | } | ||
| 725 | |||
| 726 | static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp) | ||
| 727 | { | ||
| 728 | struct the_nilfs *nilfs = inode->i_sb->s_fs_info; | ||
| 729 | __u64 range[2]; | ||
| 730 | __u64 minseg, maxseg; | ||
| 731 | unsigned long segbytes; | ||
| 732 | int ret = -EPERM; | ||
| 733 | |||
| 734 | if (!capable(CAP_SYS_ADMIN)) | ||
| 735 | goto out; | ||
| 736 | |||
| 737 | ret = -EFAULT; | ||
| 738 | if (copy_from_user(range, argp, sizeof(__u64[2]))) | ||
| 739 | goto out; | ||
| 740 | |||
| 741 | ret = -ERANGE; | ||
| 742 | if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode)) | ||
| 743 | goto out; | ||
| 744 | |||
| 745 | segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize; | ||
| 746 | |||
| 747 | minseg = range[0] + segbytes - 1; | ||
| 748 | do_div(minseg, segbytes); | ||
| 749 | maxseg = NILFS_SB2_OFFSET_BYTES(range[1]); | ||
| 750 | do_div(maxseg, segbytes); | ||
| 751 | maxseg--; | ||
| 752 | |||
| 753 | ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg); | ||
| 754 | out: | ||
| 755 | return ret; | ||
| 756 | } | ||
| 757 | |||
| 701 | static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, | 758 | static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, |
| 702 | unsigned int cmd, void __user *argp, | 759 | unsigned int cmd, void __user *argp, |
| 703 | size_t membsz, | 760 | size_t membsz, |
| @@ -763,6 +820,10 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 763 | return nilfs_ioctl_clean_segments(inode, filp, cmd, argp); | 820 | return nilfs_ioctl_clean_segments(inode, filp, cmd, argp); |
| 764 | case NILFS_IOCTL_SYNC: | 821 | case NILFS_IOCTL_SYNC: |
| 765 | return nilfs_ioctl_sync(inode, filp, cmd, argp); | 822 | return nilfs_ioctl_sync(inode, filp, cmd, argp); |
| 823 | case NILFS_IOCTL_RESIZE: | ||
| 824 | return nilfs_ioctl_resize(inode, filp, argp); | ||
| 825 | case NILFS_IOCTL_SET_ALLOC_RANGE: | ||
| 826 | return nilfs_ioctl_set_alloc_range(inode, argp); | ||
| 766 | default: | 827 | default: |
| 767 | return -ENOTTY; | 828 | return -ENOTTY; |
| 768 | } | 829 | } |
