diff options
| -rw-r--r-- | fs/f2fs/file.c | 138 |
1 files changed, 75 insertions, 63 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 11842076d960..735e9a20f939 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
| @@ -805,90 +805,102 @@ static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags) | |||
| 805 | return flags & F2FS_OTHER_FLMASK; | 805 | return flags & F2FS_OTHER_FLMASK; |
| 806 | } | 806 | } |
| 807 | 807 | ||
| 808 | long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 808 | static int f2fs_ioc_getflags(struct file *filp, unsigned long arg) |
| 809 | { | 809 | { |
| 810 | struct inode *inode = file_inode(filp); | 810 | struct inode *inode = file_inode(filp); |
| 811 | struct f2fs_inode_info *fi = F2FS_I(inode); | 811 | struct f2fs_inode_info *fi = F2FS_I(inode); |
| 812 | unsigned int flags; | 812 | unsigned int flags = fi->i_flags & FS_FL_USER_VISIBLE; |
| 813 | int ret; | 813 | return put_user(flags, (int __user *)arg); |
| 814 | } | ||
| 814 | 815 | ||
| 815 | switch (cmd) { | 816 | static int f2fs_ioc_setflags(struct file *filp, unsigned long arg) |
| 816 | case F2FS_IOC_GETFLAGS: | 817 | { |
| 817 | flags = fi->i_flags & FS_FL_USER_VISIBLE; | 818 | struct inode *inode = file_inode(filp); |
| 818 | return put_user(flags, (int __user *) arg); | 819 | struct f2fs_inode_info *fi = F2FS_I(inode); |
| 819 | case F2FS_IOC_SETFLAGS: | 820 | unsigned int flags = fi->i_flags & FS_FL_USER_VISIBLE; |
| 820 | { | 821 | unsigned int oldflags; |
| 821 | unsigned int oldflags; | 822 | int ret; |
| 822 | 823 | ||
| 823 | ret = mnt_want_write_file(filp); | 824 | ret = mnt_want_write_file(filp); |
| 824 | if (ret) | 825 | if (ret) |
| 825 | return ret; | 826 | return ret; |
| 826 | 827 | ||
| 827 | if (!inode_owner_or_capable(inode)) { | 828 | if (!inode_owner_or_capable(inode)) { |
| 828 | ret = -EACCES; | 829 | ret = -EACCES; |
| 829 | goto out; | 830 | goto out; |
| 830 | } | 831 | } |
| 831 | 832 | ||
| 832 | if (get_user(flags, (int __user *) arg)) { | 833 | if (get_user(flags, (int __user *)arg)) { |
| 833 | ret = -EFAULT; | 834 | ret = -EFAULT; |
| 834 | goto out; | 835 | goto out; |
| 835 | } | 836 | } |
| 836 | 837 | ||
| 837 | flags = f2fs_mask_flags(inode->i_mode, flags); | 838 | flags = f2fs_mask_flags(inode->i_mode, flags); |
| 838 | 839 | ||
| 839 | mutex_lock(&inode->i_mutex); | 840 | mutex_lock(&inode->i_mutex); |
| 840 | 841 | ||
| 841 | oldflags = fi->i_flags; | 842 | oldflags = fi->i_flags; |
| 842 | 843 | ||
| 843 | if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) { | 844 | if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) { |
| 844 | if (!capable(CAP_LINUX_IMMUTABLE)) { | 845 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
| 845 | mutex_unlock(&inode->i_mutex); | 846 | mutex_unlock(&inode->i_mutex); |
| 846 | ret = -EPERM; | 847 | ret = -EPERM; |
| 847 | goto out; | 848 | goto out; |
| 848 | } | ||
| 849 | } | 849 | } |
| 850 | } | ||
| 850 | 851 | ||
| 851 | flags = flags & FS_FL_USER_MODIFIABLE; | 852 | flags = flags & FS_FL_USER_MODIFIABLE; |
| 852 | flags |= oldflags & ~FS_FL_USER_MODIFIABLE; | 853 | flags |= oldflags & ~FS_FL_USER_MODIFIABLE; |
| 853 | fi->i_flags = flags; | 854 | fi->i_flags = flags; |
| 854 | mutex_unlock(&inode->i_mutex); | 855 | mutex_unlock(&inode->i_mutex); |
| 855 | 856 | ||
| 856 | f2fs_set_inode_flags(inode); | 857 | f2fs_set_inode_flags(inode); |
| 857 | inode->i_ctime = CURRENT_TIME; | 858 | inode->i_ctime = CURRENT_TIME; |
| 858 | mark_inode_dirty(inode); | 859 | mark_inode_dirty(inode); |
| 859 | out: | 860 | out: |
| 860 | mnt_drop_write_file(filp); | 861 | mnt_drop_write_file(filp); |
| 861 | return ret; | 862 | return ret; |
| 862 | } | 863 | } |
| 863 | case FITRIM: | ||
| 864 | { | ||
| 865 | struct super_block *sb = inode->i_sb; | ||
| 866 | struct request_queue *q = bdev_get_queue(sb->s_bdev); | ||
| 867 | struct fstrim_range range; | ||
| 868 | int ret = 0; | ||
| 869 | 864 | ||
| 870 | if (!capable(CAP_SYS_ADMIN)) | 865 | static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) |
| 871 | return -EPERM; | 866 | { |
| 867 | struct inode *inode = file_inode(filp); | ||
| 868 | struct super_block *sb = inode->i_sb; | ||
| 869 | struct request_queue *q = bdev_get_queue(sb->s_bdev); | ||
| 870 | struct fstrim_range range; | ||
| 871 | int ret; | ||
| 872 | 872 | ||
| 873 | if (!blk_queue_discard(q)) | 873 | if (!capable(CAP_SYS_ADMIN)) |
| 874 | return -EOPNOTSUPP; | 874 | return -EPERM; |
| 875 | 875 | ||
| 876 | if (copy_from_user(&range, (struct fstrim_range __user *)arg, | 876 | if (!blk_queue_discard(q)) |
| 877 | sizeof(range))) | 877 | return -EOPNOTSUPP; |
| 878 | return -EFAULT; | ||
| 879 | 878 | ||
| 880 | range.minlen = max((unsigned int)range.minlen, | 879 | if (copy_from_user(&range, (struct fstrim_range __user *)arg, |
| 881 | q->limits.discard_granularity); | 880 | sizeof(range))) |
| 882 | ret = f2fs_trim_fs(F2FS_SB(sb), &range); | 881 | return -EFAULT; |
| 883 | if (ret < 0) | ||
| 884 | return ret; | ||
| 885 | 882 | ||
| 886 | if (copy_to_user((struct fstrim_range __user *)arg, &range, | 883 | range.minlen = max((unsigned int)range.minlen, |
| 887 | sizeof(range))) | 884 | q->limits.discard_granularity); |
| 888 | return -EFAULT; | 885 | ret = f2fs_trim_fs(F2FS_SB(sb), &range); |
| 886 | if (ret < 0) | ||
| 887 | return ret; | ||
| 889 | 888 | ||
| 890 | return 0; | 889 | if (copy_to_user((struct fstrim_range __user *)arg, &range, |
| 891 | } | 890 | sizeof(range))) |
| 891 | return -EFAULT; | ||
| 892 | return 0; | ||
| 893 | } | ||
| 894 | |||
| 895 | long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
| 896 | { | ||
| 897 | switch (cmd) { | ||
| 898 | case F2FS_IOC_GETFLAGS: | ||
| 899 | return f2fs_ioc_getflags(filp, arg); | ||
| 900 | case F2FS_IOC_SETFLAGS: | ||
| 901 | return f2fs_ioc_setflags(filp, arg); | ||
| 902 | case FITRIM: | ||
| 903 | return f2fs_ioc_fitrim(filp, arg); | ||
| 892 | default: | 904 | default: |
| 893 | return -ENOTTY; | 905 | return -ENOTTY; |
| 894 | } | 906 | } |
