aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2010-12-20 03:04:08 -0500
committerLi Zefan <lizf@cn.fujitsu.com>2010-12-22 19:49:17 -0500
commitb83cc9693f39689490970c19f6c5b866f6719a70 (patch)
treeb86d09884015fce195a4ac5ff1e8ec5f6ec00677 /fs/btrfs/ioctl.c
parentfa0d2b9bd717340e0bc4850a80ac0eb344e9a7fb (diff)
Btrfs: Add readonly snapshots support
Usage: Set BTRFS_SUBVOL_RDONLY of btrfs_ioctl_vol_arg_v2->flags, and call ioctl(BTRFS_I0CTL_SNAP_CREATE_V2). Implementation: - Set readonly bit of btrfs_root_item->flags. - Add readonly checks in btrfs_permission (inode_permission), btrfs_setattr, btrfs_set/remove_xattr and some ioctls. Changelog for v3: - Eliminate btrfs_root->readonly, but check btrfs_root->root_item.flags. - Rename BTRFS_ROOT_SNAP_RDONLY to BTRFS_ROOT_SUBVOL_RDONLY. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 02554e19d974..f066ccb5dddf 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -147,6 +147,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
147 unsigned int flags, oldflags; 147 unsigned int flags, oldflags;
148 int ret; 148 int ret;
149 149
150 if (btrfs_root_readonly(root))
151 return -EROFS;
152
150 if (copy_from_user(&flags, arg, sizeof(flags))) 153 if (copy_from_user(&flags, arg, sizeof(flags)))
151 return -EFAULT; 154 return -EFAULT;
152 155
@@ -360,7 +363,8 @@ fail:
360} 363}
361 364
362static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, 365static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
363 char *name, int namelen, u64 *async_transid) 366 char *name, int namelen, u64 *async_transid,
367 bool readonly)
364{ 368{
365 struct inode *inode; 369 struct inode *inode;
366 struct dentry *parent; 370 struct dentry *parent;
@@ -378,6 +382,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
378 btrfs_init_block_rsv(&pending_snapshot->block_rsv); 382 btrfs_init_block_rsv(&pending_snapshot->block_rsv);
379 pending_snapshot->dentry = dentry; 383 pending_snapshot->dentry = dentry;
380 pending_snapshot->root = root; 384 pending_snapshot->root = root;
385 pending_snapshot->readonly = readonly;
381 386
382 trans = btrfs_start_transaction(root->fs_info->extent_root, 5); 387 trans = btrfs_start_transaction(root->fs_info->extent_root, 5);
383 if (IS_ERR(trans)) { 388 if (IS_ERR(trans)) {
@@ -509,7 +514,7 @@ static inline int btrfs_may_create(struct inode *dir, struct dentry *child)
509static noinline int btrfs_mksubvol(struct path *parent, 514static noinline int btrfs_mksubvol(struct path *parent,
510 char *name, int namelen, 515 char *name, int namelen,
511 struct btrfs_root *snap_src, 516 struct btrfs_root *snap_src,
512 u64 *async_transid) 517 u64 *async_transid, bool readonly)
513{ 518{
514 struct inode *dir = parent->dentry->d_inode; 519 struct inode *dir = parent->dentry->d_inode;
515 struct dentry *dentry; 520 struct dentry *dentry;
@@ -541,7 +546,7 @@ static noinline int btrfs_mksubvol(struct path *parent,
541 546
542 if (snap_src) { 547 if (snap_src) {
543 error = create_snapshot(snap_src, dentry, 548 error = create_snapshot(snap_src, dentry,
544 name, namelen, async_transid); 549 name, namelen, async_transid, readonly);
545 } else { 550 } else {
546 error = create_subvol(BTRFS_I(dir)->root, dentry, 551 error = create_subvol(BTRFS_I(dir)->root, dentry,
547 name, namelen, async_transid); 552 name, namelen, async_transid);
@@ -901,7 +906,8 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
901 char *name, 906 char *name,
902 unsigned long fd, 907 unsigned long fd,
903 int subvol, 908 int subvol,
904 u64 *transid) 909 u64 *transid,
910 bool readonly)
905{ 911{
906 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; 912 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
907 struct file *src_file; 913 struct file *src_file;
@@ -919,7 +925,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
919 925
920 if (subvol) { 926 if (subvol) {
921 ret = btrfs_mksubvol(&file->f_path, name, namelen, 927 ret = btrfs_mksubvol(&file->f_path, name, namelen,
922 NULL, transid); 928 NULL, transid, readonly);
923 } else { 929 } else {
924 struct inode *src_inode; 930 struct inode *src_inode;
925 src_file = fget(fd); 931 src_file = fget(fd);
@@ -938,7 +944,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
938 } 944 }
939 ret = btrfs_mksubvol(&file->f_path, name, namelen, 945 ret = btrfs_mksubvol(&file->f_path, name, namelen,
940 BTRFS_I(src_inode)->root, 946 BTRFS_I(src_inode)->root,
941 transid); 947 transid, readonly);
942 fput(src_file); 948 fput(src_file);
943 } 949 }
944out: 950out:
@@ -957,7 +963,8 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
957 vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; 963 vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
958 964
959 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, 965 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
960 vol_args->fd, subvol, NULL); 966 vol_args->fd, subvol,
967 NULL, false);
961 968
962 kfree(vol_args); 969 kfree(vol_args);
963 return ret; 970 return ret;
@@ -970,22 +977,27 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
970 int ret; 977 int ret;
971 u64 transid = 0; 978 u64 transid = 0;
972 u64 *ptr = NULL; 979 u64 *ptr = NULL;
980 bool readonly = false;
973 981
974 vol_args = memdup_user(arg, sizeof(*vol_args)); 982 vol_args = memdup_user(arg, sizeof(*vol_args));
975 if (IS_ERR(vol_args)) 983 if (IS_ERR(vol_args))
976 return PTR_ERR(vol_args); 984 return PTR_ERR(vol_args);
977 vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; 985 vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
978 986
979 if (vol_args->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) { 987 if (vol_args->flags &
980 ret = -EINVAL; 988 ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY)) {
989 ret = -EOPNOTSUPP;
981 goto out; 990 goto out;
982 } 991 }
983 992
984 if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC) 993 if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
985 ptr = &transid; 994 ptr = &transid;
995 if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
996 readonly = true;
986 997
987 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, 998 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
988 vol_args->fd, subvol, ptr); 999 vol_args->fd, subvol,
1000 ptr, readonly);
989 1001
990 if (ret == 0 && ptr && 1002 if (ret == 0 && ptr &&
991 copy_to_user(arg + 1003 copy_to_user(arg +
@@ -1505,6 +1517,9 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
1505 struct btrfs_ioctl_defrag_range_args *range; 1517 struct btrfs_ioctl_defrag_range_args *range;
1506 int ret; 1518 int ret;
1507 1519
1520 if (btrfs_root_readonly(root))
1521 return -EROFS;
1522
1508 ret = mnt_want_write(file->f_path.mnt); 1523 ret = mnt_want_write(file->f_path.mnt);
1509 if (ret) 1524 if (ret)
1510 return ret; 1525 return ret;
@@ -1633,6 +1648,9 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
1633 if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) 1648 if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND))
1634 return -EINVAL; 1649 return -EINVAL;
1635 1650
1651 if (btrfs_root_readonly(root))
1652 return -EROFS;
1653
1636 ret = mnt_want_write(file->f_path.mnt); 1654 ret = mnt_want_write(file->f_path.mnt);
1637 if (ret) 1655 if (ret)
1638 return ret; 1656 return ret;
@@ -1954,6 +1972,10 @@ static long btrfs_ioctl_trans_start(struct file *file)
1954 if (file->private_data) 1972 if (file->private_data)
1955 goto out; 1973 goto out;
1956 1974
1975 ret = -EROFS;
1976 if (btrfs_root_readonly(root))
1977 goto out;
1978
1957 ret = mnt_want_write(file->f_path.mnt); 1979 ret = mnt_want_write(file->f_path.mnt);
1958 if (ret) 1980 if (ret)
1959 goto out; 1981 goto out;