aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/f2fs/file.c138
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
808long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 808static 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) { 816static 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);
859out: 860out:
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)) 865static 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
895long 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 }