diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_ioctl.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 676 |
1 files changed, 312 insertions, 364 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index f34bd010eb51..bf7759793856 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -651,314 +651,6 @@ xfs_attrmulti_by_handle( | |||
651 | return -error; | 651 | return -error; |
652 | } | 652 | } |
653 | 653 | ||
654 | /* prototypes for a few of the stack-hungry cases that have | ||
655 | * their own functions. Functions are defined after their use | ||
656 | * so gcc doesn't get fancy and inline them with -03 */ | ||
657 | |||
658 | STATIC int | ||
659 | xfs_ioc_space( | ||
660 | struct xfs_inode *ip, | ||
661 | struct inode *inode, | ||
662 | struct file *filp, | ||
663 | int flags, | ||
664 | unsigned int cmd, | ||
665 | void __user *arg); | ||
666 | |||
667 | STATIC int | ||
668 | xfs_ioc_bulkstat( | ||
669 | xfs_mount_t *mp, | ||
670 | unsigned int cmd, | ||
671 | void __user *arg); | ||
672 | |||
673 | STATIC int | ||
674 | xfs_ioc_fsgeometry_v1( | ||
675 | xfs_mount_t *mp, | ||
676 | void __user *arg); | ||
677 | |||
678 | STATIC int | ||
679 | xfs_ioc_fsgeometry( | ||
680 | xfs_mount_t *mp, | ||
681 | void __user *arg); | ||
682 | |||
683 | STATIC int | ||
684 | xfs_ioc_xattr( | ||
685 | xfs_inode_t *ip, | ||
686 | struct file *filp, | ||
687 | unsigned int cmd, | ||
688 | void __user *arg); | ||
689 | |||
690 | STATIC int | ||
691 | xfs_ioc_fsgetxattr( | ||
692 | xfs_inode_t *ip, | ||
693 | int attr, | ||
694 | void __user *arg); | ||
695 | |||
696 | STATIC int | ||
697 | xfs_ioc_getbmap( | ||
698 | struct xfs_inode *ip, | ||
699 | int flags, | ||
700 | unsigned int cmd, | ||
701 | void __user *arg); | ||
702 | |||
703 | STATIC int | ||
704 | xfs_ioc_getbmapx( | ||
705 | struct xfs_inode *ip, | ||
706 | void __user *arg); | ||
707 | |||
708 | int | ||
709 | xfs_ioctl( | ||
710 | xfs_inode_t *ip, | ||
711 | struct file *filp, | ||
712 | int ioflags, | ||
713 | unsigned int cmd, | ||
714 | void __user *arg) | ||
715 | { | ||
716 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
717 | xfs_mount_t *mp = ip->i_mount; | ||
718 | int error; | ||
719 | |||
720 | xfs_itrace_entry(XFS_I(inode)); | ||
721 | switch (cmd) { | ||
722 | |||
723 | case XFS_IOC_ALLOCSP: | ||
724 | case XFS_IOC_FREESP: | ||
725 | case XFS_IOC_RESVSP: | ||
726 | case XFS_IOC_UNRESVSP: | ||
727 | case XFS_IOC_ALLOCSP64: | ||
728 | case XFS_IOC_FREESP64: | ||
729 | case XFS_IOC_RESVSP64: | ||
730 | case XFS_IOC_UNRESVSP64: | ||
731 | /* | ||
732 | * Only allow the sys admin to reserve space unless | ||
733 | * unwritten extents are enabled. | ||
734 | */ | ||
735 | if (!xfs_sb_version_hasextflgbit(&mp->m_sb) && | ||
736 | !capable(CAP_SYS_ADMIN)) | ||
737 | return -EPERM; | ||
738 | |||
739 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg); | ||
740 | |||
741 | case XFS_IOC_DIOINFO: { | ||
742 | struct dioattr da; | ||
743 | xfs_buftarg_t *target = | ||
744 | XFS_IS_REALTIME_INODE(ip) ? | ||
745 | mp->m_rtdev_targp : mp->m_ddev_targp; | ||
746 | |||
747 | da.d_mem = da.d_miniosz = 1 << target->bt_sshift; | ||
748 | da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); | ||
749 | |||
750 | if (copy_to_user(arg, &da, sizeof(da))) | ||
751 | return -XFS_ERROR(EFAULT); | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | case XFS_IOC_FSBULKSTAT_SINGLE: | ||
756 | case XFS_IOC_FSBULKSTAT: | ||
757 | case XFS_IOC_FSINUMBERS: | ||
758 | return xfs_ioc_bulkstat(mp, cmd, arg); | ||
759 | |||
760 | case XFS_IOC_FSGEOMETRY_V1: | ||
761 | return xfs_ioc_fsgeometry_v1(mp, arg); | ||
762 | |||
763 | case XFS_IOC_FSGEOMETRY: | ||
764 | return xfs_ioc_fsgeometry(mp, arg); | ||
765 | |||
766 | case XFS_IOC_GETVERSION: | ||
767 | return put_user(inode->i_generation, (int __user *)arg); | ||
768 | |||
769 | case XFS_IOC_FSGETXATTR: | ||
770 | return xfs_ioc_fsgetxattr(ip, 0, arg); | ||
771 | case XFS_IOC_FSGETXATTRA: | ||
772 | return xfs_ioc_fsgetxattr(ip, 1, arg); | ||
773 | case XFS_IOC_GETXFLAGS: | ||
774 | case XFS_IOC_SETXFLAGS: | ||
775 | case XFS_IOC_FSSETXATTR: | ||
776 | return xfs_ioc_xattr(ip, filp, cmd, arg); | ||
777 | |||
778 | case XFS_IOC_FSSETDM: { | ||
779 | struct fsdmidata dmi; | ||
780 | |||
781 | if (copy_from_user(&dmi, arg, sizeof(dmi))) | ||
782 | return -XFS_ERROR(EFAULT); | ||
783 | |||
784 | error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, | ||
785 | dmi.fsd_dmstate); | ||
786 | return -error; | ||
787 | } | ||
788 | |||
789 | case XFS_IOC_GETBMAP: | ||
790 | case XFS_IOC_GETBMAPA: | ||
791 | return xfs_ioc_getbmap(ip, ioflags, cmd, arg); | ||
792 | |||
793 | case XFS_IOC_GETBMAPX: | ||
794 | return xfs_ioc_getbmapx(ip, arg); | ||
795 | |||
796 | case XFS_IOC_FD_TO_HANDLE: | ||
797 | case XFS_IOC_PATH_TO_HANDLE: | ||
798 | case XFS_IOC_PATH_TO_FSHANDLE: | ||
799 | return xfs_find_handle(cmd, arg); | ||
800 | |||
801 | case XFS_IOC_OPEN_BY_HANDLE: | ||
802 | return xfs_open_by_handle(mp, arg, filp, inode); | ||
803 | |||
804 | case XFS_IOC_FSSETDM_BY_HANDLE: | ||
805 | return xfs_fssetdm_by_handle(mp, arg, inode); | ||
806 | |||
807 | case XFS_IOC_READLINK_BY_HANDLE: | ||
808 | return xfs_readlink_by_handle(mp, arg, inode); | ||
809 | |||
810 | case XFS_IOC_ATTRLIST_BY_HANDLE: | ||
811 | return xfs_attrlist_by_handle(mp, arg, inode); | ||
812 | |||
813 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | ||
814 | return xfs_attrmulti_by_handle(mp, arg, inode); | ||
815 | |||
816 | case XFS_IOC_SWAPEXT: { | ||
817 | error = xfs_swapext((struct xfs_swapext __user *)arg); | ||
818 | return -error; | ||
819 | } | ||
820 | |||
821 | case XFS_IOC_FSCOUNTS: { | ||
822 | xfs_fsop_counts_t out; | ||
823 | |||
824 | error = xfs_fs_counts(mp, &out); | ||
825 | if (error) | ||
826 | return -error; | ||
827 | |||
828 | if (copy_to_user(arg, &out, sizeof(out))) | ||
829 | return -XFS_ERROR(EFAULT); | ||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | case XFS_IOC_SET_RESBLKS: { | ||
834 | xfs_fsop_resblks_t inout; | ||
835 | __uint64_t in; | ||
836 | |||
837 | if (!capable(CAP_SYS_ADMIN)) | ||
838 | return -EPERM; | ||
839 | |||
840 | if (copy_from_user(&inout, arg, sizeof(inout))) | ||
841 | return -XFS_ERROR(EFAULT); | ||
842 | |||
843 | /* input parameter is passed in resblks field of structure */ | ||
844 | in = inout.resblks; | ||
845 | error = xfs_reserve_blocks(mp, &in, &inout); | ||
846 | if (error) | ||
847 | return -error; | ||
848 | |||
849 | if (copy_to_user(arg, &inout, sizeof(inout))) | ||
850 | return -XFS_ERROR(EFAULT); | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | case XFS_IOC_GET_RESBLKS: { | ||
855 | xfs_fsop_resblks_t out; | ||
856 | |||
857 | if (!capable(CAP_SYS_ADMIN)) | ||
858 | return -EPERM; | ||
859 | |||
860 | error = xfs_reserve_blocks(mp, NULL, &out); | ||
861 | if (error) | ||
862 | return -error; | ||
863 | |||
864 | if (copy_to_user(arg, &out, sizeof(out))) | ||
865 | return -XFS_ERROR(EFAULT); | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | case XFS_IOC_FSGROWFSDATA: { | ||
871 | xfs_growfs_data_t in; | ||
872 | |||
873 | if (!capable(CAP_SYS_ADMIN)) | ||
874 | return -EPERM; | ||
875 | |||
876 | if (copy_from_user(&in, arg, sizeof(in))) | ||
877 | return -XFS_ERROR(EFAULT); | ||
878 | |||
879 | error = xfs_growfs_data(mp, &in); | ||
880 | return -error; | ||
881 | } | ||
882 | |||
883 | case XFS_IOC_FSGROWFSLOG: { | ||
884 | xfs_growfs_log_t in; | ||
885 | |||
886 | if (!capable(CAP_SYS_ADMIN)) | ||
887 | return -EPERM; | ||
888 | |||
889 | if (copy_from_user(&in, arg, sizeof(in))) | ||
890 | return -XFS_ERROR(EFAULT); | ||
891 | |||
892 | error = xfs_growfs_log(mp, &in); | ||
893 | return -error; | ||
894 | } | ||
895 | |||
896 | case XFS_IOC_FSGROWFSRT: { | ||
897 | xfs_growfs_rt_t in; | ||
898 | |||
899 | if (!capable(CAP_SYS_ADMIN)) | ||
900 | return -EPERM; | ||
901 | |||
902 | if (copy_from_user(&in, arg, sizeof(in))) | ||
903 | return -XFS_ERROR(EFAULT); | ||
904 | |||
905 | error = xfs_growfs_rt(mp, &in); | ||
906 | return -error; | ||
907 | } | ||
908 | |||
909 | case XFS_IOC_FREEZE: | ||
910 | if (!capable(CAP_SYS_ADMIN)) | ||
911 | return -EPERM; | ||
912 | |||
913 | if (inode->i_sb->s_frozen == SB_UNFROZEN) | ||
914 | freeze_bdev(inode->i_sb->s_bdev); | ||
915 | return 0; | ||
916 | |||
917 | case XFS_IOC_THAW: | ||
918 | if (!capable(CAP_SYS_ADMIN)) | ||
919 | return -EPERM; | ||
920 | if (inode->i_sb->s_frozen != SB_UNFROZEN) | ||
921 | thaw_bdev(inode->i_sb->s_bdev, inode->i_sb); | ||
922 | return 0; | ||
923 | |||
924 | case XFS_IOC_GOINGDOWN: { | ||
925 | __uint32_t in; | ||
926 | |||
927 | if (!capable(CAP_SYS_ADMIN)) | ||
928 | return -EPERM; | ||
929 | |||
930 | if (get_user(in, (__uint32_t __user *)arg)) | ||
931 | return -XFS_ERROR(EFAULT); | ||
932 | |||
933 | error = xfs_fs_goingdown(mp, in); | ||
934 | return -error; | ||
935 | } | ||
936 | |||
937 | case XFS_IOC_ERROR_INJECTION: { | ||
938 | xfs_error_injection_t in; | ||
939 | |||
940 | if (!capable(CAP_SYS_ADMIN)) | ||
941 | return -EPERM; | ||
942 | |||
943 | if (copy_from_user(&in, arg, sizeof(in))) | ||
944 | return -XFS_ERROR(EFAULT); | ||
945 | |||
946 | error = xfs_errortag_add(in.errtag, mp); | ||
947 | return -error; | ||
948 | } | ||
949 | |||
950 | case XFS_IOC_ERROR_CLEARALL: | ||
951 | if (!capable(CAP_SYS_ADMIN)) | ||
952 | return -EPERM; | ||
953 | |||
954 | error = xfs_errortag_clearall(mp, 1); | ||
955 | return -error; | ||
956 | |||
957 | default: | ||
958 | return -ENOTTY; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | STATIC int | 654 | STATIC int |
963 | xfs_ioc_space( | 655 | xfs_ioc_space( |
964 | struct xfs_inode *ip, | 656 | struct xfs_inode *ip, |
@@ -1179,85 +871,85 @@ xfs_ioc_fsgetxattr( | |||
1179 | } | 871 | } |
1180 | 872 | ||
1181 | STATIC int | 873 | STATIC int |
1182 | xfs_ioc_xattr( | 874 | xfs_ioc_fssetxattr( |
1183 | xfs_inode_t *ip, | 875 | xfs_inode_t *ip, |
1184 | struct file *filp, | 876 | struct file *filp, |
1185 | unsigned int cmd, | ||
1186 | void __user *arg) | 877 | void __user *arg) |
1187 | { | 878 | { |
1188 | struct fsxattr fa; | 879 | struct fsxattr fa; |
1189 | struct bhv_vattr *vattr; | 880 | struct bhv_vattr *vattr; |
1190 | int error = 0; | 881 | int error; |
1191 | int attr_flags; | 882 | int attr_flags; |
1192 | unsigned int flags; | 883 | |
884 | if (copy_from_user(&fa, arg, sizeof(fa))) | ||
885 | return -EFAULT; | ||
1193 | 886 | ||
1194 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); | 887 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
1195 | if (unlikely(!vattr)) | 888 | if (unlikely(!vattr)) |
1196 | return -ENOMEM; | 889 | return -ENOMEM; |
1197 | 890 | ||
1198 | switch (cmd) { | 891 | attr_flags = 0; |
1199 | case XFS_IOC_FSSETXATTR: { | 892 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
1200 | if (copy_from_user(&fa, arg, sizeof(fa))) { | 893 | attr_flags |= ATTR_NONBLOCK; |
1201 | error = -EFAULT; | ||
1202 | break; | ||
1203 | } | ||
1204 | 894 | ||
1205 | attr_flags = 0; | 895 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; |
1206 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 896 | vattr->va_xflags = fa.fsx_xflags; |
1207 | attr_flags |= ATTR_NONBLOCK; | 897 | vattr->va_extsize = fa.fsx_extsize; |
898 | vattr->va_projid = fa.fsx_projid; | ||
1208 | 899 | ||
1209 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; | 900 | error = -xfs_setattr(ip, vattr, attr_flags, NULL); |
1210 | vattr->va_xflags = fa.fsx_xflags; | 901 | if (!error) |
1211 | vattr->va_extsize = fa.fsx_extsize; | 902 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ |
1212 | vattr->va_projid = fa.fsx_projid; | 903 | kfree(vattr); |
904 | return 0; | ||
905 | } | ||
1213 | 906 | ||
1214 | error = xfs_setattr(ip, vattr, attr_flags, NULL); | 907 | STATIC int |
1215 | if (likely(!error)) | 908 | xfs_ioc_getxflags( |
1216 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | 909 | xfs_inode_t *ip, |
1217 | error = -error; | 910 | void __user *arg) |
1218 | break; | 911 | { |
1219 | } | 912 | unsigned int flags; |
1220 | 913 | ||
1221 | case XFS_IOC_GETXFLAGS: { | 914 | flags = xfs_di2lxflags(ip->i_d.di_flags); |
1222 | flags = xfs_di2lxflags(ip->i_d.di_flags); | 915 | if (copy_to_user(arg, &flags, sizeof(flags))) |
1223 | if (copy_to_user(arg, &flags, sizeof(flags))) | 916 | return -EFAULT; |
1224 | error = -EFAULT; | 917 | return 0; |
1225 | break; | 918 | } |
1226 | } | ||
1227 | 919 | ||
1228 | case XFS_IOC_SETXFLAGS: { | 920 | STATIC int |
1229 | if (copy_from_user(&flags, arg, sizeof(flags))) { | 921 | xfs_ioc_setxflags( |
1230 | error = -EFAULT; | 922 | xfs_inode_t *ip, |
1231 | break; | 923 | struct file *filp, |
1232 | } | 924 | void __user *arg) |
925 | { | ||
926 | struct bhv_vattr *vattr; | ||
927 | unsigned int flags; | ||
928 | int attr_flags; | ||
929 | int error; | ||
1233 | 930 | ||
1234 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ | 931 | if (copy_from_user(&flags, arg, sizeof(flags))) |
1235 | FS_NOATIME_FL | FS_NODUMP_FL | \ | 932 | return -EFAULT; |
1236 | FS_SYNC_FL)) { | ||
1237 | error = -EOPNOTSUPP; | ||
1238 | break; | ||
1239 | } | ||
1240 | 933 | ||
1241 | attr_flags = 0; | 934 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ |
1242 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 935 | FS_NOATIME_FL | FS_NODUMP_FL | \ |
1243 | attr_flags |= ATTR_NONBLOCK; | 936 | FS_SYNC_FL)) |
937 | return -EOPNOTSUPP; | ||
1244 | 938 | ||
1245 | vattr->va_mask = XFS_AT_XFLAGS; | 939 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
1246 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, | 940 | if (unlikely(!vattr)) |
1247 | xfs_ip2xflags(ip)); | 941 | return -ENOMEM; |
1248 | 942 | ||
1249 | error = xfs_setattr(ip, vattr, attr_flags, NULL); | 943 | attr_flags = 0; |
1250 | if (likely(!error)) | 944 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
1251 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | 945 | attr_flags |= ATTR_NONBLOCK; |
1252 | error = -error; | ||
1253 | break; | ||
1254 | } | ||
1255 | 946 | ||
1256 | default: | 947 | vattr->va_mask = XFS_AT_XFLAGS; |
1257 | error = -ENOTTY; | 948 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); |
1258 | break; | ||
1259 | } | ||
1260 | 949 | ||
950 | error = -xfs_setattr(ip, vattr, attr_flags, NULL); | ||
951 | if (likely(!error)) | ||
952 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | ||
1261 | kfree(vattr); | 953 | kfree(vattr); |
1262 | return error; | 954 | return error; |
1263 | } | 955 | } |
@@ -1332,3 +1024,259 @@ xfs_ioc_getbmapx( | |||
1332 | 1024 | ||
1333 | return 0; | 1025 | return 0; |
1334 | } | 1026 | } |
1027 | |||
1028 | int | ||
1029 | xfs_ioctl( | ||
1030 | xfs_inode_t *ip, | ||
1031 | struct file *filp, | ||
1032 | int ioflags, | ||
1033 | unsigned int cmd, | ||
1034 | void __user *arg) | ||
1035 | { | ||
1036 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1037 | xfs_mount_t *mp = ip->i_mount; | ||
1038 | int error; | ||
1039 | |||
1040 | xfs_itrace_entry(XFS_I(inode)); | ||
1041 | switch (cmd) { | ||
1042 | |||
1043 | case XFS_IOC_ALLOCSP: | ||
1044 | case XFS_IOC_FREESP: | ||
1045 | case XFS_IOC_RESVSP: | ||
1046 | case XFS_IOC_UNRESVSP: | ||
1047 | case XFS_IOC_ALLOCSP64: | ||
1048 | case XFS_IOC_FREESP64: | ||
1049 | case XFS_IOC_RESVSP64: | ||
1050 | case XFS_IOC_UNRESVSP64: | ||
1051 | /* | ||
1052 | * Only allow the sys admin to reserve space unless | ||
1053 | * unwritten extents are enabled. | ||
1054 | */ | ||
1055 | if (!xfs_sb_version_hasextflgbit(&mp->m_sb) && | ||
1056 | !capable(CAP_SYS_ADMIN)) | ||
1057 | return -EPERM; | ||
1058 | |||
1059 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg); | ||
1060 | |||
1061 | case XFS_IOC_DIOINFO: { | ||
1062 | struct dioattr da; | ||
1063 | xfs_buftarg_t *target = | ||
1064 | XFS_IS_REALTIME_INODE(ip) ? | ||
1065 | mp->m_rtdev_targp : mp->m_ddev_targp; | ||
1066 | |||
1067 | da.d_mem = da.d_miniosz = 1 << target->bt_sshift; | ||
1068 | da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); | ||
1069 | |||
1070 | if (copy_to_user(arg, &da, sizeof(da))) | ||
1071 | return -XFS_ERROR(EFAULT); | ||
1072 | return 0; | ||
1073 | } | ||
1074 | |||
1075 | case XFS_IOC_FSBULKSTAT_SINGLE: | ||
1076 | case XFS_IOC_FSBULKSTAT: | ||
1077 | case XFS_IOC_FSINUMBERS: | ||
1078 | return xfs_ioc_bulkstat(mp, cmd, arg); | ||
1079 | |||
1080 | case XFS_IOC_FSGEOMETRY_V1: | ||
1081 | return xfs_ioc_fsgeometry_v1(mp, arg); | ||
1082 | |||
1083 | case XFS_IOC_FSGEOMETRY: | ||
1084 | return xfs_ioc_fsgeometry(mp, arg); | ||
1085 | |||
1086 | case XFS_IOC_GETVERSION: | ||
1087 | return put_user(inode->i_generation, (int __user *)arg); | ||
1088 | |||
1089 | case XFS_IOC_FSGETXATTR: | ||
1090 | return xfs_ioc_fsgetxattr(ip, 0, arg); | ||
1091 | case XFS_IOC_FSGETXATTRA: | ||
1092 | return xfs_ioc_fsgetxattr(ip, 1, arg); | ||
1093 | case XFS_IOC_FSSETXATTR: | ||
1094 | return xfs_ioc_fssetxattr(ip, filp, arg); | ||
1095 | case XFS_IOC_GETXFLAGS: | ||
1096 | return xfs_ioc_getxflags(ip, arg); | ||
1097 | case XFS_IOC_SETXFLAGS: | ||
1098 | return xfs_ioc_setxflags(ip, filp, arg); | ||
1099 | |||
1100 | case XFS_IOC_FSSETDM: { | ||
1101 | struct fsdmidata dmi; | ||
1102 | |||
1103 | if (copy_from_user(&dmi, arg, sizeof(dmi))) | ||
1104 | return -XFS_ERROR(EFAULT); | ||
1105 | |||
1106 | error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, | ||
1107 | dmi.fsd_dmstate); | ||
1108 | return -error; | ||
1109 | } | ||
1110 | |||
1111 | case XFS_IOC_GETBMAP: | ||
1112 | case XFS_IOC_GETBMAPA: | ||
1113 | return xfs_ioc_getbmap(ip, ioflags, cmd, arg); | ||
1114 | |||
1115 | case XFS_IOC_GETBMAPX: | ||
1116 | return xfs_ioc_getbmapx(ip, arg); | ||
1117 | |||
1118 | case XFS_IOC_FD_TO_HANDLE: | ||
1119 | case XFS_IOC_PATH_TO_HANDLE: | ||
1120 | case XFS_IOC_PATH_TO_FSHANDLE: | ||
1121 | return xfs_find_handle(cmd, arg); | ||
1122 | |||
1123 | case XFS_IOC_OPEN_BY_HANDLE: | ||
1124 | return xfs_open_by_handle(mp, arg, filp, inode); | ||
1125 | |||
1126 | case XFS_IOC_FSSETDM_BY_HANDLE: | ||
1127 | return xfs_fssetdm_by_handle(mp, arg, inode); | ||
1128 | |||
1129 | case XFS_IOC_READLINK_BY_HANDLE: | ||
1130 | return xfs_readlink_by_handle(mp, arg, inode); | ||
1131 | |||
1132 | case XFS_IOC_ATTRLIST_BY_HANDLE: | ||
1133 | return xfs_attrlist_by_handle(mp, arg, inode); | ||
1134 | |||
1135 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | ||
1136 | return xfs_attrmulti_by_handle(mp, arg, inode); | ||
1137 | |||
1138 | case XFS_IOC_SWAPEXT: { | ||
1139 | error = xfs_swapext((struct xfs_swapext __user *)arg); | ||
1140 | return -error; | ||
1141 | } | ||
1142 | |||
1143 | case XFS_IOC_FSCOUNTS: { | ||
1144 | xfs_fsop_counts_t out; | ||
1145 | |||
1146 | error = xfs_fs_counts(mp, &out); | ||
1147 | if (error) | ||
1148 | return -error; | ||
1149 | |||
1150 | if (copy_to_user(arg, &out, sizeof(out))) | ||
1151 | return -XFS_ERROR(EFAULT); | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | case XFS_IOC_SET_RESBLKS: { | ||
1156 | xfs_fsop_resblks_t inout; | ||
1157 | __uint64_t in; | ||
1158 | |||
1159 | if (!capable(CAP_SYS_ADMIN)) | ||
1160 | return -EPERM; | ||
1161 | |||
1162 | if (copy_from_user(&inout, arg, sizeof(inout))) | ||
1163 | return -XFS_ERROR(EFAULT); | ||
1164 | |||
1165 | /* input parameter is passed in resblks field of structure */ | ||
1166 | in = inout.resblks; | ||
1167 | error = xfs_reserve_blocks(mp, &in, &inout); | ||
1168 | if (error) | ||
1169 | return -error; | ||
1170 | |||
1171 | if (copy_to_user(arg, &inout, sizeof(inout))) | ||
1172 | return -XFS_ERROR(EFAULT); | ||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | case XFS_IOC_GET_RESBLKS: { | ||
1177 | xfs_fsop_resblks_t out; | ||
1178 | |||
1179 | if (!capable(CAP_SYS_ADMIN)) | ||
1180 | return -EPERM; | ||
1181 | |||
1182 | error = xfs_reserve_blocks(mp, NULL, &out); | ||
1183 | if (error) | ||
1184 | return -error; | ||
1185 | |||
1186 | if (copy_to_user(arg, &out, sizeof(out))) | ||
1187 | return -XFS_ERROR(EFAULT); | ||
1188 | |||
1189 | return 0; | ||
1190 | } | ||
1191 | |||
1192 | case XFS_IOC_FSGROWFSDATA: { | ||
1193 | xfs_growfs_data_t in; | ||
1194 | |||
1195 | if (!capable(CAP_SYS_ADMIN)) | ||
1196 | return -EPERM; | ||
1197 | |||
1198 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1199 | return -XFS_ERROR(EFAULT); | ||
1200 | |||
1201 | error = xfs_growfs_data(mp, &in); | ||
1202 | return -error; | ||
1203 | } | ||
1204 | |||
1205 | case XFS_IOC_FSGROWFSLOG: { | ||
1206 | xfs_growfs_log_t in; | ||
1207 | |||
1208 | if (!capable(CAP_SYS_ADMIN)) | ||
1209 | return -EPERM; | ||
1210 | |||
1211 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1212 | return -XFS_ERROR(EFAULT); | ||
1213 | |||
1214 | error = xfs_growfs_log(mp, &in); | ||
1215 | return -error; | ||
1216 | } | ||
1217 | |||
1218 | case XFS_IOC_FSGROWFSRT: { | ||
1219 | xfs_growfs_rt_t in; | ||
1220 | |||
1221 | if (!capable(CAP_SYS_ADMIN)) | ||
1222 | return -EPERM; | ||
1223 | |||
1224 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1225 | return -XFS_ERROR(EFAULT); | ||
1226 | |||
1227 | error = xfs_growfs_rt(mp, &in); | ||
1228 | return -error; | ||
1229 | } | ||
1230 | |||
1231 | case XFS_IOC_FREEZE: | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | ||
1233 | return -EPERM; | ||
1234 | |||
1235 | if (inode->i_sb->s_frozen == SB_UNFROZEN) | ||
1236 | freeze_bdev(inode->i_sb->s_bdev); | ||
1237 | return 0; | ||
1238 | |||
1239 | case XFS_IOC_THAW: | ||
1240 | if (!capable(CAP_SYS_ADMIN)) | ||
1241 | return -EPERM; | ||
1242 | if (inode->i_sb->s_frozen != SB_UNFROZEN) | ||
1243 | thaw_bdev(inode->i_sb->s_bdev, inode->i_sb); | ||
1244 | return 0; | ||
1245 | |||
1246 | case XFS_IOC_GOINGDOWN: { | ||
1247 | __uint32_t in; | ||
1248 | |||
1249 | if (!capable(CAP_SYS_ADMIN)) | ||
1250 | return -EPERM; | ||
1251 | |||
1252 | if (get_user(in, (__uint32_t __user *)arg)) | ||
1253 | return -XFS_ERROR(EFAULT); | ||
1254 | |||
1255 | error = xfs_fs_goingdown(mp, in); | ||
1256 | return -error; | ||
1257 | } | ||
1258 | |||
1259 | case XFS_IOC_ERROR_INJECTION: { | ||
1260 | xfs_error_injection_t in; | ||
1261 | |||
1262 | if (!capable(CAP_SYS_ADMIN)) | ||
1263 | return -EPERM; | ||
1264 | |||
1265 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1266 | return -XFS_ERROR(EFAULT); | ||
1267 | |||
1268 | error = xfs_errortag_add(in.errtag, mp); | ||
1269 | return -error; | ||
1270 | } | ||
1271 | |||
1272 | case XFS_IOC_ERROR_CLEARALL: | ||
1273 | if (!capable(CAP_SYS_ADMIN)) | ||
1274 | return -EPERM; | ||
1275 | |||
1276 | error = xfs_errortag_clearall(mp, 1); | ||
1277 | return -error; | ||
1278 | |||
1279 | default: | ||
1280 | return -ENOTTY; | ||
1281 | } | ||
1282 | } | ||