aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2011-01-16 11:24:45 -0500
committerChris Mason <chris.mason@oracle.com>2011-01-16 11:24:45 -0500
commit26c79f6ba0ccdc4bbc8ef8721406d37e9178e30b (patch)
treec5bcbf8f605afdae1a89ea2617f29052ac8c6f18 /fs
parent65e5341b9a0c39767ae1fecc727d70eda0dd6d83 (diff)
parent0caa102da82799efaba88e234484786a9591c797 (diff)
Merge branch 'readonly-snapshots' of git://repo.or.cz/linux-btrfs-devel into btrfs-38
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h7
-rw-r--r--fs/btrfs/inode.c8
-rw-r--r--fs/btrfs/ioctl.c199
-rw-r--r--fs/btrfs/ioctl.h3
-rw-r--r--fs/btrfs/transaction.c8
-rw-r--r--fs/btrfs/transaction.h1
-rw-r--r--fs/btrfs/xattr.c18
7 files changed, 195 insertions, 49 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index af52f6d7a4d8..4403e5643d43 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -597,6 +597,8 @@ struct btrfs_dir_item {
597 u8 type; 597 u8 type;
598} __attribute__ ((__packed__)); 598} __attribute__ ((__packed__));
599 599
600#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0)
601
600struct btrfs_root_item { 602struct btrfs_root_item {
601 struct btrfs_inode_item inode; 603 struct btrfs_inode_item inode;
602 __le64 generation; 604 __le64 generation;
@@ -1893,6 +1895,11 @@ BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64);
1893BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item, 1895BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
1894 last_snapshot, 64); 1896 last_snapshot, 64);
1895 1897
1898static inline bool btrfs_root_readonly(struct btrfs_root *root)
1899{
1900 return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY;
1901}
1902
1896/* struct btrfs_super_block */ 1903/* struct btrfs_super_block */
1897 1904
1898BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); 1905BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5f9194438f7c..956f1eb913b1 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3671,8 +3671,12 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
3671static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) 3671static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
3672{ 3672{
3673 struct inode *inode = dentry->d_inode; 3673 struct inode *inode = dentry->d_inode;
3674 struct btrfs_root *root = BTRFS_I(inode)->root;
3674 int err; 3675 int err;
3675 3676
3677 if (btrfs_root_readonly(root))
3678 return -EROFS;
3679
3676 err = inode_change_ok(inode, attr); 3680 err = inode_change_ok(inode, attr);
3677 if (err) 3681 if (err)
3678 return err; 3682 return err;
@@ -7206,6 +7210,10 @@ static int btrfs_set_page_dirty(struct page *page)
7206 7210
7207static int btrfs_permission(struct inode *inode, int mask) 7211static int btrfs_permission(struct inode *inode, int mask)
7208{ 7212{
7213 struct btrfs_root *root = BTRFS_I(inode)->root;
7214
7215 if (btrfs_root_readonly(root) && (mask & MAY_WRITE))
7216 return -EROFS;
7209 if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE)) 7217 if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE))
7210 return -EACCES; 7218 return -EACCES;
7211 return generic_permission(inode, mask, btrfs_check_acl); 7219 return generic_permission(inode, mask, btrfs_check_acl);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index f87552a1d7ea..ad1983524f97 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:
@@ -946,58 +952,139 @@ out:
946} 952}
947 953
948static noinline int btrfs_ioctl_snap_create(struct file *file, 954static noinline int btrfs_ioctl_snap_create(struct file *file,
949 void __user *arg, int subvol, 955 void __user *arg, int subvol)
950 int v2)
951{ 956{
952 struct btrfs_ioctl_vol_args *vol_args = NULL; 957 struct btrfs_ioctl_vol_args *vol_args;
953 struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL;
954 char *name;
955 u64 fd;
956 int ret; 958 int ret;
957 959
958 if (v2) { 960 vol_args = memdup_user(arg, sizeof(*vol_args));
959 u64 transid = 0; 961 if (IS_ERR(vol_args))
960 u64 *ptr = NULL; 962 return PTR_ERR(vol_args);
961 963 vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
962 vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2));
963 if (IS_ERR(vol_args_v2))
964 return PTR_ERR(vol_args_v2);
965 964
966 if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) { 965 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
967 ret = -EINVAL; 966 vol_args->fd, subvol,
968 goto out; 967 NULL, false);
969 }
970 968
971 name = vol_args_v2->name; 969 kfree(vol_args);
972 fd = vol_args_v2->fd; 970 return ret;
973 vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; 971}
974 972
975 if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC) 973static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
976 ptr = &transid; 974 void __user *arg, int subvol)
975{
976 struct btrfs_ioctl_vol_args_v2 *vol_args;
977 int ret;
978 u64 transid = 0;
979 u64 *ptr = NULL;
980 bool readonly = false;
977 981
978 ret = btrfs_ioctl_snap_create_transid(file, name, fd, 982 vol_args = memdup_user(arg, sizeof(*vol_args));
979 subvol, ptr); 983 if (IS_ERR(vol_args))
984 return PTR_ERR(vol_args);
985 vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
980 986
981 if (ret == 0 && ptr && 987 if (vol_args->flags &
982 copy_to_user(arg + 988 ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY)) {
983 offsetof(struct btrfs_ioctl_vol_args_v2, 989 ret = -EOPNOTSUPP;
984 transid), ptr, sizeof(*ptr))) 990 goto out;
985 ret = -EFAULT;
986 } else {
987 vol_args = memdup_user(arg, sizeof(*vol_args));
988 if (IS_ERR(vol_args))
989 return PTR_ERR(vol_args);
990 name = vol_args->name;
991 fd = vol_args->fd;
992 vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
993
994 ret = btrfs_ioctl_snap_create_transid(file, name, fd,
995 subvol, NULL);
996 } 991 }
992
993 if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
994 ptr = &transid;
995 if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
996 readonly = true;
997
998 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
999 vol_args->fd, subvol,
1000 ptr, readonly);
1001
1002 if (ret == 0 && ptr &&
1003 copy_to_user(arg +
1004 offsetof(struct btrfs_ioctl_vol_args_v2,
1005 transid), ptr, sizeof(*ptr)))
1006 ret = -EFAULT;
997out: 1007out:
998 kfree(vol_args); 1008 kfree(vol_args);
999 kfree(vol_args_v2); 1009 return ret;
1010}
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 }
1000 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);
1001 return ret; 1088 return ret;
1002} 1089}
1003 1090
@@ -1509,6 +1596,9 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
1509 struct btrfs_ioctl_defrag_range_args *range; 1596 struct btrfs_ioctl_defrag_range_args *range;
1510 int ret; 1597 int ret;
1511 1598
1599 if (btrfs_root_readonly(root))
1600 return -EROFS;
1601
1512 ret = mnt_want_write(file->f_path.mnt); 1602 ret = mnt_want_write(file->f_path.mnt);
1513 if (ret) 1603 if (ret)
1514 return ret; 1604 return ret;
@@ -1637,6 +1727,9 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
1637 if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) 1727 if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND))
1638 return -EINVAL; 1728 return -EINVAL;
1639 1729
1730 if (btrfs_root_readonly(root))
1731 return -EROFS;
1732
1640 ret = mnt_want_write(file->f_path.mnt); 1733 ret = mnt_want_write(file->f_path.mnt);
1641 if (ret) 1734 if (ret)
1642 return ret; 1735 return ret;
@@ -1958,6 +2051,10 @@ static long btrfs_ioctl_trans_start(struct file *file)
1958 if (file->private_data) 2051 if (file->private_data)
1959 goto out; 2052 goto out;
1960 2053
2054 ret = -EROFS;
2055 if (btrfs_root_readonly(root))
2056 goto out;
2057
1961 ret = mnt_want_write(file->f_path.mnt); 2058 ret = mnt_want_write(file->f_path.mnt);
1962 if (ret) 2059 if (ret)
1963 goto out; 2060 goto out;
@@ -2257,13 +2354,17 @@ long btrfs_ioctl(struct file *file, unsigned int
2257 case FS_IOC_GETVERSION: 2354 case FS_IOC_GETVERSION:
2258 return btrfs_ioctl_getversion(file, argp); 2355 return btrfs_ioctl_getversion(file, argp);
2259 case BTRFS_IOC_SNAP_CREATE: 2356 case BTRFS_IOC_SNAP_CREATE:
2260 return btrfs_ioctl_snap_create(file, argp, 0, 0); 2357 return btrfs_ioctl_snap_create(file, argp, 0);
2261 case BTRFS_IOC_SNAP_CREATE_V2: 2358 case BTRFS_IOC_SNAP_CREATE_V2:
2262 return btrfs_ioctl_snap_create(file, argp, 0, 1); 2359 return btrfs_ioctl_snap_create_v2(file, argp, 0);
2263 case BTRFS_IOC_SUBVOL_CREATE: 2360 case BTRFS_IOC_SUBVOL_CREATE:
2264 return btrfs_ioctl_snap_create(file, argp, 1, 0); 2361 return btrfs_ioctl_snap_create(file, argp, 1);
2265 case BTRFS_IOC_SNAP_DESTROY: 2362 case BTRFS_IOC_SNAP_DESTROY:
2266 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);
2267 case BTRFS_IOC_DEFAULT_SUBVOL: 2368 case BTRFS_IOC_DEFAULT_SUBVOL:
2268 return btrfs_ioctl_default_subvol(file, argp); 2369 return btrfs_ioctl_default_subvol(file, argp);
2269 case BTRFS_IOC_DEFRAG: 2370 case BTRFS_IOC_DEFRAG:
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index c344d12c646b..1223223351fa 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -31,6 +31,7 @@ struct btrfs_ioctl_vol_args {
31}; 31};
32 32
33#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) 33#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0)
34#define BTRFS_SUBVOL_RDONLY (1ULL << 1)
34 35
35#define BTRFS_SUBVOL_NAME_MAX 4039 36#define BTRFS_SUBVOL_NAME_MAX 4039
36struct btrfs_ioctl_vol_args_v2 { 37struct btrfs_ioctl_vol_args_v2 {
@@ -193,4 +194,6 @@ struct btrfs_ioctl_space_args {
193#define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) 194#define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
194#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ 195#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
195 struct btrfs_ioctl_vol_args_v2) 196 struct btrfs_ioctl_vol_args_v2)
197#define BTRFS_IOC_SUBVOL_GETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 25, __u64)
198#define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64)
196#endif 199#endif
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index f50e931fc217..29e30d832ec9 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -910,6 +910,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
910 u64 to_reserve = 0; 910 u64 to_reserve = 0;
911 u64 index = 0; 911 u64 index = 0;
912 u64 objectid; 912 u64 objectid;
913 u64 root_flags;
913 914
914 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); 915 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
915 if (!new_root_item) { 916 if (!new_root_item) {
@@ -967,6 +968,13 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
967 btrfs_set_root_last_snapshot(&root->root_item, trans->transid); 968 btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
968 memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); 969 memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
969 970
971 root_flags = btrfs_root_flags(new_root_item);
972 if (pending->readonly)
973 root_flags |= BTRFS_ROOT_SUBVOL_RDONLY;
974 else
975 root_flags &= ~BTRFS_ROOT_SUBVOL_RDONLY;
976 btrfs_set_root_flags(new_root_item, root_flags);
977
970 old = btrfs_lock_root_node(root); 978 old = btrfs_lock_root_node(root);
971 btrfs_cow_block(trans, root, old, NULL, 0, &old); 979 btrfs_cow_block(trans, root, old, NULL, 0, &old);
972 btrfs_set_lock_blocking(old); 980 btrfs_set_lock_blocking(old);
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index f104b57ad4ef..229a594cacd5 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -62,6 +62,7 @@ struct btrfs_pending_snapshot {
62 struct btrfs_block_rsv block_rsv; 62 struct btrfs_block_rsv block_rsv;
63 /* extra metadata reseration for relocation */ 63 /* extra metadata reseration for relocation */
64 int error; 64 int error;
65 bool readonly;
65 struct list_head list; 66 struct list_head list;
66}; 67};
67 68
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 698fdd2c739c..a5776531dc2b 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -316,6 +316,15 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
316int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, 316int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
317 size_t size, int flags) 317 size_t size, int flags)
318{ 318{
319 struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
320
321 /*
322 * The permission on security.* and system.* is not checked
323 * in permission().
324 */
325 if (btrfs_root_readonly(root))
326 return -EROFS;
327
319 /* 328 /*
320 * If this is a request for a synthetic attribute in the system.* 329 * If this is a request for a synthetic attribute in the system.*
321 * namespace use the generic infrastructure to resolve a handler 330 * namespace use the generic infrastructure to resolve a handler
@@ -336,6 +345,15 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
336 345
337int btrfs_removexattr(struct dentry *dentry, const char *name) 346int btrfs_removexattr(struct dentry *dentry, const char *name)
338{ 347{
348 struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
349
350 /*
351 * The permission on security.* and system.* is not checked
352 * in permission().
353 */
354 if (btrfs_root_readonly(root))
355 return -EROFS;
356
339 /* 357 /*
340 * If this is a request for a synthetic attribute in the system.* 358 * If this is a request for a synthetic attribute in the system.*
341 * namespace use the generic infrastructure to resolve a handler 359 * namespace use the generic infrastructure to resolve a handler