diff options
author | Steve French <sfrench@us.ibm.com> | 2008-04-24 11:26:50 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-04-24 11:26:50 -0400 |
commit | 36d99df2fb474222ab47fbe8ae7385661033223b (patch) | |
tree | 962e068491b752a944f61c454fad3f8619a1ea3f /fs/xfs/linux-2.6/xfs_ioctl.c | |
parent | 076d8423a98659a92837b07aa494cb74bfefe77c (diff) | |
parent | 3dc5063786b273f1aee545844f6bd4e9651ebffe (diff) |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_ioctl.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 689 |
1 files changed, 321 insertions, 368 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index f34bd010eb51..4ddb86b73c6b 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -535,8 +535,6 @@ xfs_attrmulti_attr_set( | |||
535 | char *kbuf; | 535 | char *kbuf; |
536 | int error = EFAULT; | 536 | int error = EFAULT; |
537 | 537 | ||
538 | if (IS_RDONLY(inode)) | ||
539 | return -EROFS; | ||
540 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 538 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
541 | return EPERM; | 539 | return EPERM; |
542 | if (len > XATTR_SIZE_MAX) | 540 | if (len > XATTR_SIZE_MAX) |
@@ -562,8 +560,6 @@ xfs_attrmulti_attr_remove( | |||
562 | char *name, | 560 | char *name, |
563 | __uint32_t flags) | 561 | __uint32_t flags) |
564 | { | 562 | { |
565 | if (IS_RDONLY(inode)) | ||
566 | return -EROFS; | ||
567 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 563 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
568 | return EPERM; | 564 | return EPERM; |
569 | return xfs_attr_remove(XFS_I(inode), name, flags); | 565 | return xfs_attr_remove(XFS_I(inode), name, flags); |
@@ -573,6 +569,7 @@ STATIC int | |||
573 | xfs_attrmulti_by_handle( | 569 | xfs_attrmulti_by_handle( |
574 | xfs_mount_t *mp, | 570 | xfs_mount_t *mp, |
575 | void __user *arg, | 571 | void __user *arg, |
572 | struct file *parfilp, | ||
576 | struct inode *parinode) | 573 | struct inode *parinode) |
577 | { | 574 | { |
578 | int error; | 575 | int error; |
@@ -626,13 +623,21 @@ xfs_attrmulti_by_handle( | |||
626 | &ops[i].am_length, ops[i].am_flags); | 623 | &ops[i].am_length, ops[i].am_flags); |
627 | break; | 624 | break; |
628 | case ATTR_OP_SET: | 625 | case ATTR_OP_SET: |
626 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); | ||
627 | if (ops[i].am_error) | ||
628 | break; | ||
629 | ops[i].am_error = xfs_attrmulti_attr_set(inode, | 629 | ops[i].am_error = xfs_attrmulti_attr_set(inode, |
630 | attr_name, ops[i].am_attrvalue, | 630 | attr_name, ops[i].am_attrvalue, |
631 | ops[i].am_length, ops[i].am_flags); | 631 | ops[i].am_length, ops[i].am_flags); |
632 | mnt_drop_write(parfilp->f_path.mnt); | ||
632 | break; | 633 | break; |
633 | case ATTR_OP_REMOVE: | 634 | case ATTR_OP_REMOVE: |
635 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); | ||
636 | if (ops[i].am_error) | ||
637 | break; | ||
634 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, | 638 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, |
635 | attr_name, ops[i].am_flags); | 639 | attr_name, ops[i].am_flags); |
640 | mnt_drop_write(parfilp->f_path.mnt); | ||
636 | break; | 641 | break; |
637 | default: | 642 | default: |
638 | ops[i].am_error = EINVAL; | 643 | ops[i].am_error = EINVAL; |
@@ -651,314 +656,6 @@ xfs_attrmulti_by_handle( | |||
651 | return -error; | 656 | return -error; |
652 | } | 657 | } |
653 | 658 | ||
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 | 659 | STATIC int |
963 | xfs_ioc_space( | 660 | xfs_ioc_space( |
964 | struct xfs_inode *ip, | 661 | struct xfs_inode *ip, |
@@ -1179,85 +876,85 @@ xfs_ioc_fsgetxattr( | |||
1179 | } | 876 | } |
1180 | 877 | ||
1181 | STATIC int | 878 | STATIC int |
1182 | xfs_ioc_xattr( | 879 | xfs_ioc_fssetxattr( |
1183 | xfs_inode_t *ip, | 880 | xfs_inode_t *ip, |
1184 | struct file *filp, | 881 | struct file *filp, |
1185 | unsigned int cmd, | ||
1186 | void __user *arg) | 882 | void __user *arg) |
1187 | { | 883 | { |
1188 | struct fsxattr fa; | 884 | struct fsxattr fa; |
1189 | struct bhv_vattr *vattr; | 885 | struct bhv_vattr *vattr; |
1190 | int error = 0; | 886 | int error; |
1191 | int attr_flags; | 887 | int attr_flags; |
1192 | unsigned int flags; | 888 | |
889 | if (copy_from_user(&fa, arg, sizeof(fa))) | ||
890 | return -EFAULT; | ||
1193 | 891 | ||
1194 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); | 892 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
1195 | if (unlikely(!vattr)) | 893 | if (unlikely(!vattr)) |
1196 | return -ENOMEM; | 894 | return -ENOMEM; |
1197 | 895 | ||
1198 | switch (cmd) { | 896 | attr_flags = 0; |
1199 | case XFS_IOC_FSSETXATTR: { | 897 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
1200 | if (copy_from_user(&fa, arg, sizeof(fa))) { | 898 | attr_flags |= ATTR_NONBLOCK; |
1201 | error = -EFAULT; | ||
1202 | break; | ||
1203 | } | ||
1204 | 899 | ||
1205 | attr_flags = 0; | 900 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; |
1206 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 901 | vattr->va_xflags = fa.fsx_xflags; |
1207 | attr_flags |= ATTR_NONBLOCK; | 902 | vattr->va_extsize = fa.fsx_extsize; |
903 | vattr->va_projid = fa.fsx_projid; | ||
1208 | 904 | ||
1209 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; | 905 | error = -xfs_setattr(ip, vattr, attr_flags, NULL); |
1210 | vattr->va_xflags = fa.fsx_xflags; | 906 | if (!error) |
1211 | vattr->va_extsize = fa.fsx_extsize; | 907 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ |
1212 | vattr->va_projid = fa.fsx_projid; | 908 | kfree(vattr); |
909 | return 0; | ||
910 | } | ||
1213 | 911 | ||
1214 | error = xfs_setattr(ip, vattr, attr_flags, NULL); | 912 | STATIC int |
1215 | if (likely(!error)) | 913 | xfs_ioc_getxflags( |
1216 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | 914 | xfs_inode_t *ip, |
1217 | error = -error; | 915 | void __user *arg) |
1218 | break; | 916 | { |
1219 | } | 917 | unsigned int flags; |
1220 | 918 | ||
1221 | case XFS_IOC_GETXFLAGS: { | 919 | flags = xfs_di2lxflags(ip->i_d.di_flags); |
1222 | flags = xfs_di2lxflags(ip->i_d.di_flags); | 920 | if (copy_to_user(arg, &flags, sizeof(flags))) |
1223 | if (copy_to_user(arg, &flags, sizeof(flags))) | 921 | return -EFAULT; |
1224 | error = -EFAULT; | 922 | return 0; |
1225 | break; | 923 | } |
1226 | } | ||
1227 | 924 | ||
1228 | case XFS_IOC_SETXFLAGS: { | 925 | STATIC int |
1229 | if (copy_from_user(&flags, arg, sizeof(flags))) { | 926 | xfs_ioc_setxflags( |
1230 | error = -EFAULT; | 927 | xfs_inode_t *ip, |
1231 | break; | 928 | struct file *filp, |
1232 | } | 929 | void __user *arg) |
930 | { | ||
931 | struct bhv_vattr *vattr; | ||
932 | unsigned int flags; | ||
933 | int attr_flags; | ||
934 | int error; | ||
1233 | 935 | ||
1234 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ | 936 | if (copy_from_user(&flags, arg, sizeof(flags))) |
1235 | FS_NOATIME_FL | FS_NODUMP_FL | \ | 937 | return -EFAULT; |
1236 | FS_SYNC_FL)) { | ||
1237 | error = -EOPNOTSUPP; | ||
1238 | break; | ||
1239 | } | ||
1240 | 938 | ||
1241 | attr_flags = 0; | 939 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ |
1242 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) | 940 | FS_NOATIME_FL | FS_NODUMP_FL | \ |
1243 | attr_flags |= ATTR_NONBLOCK; | 941 | FS_SYNC_FL)) |
942 | return -EOPNOTSUPP; | ||
1244 | 943 | ||
1245 | vattr->va_mask = XFS_AT_XFLAGS; | 944 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
1246 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, | 945 | if (unlikely(!vattr)) |
1247 | xfs_ip2xflags(ip)); | 946 | return -ENOMEM; |
1248 | 947 | ||
1249 | error = xfs_setattr(ip, vattr, attr_flags, NULL); | 948 | attr_flags = 0; |
1250 | if (likely(!error)) | 949 | if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) |
1251 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | 950 | attr_flags |= ATTR_NONBLOCK; |
1252 | error = -error; | ||
1253 | break; | ||
1254 | } | ||
1255 | 951 | ||
1256 | default: | 952 | vattr->va_mask = XFS_AT_XFLAGS; |
1257 | error = -ENOTTY; | 953 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); |
1258 | break; | ||
1259 | } | ||
1260 | 954 | ||
955 | error = -xfs_setattr(ip, vattr, attr_flags, NULL); | ||
956 | if (likely(!error)) | ||
957 | vn_revalidate(XFS_ITOV(ip)); /* update flags */ | ||
1261 | kfree(vattr); | 958 | kfree(vattr); |
1262 | return error; | 959 | return error; |
1263 | } | 960 | } |
@@ -1332,3 +1029,259 @@ xfs_ioc_getbmapx( | |||
1332 | 1029 | ||
1333 | return 0; | 1030 | return 0; |
1334 | } | 1031 | } |
1032 | |||
1033 | int | ||
1034 | xfs_ioctl( | ||
1035 | xfs_inode_t *ip, | ||
1036 | struct file *filp, | ||
1037 | int ioflags, | ||
1038 | unsigned int cmd, | ||
1039 | void __user *arg) | ||
1040 | { | ||
1041 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1042 | xfs_mount_t *mp = ip->i_mount; | ||
1043 | int error; | ||
1044 | |||
1045 | xfs_itrace_entry(XFS_I(inode)); | ||
1046 | switch (cmd) { | ||
1047 | |||
1048 | case XFS_IOC_ALLOCSP: | ||
1049 | case XFS_IOC_FREESP: | ||
1050 | case XFS_IOC_RESVSP: | ||
1051 | case XFS_IOC_UNRESVSP: | ||
1052 | case XFS_IOC_ALLOCSP64: | ||
1053 | case XFS_IOC_FREESP64: | ||
1054 | case XFS_IOC_RESVSP64: | ||
1055 | case XFS_IOC_UNRESVSP64: | ||
1056 | /* | ||
1057 | * Only allow the sys admin to reserve space unless | ||
1058 | * unwritten extents are enabled. | ||
1059 | */ | ||
1060 | if (!xfs_sb_version_hasextflgbit(&mp->m_sb) && | ||
1061 | !capable(CAP_SYS_ADMIN)) | ||
1062 | return -EPERM; | ||
1063 | |||
1064 | return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg); | ||
1065 | |||
1066 | case XFS_IOC_DIOINFO: { | ||
1067 | struct dioattr da; | ||
1068 | xfs_buftarg_t *target = | ||
1069 | XFS_IS_REALTIME_INODE(ip) ? | ||
1070 | mp->m_rtdev_targp : mp->m_ddev_targp; | ||
1071 | |||
1072 | da.d_mem = da.d_miniosz = 1 << target->bt_sshift; | ||
1073 | da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); | ||
1074 | |||
1075 | if (copy_to_user(arg, &da, sizeof(da))) | ||
1076 | return -XFS_ERROR(EFAULT); | ||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1080 | case XFS_IOC_FSBULKSTAT_SINGLE: | ||
1081 | case XFS_IOC_FSBULKSTAT: | ||
1082 | case XFS_IOC_FSINUMBERS: | ||
1083 | return xfs_ioc_bulkstat(mp, cmd, arg); | ||
1084 | |||
1085 | case XFS_IOC_FSGEOMETRY_V1: | ||
1086 | return xfs_ioc_fsgeometry_v1(mp, arg); | ||
1087 | |||
1088 | case XFS_IOC_FSGEOMETRY: | ||
1089 | return xfs_ioc_fsgeometry(mp, arg); | ||
1090 | |||
1091 | case XFS_IOC_GETVERSION: | ||
1092 | return put_user(inode->i_generation, (int __user *)arg); | ||
1093 | |||
1094 | case XFS_IOC_FSGETXATTR: | ||
1095 | return xfs_ioc_fsgetxattr(ip, 0, arg); | ||
1096 | case XFS_IOC_FSGETXATTRA: | ||
1097 | return xfs_ioc_fsgetxattr(ip, 1, arg); | ||
1098 | case XFS_IOC_FSSETXATTR: | ||
1099 | return xfs_ioc_fssetxattr(ip, filp, arg); | ||
1100 | case XFS_IOC_GETXFLAGS: | ||
1101 | return xfs_ioc_getxflags(ip, arg); | ||
1102 | case XFS_IOC_SETXFLAGS: | ||
1103 | return xfs_ioc_setxflags(ip, filp, arg); | ||
1104 | |||
1105 | case XFS_IOC_FSSETDM: { | ||
1106 | struct fsdmidata dmi; | ||
1107 | |||
1108 | if (copy_from_user(&dmi, arg, sizeof(dmi))) | ||
1109 | return -XFS_ERROR(EFAULT); | ||
1110 | |||
1111 | error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, | ||
1112 | dmi.fsd_dmstate); | ||
1113 | return -error; | ||
1114 | } | ||
1115 | |||
1116 | case XFS_IOC_GETBMAP: | ||
1117 | case XFS_IOC_GETBMAPA: | ||
1118 | return xfs_ioc_getbmap(ip, ioflags, cmd, arg); | ||
1119 | |||
1120 | case XFS_IOC_GETBMAPX: | ||
1121 | return xfs_ioc_getbmapx(ip, arg); | ||
1122 | |||
1123 | case XFS_IOC_FD_TO_HANDLE: | ||
1124 | case XFS_IOC_PATH_TO_HANDLE: | ||
1125 | case XFS_IOC_PATH_TO_FSHANDLE: | ||
1126 | return xfs_find_handle(cmd, arg); | ||
1127 | |||
1128 | case XFS_IOC_OPEN_BY_HANDLE: | ||
1129 | return xfs_open_by_handle(mp, arg, filp, inode); | ||
1130 | |||
1131 | case XFS_IOC_FSSETDM_BY_HANDLE: | ||
1132 | return xfs_fssetdm_by_handle(mp, arg, inode); | ||
1133 | |||
1134 | case XFS_IOC_READLINK_BY_HANDLE: | ||
1135 | return xfs_readlink_by_handle(mp, arg, inode); | ||
1136 | |||
1137 | case XFS_IOC_ATTRLIST_BY_HANDLE: | ||
1138 | return xfs_attrlist_by_handle(mp, arg, inode); | ||
1139 | |||
1140 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | ||
1141 | return xfs_attrmulti_by_handle(mp, arg, filp, inode); | ||
1142 | |||
1143 | case XFS_IOC_SWAPEXT: { | ||
1144 | error = xfs_swapext((struct xfs_swapext __user *)arg); | ||
1145 | return -error; | ||
1146 | } | ||
1147 | |||
1148 | case XFS_IOC_FSCOUNTS: { | ||
1149 | xfs_fsop_counts_t out; | ||
1150 | |||
1151 | error = xfs_fs_counts(mp, &out); | ||
1152 | if (error) | ||
1153 | return -error; | ||
1154 | |||
1155 | if (copy_to_user(arg, &out, sizeof(out))) | ||
1156 | return -XFS_ERROR(EFAULT); | ||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | case XFS_IOC_SET_RESBLKS: { | ||
1161 | xfs_fsop_resblks_t inout; | ||
1162 | __uint64_t in; | ||
1163 | |||
1164 | if (!capable(CAP_SYS_ADMIN)) | ||
1165 | return -EPERM; | ||
1166 | |||
1167 | if (copy_from_user(&inout, arg, sizeof(inout))) | ||
1168 | return -XFS_ERROR(EFAULT); | ||
1169 | |||
1170 | /* input parameter is passed in resblks field of structure */ | ||
1171 | in = inout.resblks; | ||
1172 | error = xfs_reserve_blocks(mp, &in, &inout); | ||
1173 | if (error) | ||
1174 | return -error; | ||
1175 | |||
1176 | if (copy_to_user(arg, &inout, sizeof(inout))) | ||
1177 | return -XFS_ERROR(EFAULT); | ||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | case XFS_IOC_GET_RESBLKS: { | ||
1182 | xfs_fsop_resblks_t out; | ||
1183 | |||
1184 | if (!capable(CAP_SYS_ADMIN)) | ||
1185 | return -EPERM; | ||
1186 | |||
1187 | error = xfs_reserve_blocks(mp, NULL, &out); | ||
1188 | if (error) | ||
1189 | return -error; | ||
1190 | |||
1191 | if (copy_to_user(arg, &out, sizeof(out))) | ||
1192 | return -XFS_ERROR(EFAULT); | ||
1193 | |||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | case XFS_IOC_FSGROWFSDATA: { | ||
1198 | xfs_growfs_data_t in; | ||
1199 | |||
1200 | if (!capable(CAP_SYS_ADMIN)) | ||
1201 | return -EPERM; | ||
1202 | |||
1203 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1204 | return -XFS_ERROR(EFAULT); | ||
1205 | |||
1206 | error = xfs_growfs_data(mp, &in); | ||
1207 | return -error; | ||
1208 | } | ||
1209 | |||
1210 | case XFS_IOC_FSGROWFSLOG: { | ||
1211 | xfs_growfs_log_t in; | ||
1212 | |||
1213 | if (!capable(CAP_SYS_ADMIN)) | ||
1214 | return -EPERM; | ||
1215 | |||
1216 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1217 | return -XFS_ERROR(EFAULT); | ||
1218 | |||
1219 | error = xfs_growfs_log(mp, &in); | ||
1220 | return -error; | ||
1221 | } | ||
1222 | |||
1223 | case XFS_IOC_FSGROWFSRT: { | ||
1224 | xfs_growfs_rt_t in; | ||
1225 | |||
1226 | if (!capable(CAP_SYS_ADMIN)) | ||
1227 | return -EPERM; | ||
1228 | |||
1229 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1230 | return -XFS_ERROR(EFAULT); | ||
1231 | |||
1232 | error = xfs_growfs_rt(mp, &in); | ||
1233 | return -error; | ||
1234 | } | ||
1235 | |||
1236 | case XFS_IOC_FREEZE: | ||
1237 | if (!capable(CAP_SYS_ADMIN)) | ||
1238 | return -EPERM; | ||
1239 | |||
1240 | if (inode->i_sb->s_frozen == SB_UNFROZEN) | ||
1241 | freeze_bdev(inode->i_sb->s_bdev); | ||
1242 | return 0; | ||
1243 | |||
1244 | case XFS_IOC_THAW: | ||
1245 | if (!capable(CAP_SYS_ADMIN)) | ||
1246 | return -EPERM; | ||
1247 | if (inode->i_sb->s_frozen != SB_UNFROZEN) | ||
1248 | thaw_bdev(inode->i_sb->s_bdev, inode->i_sb); | ||
1249 | return 0; | ||
1250 | |||
1251 | case XFS_IOC_GOINGDOWN: { | ||
1252 | __uint32_t in; | ||
1253 | |||
1254 | if (!capable(CAP_SYS_ADMIN)) | ||
1255 | return -EPERM; | ||
1256 | |||
1257 | if (get_user(in, (__uint32_t __user *)arg)) | ||
1258 | return -XFS_ERROR(EFAULT); | ||
1259 | |||
1260 | error = xfs_fs_goingdown(mp, in); | ||
1261 | return -error; | ||
1262 | } | ||
1263 | |||
1264 | case XFS_IOC_ERROR_INJECTION: { | ||
1265 | xfs_error_injection_t in; | ||
1266 | |||
1267 | if (!capable(CAP_SYS_ADMIN)) | ||
1268 | return -EPERM; | ||
1269 | |||
1270 | if (copy_from_user(&in, arg, sizeof(in))) | ||
1271 | return -XFS_ERROR(EFAULT); | ||
1272 | |||
1273 | error = xfs_errortag_add(in.errtag, mp); | ||
1274 | return -error; | ||
1275 | } | ||
1276 | |||
1277 | case XFS_IOC_ERROR_CLEARALL: | ||
1278 | if (!capable(CAP_SYS_ADMIN)) | ||
1279 | return -EPERM; | ||
1280 | |||
1281 | error = xfs_errortag_clearall(mp, 1); | ||
1282 | return -error; | ||
1283 | |||
1284 | default: | ||
1285 | return -ENOTTY; | ||
1286 | } | ||
1287 | } | ||