aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index f066ccb5dddf..ad1983524f97 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1009,6 +1009,85 @@ out:
1009 return ret; 1009 return ret;
1010} 1010}
1011 1011
1012static noinline int btrfs_ioctl_subvol_getflags(struct file *file,
1013 void __user *arg)
1014{
1015 struct inode *inode = fdentry(file)->d_inode;
1016 struct btrfs_root *root = BTRFS_I(inode)->root;
1017 int ret = 0;
1018 u64 flags = 0;
1019
1020 if (inode->i_ino != BTRFS_FIRST_FREE_OBJECTID)
1021 return -EINVAL;
1022
1023 down_read(&root->fs_info->subvol_sem);
1024 if (btrfs_root_readonly(root))
1025 flags |= BTRFS_SUBVOL_RDONLY;
1026 up_read(&root->fs_info->subvol_sem);
1027
1028 if (copy_to_user(arg, &flags, sizeof(flags)))
1029 ret = -EFAULT;
1030
1031 return ret;
1032}
1033
1034static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
1035 void __user *arg)
1036{
1037 struct inode *inode = fdentry(file)->d_inode;
1038 struct btrfs_root *root = BTRFS_I(inode)->root;
1039 struct btrfs_trans_handle *trans;
1040 u64 root_flags;
1041 u64 flags;
1042 int ret = 0;
1043
1044 if (root->fs_info->sb->s_flags & MS_RDONLY)
1045 return -EROFS;
1046
1047 if (inode->i_ino != BTRFS_FIRST_FREE_OBJECTID)
1048 return -EINVAL;
1049
1050 if (copy_from_user(&flags, arg, sizeof(flags)))
1051 return -EFAULT;
1052
1053 if (flags & ~BTRFS_SUBVOL_CREATE_ASYNC)
1054 return -EINVAL;
1055
1056 if (flags & ~BTRFS_SUBVOL_RDONLY)
1057 return -EOPNOTSUPP;
1058
1059 down_write(&root->fs_info->subvol_sem);
1060
1061 /* nothing to do */
1062 if (!!(flags & BTRFS_SUBVOL_RDONLY) == btrfs_root_readonly(root))
1063 goto out;
1064
1065 root_flags = btrfs_root_flags(&root->root_item);
1066 if (flags & BTRFS_SUBVOL_RDONLY)
1067 btrfs_set_root_flags(&root->root_item,
1068 root_flags | BTRFS_ROOT_SUBVOL_RDONLY);
1069 else
1070 btrfs_set_root_flags(&root->root_item,
1071 root_flags & ~BTRFS_ROOT_SUBVOL_RDONLY);
1072
1073 trans = btrfs_start_transaction(root, 1);
1074 if (IS_ERR(trans)) {
1075 ret = PTR_ERR(trans);
1076 goto out_reset;
1077 }
1078
1079 ret = btrfs_update_root(trans, root,
1080 &root->root_key, &root->root_item);
1081
1082 btrfs_commit_transaction(trans, root);
1083out_reset:
1084 if (ret)
1085 btrfs_set_root_flags(&root->root_item, root_flags);
1086out:
1087 up_write(&root->fs_info->subvol_sem);
1088 return ret;
1089}
1090
1012/* 1091/*
1013 * helper to check if the subvolume references other subvolumes 1092 * helper to check if the subvolume references other subvolumes
1014 */ 1093 */
@@ -2282,6 +2361,10 @@ long btrfs_ioctl(struct file *file, unsigned int
2282 return btrfs_ioctl_snap_create(file, argp, 1); 2361 return btrfs_ioctl_snap_create(file, argp, 1);
2283 case BTRFS_IOC_SNAP_DESTROY: 2362 case BTRFS_IOC_SNAP_DESTROY:
2284 return btrfs_ioctl_snap_destroy(file, argp); 2363 return btrfs_ioctl_snap_destroy(file, argp);
2364 case BTRFS_IOC_SUBVOL_GETFLAGS:
2365 return btrfs_ioctl_subvol_getflags(file, argp);
2366 case BTRFS_IOC_SUBVOL_SETFLAGS:
2367 return btrfs_ioctl_subvol_setflags(file, argp);
2285 case BTRFS_IOC_DEFAULT_SUBVOL: 2368 case BTRFS_IOC_DEFAULT_SUBVOL:
2286 return btrfs_ioctl_default_subvol(file, argp); 2369 return btrfs_ioctl_default_subvol(file, argp);
2287 case BTRFS_IOC_DEFRAG: 2370 case BTRFS_IOC_DEFRAG: