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
nexedi
linux
Commits
ebfee3d7
Commit
ebfee3d7
authored
Dec 17, 2009
by
Chris Mason
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch btrfs-master into for-linus
Conflicts: fs/btrfs/acl.c
parents
b8a7f3cd
83d3c969
Changes
20
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1168 additions
and
916 deletions
+1168
-916
fs/btrfs/acl.c
fs/btrfs/acl.c
+13
-10
fs/btrfs/btrfs_inode.h
fs/btrfs/btrfs_inode.h
+1
-4
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+153
-76
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+28
-12
fs/btrfs/dir-item.c
fs/btrfs/dir-item.c
+7
-12
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+18
-9
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+47
-25
fs/btrfs/file.c
fs/btrfs/file.c
+266
-403
fs/btrfs/inode.c
fs/btrfs/inode.c
+355
-211
fs/btrfs/ioctl.c
fs/btrfs/ioctl.c
+19
-15
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.c
+88
-27
fs/btrfs/ordered-data.h
fs/btrfs/ordered-data.h
+3
-2
fs/btrfs/relocation.c
fs/btrfs/relocation.c
+23
-15
fs/btrfs/super.c
fs/btrfs/super.c
+12
-3
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+26
-18
fs/btrfs/transaction.h
fs/btrfs/transaction.h
+3
-3
fs/btrfs/tree-log.c
fs/btrfs/tree-log.c
+46
-40
fs/btrfs/volumes.c
fs/btrfs/volumes.c
+1
-1
fs/btrfs/xattr.c
fs/btrfs/xattr.c
+54
-26
fs/btrfs/xattr.h
fs/btrfs/xattr.h
+5
-4
No files found.
fs/btrfs/acl.c
View file @
ebfee3d7
...
@@ -94,7 +94,8 @@ static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name,
...
@@ -94,7 +94,8 @@ static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name,
/*
/*
* Needs to be called with fs_mutex held
* Needs to be called with fs_mutex held
*/
*/
static
int
btrfs_set_acl
(
struct
inode
*
inode
,
struct
posix_acl
*
acl
,
int
type
)
static
int
btrfs_set_acl
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
posix_acl
*
acl
,
int
type
)
{
{
int
ret
,
size
=
0
;
int
ret
,
size
=
0
;
const
char
*
name
;
const
char
*
name
;
...
@@ -140,8 +141,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
...
@@ -140,8 +141,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
goto
out
;
goto
out
;
}
}
ret
=
__btrfs_setxattr
(
inode
,
name
,
value
,
size
,
0
);
ret
=
__btrfs_setxattr
(
trans
,
inode
,
name
,
value
,
size
,
0
);
out:
out:
kfree
(
value
);
kfree
(
value
);
...
@@ -154,7 +154,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
...
@@ -154,7 +154,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
static
int
btrfs_xattr_acl_set
(
struct
dentry
*
dentry
,
const
char
*
name
,
static
int
btrfs_xattr_acl_set
(
struct
dentry
*
dentry
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
,
int
type
)
const
void
*
value
,
size_t
size
,
int
flags
,
int
type
)
{
{
int
ret
=
0
;
int
ret
;
struct
posix_acl
*
acl
=
NULL
;
struct
posix_acl
*
acl
=
NULL
;
if
(
value
)
{
if
(
value
)
{
...
@@ -167,7 +167,7 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
...
@@ -167,7 +167,7 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
}
}
}
}
ret
=
btrfs_set_acl
(
dentry
->
d_inode
,
acl
,
type
);
ret
=
btrfs_set_acl
(
NULL
,
dentry
->
d_inode
,
acl
,
type
);
posix_acl_release
(
acl
);
posix_acl_release
(
acl
);
...
@@ -196,7 +196,8 @@ int btrfs_check_acl(struct inode *inode, int mask)
...
@@ -196,7 +196,8 @@ int btrfs_check_acl(struct inode *inode, int mask)
* stuff has been fixed to work with that. If the locking stuff changes, we
* stuff has been fixed to work with that. If the locking stuff changes, we
* need to re-evaluate the acl locking stuff.
* need to re-evaluate the acl locking stuff.
*/
*/
int
btrfs_init_acl
(
struct
inode
*
inode
,
struct
inode
*
dir
)
int
btrfs_init_acl
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
)
{
{
struct
posix_acl
*
acl
=
NULL
;
struct
posix_acl
*
acl
=
NULL
;
int
ret
=
0
;
int
ret
=
0
;
...
@@ -221,7 +222,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
...
@@ -221,7 +222,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
mode_t
mode
;
mode_t
mode
;
if
(
S_ISDIR
(
inode
->
i_mode
))
{
if
(
S_ISDIR
(
inode
->
i_mode
))
{
ret
=
btrfs_set_acl
(
inode
,
acl
,
ACL_TYPE_DEFAULT
);
ret
=
btrfs_set_acl
(
trans
,
inode
,
acl
,
ACL_TYPE_DEFAULT
);
if
(
ret
)
if
(
ret
)
goto
failed
;
goto
failed
;
}
}
...
@@ -236,7 +238,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
...
@@ -236,7 +238,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
inode
->
i_mode
=
mode
;
inode
->
i_mode
=
mode
;
if
(
ret
>
0
)
{
if
(
ret
>
0
)
{
/* we need an acl */
/* we need an acl */
ret
=
btrfs_set_acl
(
inode
,
clone
,
ret
=
btrfs_set_acl
(
trans
,
inode
,
clone
,
ACL_TYPE_ACCESS
);
ACL_TYPE_ACCESS
);
}
}
}
}
...
@@ -269,7 +271,7 @@ int btrfs_acl_chmod(struct inode *inode)
...
@@ -269,7 +271,7 @@ int btrfs_acl_chmod(struct inode *inode)
ret
=
posix_acl_chmod_masq
(
clone
,
inode
->
i_mode
);
ret
=
posix_acl_chmod_masq
(
clone
,
inode
->
i_mode
);
if
(
!
ret
)
if
(
!
ret
)
ret
=
btrfs_set_acl
(
inode
,
clone
,
ACL_TYPE_ACCESS
);
ret
=
btrfs_set_acl
(
NULL
,
inode
,
clone
,
ACL_TYPE_ACCESS
);
posix_acl_release
(
clone
);
posix_acl_release
(
clone
);
...
@@ -297,7 +299,8 @@ int btrfs_acl_chmod(struct inode *inode)
...
@@ -297,7 +299,8 @@ int btrfs_acl_chmod(struct inode *inode)
return
0
;
return
0
;
}
}
int
btrfs_init_acl
(
struct
inode
*
inode
,
struct
inode
*
dir
)
int
btrfs_init_acl
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
)
{
{
return
0
;
return
0
;
}
}
...
...
fs/btrfs/btrfs_inode.h
View file @
ebfee3d7
...
@@ -44,9 +44,6 @@ struct btrfs_inode {
...
@@ -44,9 +44,6 @@ struct btrfs_inode {
*/
*/
struct
extent_io_tree
io_failure_tree
;
struct
extent_io_tree
io_failure_tree
;
/* held while inesrting or deleting extents from files */
struct
mutex
extent_mutex
;
/* held while logging the inode in tree-log.c */
/* held while logging the inode in tree-log.c */
struct
mutex
log_mutex
;
struct
mutex
log_mutex
;
...
@@ -166,7 +163,7 @@ static inline struct btrfs_inode *BTRFS_I(struct inode *inode)
...
@@ -166,7 +163,7 @@ static inline struct btrfs_inode *BTRFS_I(struct inode *inode)
static
inline
void
btrfs_i_size_write
(
struct
inode
*
inode
,
u64
size
)
static
inline
void
btrfs_i_size_write
(
struct
inode
*
inode
,
u64
size
)
{
{
i
node
->
i_size
=
size
;
i
_size_write
(
inode
,
size
)
;
BTRFS_I
(
inode
)
->
disk_i_size
=
size
;
BTRFS_I
(
inode
)
->
disk_i_size
=
size
;
}
}
...
...
fs/btrfs/ctree.c
View file @
ebfee3d7
This diff is collapsed.
Click to expand it.
fs/btrfs/ctree.h
View file @
ebfee3d7
...
@@ -310,6 +310,9 @@ struct btrfs_header {
...
@@ -310,6 +310,9 @@ struct btrfs_header {
#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
sizeof(struct btrfs_item) - \
sizeof(struct btrfs_item) - \
sizeof(struct btrfs_file_extent_item))
sizeof(struct btrfs_file_extent_item))
#define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
sizeof(struct btrfs_item) -\
sizeof(struct btrfs_dir_item))
/*
/*
...
@@ -859,8 +862,9 @@ struct btrfs_fs_info {
...
@@ -859,8 +862,9 @@ struct btrfs_fs_info {
struct
mutex
ordered_operations_mutex
;
struct
mutex
ordered_operations_mutex
;
struct
rw_semaphore
extent_commit_sem
;
struct
rw_semaphore
extent_commit_sem
;
struct
rw_semaphore
subvol
_sem
;
struct
rw_semaphore
cleanup_work
_sem
;
struct
rw_semaphore
subvol_sem
;
struct
srcu_struct
subvol_srcu
;
struct
srcu_struct
subvol_srcu
;
struct
list_head
trans_list
;
struct
list_head
trans_list
;
...
@@ -868,6 +872,9 @@ struct btrfs_fs_info {
...
@@ -868,6 +872,9 @@ struct btrfs_fs_info {
struct
list_head
dead_roots
;
struct
list_head
dead_roots
;
struct
list_head
caching_block_groups
;
struct
list_head
caching_block_groups
;
spinlock_t
delayed_iput_lock
;
struct
list_head
delayed_iputs
;
atomic_t
nr_async_submits
;
atomic_t
nr_async_submits
;
atomic_t
async_submit_draining
;
atomic_t
async_submit_draining
;
atomic_t
nr_async_bios
;
atomic_t
nr_async_bios
;
...
@@ -1034,12 +1041,12 @@ struct btrfs_root {
...
@@ -1034,12 +1041,12 @@ struct btrfs_root {
int
ref_cows
;
int
ref_cows
;
int
track_dirty
;
int
track_dirty
;
int
in_radix
;
int
in_radix
;
int
clean_orphans
;
u64
defrag_trans_start
;
u64
defrag_trans_start
;
struct
btrfs_key
defrag_progress
;
struct
btrfs_key
defrag_progress
;
struct
btrfs_key
defrag_max
;
struct
btrfs_key
defrag_max
;
int
defrag_running
;
int
defrag_running
;
int
defrag_level
;
char
*
name
;
char
*
name
;
int
in_sysfs
;
int
in_sysfs
;
...
@@ -1975,6 +1982,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
...
@@ -1975,6 +1982,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
u64
parent
,
u64
root_objectid
,
u64
parent
,
u64
root_objectid
,
struct
btrfs_disk_key
*
key
,
int
level
,
struct
btrfs_disk_key
*
key
,
int
level
,
u64
hint
,
u64
empty_size
);
u64
hint
,
u64
empty_size
);
int
btrfs_free_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
,
u64
parent
,
u64
root_objectid
,
int
level
);
struct
extent_buffer
*
btrfs_init_new_buffer
(
struct
btrfs_trans_handle
*
trans
,
struct
extent_buffer
*
btrfs_init_new_buffer
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
,
u64
bytenr
,
u32
blocksize
,
...
@@ -2089,6 +2100,10 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
...
@@ -2089,6 +2100,10 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
struct
btrfs_path
*
path
,
struct
btrfs_path
*
path
,
struct
btrfs_key
*
new_key
,
struct
btrfs_key
*
new_key
,
unsigned
long
split_offset
);
unsigned
long
split_offset
);
int
btrfs_duplicate_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_key
*
new_key
);
int
btrfs_search_slot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
int
btrfs_search_slot
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_key
*
key
,
struct
btrfs_path
*
p
,
int
*
root
,
struct
btrfs_key
*
key
,
struct
btrfs_path
*
p
,
int
ins_len
,
int
cow
);
ins_len
,
int
cow
);
...
@@ -2196,9 +2211,10 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
...
@@ -2196,9 +2211,10 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
struct
btrfs_path
*
path
,
struct
btrfs_path
*
path
,
struct
btrfs_dir_item
*
di
);
struct
btrfs_dir_item
*
di
);
int
btrfs_insert_xattr_item
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_insert_xattr_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
const
char
*
name
,
struct
btrfs_root
*
root
,
u16
name_len
,
const
void
*
data
,
u16
data_len
,
struct
btrfs_path
*
path
,
u64
objectid
,
u64
dir
);
const
char
*
name
,
u16
name_len
,
const
void
*
data
,
u16
data_len
);
struct
btrfs_dir_item
*
btrfs_lookup_xattr
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_dir_item
*
btrfs_lookup_xattr
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
u64
dir
,
struct
btrfs_path
*
path
,
u64
dir
,
...
@@ -2292,7 +2308,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
...
@@ -2292,7 +2308,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
struct
inode
*
inode
,
u64
new_size
,
struct
inode
*
inode
,
u64
new_size
,
u32
min_type
);
u32
min_type
);
int
btrfs_start_delalloc_inodes
(
struct
btrfs_root
*
root
);
int
btrfs_start_delalloc_inodes
(
struct
btrfs_root
*
root
,
int
delay_iput
);
int
btrfs_set_extent_delalloc
(
struct
inode
*
inode
,
u64
start
,
u64
end
);
int
btrfs_set_extent_delalloc
(
struct
inode
*
inode
,
u64
start
,
u64
end
);
int
btrfs_writepages
(
struct
address_space
*
mapping
,
int
btrfs_writepages
(
struct
address_space
*
mapping
,
struct
writeback_control
*
wbc
);
struct
writeback_control
*
wbc
);
...
@@ -2332,6 +2348,8 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
...
@@ -2332,6 +2348,8 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
void
btrfs_orphan_cleanup
(
struct
btrfs_root
*
root
);
void
btrfs_orphan_cleanup
(
struct
btrfs_root
*
root
);
int
btrfs_cont_expand
(
struct
inode
*
inode
,
loff_t
size
);
int
btrfs_cont_expand
(
struct
inode
*
inode
,
loff_t
size
);
int
btrfs_invalidate_inodes
(
struct
btrfs_root
*
root
);
int
btrfs_invalidate_inodes
(
struct
btrfs_root
*
root
);
void
btrfs_add_delayed_iput
(
struct
inode
*
inode
);
void
btrfs_run_delayed_iputs
(
struct
btrfs_root
*
root
);
extern
const
struct
dentry_operations
btrfs_dentry_operations
;
extern
const
struct
dentry_operations
btrfs_dentry_operations
;
/* ioctl.c */
/* ioctl.c */
...
@@ -2345,12 +2363,9 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
...
@@ -2345,12 +2363,9 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
int
skip_pinned
);
int
skip_pinned
);
int
btrfs_check_file
(
struct
btrfs_root
*
root
,
struct
inode
*
inode
);
int
btrfs_check_file
(
struct
btrfs_root
*
root
,
struct
inode
*
inode
);
extern
const
struct
file_operations
btrfs_file_operations
;
extern
const
struct
file_operations
btrfs_file_operations
;
int
btrfs_drop_extents
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_drop_extents
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
,
u64
start
,
u64
end
,
u64
*
hint_byte
,
int
drop_cache
);
u64
start
,
u64
end
,
u64
locked_end
,
u64
inline_limit
,
u64
*
hint_block
,
int
drop_cache
);
int
btrfs_mark_extent_written
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_mark_extent_written
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
,
u64
start
,
u64
end
);
struct
inode
*
inode
,
u64
start
,
u64
end
);
int
btrfs_release_file
(
struct
inode
*
inode
,
struct
file
*
file
);
int
btrfs_release_file
(
struct
inode
*
inode
,
struct
file
*
file
);
...
@@ -2380,7 +2395,8 @@ int btrfs_check_acl(struct inode *inode, int mask);
...
@@ -2380,7 +2395,8 @@ int btrfs_check_acl(struct inode *inode, int mask);
#else
#else
#define btrfs_check_acl NULL
#define btrfs_check_acl NULL
#endif
#endif
int
btrfs_init_acl
(
struct
inode
*
inode
,
struct
inode
*
dir
);
int
btrfs_init_acl
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
);
int
btrfs_acl_chmod
(
struct
inode
*
inode
);
int
btrfs_acl_chmod
(
struct
inode
*
inode
);
/* relocation.c */
/* relocation.c */
...
...
fs/btrfs/dir-item.c
View file @
ebfee3d7
...
@@ -68,12 +68,12 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
...
@@ -68,12 +68,12 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
* into the tree
* into the tree
*/
*/
int
btrfs_insert_xattr_item
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_insert_xattr_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
const
char
*
name
,
struct
btrfs_root
*
root
,
u16
name_len
,
const
void
*
data
,
u16
data_len
,
struct
btrfs_path
*
path
,
u64
objectid
,
u64
dir
)
const
char
*
name
,
u16
name_len
,
const
void
*
data
,
u16
data_len
)
{
{
int
ret
=
0
;
int
ret
=
0
;
struct
btrfs_path
*
path
;
struct
btrfs_dir_item
*
dir_item
;
struct
btrfs_dir_item
*
dir_item
;
unsigned
long
name_ptr
,
data_ptr
;
unsigned
long
name_ptr
,
data_ptr
;
struct
btrfs_key
key
,
location
;
struct
btrfs_key
key
,
location
;
...
@@ -81,15 +81,11 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
...
@@ -81,15 +81,11 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
struct
extent_buffer
*
leaf
;
struct
extent_buffer
*
leaf
;
u32
data_size
;
u32
data_size
;
key
.
objectid
=
dir
;
BUG_ON
(
name_len
+
data_len
>
BTRFS_MAX_XATTR_SIZE
(
root
));
key
.
objectid
=
objectid
;
btrfs_set_key_type
(
&
key
,
BTRFS_XATTR_ITEM_KEY
);
btrfs_set_key_type
(
&
key
,
BTRFS_XATTR_ITEM_KEY
);
key
.
offset
=
btrfs_name_hash
(
name
,
name_len
);
key
.
offset
=
btrfs_name_hash
(
name
,
name_len
);
path
=
btrfs_alloc_path
();
if
(
!
path
)
return
-
ENOMEM
;
if
(
name_len
+
data_len
+
sizeof
(
struct
btrfs_dir_item
)
>
BTRFS_LEAF_DATA_SIZE
(
root
)
-
sizeof
(
struct
btrfs_item
))
return
-
ENOSPC
;
data_size
=
sizeof
(
*
dir_item
)
+
name_len
+
data_len
;
data_size
=
sizeof
(
*
dir_item
)
+
name_len
+
data_len
;
dir_item
=
insert_with_overflow
(
trans
,
root
,
path
,
&
key
,
data_size
,
dir_item
=
insert_with_overflow
(
trans
,
root
,
path
,
&
key
,
data_size
,
...
@@ -117,7 +113,6 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
...
@@ -117,7 +113,6 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
write_extent_buffer
(
leaf
,
data
,
data_ptr
,
data_len
);
write_extent_buffer
(
leaf
,
data
,
data_ptr
,
data_len
);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_free_path
(
path
);
return
ret
;
return
ret
;
}
}
...
...
fs/btrfs/disk-io.c
View file @
ebfee3d7
...
@@ -892,6 +892,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
...
@@ -892,6 +892,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root
->
stripesize
=
stripesize
;
root
->
stripesize
=
stripesize
;
root
->
ref_cows
=
0
;
root
->
ref_cows
=
0
;
root
->
track_dirty
=
0
;
root
->
track_dirty
=
0
;
root
->
in_radix
=
0
;
root
->
clean_orphans
=
0
;
root
->
fs_info
=
fs_info
;
root
->
fs_info
=
fs_info
;
root
->
objectid
=
objectid
;
root
->
objectid
=
objectid
;
...
@@ -928,7 +930,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
...
@@ -928,7 +930,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root
->
defrag_trans_start
=
fs_info
->
generation
;
root
->
defrag_trans_start
=
fs_info
->
generation
;
init_completion
(
&
root
->
kobj_unregister
);
init_completion
(
&
root
->
kobj_unregister
);
root
->
defrag_running
=
0
;
root
->
defrag_running
=
0
;
root
->
defrag_level
=
0
;
root
->
root_key
.
objectid
=
objectid
;
root
->
root_key
.
objectid
=
objectid
;
root
->
anon_super
.
s_root
=
NULL
;
root
->
anon_super
.
s_root
=
NULL
;
root
->
anon_super
.
s_dev
=
0
;
root
->
anon_super
.
s_dev
=
0
;
...
@@ -980,12 +981,12 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
...
@@ -980,12 +981,12 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
while
(
1
)
{
while
(
1
)
{
ret
=
find_first_extent_bit
(
&
log_root_tree
->
dirty_log_pages
,
ret
=
find_first_extent_bit
(
&
log_root_tree
->
dirty_log_pages
,
0
,
&
start
,
&
end
,
EXTENT_DIRTY
);
0
,
&
start
,
&
end
,
EXTENT_DIRTY
|
EXTENT_NEW
);
if
(
ret
)
if
(
ret
)
break
;
break
;
clear_extent_
dirty
(
&
log_root_tree
->
dirty_log_pages
,
clear_extent_
bits
(
&
log_root_tree
->
dirty_log_pages
,
start
,
end
,
start
,
end
,
GFP_NOFS
);
EXTENT_DIRTY
|
EXTENT_NEW
,
GFP_NOFS
);
}
}
eb
=
fs_info
->
log_root_tree
->
node
;
eb
=
fs_info
->
log_root_tree
->
node
;
...
@@ -1210,8 +1211,10 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
...
@@ -1210,8 +1211,10 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
ret
=
radix_tree_insert
(
&
fs_info
->
fs_roots_radix
,
ret
=
radix_tree_insert
(
&
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
root
);
root
);
if
(
ret
==
0
)
if
(
ret
==
0
)
{
root
->
in_radix
=
1
;
root
->
in_radix
=
1
;
root
->
clean_orphans
=
1
;
}
spin_unlock
(
&
fs_info
->
fs_roots_radix_lock
);
spin_unlock
(
&
fs_info
->
fs_roots_radix_lock
);
radix_tree_preload_end
();
radix_tree_preload_end
();
if
(
ret
)
{
if
(
ret
)
{
...
@@ -1225,10 +1228,6 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
...
@@ -1225,10 +1228,6 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
ret
=
btrfs_find_dead_roots
(
fs_info
->
tree_root
,
ret
=
btrfs_find_dead_roots
(
fs_info
->
tree_root
,
root
->
root_key
.
objectid
);
root
->
root_key
.
objectid
);
WARN_ON
(
ret
);
WARN_ON
(
ret
);
if
(
!
(
fs_info
->
sb
->
s_flags
&
MS_RDONLY
))
btrfs_orphan_cleanup
(
root
);
return
root
;
return
root
;
fail:
fail:
free_fs_root
(
root
);
free_fs_root
(
root
);
...
@@ -1477,6 +1476,7 @@ static int cleaner_kthread(void *arg)
...
@@ -1477,6 +1476,7 @@ static int cleaner_kthread(void *arg)
if
(
!
(
root
->
fs_info
->
sb
->
s_flags
&
MS_RDONLY
)
&&
if
(
!
(
root
->
fs_info
->
sb
->
s_flags
&
MS_RDONLY
)
&&
mutex_trylock
(
&
root
->
fs_info
->
cleaner_mutex
))
{
mutex_trylock
(
&
root
->
fs_info
->
cleaner_mutex
))
{
btrfs_run_delayed_iputs
(
root
);
btrfs_clean_old_snapshots
(
root
);
btrfs_clean_old_snapshots
(
root
);
mutex_unlock
(
&
root
->
fs_info
->
cleaner_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
cleaner_mutex
);
}
}
...
@@ -1606,6 +1606,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
...
@@ -1606,6 +1606,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
INIT_RADIX_TREE
(
&
fs_info
->
fs_roots_radix
,
GFP_ATOMIC
);
INIT_RADIX_TREE
(
&
fs_info
->
fs_roots_radix
,
GFP_ATOMIC
);
INIT_LIST_HEAD
(
&
fs_info
->
trans_list
);
INIT_LIST_HEAD
(
&
fs_info
->
trans_list
);
INIT_LIST_HEAD
(
&
fs_info
->
dead_roots
);
INIT_LIST_HEAD
(
&
fs_info
->
dead_roots
);
INIT_LIST_HEAD
(
&
fs_info
->
delayed_iputs
);
INIT_LIST_HEAD
(
&
fs_info
->
hashers
);
INIT_LIST_HEAD
(
&
fs_info
->
hashers
);
INIT_LIST_HEAD
(
&
fs_info
->
delalloc_inodes
);
INIT_LIST_HEAD
(
&
fs_info
->
delalloc_inodes
);
INIT_LIST_HEAD
(
&
fs_info
->
ordered_operations
);
INIT_LIST_HEAD
(
&
fs_info
->
ordered_operations
);
...
@@ -1614,6 +1615,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
...
@@ -1614,6 +1615,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
spin_lock_init
(
&
fs_info
->
new_trans_lock
);
spin_lock_init
(
&
fs_info
->
new_trans_lock
);
spin_lock_init
(
&
fs_info
->
ref_cache_lock
);
spin_lock_init
(
&
fs_info
->
ref_cache_lock
);
spin_lock_init
(
&
fs_info
->
fs_roots_radix_lock
);
spin_lock_init
(
&
fs_info
->
fs_roots_radix_lock
);
spin_lock_init
(
&
fs_info
->
delayed_iput_lock
);
init_completion
(
&
fs_info
->
kobj_unregister
);
init_completion
(
&
fs_info
->
kobj_unregister
);
fs_info
->
tree_root
=
tree_root
;
fs_info
->
tree_root
=
tree_root
;
...
@@ -1689,6 +1691,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
...
@@ -1689,6 +1691,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
mutex_init
(
&
fs_info
->
cleaner_mutex
);
mutex_init
(
&
fs_info
->
cleaner_mutex
);
mutex_init
(
&
fs_info
->
volume_mutex
);
mutex_init
(
&
fs_info
->
volume_mutex
);
init_rwsem
(
&
fs_info
->
extent_commit_sem
);
init_rwsem
(
&
fs_info
->
extent_commit_sem
);
init_rwsem
(
&
fs_info
->
cleanup_work_sem
);
init_rwsem
(
&
fs_info
->
subvol_sem
);
init_rwsem
(
&
fs_info
->
subvol_sem
);
btrfs_init_free_cluster
(
&
fs_info
->
meta_alloc_cluster
);
btrfs_init_free_cluster
(
&
fs_info
->
meta_alloc_cluster
);
...
@@ -2386,8 +2389,14 @@ int btrfs_commit_super(struct btrfs_root *root)
...
@@ -2386,8 +2389,14 @@ int btrfs_commit_super(struct btrfs_root *root)
int
ret
;
int
ret
;
mutex_lock
(
&
root
->
fs_info
->
cleaner_mutex
);
mutex_lock
(
&
root
->
fs_info
->
cleaner_mutex
);
btrfs_run_delayed_iputs
(
root
);
btrfs_clean_old_snapshots
(
root
);
btrfs_clean_old_snapshots
(
root
);
mutex_unlock
(
&
root
->
fs_info
->
cleaner_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
cleaner_mutex
);
/* wait until ongoing cleanup work done */
down_write
(
&
root
->
fs_info
->
cleanup_work_sem
);
up_write
(
&
root
->
fs_info
->
cleanup_work_sem
);
trans
=
btrfs_start_transaction
(
root
,
1
);
trans
=
btrfs_start_transaction
(
root
,
1
);
ret
=
btrfs_commit_transaction
(
trans
,
root
);
ret
=
btrfs_commit_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
...
...
fs/btrfs/extent-tree.c
View file @
ebfee3d7
...
@@ -195,6 +195,14 @@ static int exclude_super_stripes(struct btrfs_root *root,
...
@@ -195,6 +195,14 @@ static int exclude_super_stripes(struct btrfs_root *root,
int
stripe_len
;
int
stripe_len
;
int
i
,
nr
,
ret
;
int
i
,
nr
,
ret
;
if
(
cache
->
key
.
objectid
<
BTRFS_SUPER_INFO_OFFSET
)
{
stripe_len
=
BTRFS_SUPER_INFO_OFFSET
-
cache
->
key
.
objectid
;
cache
->
bytes_super
+=
stripe_len
;
ret
=
add_excluded_extent
(
root
,
cache
->
key
.
objectid
,
stripe_len
);
BUG_ON
(
ret
);
}
for
(
i
=
0
;
i
<
BTRFS_SUPER_MIRROR_MAX
;
i
++
)
{
for
(
i
=
0
;
i
<
BTRFS_SUPER_MIRROR_MAX
;
i
++
)
{
bytenr
=
btrfs_sb_offset
(
i
);
bytenr
=
btrfs_sb_offset
(
i
);
ret
=
btrfs_rmap_block
(
&
root
->
fs_info
->
mapping_tree
,
ret
=
btrfs_rmap_block
(
&
root
->
fs_info
->
mapping_tree
,
...
@@ -255,7 +263,7 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
...
@@ -255,7 +263,7 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
if
(
ret
)
if
(
ret
)
break
;
break
;
if
(
extent_start
=
=
start
)
{
if
(
extent_start
<
=
start
)
{
start
=
extent_end
+
1
;
start
=
extent_end
+
1
;
}
else
if
(
extent_start
>
start
&&
extent_start
<
end
)
{
}
else
if
(
extent_start
>
start
&&
extent_start
<
end
)
{
size
=
extent_start
-
start
;
size
=
extent_start
-
start
;
...
@@ -2880,9 +2888,9 @@ static noinline void flush_delalloc_async(struct btrfs_work *work)
...
@@ -2880,9 +2888,9 @@ static noinline void flush_delalloc_async(struct btrfs_work *work)
root
=
async
->
root
;
root
=
async
->
root
;
info
=
async
->
info
;
info
=
async
->
info
;
btrfs_start_delalloc_inodes
(
root
);
btrfs_start_delalloc_inodes
(
root
,
0
);
wake_up
(
&
info
->
flush_wait
);
wake_up
(
&
info
->
flush_wait
);
btrfs_wait_ordered_extents
(
root
,
0
);
btrfs_wait_ordered_extents
(
root
,
0
,
0
);
spin_lock
(
&
info
->
lock
);
spin_lock
(
&
info
->
lock
);
info
->
flushing
=
0
;
info
->
flushing
=
0
;
...
@@ -2956,8 +2964,8 @@ static void flush_delalloc(struct btrfs_root *root,
...
@@ -2956,8 +2964,8 @@ static void flush_delalloc(struct btrfs_root *root,
return
;
return
;
flush:
flush:
btrfs_start_delalloc_inodes
(
root
);
btrfs_start_delalloc_inodes
(
root
,
0
);
btrfs_wait_ordered_extents
(
root
,
0
);
btrfs_wait_ordered_extents
(
root
,
0
,
0
);
spin_lock
(
&
info
->
lock
);
spin_lock
(
&
info
->
lock
);
info
->
flushing
=
0
;
info
->
flushing
=
0
;
...
@@ -3454,14 +3462,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
...
@@ -3454,14 +3462,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
else
else
old_val
-=
num_bytes
;
old_val
-=
num_bytes
;
btrfs_set_super_bytes_used
(
&
info
->
super_copy
,
old_val
);
btrfs_set_super_bytes_used
(
&
info
->
super_copy
,
old_val
);
/* block accounting for root item */
old_val
=
btrfs_root_used
(
&
root
->
root_item
);
if
(
alloc
)
old_val
+=
num_bytes
;
else
old_val
-=
num_bytes
;
btrfs_set_root_used
(
&
root
->
root_item
,
old_val
);
spin_unlock
(
&
info
->
delalloc_lock
);
spin_unlock
(
&
info
->
delalloc_lock
);
while
(
total
)
{
while
(
total
)
{
...
@@ -4049,6 +4049,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
...
@@ -4049,6 +4049,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
return
ret
;
return
ret
;
}
}
int
btrfs_free_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
bytenr
,
u32
blocksize
,
u64
parent
,
u64
root_objectid
,
int
level
)
{
u64
used
;
spin_lock
(
&
root
->
node_lock
);
used
=
btrfs_root_used
(
&
root
->
root_item
)
-
blocksize
;
btrfs_set_root_used
(
&
root
->
root_item
,
used
);
spin_unlock
(
&
root
->
node_lock
);
return
btrfs_free_extent
(
trans
,
root
,
bytenr
,
blocksize
,
parent
,
root_objectid
,
level
,
0
);
}
static
u64
stripe_align
(
struct
btrfs_root
*
root
,
u64
val
)
static
u64
stripe_align
(
struct
btrfs_root
*
root
,
u64
val
)
{
{
u64
mask
=
((
u64
)
root
->
stripesize
-
1
);
u64
mask
=
((
u64
)
root
->
stripesize
-
1
);
...
@@ -4578,7 +4593,6 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
...
@@ -4578,7 +4593,6 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
{
{
int
ret
;
int
ret
;
u64
search_start
=
0
;
u64
search_start
=
0
;
struct
btrfs_fs_info
*
info
=
root
->
fs_info
;
data
=
btrfs_get_alloc_profile
(
root
,
data
);
data
=
btrfs_get_alloc_profile
(
root
,
data
);
again:
again:
...
@@ -4586,17 +4600,9 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
...
@@ -4586,17 +4600,9 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
* the only place that sets empty_size is btrfs_realloc_node, which
* the only place that sets empty_size is btrfs_realloc_node, which
* is not called recursively on allocations
* is not called recursively on allocations
*/
*/
if
(
empty_size
||
root
->
ref_cows
)
{
if
(
empty_size
||
root
->
ref_cows
)
if
(
!
(
data
&
BTRFS_BLOCK_GROUP_METADATA
))
{
ret
=
do_chunk_alloc
(
trans
,
root
->
fs_info
->
extent_root
,
2
*
1024
*
1024
,
BTRFS_BLOCK_GROUP_METADATA
|
(
info
->
metadata_alloc_profile
&
info
->
avail_metadata_alloc_bits
),
0
);
}
ret
=
do_chunk_alloc
(
trans
,
root
->
fs_info
->
extent_root
,
ret
=
do_chunk_alloc
(
trans
,
root
->
fs_info
->
extent_root
,
num_bytes
+
2
*
1024
*
1024
,
data
,
0
);
num_bytes
+
2
*
1024
*
1024
,
data
,
0
);
}
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
WARN_ON
(
num_bytes
<
root
->
sectorsize
);
ret
=
find_free_extent
(
trans
,
root
,
num_bytes
,
empty_size
,
ret
=
find_free_extent
(
trans
,
root
,
num_bytes
,
empty_size
,
...
@@ -4897,6 +4903,14 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans,
...
@@ -4897,6 +4903,14 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans,
extent_op
);
extent_op
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
}
}
if
(
root_objectid
==
root
->
root_key
.
objectid
)
{
u64
used
;
spin_lock
(
&
root
->
node_lock
);
used
=
btrfs_root_used
(
&
root
->
root_item
)
+
num_bytes
;
btrfs_set_root_used
(
&
root
->
root_item
,
used
);
spin_unlock
(
&
root
->
node_lock
);
}
return
ret
;
return
ret
;
}
}
...
@@ -4919,8 +4933,16 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
...
@@ -4919,8 +4933,16 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
btrfs_set_buffer_uptodate
(
buf
);
btrfs_set_buffer_uptodate
(
buf
);
if
(
root
->
root_key
.
objectid
==
BTRFS_TREE_LOG_OBJECTID
)
{
if
(
root
->
root_key
.
objectid
==
BTRFS_TREE_LOG_OBJECTID
)
{
/*
* we allow two log transactions at a time, use different
* EXENT bit to differentiate dirty pages.
*/
if
(
root
->
log_transid
%
2
==
0
)
set_extent_dirty
(
&
root
->
dirty_log_pages
,
buf
->
start
,
set_extent_dirty
(
&
root
->
dirty_log_pages
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
else
set_extent_new
(
&
root
->
dirty_log_pages
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
}
else
{
}
else
{
set_extent_dirty
(
&
trans
->
transaction
->
dirty_pages
,
buf
->
start
,
set_extent_dirty
(
&
trans
->
transaction
->
dirty_pages
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
...
...
fs/btrfs/file.c
View file @
ebfee3d7
This diff is collapsed.
Click to expand it.
fs/btrfs/inode.c
View file @
ebfee3d7
This diff is collapsed.
Click to expand it.
fs/btrfs/ioctl.c
View file @
ebfee3d7
...
@@ -237,7 +237,6 @@ static noinline int create_subvol(struct btrfs_root *root,
...
@@ -237,7 +237,6 @@ static noinline int create_subvol(struct btrfs_root *root,
u64
objectid
;
u64
objectid
;
u64
new_dirid
=
BTRFS_FIRST_FREE_OBJECTID
;
u64
new_dirid
=
BTRFS_FIRST_FREE_OBJECTID
;
u64
index
=
0
;
u64
index
=
0
;
unsigned
long
nr
=
1
;
/*
/*
* 1 - inode item
* 1 - inode item
...
@@ -290,7 +289,7 @@ static noinline int create_subvol(struct btrfs_root *root,
...
@@ -290,7 +289,7 @@ static noinline int create_subvol(struct btrfs_root *root,
btrfs_set_root_generation
(
&
root_item
,
trans
->
transid
);
btrfs_set_root_generation
(
&
root_item
,
trans
->
transid
);
btrfs_set_root_level
(
&
root_item
,
0
);
btrfs_set_root_level
(
&
root_item
,
0
);
btrfs_set_root_refs
(
&
root_item
,
1
);
btrfs_set_root_refs
(
&
root_item
,
1
);
btrfs_set_root_used
(
&
root_item
,
0
);
btrfs_set_root_used
(
&
root_item
,
leaf
->
len
);
btrfs_set_root_last_snapshot
(
&
root_item
,
0
);
btrfs_set_root_last_snapshot
(
&
root_item
,
0
);
memset
(
&
root_item
.
drop_progress
,
0
,
sizeof
(
root_item
.
drop_progress
));
memset
(
&
root_item
.
drop_progress
,
0
,
sizeof
(
root_item
.
drop_progress
));
...
@@ -342,24 +341,21 @@ static noinline int create_subvol(struct btrfs_root *root,
...
@@ -342,24 +341,21 @@ static noinline int create_subvol(struct btrfs_root *root,
d_instantiate
(
dentry
,
btrfs_lookup_dentry
(
dir
,
dentry
));
d_instantiate
(
dentry
,
btrfs_lookup_dentry
(
dir
,
dentry
));
fail:
fail:
nr
=
trans
->
blocks_used
;
err
=
btrfs_commit_transaction
(
trans
,
root
);
err
=
btrfs_commit_transaction
(
trans
,
root
);
if
(
err
&&
!
ret
)
if
(
err
&&
!
ret
)
ret
=
err
;
ret
=
err
;
btrfs_unreserve_metadata_space
(
root
,
6
);
btrfs_unreserve_metadata_space
(
root
,
6
);
btrfs_btree_balance_dirty
(
root
,
nr
);
return
ret
;
return
ret
;
}
}
static
int
create_snapshot
(
struct
btrfs_root
*
root
,
struct
dentry
*
dentry
,
static
int
create_snapshot
(
struct
btrfs_root
*
root
,
struct
dentry
*
dentry
,
char
*
name
,
int
namelen
)
char
*
name
,
int
namelen
)
{
{
struct
inode
*
inode
;
struct
btrfs_pending_snapshot
*
pending_snapshot
;
struct
btrfs_pending_snapshot
*
pending_snapshot
;
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_trans_handle
*
trans
;
int
ret
=
0
;
int
ret
;
int
err
;
unsigned
long
nr
=
0
;
if
(
!
root
->
ref_cows
)
if
(
!
root
->
ref_cows
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -372,20 +368,20 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
...
@@ -372,20 +368,20 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
*/
*/
ret
=
btrfs_reserve_metadata_space
(
root
,
6
);
ret
=
btrfs_reserve_metadata_space
(
root
,
6
);
if
(
ret
)
if
(
ret
)
goto
fail
_unlock
;
goto
fail
;
pending_snapshot
=
kzalloc
(
sizeof
(
*
pending_snapshot
),
GFP_NOFS
);
pending_snapshot
=
kzalloc
(
sizeof
(
*
pending_snapshot
),
GFP_NOFS
);
if
(
!
pending_snapshot
)
{
if
(
!
pending_snapshot
)
{
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
btrfs_unreserve_metadata_space
(
root
,
6
);
btrfs_unreserve_metadata_space
(
root
,
6
);
goto
fail
_unlock
;
goto
fail
;
}
}
pending_snapshot
->
name
=
kmalloc
(
namelen
+
1
,
GFP_NOFS
);
pending_snapshot
->
name
=
kmalloc
(
namelen
+
1
,
GFP_NOFS
);
if
(
!
pending_snapshot
->
name
)
{
if
(
!
pending_snapshot
->
name
)
{
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
kfree
(
pending_snapshot
);
kfree
(
pending_snapshot
);
btrfs_unreserve_metadata_space
(
root
,
6
);
btrfs_unreserve_metadata_space
(
root
,
6
);
goto
fail
_unlock
;
goto
fail
;
}
}
memcpy
(
pending_snapshot
->
name
,
name
,
namelen
);
memcpy
(
pending_snapshot
->
name
,
name
,
namelen
);
pending_snapshot
->
name
[
namelen
]
=
'\0'
;
pending_snapshot
->
name
[
namelen
]
=
'\0'
;
...
@@ -395,10 +391,19 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
...
@@ -395,10 +391,19 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
pending_snapshot
->
root
=
root
;
pending_snapshot
->
root
=
root
;
list_add
(
&
pending_snapshot
->
list
,
list_add
(
&
pending_snapshot
->
list
,
&
trans
->
transaction
->
pending_snapshots
);
&
trans
->
transaction
->
pending_snapshots
);
err
=
btrfs_commit_transaction
(
trans
,
root
);
ret
=
btrfs_commit_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
btrfs_unreserve_metadata_space
(
root
,
6
);
fail_unlock:
inode
=
btrfs_lookup_dentry
(
dentry
->
d_parent
->
d_inode
,
dentry
);
btrfs_btree_balance_dirty
(
root
,
nr
);
if
(
IS_ERR
(
inode
))
{
ret
=
PTR_ERR
(
inode
);
goto
fail
;
}
BUG_ON
(
!
inode
);
d_instantiate
(
dentry
,
inode
);
ret
=
0
;
fail:
return
ret
;
return
ret
;
}
}
...
@@ -1027,8 +1032,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
...
@@ -1027,8 +1032,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
BUG_ON
(
!
trans
);
BUG_ON
(
!
trans
);
/* punch hole in destination first */
/* punch hole in destination first */
btrfs_drop_extents
(
trans
,
root
,
inode
,
off
,
off
+
len
,
btrfs_drop_extents
(
trans
,
inode
,
off
,
off
+
len
,
&
hint_byte
,
1
);
off
+
len
,
0
,
&
hint_byte
,
1
);
/* clone data */
/* clone data */
key
.
objectid
=
src
->
i_ino
;
key
.
objectid
=
src
->
i_ino
;
...
...
fs/btrfs/ordered-data.c
View file @
ebfee3d7
...
@@ -291,16 +291,16 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
...
@@ -291,16 +291,16 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
/*
/*
* remove an ordered extent from the tree. No references are dropped
* remove an ordered extent from the tree. No references are dropped
* but, anyone waiting on this extent is woken up.
* and you must wake_up entry->wait. You must hold the tree mutex
* while you call this function.
*/
*/
int
btrfs_remove_ordered_extent
(
struct
inode
*
inode
,
static
int
__
btrfs_remove_ordered_extent
(
struct
inode
*
inode
,
struct
btrfs_ordered_extent
*
entry
)
struct
btrfs_ordered_extent
*
entry
)
{
{
struct
btrfs_ordered_inode_tree
*
tree
;
struct
btrfs_ordered_inode_tree
*
tree
;
struct
rb_node
*
node
;
struct
rb_node
*
node
;
tree
=
&
BTRFS_I
(
inode
)
->
ordered_tree
;
tree
=
&
BTRFS_I
(
inode
)
->
ordered_tree
;
mutex_lock
(
&
tree
->
mutex
);
node
=
&
entry
->
rb_node
;
node
=
&
entry
->
rb_node
;
rb_erase
(
node
,
&
tree
->
tree
);
rb_erase
(
node
,
&
tree
->
tree
);
tree
->
last
=
NULL
;
tree
->
last
=
NULL
;
...
@@ -326,16 +326,34 @@ int btrfs_remove_ordered_extent(struct inode *inode,
...
@@ -326,16 +326,34 @@ int btrfs_remove_ordered_extent(struct inode *inode,
}
}
spin_unlock
(
&
BTRFS_I
(
inode
)
->
root
->
fs_info
->
ordered_extent_lock
);
spin_unlock
(
&
BTRFS_I
(
inode
)
->
root
->
fs_info
->
ordered_extent_lock
);
return
0
;
}
/*
* remove an ordered extent from the tree. No references are dropped
* but any waiters are woken.
*/
int
btrfs_remove_ordered_extent
(
struct
inode
*
inode
,
struct
btrfs_ordered_extent
*
entry
)
{
struct
btrfs_ordered_inode_tree
*
tree
;
int
ret
;
tree
=
&
BTRFS_I
(
inode
)
->
ordered_tree
;
mutex_lock
(
&
tree
->
mutex
);
ret
=
__btrfs_remove_ordered_extent
(
inode
,
entry
);
mutex_unlock
(
&
tree
->
mutex
);
mutex_unlock
(
&
tree
->
mutex
);
wake_up
(
&
entry
->
wait
);
wake_up
(
&
entry
->
wait
);
return
0
;
return
ret
;
}
}
/*
/*
* wait for all the ordered extents in a root. This is done when balancing
* wait for all the ordered extents in a root. This is done when balancing
* space between drives.
* space between drives.
*/
*/
int
btrfs_wait_ordered_extents
(
struct
btrfs_root
*
root
,
int
nocow_only
)
int
btrfs_wait_ordered_extents
(
struct
btrfs_root
*
root
,
int
nocow_only
,
int
delay_iput
)
{
{
struct
list_head
splice
;
struct
list_head
splice
;
struct
list_head
*
cur
;
struct
list_head
*
cur
;
...
@@ -372,6 +390,9 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only)
...
@@ -372,6 +390,9 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only)
if
(
inode
)
{
if
(
inode
)
{
btrfs_start_ordered_extent
(
inode
,
ordered
,
1
);
btrfs_start_ordered_extent
(
inode
,
ordered
,
1
);
btrfs_put_ordered_extent
(
ordered
);
btrfs_put_ordered_extent
(
ordered
);
if
(
delay_iput
)
btrfs_add_delayed_iput
(
inode
);
else
iput
(
inode
);
iput
(
inode
);
}
else
{
}
else
{
btrfs_put_ordered_extent
(
ordered
);
btrfs_put_ordered_extent
(
ordered
);
...
@@ -430,7 +451,7 @@ int btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
...
@@ -430,7 +451,7 @@ int btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
btrfs_wait_ordered_range
(
inode
,
0
,
(
u64
)
-
1
);
btrfs_wait_ordered_range
(
inode
,
0
,
(
u64
)
-
1
);
else
else
filemap_flush
(
inode
->
i_mapping
);
filemap_flush
(
inode
->
i_mapping
);
iput
(
inode
);
btrfs_add_delayed_
iput
(
inode
);
}
}
cond_resched
();
cond_resched
();
...
@@ -589,7 +610,7 @@ btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset)
...
@@ -589,7 +610,7 @@ btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset)
* After an extent is done, call this to conditionally update the on disk
* After an extent is done, call this to conditionally update the on disk
* i_size. i_size is updated to cover any fully written part of the file.
* i_size. i_size is updated to cover any fully written part of the file.
*/
*/
int
btrfs_ordered_update_i_size
(
struct
inode
*
inode
,
int
btrfs_ordered_update_i_size
(
struct
inode
*
inode
,
u64
offset
,
struct
btrfs_ordered_extent
*
ordered
)
struct
btrfs_ordered_extent
*
ordered
)
{
{
struct
btrfs_ordered_inode_tree
*
tree
=
&
BTRFS_I
(
inode
)
->
ordered_tree
;
struct
btrfs_ordered_inode_tree
*
tree
=
&
BTRFS_I
(
inode
)
->
ordered_tree
;
...
@@ -597,18 +618,30 @@ int btrfs_ordered_update_i_size(struct inode *inode,
...
@@ -597,18 +618,30 @@ int btrfs_ordered_update_i_size(struct inode *inode,
u64
disk_i_size
;
u64
disk_i_size
;
u64
new_i_size
;
u64
new_i_size
;
u64
i_size_test
;
u64
i_size_test
;
u64
i_size
=
i_size_read
(
inode
);
struct
rb_node
*
node
;
struct
rb_node
*
node
;
struct
rb_node
*
prev
=
NULL
;
struct
btrfs_ordered_extent
*
test
;
struct
btrfs_ordered_extent
*
test
;
int
ret
=
1
;
if
(
ordered
)
offset
=
entry_end
(
ordered
);
mutex_lock
(
&
tree
->
mutex
);
mutex_lock
(
&
tree
->
mutex
);
disk_i_size
=
BTRFS_I
(
inode
)
->
disk_i_size
;
disk_i_size
=
BTRFS_I
(
inode
)
->
disk_i_size
;
/* truncate file */
if
(
disk_i_size
>
i_size
)
{
BTRFS_I
(
inode
)
->
disk_i_size
=
i_size
;
ret
=
0
;
goto
out
;
}
/*
/*
* if the disk i_size is already at the inode->i_size, or
* if the disk i_size is already at the inode->i_size, or
* this ordered extent is inside the disk i_size, we're done
* this ordered extent is inside the disk i_size, we're done
*/
*/
if
(
disk_i_size
>=
inode
->
i_size
||
if
(
disk_i_size
==
i_size
||
offset
<=
disk_i_size
)
{
ordered
->
file_offset
+
ordered
->
len
<=
disk_i_size
)
{
goto
out
;
goto
out
;
}
}
...
@@ -616,8 +649,7 @@ int btrfs_ordered_update_i_size(struct inode *inode,
...
@@ -616,8 +649,7 @@ int btrfs_ordered_update_i_size(struct inode *inode,
* we can't update the disk_isize if there are delalloc bytes
* we can't update the disk_isize if there are delalloc bytes
* between disk_i_size and this ordered extent
* between disk_i_size and this ordered extent
*/
*/
if
(
test_range_bit
(
io_tree
,
disk_i_size
,
if
(
test_range_bit
(
io_tree
,
disk_i_size
,
offset
-
1
,
ordered
->
file_offset
+
ordered
->
len
-
1
,
EXTENT_DELALLOC
,
0
,
NULL
))
{
EXTENT_DELALLOC
,
0
,
NULL
))
{
goto
out
;
goto
out
;
}
}
...
@@ -626,20 +658,32 @@ int btrfs_ordered_update_i_size(struct inode *inode,
...
@@ -626,20 +658,32 @@ int btrfs_ordered_update_i_size(struct inode *inode,
* if we find an ordered extent then we can't update disk i_size
* if we find an ordered extent then we can't update disk i_size
* yet
* yet
*/
*/
node
=
&
ordered
->
rb_node
;
if
(
ordered
)
{
while
(
1
)
{
node
=
rb_prev
(
&
ordered
->
rb_node
);
node
=
rb_prev
(
node
);
}
else
{
if
(
!
node
)
prev
=
tree_search
(
tree
,
offset
);
break
;
/*
* we insert file extents without involving ordered struct,
* so there should be no ordered struct cover this offset
*/
if
(
prev
)
{
test
=
rb_entry
(
prev
,
struct
btrfs_ordered_extent
,
rb_node
);
BUG_ON
(
offset_in_entry
(
test
,
offset
));
}
node
=
prev
;
}
while
(
node
)
{
test
=
rb_entry
(
node
,
struct
btrfs_ordered_extent
,
rb_node
);
test
=
rb_entry
(
node
,
struct
btrfs_ordered_extent
,
rb_node
);
if
(
test
->
file_offset
+
test
->
len
<=
disk_i_size
)
if
(
test
->
file_offset
+
test
->
len
<=
disk_i_size
)
break
;
break
;
if
(
test
->
file_offset
>=
i
node
->
i
_size
)
if
(
test
->
file_offset
>=
i_size
)
break
;
break
;
if
(
test
->
file_offset
>=
disk_i_size
)
if
(
test
->
file_offset
>=
disk_i_size
)
goto
out
;
goto
out
;
node
=
rb_prev
(
node
);
}
}
new_i_size
=
min_t
(
u64
,
entry_end
(
ordered
),
i_size_read
(
inode
)
);
new_i_size
=
min_t
(
u64
,
offset
,
i_size
);
/*
/*
* at this point, we know we can safely update i_size to at least
* at this point, we know we can safely update i_size to at least
...
@@ -647,7 +691,14 @@ int btrfs_ordered_update_i_size(struct inode *inode,
...
@@ -647,7 +691,14 @@ int btrfs_ordered_update_i_size(struct inode *inode,
* walk forward and see if ios from higher up in the file have
* walk forward and see if ios from higher up in the file have
* finished.
* finished.
*/
*/
if
(
ordered
)
{
node
=
rb_next
(
&
ordered
->
rb_node
);
node
=
rb_next
(
&
ordered
->
rb_node
);
}
else
{
if
(
prev
)
node
=
rb_next
(
prev
);
else
node
=
rb_first
(
&
tree
->
tree
);
}
i_size_test
=
0
;
i_size_test
=
0
;
if
(
node
)
{
if
(
node
)
{
/*
/*
...
@@ -655,10 +706,10 @@ int btrfs_ordered_update_i_size(struct inode *inode,
...
@@ -655,10 +706,10 @@ int btrfs_ordered_update_i_size(struct inode *inode,
* between our ordered extent and the next one.
* between our ordered extent and the next one.
*/
*/
test
=
rb_entry
(
node
,
struct
btrfs_ordered_extent
,
rb_node
);
test
=
rb_entry
(
node
,
struct
btrfs_ordered_extent
,
rb_node
);
if
(
test
->
file_offset
>
entry_end
(
ordered
)
)
if
(
test
->
file_offset
>
offset
)
i_size_test
=
test
->
file_offset
;
i_size_test
=
test
->
file_offset
;
}
else
{
}
else
{
i_size_test
=
i_size
_read
(
inode
)
;
i_size_test
=
i_size
;
}
}
/*
/*
...
@@ -667,15 +718,25 @@ int btrfs_ordered_update_i_size(struct inode *inode,
...
@@ -667,15 +718,25 @@ int btrfs_ordered_update_i_size(struct inode *inode,
* are no delalloc bytes in this area, it is safe to update
* are no delalloc bytes in this area, it is safe to update
* disk_i_size to the end of the region.
* disk_i_size to the end of the region.
*/
*/
if
(
i_size_test
>
entry_end
(
ordered
)
&&
if
(
i_size_test
>
offset
&&
!
test_range_bit
(
io_tree
,
entry_end
(
ordered
)
,
i_size_test
-
1
,
!
test_range_bit
(
io_tree
,
offset
,
i_size_test
-
1
,
EXTENT_DELALLOC
,
0
,
NULL
))
{
EXTENT_DELALLOC
,
0
,
NULL
))
{
new_i_size
=
min_t
(
u64
,
i_size_test
,
i_size
_read
(
inode
)
);
new_i_size
=
min_t
(
u64
,
i_size_test
,
i_size
);
}
}
BTRFS_I
(
inode
)
->
disk_i_size
=
new_i_size
;
BTRFS_I
(
inode
)
->
disk_i_size
=
new_i_size
;
ret
=
0
;
out:
out:
/*
* we need to remove the ordered extent with the tree lock held
* so that other people calling this function don't find our fully
* processed ordered entry and skip updating the i_size
*/
if
(
ordered
)
__btrfs_remove_ordered_extent
(
inode
,
ordered
);
mutex_unlock
(
&
tree
->
mutex
);
mutex_unlock
(
&
tree
->
mutex
);
return
0
;
if
(
ordered
)
wake_up
(
&
ordered
->
wait
);
return
ret
;
}
}
/*
/*
...
...
fs/btrfs/ordered-data.h
View file @
ebfee3d7
...
@@ -150,12 +150,13 @@ void btrfs_start_ordered_extent(struct inode *inode,
...
@@ -150,12 +150,13 @@ void btrfs_start_ordered_extent(struct inode *inode,
int
btrfs_wait_ordered_range
(
struct
inode
*
inode
,
u64
start
,
u64
len
);
int
btrfs_wait_ordered_range
(
struct
inode
*
inode
,
u64
start
,
u64
len
);
struct
btrfs_ordered_extent
*
struct
btrfs_ordered_extent
*
btrfs_lookup_first_ordered_extent
(
struct
inode
*
inode
,
u64
file_offset
);
btrfs_lookup_first_ordered_extent
(
struct
inode
*
inode
,
u64
file_offset
);
int
btrfs_ordered_update_i_size
(
struct
inode
*
inode
,
int
btrfs_ordered_update_i_size
(
struct
inode
*
inode
,
u64
offset
,
struct
btrfs_ordered_extent
*
ordered
);
struct
btrfs_ordered_extent
*
ordered
);
int
btrfs_find_ordered_sum
(
struct
inode
*
inode
,
u64
offset
,
u64
disk_bytenr
,
u32
*
sum
);
int
btrfs_find_ordered_sum
(
struct
inode
*
inode
,
u64
offset
,
u64
disk_bytenr
,
u32
*
sum
);
int
btrfs_wait_ordered_extents
(
struct
btrfs_root
*
root
,
int
nocow_only
);
int
btrfs_run_ordered_operations
(
struct
btrfs_root
*
root
,
int
wait
);
int
btrfs_run_ordered_operations
(
struct
btrfs_root
*
root
,
int
wait
);
int
btrfs_add_ordered_operation
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_add_ordered_operation
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
);
struct
inode
*
inode
);
int
btrfs_wait_ordered_extents
(
struct
btrfs_root
*
root
,
int
nocow_only
,
int
delay_iput
);
#endif
#endif
fs/btrfs/relocation.c
View file @
ebfee3d7
...
@@ -1561,6 +1561,20 @@ static int invalidate_extent_cache(struct btrfs_root *root,
...
@@ -1561,6 +1561,20 @@ static int invalidate_extent_cache(struct btrfs_root *root,
return
0
;
return
0
;
}
}
static
void
put_inodes
(
struct
list_head
*
list
)
{
struct
inodevec
*
ivec
;
while
(
!
list_empty
(
list
))
{
ivec
=
list_entry
(
list
->
next
,
struct
inodevec
,
list
);
list_del
(
&
ivec
->
list
);
while
(
ivec
->
nr
>
0
)
{
ivec
->
nr
--
;
iput
(
ivec
->
inode
[
ivec
->
nr
]);
}
kfree
(
ivec
);
}
}
static
int
find_next_key
(
struct
btrfs_path
*
path
,
int
level
,
static
int
find_next_key
(
struct
btrfs_path
*
path
,
int
level
,
struct
btrfs_key
*
key
)
struct
btrfs_key
*
key
)
...
@@ -1723,6 +1737,11 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
...
@@ -1723,6 +1737,11 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
btrfs_btree_balance_dirty
(
root
,
nr
);
btrfs_btree_balance_dirty
(
root
,
nr
);
/*
* put inodes outside transaction, otherwise we may deadlock.
*/
put_inodes
(
&
inode_list
);
if
(
replaced
&&
rc
->
stage
==
UPDATE_DATA_PTRS
)
if
(
replaced
&&
rc
->
stage
==
UPDATE_DATA_PTRS
)
invalidate_extent_cache
(
root
,
&
key
,
&
next_key
);
invalidate_extent_cache
(
root
,
&
key
,
&
next_key
);
}
}
...
@@ -1752,19 +1771,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
...
@@ -1752,19 +1771,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
btrfs_btree_balance_dirty
(
root
,
nr
);
btrfs_btree_balance_dirty
(
root
,
nr
);
/*
put_inodes
(
&
inode_list
);
* put inodes while we aren't holding the tree locks
*/
while
(
!
list_empty
(
&
inode_list
))
{
struct
inodevec
*
ivec
;
ivec
=
list_entry
(
inode_list
.
next
,
struct
inodevec
,
list
);
list_del
(
&
ivec
->
list
);
while
(
ivec
->
nr
>
0
)
{
ivec
->
nr
--
;
iput
(
ivec
->
inode
[
ivec
->
nr
]);
}
kfree
(
ivec
);
}
if
(
replaced
&&
rc
->
stage
==
UPDATE_DATA_PTRS
)
if
(
replaced
&&
rc
->
stage
==
UPDATE_DATA_PTRS
)
invalidate_extent_cache
(
root
,
&
key
,
&
next_key
);
invalidate_extent_cache
(
root
,
&
key
,
&
next_key
);
...
@@ -3534,8 +3541,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
...
@@ -3534,8 +3541,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
(
unsigned
long
long
)
rc
->
block_group
->
key
.
objectid
,
(
unsigned
long
long
)
rc
->
block_group
->
key
.
objectid
,
(
unsigned
long
long
)
rc
->
block_group
->
flags
);
(
unsigned
long
long
)
rc
->
block_group
->
flags
);
btrfs_start_delalloc_inodes
(
fs_info
->
tree_root
);
btrfs_start_delalloc_inodes
(
fs_info
->
tree_root
,
0
);
btrfs_wait_ordered_extents
(
fs_info
->
tree_root
,
0
);
btrfs_wait_ordered_extents
(
fs_info
->
tree_root
,
0
,
0
);
while
(
1
)
{
while
(
1
)
{
rc
->
extents_found
=
0
;
rc
->
extents_found
=
0
;
...
@@ -3755,6 +3762,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
...
@@ -3755,6 +3762,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
BTRFS_DATA_RELOC_TREE_OBJECTID
);
BTRFS_DATA_RELOC_TREE_OBJECTID
);
if
(
IS_ERR
(
fs_root
))
if
(
IS_ERR
(
fs_root
))
err
=
PTR_ERR
(
fs_root
);
err
=
PTR_ERR
(
fs_root
);
btrfs_orphan_cleanup
(
fs_root
);
}
}
return
err
;
return
err
;
}
}
...
...
fs/btrfs/super.c
View file @
ebfee3d7
...
@@ -128,6 +128,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
...
@@ -128,6 +128,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
substring_t
args
[
MAX_OPT_ARGS
];
substring_t
args
[
MAX_OPT_ARGS
];
char
*
p
,
*
num
;
char
*
p
,
*
num
;
int
intarg
;
int
intarg
;
int
ret
=
0
;
if
(
!
options
)
if
(
!
options
)
return
0
;
return
0
;
...
@@ -262,12 +263,18 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
...
@@ -262,12 +263,18 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
case
Opt_discard
:
case
Opt_discard
:
btrfs_set_opt
(
info
->
mount_opt
,
DISCARD
);
btrfs_set_opt
(
info
->
mount_opt
,
DISCARD
);
break
;
break
;
case
Opt_err
:
printk
(
KERN_INFO
"btrfs: unrecognized mount option "
"'%s'
\n
"
,
p
);
ret
=
-
EINVAL
;
goto
out
;
default:
default:
break
;
break
;
}
}
}
}
out:
kfree
(
options
);
kfree
(
options
);
return
0
;
return
ret
;
}
}
/*
/*
...
@@ -405,8 +412,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
...
@@ -405,8 +412,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
return
0
;
return
0
;
}
}
btrfs_start_delalloc_inodes
(
root
);
btrfs_start_delalloc_inodes
(
root
,
0
);
btrfs_wait_ordered_extents
(
root
,
0
);
btrfs_wait_ordered_extents
(
root
,
0
,
0
);
trans
=
btrfs_start_transaction
(
root
,
1
);
trans
=
btrfs_start_transaction
(
root
,
1
);
ret
=
btrfs_commit_transaction
(
trans
,
root
);
ret
=
btrfs_commit_transaction
(
trans
,
root
);
...
@@ -450,6 +457,8 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
...
@@ -450,6 +457,8 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
seq_puts
(
seq
,
",notreelog"
);
seq_puts
(
seq
,
",notreelog"
);
if
(
btrfs_test_opt
(
root
,
FLUSHONCOMMIT
))
if
(
btrfs_test_opt
(
root
,
FLUSHONCOMMIT
))
seq_puts
(
seq
,
",flushoncommit"
);
seq_puts
(
seq
,
",flushoncommit"
);
if
(
btrfs_test_opt
(
root
,
DISCARD
))
seq_puts
(
seq
,
",discard"
);
if
(
!
(
root
->
fs_info
->
sb
->
s_flags
&
MS_POSIXACL
))
if
(
!
(
root
->
fs_info
->
sb
->
s_flags
&
MS_POSIXACL
))
seq_puts
(
seq
,
",noacl"
);
seq_puts
(
seq
,
",noacl"
);
return
0
;
return
0
;
...
...
fs/btrfs/transaction.c
View file @
ebfee3d7
...
@@ -333,6 +333,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
...
@@ -333,6 +333,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
memset
(
trans
,
0
,
sizeof
(
*
trans
));
memset
(
trans
,
0
,
sizeof
(
*
trans
));
kmem_cache_free
(
btrfs_trans_handle_cachep
,
trans
);
kmem_cache_free
(
btrfs_trans_handle_cachep
,
trans
);
if
(
throttle
)
btrfs_run_delayed_iputs
(
root
);
return
0
;
return
0
;
}
}
...
@@ -354,7 +357,7 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
...
@@ -354,7 +357,7 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
* those extents are sent to disk but does not wait on them
* those extents are sent to disk but does not wait on them
*/
*/
int
btrfs_write_marked_extents
(
struct
btrfs_root
*
root
,
int
btrfs_write_marked_extents
(
struct
btrfs_root
*
root
,
struct
extent_io_tree
*
dirty_pages
)
struct
extent_io_tree
*
dirty_pages
,
int
mark
)
{
{
int
ret
;
int
ret
;
int
err
=
0
;
int
err
=
0
;
...
@@ -367,7 +370,7 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
...
@@ -367,7 +370,7 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
while
(
1
)
{
while
(
1
)
{
ret
=
find_first_extent_bit
(
dirty_pages
,
start
,
&
start
,
&
end
,
ret
=
find_first_extent_bit
(
dirty_pages
,
start
,
&
start
,
&
end
,
EXTENT_DIRTY
);
mark
);
if
(
ret
)
if
(
ret
)
break
;
break
;
while
(
start
<=
end
)
{
while
(
start
<=
end
)
{
...
@@ -413,7 +416,7 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
...
@@ -413,7 +416,7 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
* on all the pages and clear them from the dirty pages state tree
* on all the pages and clear them from the dirty pages state tree
*/
*/
int
btrfs_wait_marked_extents
(
struct
btrfs_root
*
root
,
int
btrfs_wait_marked_extents
(
struct
btrfs_root
*
root
,
struct
extent_io_tree
*
dirty_pages
)
struct
extent_io_tree
*
dirty_pages
,
int
mark
)
{
{
int
ret
;
int
ret
;
int
err
=
0
;
int
err
=
0
;
...
@@ -425,12 +428,12 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
...
@@ -425,12 +428,12 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
unsigned
long
index
;
unsigned
long
index
;
while
(
1
)
{
while
(
1
)
{
ret
=
find_first_extent_bit
(
dirty_pages
,
0
,
&
start
,
&
end
,
ret
=
find_first_extent_bit
(
dirty_pages
,
start
,
&
start
,
&
end
,
EXTENT_DIRTY
);
mark
);
if
(
ret
)
if
(
ret
)
break
;
break
;
clear_extent_
dirty
(
dirty_pages
,
start
,
end
,
GFP_NOFS
);
clear_extent_
bits
(
dirty_pages
,
start
,
end
,
mark
,
GFP_NOFS
);
while
(
start
<=
end
)
{
while
(
start
<=
end
)
{
index
=
start
>>
PAGE_CACHE_SHIFT
;
index
=
start
>>
PAGE_CACHE_SHIFT
;
start
=
(
u64
)(
index
+
1
)
<<
PAGE_CACHE_SHIFT
;
start
=
(
u64
)(
index
+
1
)
<<
PAGE_CACHE_SHIFT
;
...
@@ -460,13 +463,13 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
...
@@ -460,13 +463,13 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
* those extents are on disk for transaction or log commit
* those extents are on disk for transaction or log commit
*/
*/
int
btrfs_write_and_wait_marked_extents
(
struct
btrfs_root
*
root
,
int
btrfs_write_and_wait_marked_extents
(
struct
btrfs_root
*
root
,
struct
extent_io_tree
*
dirty_pages
)
struct
extent_io_tree
*
dirty_pages
,
int
mark
)
{
{
int
ret
;
int
ret
;
int
ret2
;
int
ret2
;
ret
=
btrfs_write_marked_extents
(
root
,
dirty_pages
);
ret
=
btrfs_write_marked_extents
(
root
,
dirty_pages
,
mark
);
ret2
=
btrfs_wait_marked_extents
(
root
,
dirty_pages
);
ret2
=
btrfs_wait_marked_extents
(
root
,
dirty_pages
,
mark
);
return
ret
||
ret2
;
return
ret
||
ret2
;
}
}
...
@@ -479,7 +482,8 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
...
@@ -479,7 +482,8 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
return
filemap_write_and_wait
(
btree_inode
->
i_mapping
);
return
filemap_write_and_wait
(
btree_inode
->
i_mapping
);
}
}
return
btrfs_write_and_wait_marked_extents
(
root
,
return
btrfs_write_and_wait_marked_extents
(
root
,
&
trans
->
transaction
->
dirty_pages
);
&
trans
->
transaction
->
dirty_pages
,
EXTENT_DIRTY
);
}
}
/*
/*
...
@@ -497,13 +501,16 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
...
@@ -497,13 +501,16 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
{
{
int
ret
;
int
ret
;
u64
old_root_bytenr
;
u64
old_root_bytenr
;
u64
old_root_used
;
struct
btrfs_root
*
tree_root
=
root
->
fs_info
->
tree_root
;
struct
btrfs_root
*
tree_root
=
root
->
fs_info
->
tree_root
;
old_root_used
=
btrfs_root_used
(
&
root
->
root_item
);
btrfs_write_dirty_block_groups
(
trans
,
root
);
btrfs_write_dirty_block_groups
(
trans
,
root
);
while
(
1
)
{
while
(
1
)
{
old_root_bytenr
=
btrfs_root_bytenr
(
&
root
->
root_item
);
old_root_bytenr
=
btrfs_root_bytenr
(
&
root
->
root_item
);
if
(
old_root_bytenr
==
root
->
node
->
start
)
if
(
old_root_bytenr
==
root
->
node
->
start
&&
old_root_used
==
btrfs_root_used
(
&
root
->
root_item
))
break
;
break
;
btrfs_set_root_node
(
&
root
->
root_item
,
root
->
node
);
btrfs_set_root_node
(
&
root
->
root_item
,
root
->
node
);
...
@@ -512,6 +519,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
...
@@ -512,6 +519,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
&
root
->
root_item
);
&
root
->
root_item
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
old_root_used
=
btrfs_root_used
(
&
root
->
root_item
);
ret
=
btrfs_write_dirty_block_groups
(
trans
,
root
);
ret
=
btrfs_write_dirty_block_groups
(
trans
,
root
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
}
}
...
@@ -795,7 +803,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
...
@@ -795,7 +803,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
memcpy
(
&
pending
->
root_key
,
&
key
,
sizeof
(
key
));
memcpy
(
&
pending
->
root_key
,
&
key
,
sizeof
(
key
));
fail:
fail:
kfree
(
new_root_item
);
kfree
(
new_root_item
);
btrfs_unreserve_metadata_space
(
root
,
6
);
return
ret
;
return
ret
;
}
}
...
@@ -807,7 +814,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
...
@@ -807,7 +814,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
u64
index
=
0
;
u64
index
=
0
;
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_trans_handle
*
trans
;
struct
inode
*
parent_inode
;
struct
inode
*
parent_inode
;
struct
inode
*
inode
;
struct
btrfs_root
*
parent_root
;
struct
btrfs_root
*
parent_root
;
parent_inode
=
pending
->
dentry
->
d_parent
->
d_inode
;
parent_inode
=
pending
->
dentry
->
d_parent
->
d_inode
;
...
@@ -839,8 +845,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
...
@@ -839,8 +845,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
BUG_ON
(
ret
);
BUG_ON
(
ret
);
inode
=
btrfs_lookup_dentry
(
parent_inode
,
pending
->
dentry
);
d_instantiate
(
pending
->
dentry
,
inode
);
fail:
fail:
btrfs_end_transaction
(
trans
,
fs_info
->
fs_root
);
btrfs_end_transaction
(
trans
,
fs_info
->
fs_root
);
return
ret
;
return
ret
;
...
@@ -994,11 +998,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
...
@@ -994,11 +998,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
if
(
flush_on_commit
)
{
if
(
flush_on_commit
)
{
btrfs_start_delalloc_inodes
(
root
);
btrfs_start_delalloc_inodes
(
root
,
1
);
ret
=
btrfs_wait_ordered_extents
(
root
,
0
);
ret
=
btrfs_wait_ordered_extents
(
root
,
0
,
1
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
}
else
if
(
snap_pending
)
{
}
else
if
(
snap_pending
)
{
ret
=
btrfs_wait_ordered_extents
(
root
,
1
);
ret
=
btrfs_wait_ordered_extents
(
root
,
0
,
1
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
}
}
...
@@ -1116,6 +1120,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
...
@@ -1116,6 +1120,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
current
->
journal_info
=
NULL
;
current
->
journal_info
=
NULL
;
kmem_cache_free
(
btrfs_trans_handle_cachep
,
trans
);
kmem_cache_free
(
btrfs_trans_handle_cachep
,
trans
);
if
(
current
!=
root
->
fs_info
->
transaction_kthread
)
btrfs_run_delayed_iputs
(
root
);
return
ret
;
return
ret
;
}
}
...
...
fs/btrfs/transaction.h
View file @
ebfee3d7
...
@@ -107,10 +107,10 @@ void btrfs_throttle(struct btrfs_root *root);
...
@@ -107,10 +107,10 @@ void btrfs_throttle(struct btrfs_root *root);
int
btrfs_record_root_in_trans
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_record_root_in_trans
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
);
struct
btrfs_root
*
root
);
int
btrfs_write_and_wait_marked_extents
(
struct
btrfs_root
*
root
,
int
btrfs_write_and_wait_marked_extents
(
struct
btrfs_root
*
root
,
struct
extent_io_tree
*
dirty_pages
);
struct
extent_io_tree
*
dirty_pages
,
int
mark
);
int
btrfs_write_marked_extents
(
struct
btrfs_root
*
root
,
int
btrfs_write_marked_extents
(
struct
btrfs_root
*
root
,
struct
extent_io_tree
*
dirty_pages
);
struct
extent_io_tree
*
dirty_pages
,
int
mark
);
int
btrfs_wait_marked_extents
(
struct
btrfs_root
*
root
,
int
btrfs_wait_marked_extents
(
struct
btrfs_root
*
root
,
struct
extent_io_tree
*
dirty_pages
);
struct
extent_io_tree
*
dirty_pages
,
int
mark
);
int
btrfs_transaction_in_commit
(
struct
btrfs_fs_info
*
info
);
int
btrfs_transaction_in_commit
(
struct
btrfs_fs_info
*
info
);
#endif
#endif
fs/btrfs/tree-log.c
View file @
ebfee3d7
...
@@ -542,8 +542,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
...
@@ -542,8 +542,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
saved_nbytes
=
inode_get_bytes
(
inode
);
saved_nbytes
=
inode_get_bytes
(
inode
);
/* drop any overlapping extents */
/* drop any overlapping extents */
ret
=
btrfs_drop_extents
(
trans
,
root
,
inode
,
ret
=
btrfs_drop_extents
(
trans
,
inode
,
start
,
extent_end
,
start
,
extent_end
,
extent_end
,
start
,
&
alloc_hint
,
1
);
&
alloc_hint
,
1
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
if
(
found_type
==
BTRFS_FILE_EXTENT_REG
||
if
(
found_type
==
BTRFS_FILE_EXTENT_REG
||
...
@@ -930,6 +930,17 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
...
@@ -930,6 +930,17 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
return
0
;
return
0
;
}
}
static
int
insert_orphan_item
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
offset
)
{
int
ret
;
ret
=
btrfs_find_orphan_item
(
root
,
offset
);
if
(
ret
>
0
)
ret
=
btrfs_insert_orphan_item
(
trans
,
root
,
offset
);
return
ret
;
}
/*
/*
* There are a few corners where the link count of the file can't
* There are a few corners where the link count of the file can't
* be properly maintained during replay. So, instead of adding
* be properly maintained during replay. So, instead of adding
...
@@ -997,11 +1008,15 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
...
@@ -997,11 +1008,15 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
}
}
BTRFS_I
(
inode
)
->
index_cnt
=
(
u64
)
-
1
;
BTRFS_I
(
inode
)
->
index_cnt
=
(
u64
)
-
1
;
if
(
inode
->
i_nlink
==
0
&&
S_ISDIR
(
inode
->
i_mode
))
{
if
(
inode
->
i_nlink
==
0
)
{
if
(
S_ISDIR
(
inode
->
i_mode
))
{
ret
=
replay_dir_deletes
(
trans
,
root
,
NULL
,
path
,
ret
=
replay_dir_deletes
(
trans
,
root
,
NULL
,
path
,
inode
->
i_ino
,
1
);
inode
->
i_ino
,
1
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
}
}
ret
=
insert_orphan_item
(
trans
,
root
,
inode
->
i_ino
);
BUG_ON
(
ret
);
}
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
return
0
;
return
0
;
...
@@ -1587,7 +1602,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
...
@@ -1587,7 +1602,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
/* inode keys are done during the first stage */
/* inode keys are done during the first stage */
if
(
key
.
type
==
BTRFS_INODE_ITEM_KEY
&&
if
(
key
.
type
==
BTRFS_INODE_ITEM_KEY
&&
wc
->
stage
==
LOG_WALK_REPLAY_INODES
)
{
wc
->
stage
==
LOG_WALK_REPLAY_INODES
)
{
struct
inode
*
inode
;
struct
btrfs_inode_item
*
inode_item
;
struct
btrfs_inode_item
*
inode_item
;
u32
mode
;
u32
mode
;
...
@@ -1603,31 +1617,16 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
...
@@ -1603,31 +1617,16 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
eb
,
i
,
&
key
);
eb
,
i
,
&
key
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
/* for regular files, truncate away
/* for regular files, make sure corresponding
* extents past the new EOF
* orhpan item exist. extents past the new EOF
* will be truncated later by orphan cleanup.
*/
*/
if
(
S_ISREG
(
mode
))
{
if
(
S_ISREG
(
mode
))
{
inode
=
read_one_inode
(
root
,
ret
=
insert_orphan_item
(
wc
->
trans
,
root
,
key
.
objectid
);
key
.
objectid
);
BUG_ON
(
!
inode
);
ret
=
btrfs_truncate_inode_items
(
wc
->
trans
,
root
,
inode
,
inode
->
i_size
,
BTRFS_EXTENT_DATA_KEY
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
/* if the nlink count is zero here, the iput
* will free the inode. We bump it to make
* sure it doesn't get freed until the link
* count fixup is done
*/
if
(
inode
->
i_nlink
==
0
)
{
btrfs_inc_nlink
(
inode
);
btrfs_update_inode
(
wc
->
trans
,
root
,
inode
);
}
iput
(
inode
);
}
}
ret
=
link_to_fixup_dir
(
wc
->
trans
,
root
,
ret
=
link_to_fixup_dir
(
wc
->
trans
,
root
,
path
,
key
.
objectid
);
path
,
key
.
objectid
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
...
@@ -1977,10 +1976,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
...
@@ -1977,10 +1976,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
{
{
int
index1
;
int
index1
;
int
index2
;
int
index2
;
int
mark
;
int
ret
;
int
ret
;
struct
btrfs_root
*
log
=
root
->
log_root
;
struct
btrfs_root
*
log
=
root
->
log_root
;
struct
btrfs_root
*
log_root_tree
=
root
->
fs_info
->
log_root_tree
;
struct
btrfs_root
*
log_root_tree
=
root
->
fs_info
->
log_root_tree
;
u
64
log_transid
=
0
;
u
nsigned
long
log_transid
=
0
;
mutex_lock
(
&
root
->
log_mutex
);
mutex_lock
(
&
root
->
log_mutex
);
index1
=
root
->
log_transid
%
2
;
index1
=
root
->
log_transid
%
2
;
...
@@ -2014,24 +2014,29 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
...
@@ -2014,24 +2014,29 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
goto
out
;
goto
out
;
}
}
log_transid
=
root
->
log_transid
;
if
(
log_transid
%
2
==
0
)
mark
=
EXTENT_DIRTY
;
else
mark
=
EXTENT_NEW
;
/* we start IO on all the marked extents here, but we don't actually
/* we start IO on all the marked extents here, but we don't actually
* wait for them until later.
* wait for them until later.
*/
*/
ret
=
btrfs_write_marked_extents
(
log
,
&
log
->
dirty_log_pages
);
ret
=
btrfs_write_marked_extents
(
log
,
&
log
->
dirty_log_pages
,
mark
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
btrfs_set_root_node
(
&
log
->
root_item
,
log
->
node
);
btrfs_set_root_node
(
&
log
->
root_item
,
log
->
node
);
root
->
log_batch
=
0
;
root
->
log_batch
=
0
;
log_transid
=
root
->
log_transid
;
root
->
log_transid
++
;
root
->
log_transid
++
;
log
->
log_transid
=
root
->
log_transid
;
log
->
log_transid
=
root
->
log_transid
;
root
->
log_start_pid
=
0
;
root
->
log_start_pid
=
0
;
smp_mb
();
smp_mb
();
/*
/*
*
log tree has been flushed to disk, new modifications of
*
IO has been started, blocks of the log tree have WRITTEN flag set
*
the log will be written to new positions. so it's safe
to
*
in their headers. new modifications of the log will be written
to
* allow log writers to go in.
*
new positions. so it's safe to
allow log writers to go in.
*/
*/
mutex_unlock
(
&
root
->
log_mutex
);
mutex_unlock
(
&
root
->
log_mutex
);
...
@@ -2052,7 +2057,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
...
@@ -2052,7 +2057,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
index2
=
log_root_tree
->
log_transid
%
2
;
index2
=
log_root_tree
->
log_transid
%
2
;
if
(
atomic_read
(
&
log_root_tree
->
log_commit
[
index2
]))
{
if
(
atomic_read
(
&
log_root_tree
->
log_commit
[
index2
]))
{
btrfs_wait_marked_extents
(
log
,
&
log
->
dirty_log_pages
);
btrfs_wait_marked_extents
(
log
,
&
log
->
dirty_log_pages
,
mark
);
wait_log_commit
(
trans
,
log_root_tree
,
wait_log_commit
(
trans
,
log_root_tree
,
log_root_tree
->
log_transid
);
log_root_tree
->
log_transid
);
mutex_unlock
(
&
log_root_tree
->
log_mutex
);
mutex_unlock
(
&
log_root_tree
->
log_mutex
);
...
@@ -2072,16 +2077,17 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
...
@@ -2072,16 +2077,17 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
* check the full commit flag again
* check the full commit flag again
*/
*/
if
(
root
->
fs_info
->
last_trans_log_full_commit
==
trans
->
transid
)
{
if
(
root
->
fs_info
->
last_trans_log_full_commit
==
trans
->
transid
)
{
btrfs_wait_marked_extents
(
log
,
&
log
->
dirty_log_pages
);
btrfs_wait_marked_extents
(
log
,
&
log
->
dirty_log_pages
,
mark
);
mutex_unlock
(
&
log_root_tree
->
log_mutex
);
mutex_unlock
(
&
log_root_tree
->
log_mutex
);
ret
=
-
EAGAIN
;
ret
=
-
EAGAIN
;
goto
out_wake_log_root
;
goto
out_wake_log_root
;
}
}
ret
=
btrfs_write_and_wait_marked_extents
(
log_root_tree
,
ret
=
btrfs_write_and_wait_marked_extents
(
log_root_tree
,
&
log_root_tree
->
dirty_log_pages
);
&
log_root_tree
->
dirty_log_pages
,
EXTENT_DIRTY
|
EXTENT_NEW
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
btrfs_wait_marked_extents
(
log
,
&
log
->
dirty_log_pages
);
btrfs_wait_marked_extents
(
log
,
&
log
->
dirty_log_pages
,
mark
);
btrfs_set_super_log_root
(
&
root
->
fs_info
->
super_for_commit
,
btrfs_set_super_log_root
(
&
root
->
fs_info
->
super_for_commit
,
log_root_tree
->
node
->
start
);
log_root_tree
->
node
->
start
);
...
@@ -2147,12 +2153,12 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
...
@@ -2147,12 +2153,12 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
while
(
1
)
{
while
(
1
)
{
ret
=
find_first_extent_bit
(
&
log
->
dirty_log_pages
,
ret
=
find_first_extent_bit
(
&
log
->
dirty_log_pages
,
0
,
&
start
,
&
end
,
EXTENT_DIRTY
);
0
,
&
start
,
&
end
,
EXTENT_DIRTY
|
EXTENT_NEW
);
if
(
ret
)
if
(
ret
)
break
;
break
;
clear_extent_
dirty
(
&
log
->
dirty_log_pages
,
clear_extent_
bits
(
&
log
->
dirty_log_pages
,
start
,
end
,
start
,
end
,
GFP_NOFS
);
EXTENT_DIRTY
|
EXTENT_NEW
,
GFP_NOFS
);
}
}
if
(
log
->
log_transid
>
0
)
{
if
(
log
->
log_transid
>
0
)
{
...
...
fs/btrfs/volumes.c
View file @
ebfee3d7
...
@@ -2209,7 +2209,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
...
@@ -2209,7 +2209,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
max_chunk_size
=
10
*
calc_size
;
max_chunk_size
=
10
*
calc_size
;
min_stripe_size
=
64
*
1024
*
1024
;
min_stripe_size
=
64
*
1024
*
1024
;
}
else
if
(
type
&
BTRFS_BLOCK_GROUP_METADATA
)
{
}
else
if
(
type
&
BTRFS_BLOCK_GROUP_METADATA
)
{
max_chunk_size
=
4
*
calc_size
;
max_chunk_size
=
256
*
1024
*
1024
;
min_stripe_size
=
32
*
1024
*
1024
;
min_stripe_size
=
32
*
1024
*
1024
;
}
else
if
(
type
&
BTRFS_BLOCK_GROUP_SYSTEM
)
{
}
else
if
(
type
&
BTRFS_BLOCK_GROUP_SYSTEM
)
{
calc_size
=
8
*
1024
*
1024
;
calc_size
=
8
*
1024
*
1024
;
...
...
fs/btrfs/xattr.c
View file @
ebfee3d7
...
@@ -85,22 +85,23 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
...
@@ -85,22 +85,23 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
return
ret
;
return
ret
;
}
}
int
__btrfs_setxattr
(
struct
inode
*
inode
,
const
char
*
name
,
static
int
do_setxattr
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
const
void
*
value
,
size_t
size
,
int
flags
)
{
{
struct
btrfs_dir_item
*
di
;
struct
btrfs_dir_item
*
di
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_path
*
path
;
struct
btrfs_path
*
path
;
int
ret
=
0
,
mod
=
0
;
size_t
name_len
=
strlen
(
name
);
int
ret
=
0
;
if
(
name_len
+
size
>
BTRFS_MAX_XATTR_SIZE
(
root
))
return
-
ENOSPC
;
path
=
btrfs_alloc_path
();
path
=
btrfs_alloc_path
();
if
(
!
path
)
if
(
!
path
)
return
-
ENOMEM
;
return
-
ENOMEM
;
trans
=
btrfs_join_transaction
(
root
,
1
);
btrfs_set_trans_block_group
(
trans
,
inode
);
/* first lets see if we already have this xattr */
/* first lets see if we already have this xattr */
di
=
btrfs_lookup_xattr
(
trans
,
root
,
path
,
inode
->
i_ino
,
name
,
di
=
btrfs_lookup_xattr
(
trans
,
root
,
path
,
inode
->
i_ino
,
name
,
strlen
(
name
),
-
1
);
strlen
(
name
),
-
1
);
...
@@ -118,15 +119,12 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
...
@@ -118,15 +119,12 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
}
}
ret
=
btrfs_delete_one_dir_name
(
trans
,
root
,
path
,
di
);
ret
=
btrfs_delete_one_dir_name
(
trans
,
root
,
path
,
di
);
if
(
ret
)
BUG_ON
(
ret
);
goto
out
;
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
/* if we don't have a value then we are removing the xattr */
/* if we don't have a value then we are removing the xattr */
if
(
!
value
)
{
if
(
!
value
)
mod
=
1
;
goto
out
;
goto
out
;
}
}
else
{
}
else
{
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
...
@@ -138,20 +136,45 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
...
@@ -138,20 +136,45 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
}
}
/* ok we have to create a completely new xattr */
/* ok we have to create a completely new xattr */
ret
=
btrfs_insert_xattr_item
(
trans
,
root
,
name
,
strlen
(
name
),
ret
=
btrfs_insert_xattr_item
(
trans
,
root
,
path
,
inode
->
i_ino
,
value
,
size
,
inode
->
i_ino
);
name
,
name_len
,
value
,
size
);
BUG_ON
(
ret
);
out:
btrfs_free_path
(
path
);
return
ret
;
}
int
__btrfs_setxattr
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
int
ret
;
if
(
trans
)
return
do_setxattr
(
trans
,
inode
,
name
,
value
,
size
,
flags
);
ret
=
btrfs_reserve_metadata_space
(
root
,
2
);
if
(
ret
)
return
ret
;
trans
=
btrfs_start_transaction
(
root
,
1
);
if
(
!
trans
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
btrfs_set_trans_block_group
(
trans
,
inode
);
ret
=
do_setxattr
(
trans
,
inode
,
name
,
value
,
size
,
flags
);
if
(
ret
)
if
(
ret
)
goto
out
;
goto
out
;
mod
=
1
;
out:
if
(
mod
)
{
inode
->
i_ctime
=
CURRENT_TIME
;
inode
->
i_ctime
=
CURRENT_TIME
;
ret
=
btrfs_update_inode
(
trans
,
root
,
inode
);
ret
=
btrfs_update_inode
(
trans
,
root
,
inode
);
}
BUG_ON
(
ret
);
out:
btrfs_end_transaction
(
trans
,
root
);
btrfs_end_transaction
_throttle
(
trans
,
root
);
btrfs_
free_path
(
path
);
btrfs_
unreserve_metadata_space
(
root
,
2
);
return
ret
;
return
ret
;
}
}
...
@@ -314,7 +337,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
...
@@ -314,7 +337,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
if
(
size
==
0
)
if
(
size
==
0
)
value
=
""
;
/* empty EA, do not remove */
value
=
""
;
/* empty EA, do not remove */
return
__btrfs_setxattr
(
dentry
->
d_inode
,
name
,
value
,
size
,
flags
);
return
__btrfs_setxattr
(
NULL
,
dentry
->
d_inode
,
name
,
value
,
size
,
flags
);
}
}
int
btrfs_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
)
int
btrfs_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
)
...
@@ -329,10 +354,13 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
...
@@ -329,10 +354,13 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
if
(
!
btrfs_is_valid_xattr
(
name
))
if
(
!
btrfs_is_valid_xattr
(
name
))
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
return
__btrfs_setxattr
(
dentry
->
d_inode
,
name
,
NULL
,
0
,
XATTR_REPLACE
);
return
__btrfs_setxattr
(
NULL
,
dentry
->
d_inode
,
name
,
NULL
,
0
,
XATTR_REPLACE
);
}
}
int
btrfs_xattr_security_init
(
struct
inode
*
inode
,
struct
inode
*
dir
)
int
btrfs_xattr_security_init
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
)
{
{
int
err
;
int
err
;
size_t
len
;
size_t
len
;
...
@@ -354,7 +382,7 @@ int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
...
@@ -354,7 +382,7 @@ int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
}
else
{
}
else
{
strcpy
(
name
,
XATTR_SECURITY_PREFIX
);
strcpy
(
name
,
XATTR_SECURITY_PREFIX
);
strcpy
(
name
+
XATTR_SECURITY_PREFIX_LEN
,
suffix
);
strcpy
(
name
+
XATTR_SECURITY_PREFIX_LEN
,
suffix
);
err
=
__btrfs_setxattr
(
inode
,
name
,
value
,
len
,
0
);
err
=
__btrfs_setxattr
(
trans
,
inode
,
name
,
value
,
len
,
0
);
kfree
(
name
);
kfree
(
name
);
}
}
...
...
fs/btrfs/xattr.h
View file @
ebfee3d7
...
@@ -27,15 +27,16 @@ extern struct xattr_handler *btrfs_xattr_handlers[];
...
@@ -27,15 +27,16 @@ extern struct xattr_handler *btrfs_xattr_handlers[];
extern
ssize_t
__btrfs_getxattr
(
struct
inode
*
inode
,
const
char
*
name
,
extern
ssize_t
__btrfs_getxattr
(
struct
inode
*
inode
,
const
char
*
name
,
void
*
buffer
,
size_t
size
);
void
*
buffer
,
size_t
size
);
extern
int
__btrfs_setxattr
(
struct
inode
*
inode
,
const
char
*
name
,
extern
int
__btrfs_setxattr
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
);
const
void
*
value
,
size_t
size
,
int
flags
);
extern
ssize_t
btrfs_getxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
extern
ssize_t
btrfs_getxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
void
*
buffer
,
size_t
size
);
void
*
buffer
,
size_t
size
);
extern
int
btrfs_setxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
extern
int
btrfs_setxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
);
const
void
*
value
,
size_t
size
,
int
flags
);
extern
int
btrfs_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
);
extern
int
btrfs_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
);
extern
int
btrfs_xattr_security_init
(
struct
inode
*
inode
,
struct
inode
*
dir
);
extern
int
btrfs_xattr_security_init
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
);
#endif
/* __XATTR__ */
#endif
/* __XATTR__ */
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