Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
26c79f6b
Commit
26c79f6b
authored
Jan 16, 2011
by
Chris Mason
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'readonly-snapshots' of
git://repo.or.cz/linux-btrfs-devel
into btrfs-38
parents
65e5341b
0caa102d
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
195 additions
and
49 deletions
+195
-49
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+7
-0
fs/btrfs/inode.c
fs/btrfs/inode.c
+8
-0
fs/btrfs/ioctl.c
fs/btrfs/ioctl.c
+150
-49
fs/btrfs/ioctl.h
fs/btrfs/ioctl.h
+3
-0
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+8
-0
fs/btrfs/transaction.h
fs/btrfs/transaction.h
+1
-0
fs/btrfs/xattr.c
fs/btrfs/xattr.c
+18
-0
No files found.
fs/btrfs/ctree.h
View file @
26c79f6b
...
...
@@ -597,6 +597,8 @@ struct btrfs_dir_item {
u8
type
;
}
__attribute__
((
__packed__
));
#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0)
struct
btrfs_root_item
{
struct
btrfs_inode_item
inode
;
__le64
generation
;
...
...
@@ -1893,6 +1895,11 @@ BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64);
BTRFS_SETGET_STACK_FUNCS
(
root_last_snapshot
,
struct
btrfs_root_item
,
last_snapshot
,
64
);
static
inline
bool
btrfs_root_readonly
(
struct
btrfs_root
*
root
)
{
return
root
->
root_item
.
flags
&
BTRFS_ROOT_SUBVOL_RDONLY
;
}
/* struct btrfs_super_block */
BTRFS_SETGET_STACK_FUNCS
(
super_bytenr
,
struct
btrfs_super_block
,
bytenr
,
64
);
...
...
fs/btrfs/inode.c
View file @
26c79f6b
...
...
@@ -3671,8 +3671,12 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
static
int
btrfs_setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
attr
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
int
err
;
if
(
btrfs_root_readonly
(
root
))
return
-
EROFS
;
err
=
inode_change_ok
(
inode
,
attr
);
if
(
err
)
return
err
;
...
...
@@ -7206,6 +7210,10 @@ static int btrfs_set_page_dirty(struct page *page)
static
int
btrfs_permission
(
struct
inode
*
inode
,
int
mask
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
if
(
btrfs_root_readonly
(
root
)
&&
(
mask
&
MAY_WRITE
))
return
-
EROFS
;
if
((
BTRFS_I
(
inode
)
->
flags
&
BTRFS_INODE_READONLY
)
&&
(
mask
&
MAY_WRITE
))
return
-
EACCES
;
return
generic_permission
(
inode
,
mask
,
btrfs_check_acl
);
...
...
fs/btrfs/ioctl.c
View file @
26c79f6b
...
...
@@ -147,6 +147,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
unsigned
int
flags
,
oldflags
;
int
ret
;
if
(
btrfs_root_readonly
(
root
))
return
-
EROFS
;
if
(
copy_from_user
(
&
flags
,
arg
,
sizeof
(
flags
)))
return
-
EFAULT
;
...
...
@@ -360,7 +363,8 @@ static noinline int create_subvol(struct btrfs_root *root,
}
static
int
create_snapshot
(
struct
btrfs_root
*
root
,
struct
dentry
*
dentry
,
char
*
name
,
int
namelen
,
u64
*
async_transid
)
char
*
name
,
int
namelen
,
u64
*
async_transid
,
bool
readonly
)
{
struct
inode
*
inode
;
struct
dentry
*
parent
;
...
...
@@ -378,6 +382,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
btrfs_init_block_rsv
(
&
pending_snapshot
->
block_rsv
);
pending_snapshot
->
dentry
=
dentry
;
pending_snapshot
->
root
=
root
;
pending_snapshot
->
readonly
=
readonly
;
trans
=
btrfs_start_transaction
(
root
->
fs_info
->
extent_root
,
5
);
if
(
IS_ERR
(
trans
))
{
...
...
@@ -509,7 +514,7 @@ static inline int btrfs_may_create(struct inode *dir, struct dentry *child)
static
noinline
int
btrfs_mksubvol
(
struct
path
*
parent
,
char
*
name
,
int
namelen
,
struct
btrfs_root
*
snap_src
,
u64
*
async_transid
)
u64
*
async_transid
,
bool
readonly
)
{
struct
inode
*
dir
=
parent
->
dentry
->
d_inode
;
struct
dentry
*
dentry
;
...
...
@@ -541,7 +546,7 @@ static noinline int btrfs_mksubvol(struct path *parent,
if
(
snap_src
)
{
error
=
create_snapshot
(
snap_src
,
dentry
,
name
,
namelen
,
async_transid
);
name
,
namelen
,
async_transid
,
readonly
);
}
else
{
error
=
create_subvol
(
BTRFS_I
(
dir
)
->
root
,
dentry
,
name
,
namelen
,
async_transid
);
...
...
@@ -901,7 +906,8 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
char
*
name
,
unsigned
long
fd
,
int
subvol
,
u64
*
transid
)
u64
*
transid
,
bool
readonly
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
fdentry
(
file
)
->
d_inode
)
->
root
;
struct
file
*
src_file
;
...
...
@@ -919,7 +925,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
if
(
subvol
)
{
ret
=
btrfs_mksubvol
(
&
file
->
f_path
,
name
,
namelen
,
NULL
,
transid
);
NULL
,
transid
,
readonly
);
}
else
{
struct
inode
*
src_inode
;
src_file
=
fget
(
fd
);
...
...
@@ -938,7 +944,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
}
ret
=
btrfs_mksubvol
(
&
file
->
f_path
,
name
,
namelen
,
BTRFS_I
(
src_inode
)
->
root
,
transid
);
transid
,
readonly
);
fput
(
src_file
);
}
out:
...
...
@@ -946,58 +952,139 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
}
static
noinline
int
btrfs_ioctl_snap_create
(
struct
file
*
file
,
void
__user
*
arg
,
int
subvol
,
int
v2
)
void
__user
*
arg
,
int
subvol
)
{
struct
btrfs_ioctl_vol_args
*
vol_args
=
NULL
;
struct
btrfs_ioctl_vol_args_v2
*
vol_args_v2
=
NULL
;
char
*
name
;
u64
fd
;
struct
btrfs_ioctl_vol_args
*
vol_args
;
int
ret
;
if
(
v2
)
{
u64
transid
=
0
;
u64
*
ptr
=
NULL
;
vol_args_v2
=
memdup_user
(
arg
,
sizeof
(
*
vol_args_v2
));
if
(
IS_ERR
(
vol_args_v2
))
return
PTR_ERR
(
vol_args_v2
);
vol_args
=
memdup_user
(
arg
,
sizeof
(
*
vol_args
));
if
(
IS_ERR
(
vol_args
))
return
PTR_ERR
(
vol_args
);
vol_args
->
name
[
BTRFS_PATH_NAME_MAX
]
=
'\0'
;
if
(
vol_args_v2
->
flags
&
~
BTRFS_SUBVOL_CREATE_ASYNC
)
{
ret
=
-
EINVAL
;
goto
out
;
}
ret
=
btrfs_ioctl_snap_create_transid
(
file
,
vol_args
->
name
,
vol_args
->
fd
,
subvol
,
NULL
,
false
);
name
=
vol_args_v2
->
name
;
fd
=
vol_args_v2
->
fd
;
vol_args_v2
->
name
[
BTRFS_SUBVOL_NAME_MAX
]
=
'\0'
;
kfree
(
vol_args
)
;
return
ret
;
}
if
(
vol_args_v2
->
flags
&
BTRFS_SUBVOL_CREATE_ASYNC
)
ptr
=
&
transid
;
static
noinline
int
btrfs_ioctl_snap_create_v2
(
struct
file
*
file
,
void
__user
*
arg
,
int
subvol
)
{
struct
btrfs_ioctl_vol_args_v2
*
vol_args
;
int
ret
;
u64
transid
=
0
;
u64
*
ptr
=
NULL
;
bool
readonly
=
false
;
ret
=
btrfs_ioctl_snap_create_transid
(
file
,
name
,
fd
,
subvol
,
ptr
);
vol_args
=
memdup_user
(
arg
,
sizeof
(
*
vol_args
));
if
(
IS_ERR
(
vol_args
))
return
PTR_ERR
(
vol_args
);
vol_args
->
name
[
BTRFS_SUBVOL_NAME_MAX
]
=
'\0'
;
if
(
ret
==
0
&&
ptr
&&
copy_to_user
(
arg
+
offsetof
(
struct
btrfs_ioctl_vol_args_v2
,
transid
),
ptr
,
sizeof
(
*
ptr
)))
ret
=
-
EFAULT
;
}
else
{
vol_args
=
memdup_user
(
arg
,
sizeof
(
*
vol_args
));
if
(
IS_ERR
(
vol_args
))
return
PTR_ERR
(
vol_args
);
name
=
vol_args
->
name
;
fd
=
vol_args
->
fd
;
vol_args
->
name
[
BTRFS_PATH_NAME_MAX
]
=
'\0'
;
ret
=
btrfs_ioctl_snap_create_transid
(
file
,
name
,
fd
,
subvol
,
NULL
);
if
(
vol_args
->
flags
&
~
(
BTRFS_SUBVOL_CREATE_ASYNC
|
BTRFS_SUBVOL_RDONLY
))
{
ret
=
-
EOPNOTSUPP
;
goto
out
;
}
if
(
vol_args
->
flags
&
BTRFS_SUBVOL_CREATE_ASYNC
)
ptr
=
&
transid
;
if
(
vol_args
->
flags
&
BTRFS_SUBVOL_RDONLY
)
readonly
=
true
;
ret
=
btrfs_ioctl_snap_create_transid
(
file
,
vol_args
->
name
,
vol_args
->
fd
,
subvol
,
ptr
,
readonly
);
if
(
ret
==
0
&&
ptr
&&
copy_to_user
(
arg
+
offsetof
(
struct
btrfs_ioctl_vol_args_v2
,
transid
),
ptr
,
sizeof
(
*
ptr
)))
ret
=
-
EFAULT
;
out:
kfree
(
vol_args
);
kfree
(
vol_args_v2
);
return
ret
;
}
static
noinline
int
btrfs_ioctl_subvol_getflags
(
struct
file
*
file
,
void
__user
*
arg
)
{
struct
inode
*
inode
=
fdentry
(
file
)
->
d_inode
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
int
ret
=
0
;
u64
flags
=
0
;
if
(
inode
->
i_ino
!=
BTRFS_FIRST_FREE_OBJECTID
)
return
-
EINVAL
;
down_read
(
&
root
->
fs_info
->
subvol_sem
);
if
(
btrfs_root_readonly
(
root
))
flags
|=
BTRFS_SUBVOL_RDONLY
;
up_read
(
&
root
->
fs_info
->
subvol_sem
);
if
(
copy_to_user
(
arg
,
&
flags
,
sizeof
(
flags
)))
ret
=
-
EFAULT
;
return
ret
;
}
static
noinline
int
btrfs_ioctl_subvol_setflags
(
struct
file
*
file
,
void
__user
*
arg
)
{
struct
inode
*
inode
=
fdentry
(
file
)
->
d_inode
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
btrfs_trans_handle
*
trans
;
u64
root_flags
;
u64
flags
;
int
ret
=
0
;
if
(
root
->
fs_info
->
sb
->
s_flags
&
MS_RDONLY
)
return
-
EROFS
;
if
(
inode
->
i_ino
!=
BTRFS_FIRST_FREE_OBJECTID
)
return
-
EINVAL
;
if
(
copy_from_user
(
&
flags
,
arg
,
sizeof
(
flags
)))
return
-
EFAULT
;
if
(
flags
&
~
BTRFS_SUBVOL_CREATE_ASYNC
)
return
-
EINVAL
;
if
(
flags
&
~
BTRFS_SUBVOL_RDONLY
)
return
-
EOPNOTSUPP
;
down_write
(
&
root
->
fs_info
->
subvol_sem
);
/* nothing to do */
if
(
!!
(
flags
&
BTRFS_SUBVOL_RDONLY
)
==
btrfs_root_readonly
(
root
))
goto
out
;
root_flags
=
btrfs_root_flags
(
&
root
->
root_item
);
if
(
flags
&
BTRFS_SUBVOL_RDONLY
)
btrfs_set_root_flags
(
&
root
->
root_item
,
root_flags
|
BTRFS_ROOT_SUBVOL_RDONLY
);
else
btrfs_set_root_flags
(
&
root
->
root_item
,
root_flags
&
~
BTRFS_ROOT_SUBVOL_RDONLY
);
trans
=
btrfs_start_transaction
(
root
,
1
);
if
(
IS_ERR
(
trans
))
{
ret
=
PTR_ERR
(
trans
);
goto
out_reset
;
}
ret
=
btrfs_update_root
(
trans
,
root
,
&
root
->
root_key
,
&
root
->
root_item
);
btrfs_commit_transaction
(
trans
,
root
);
out_reset:
if
(
ret
)
btrfs_set_root_flags
(
&
root
->
root_item
,
root_flags
);
out:
up_write
(
&
root
->
fs_info
->
subvol_sem
);
return
ret
;
}
...
...
@@ -1509,6 +1596,9 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
struct
btrfs_ioctl_defrag_range_args
*
range
;
int
ret
;
if
(
btrfs_root_readonly
(
root
))
return
-
EROFS
;
ret
=
mnt_want_write
(
file
->
f_path
.
mnt
);
if
(
ret
)
return
ret
;
...
...
@@ -1637,6 +1727,9 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
if
(
!
(
file
->
f_mode
&
FMODE_WRITE
)
||
(
file
->
f_flags
&
O_APPEND
))
return
-
EINVAL
;
if
(
btrfs_root_readonly
(
root
))
return
-
EROFS
;
ret
=
mnt_want_write
(
file
->
f_path
.
mnt
);
if
(
ret
)
return
ret
;
...
...
@@ -1958,6 +2051,10 @@ static long btrfs_ioctl_trans_start(struct file *file)
if
(
file
->
private_data
)
goto
out
;
ret
=
-
EROFS
;
if
(
btrfs_root_readonly
(
root
))
goto
out
;
ret
=
mnt_want_write
(
file
->
f_path
.
mnt
);
if
(
ret
)
goto
out
;
...
...
@@ -2257,13 +2354,17 @@ long btrfs_ioctl(struct file *file, unsigned int
case
FS_IOC_GETVERSION
:
return
btrfs_ioctl_getversion
(
file
,
argp
);
case
BTRFS_IOC_SNAP_CREATE
:
return
btrfs_ioctl_snap_create
(
file
,
argp
,
0
,
0
);
return
btrfs_ioctl_snap_create
(
file
,
argp
,
0
);
case
BTRFS_IOC_SNAP_CREATE_V2
:
return
btrfs_ioctl_snap_create
(
file
,
argp
,
0
,
1
);
return
btrfs_ioctl_snap_create
_v2
(
file
,
argp
,
0
);
case
BTRFS_IOC_SUBVOL_CREATE
:
return
btrfs_ioctl_snap_create
(
file
,
argp
,
1
,
0
);
return
btrfs_ioctl_snap_create
(
file
,
argp
,
1
);
case
BTRFS_IOC_SNAP_DESTROY
:
return
btrfs_ioctl_snap_destroy
(
file
,
argp
);
case
BTRFS_IOC_SUBVOL_GETFLAGS
:
return
btrfs_ioctl_subvol_getflags
(
file
,
argp
);
case
BTRFS_IOC_SUBVOL_SETFLAGS
:
return
btrfs_ioctl_subvol_setflags
(
file
,
argp
);
case
BTRFS_IOC_DEFAULT_SUBVOL
:
return
btrfs_ioctl_default_subvol
(
file
,
argp
);
case
BTRFS_IOC_DEFRAG
:
...
...
fs/btrfs/ioctl.h
View file @
26c79f6b
...
...
@@ -31,6 +31,7 @@ struct btrfs_ioctl_vol_args {
};
#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0)
#define BTRFS_SUBVOL_RDONLY (1ULL << 1)
#define BTRFS_SUBVOL_NAME_MAX 4039
struct
btrfs_ioctl_vol_args_v2
{
...
...
@@ -193,4 +194,6 @@ struct btrfs_ioctl_space_args {
#define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
struct btrfs_ioctl_vol_args_v2)
#define BTRFS_IOC_SUBVOL_GETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 25, __u64)
#define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64)
#endif
fs/btrfs/transaction.c
View file @
26c79f6b
...
...
@@ -910,6 +910,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
u64
to_reserve
=
0
;
u64
index
=
0
;
u64
objectid
;
u64
root_flags
;
new_root_item
=
kmalloc
(
sizeof
(
*
new_root_item
),
GFP_NOFS
);
if
(
!
new_root_item
)
{
...
...
@@ -967,6 +968,13 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_set_root_last_snapshot
(
&
root
->
root_item
,
trans
->
transid
);
memcpy
(
new_root_item
,
&
root
->
root_item
,
sizeof
(
*
new_root_item
));
root_flags
=
btrfs_root_flags
(
new_root_item
);
if
(
pending
->
readonly
)
root_flags
|=
BTRFS_ROOT_SUBVOL_RDONLY
;
else
root_flags
&=
~
BTRFS_ROOT_SUBVOL_RDONLY
;
btrfs_set_root_flags
(
new_root_item
,
root_flags
);
old
=
btrfs_lock_root_node
(
root
);
btrfs_cow_block
(
trans
,
root
,
old
,
NULL
,
0
,
&
old
);
btrfs_set_lock_blocking
(
old
);
...
...
fs/btrfs/transaction.h
View file @
26c79f6b
...
...
@@ -62,6 +62,7 @@ struct btrfs_pending_snapshot {
struct
btrfs_block_rsv
block_rsv
;
/* extra metadata reseration for relocation */
int
error
;
bool
readonly
;
struct
list_head
list
;
};
...
...
fs/btrfs/xattr.c
View file @
26c79f6b
...
...
@@ -316,6 +316,15 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
int
btrfs_setxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
dentry
->
d_inode
)
->
root
;
/*
* The permission on security.* and system.* is not checked
* in permission().
*/
if
(
btrfs_root_readonly
(
root
))
return
-
EROFS
;
/*
* If this is a request for a synthetic attribute in the system.*
* 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,
int
btrfs_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
dentry
->
d_inode
)
->
root
;
/*
* The permission on security.* and system.* is not checked
* in permission().
*/
if
(
btrfs_root_readonly
(
root
))
return
-
EROFS
;
/*
* If this is a request for a synthetic attribute in the system.*
* namespace use the generic infrastructure to resolve a handler
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment