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
ccd467d6
Commit
ccd467d6
authored
Jun 28, 2007
by
Chris Mason
Committed by
David Woodhouse
Jun 28, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: crash recovery fixes
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
f2654de4
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
112 additions
and
48 deletions
+112
-48
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+12
-1
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+4
-8
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+14
-8
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+1
-0
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+33
-4
fs/btrfs/file.c
fs/btrfs/file.c
+11
-4
fs/btrfs/inode.c
fs/btrfs/inode.c
+3
-3
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+34
-20
No files found.
fs/btrfs/ctree.c
View file @
ccd467d6
...
@@ -75,6 +75,17 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -75,6 +75,17 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
struct
btrfs_node
*
cow_node
;
struct
btrfs_node
*
cow_node
;
int
ret
;
int
ret
;
WARN_ON
(
!
buffer_uptodate
(
buf
));
if
(
trans
->
transaction
!=
root
->
fs_info
->
running_transaction
)
{
printk
(
KERN_CRIT
"trans %Lu running %Lu
\n
"
,
trans
->
transid
,
root
->
fs_info
->
running_transaction
->
transid
);
WARN_ON
(
1
);
}
if
(
trans
->
transid
!=
root
->
fs_info
->
generation
)
{
printk
(
KERN_CRIT
"trans %Lu running %Lu
\n
"
,
trans
->
transid
,
root
->
fs_info
->
generation
);
WARN_ON
(
1
);
}
if
(
btrfs_header_generation
(
btrfs_buffer_header
(
buf
))
==
if
(
btrfs_header_generation
(
btrfs_buffer_header
(
buf
))
==
trans
->
transid
)
{
trans
->
transid
)
{
*
cow_ret
=
buf
;
*
cow_ret
=
buf
;
...
@@ -107,7 +118,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -107,7 +118,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_free_extent
(
trans
,
root
,
bh_blocknr
(
buf
),
1
,
1
);
btrfs_free_extent
(
trans
,
root
,
bh_blocknr
(
buf
),
1
,
1
);
}
}
btrfs_block_release
(
root
,
buf
);
btrfs_block_release
(
root
,
buf
);
mark_buffer_dirty
(
cow
);
btrfs_
mark_buffer_dirty
(
cow
);
*
cow_ret
=
cow
;
*
cow_ret
=
cow
;
return
0
;
return
0
;
}
}
...
...
fs/btrfs/ctree.h
View file @
ccd467d6
...
@@ -1013,18 +1013,13 @@ static inline void btrfs_memmove(struct btrfs_root *root,
...
@@ -1013,18 +1013,13 @@ static inline void btrfs_memmove(struct btrfs_root *root,
memmove
(
dst
,
src
,
nr
);
memmove
(
dst
,
src
,
nr
);
}
}
static
inline
void
btrfs_mark_buffer_dirty
(
struct
buffer_head
*
bh
)
{
WARN_ON
(
!
atomic_read
(
&
bh
->
b_count
));
mark_buffer_dirty
(
bh
);
}
/* helper function to cast into the data area of the leaf. */
/* helper function to cast into the data area of the leaf. */
#define btrfs_item_ptr(leaf, slot, type) \
#define btrfs_item_ptr(leaf, slot, type) \
((type *)(btrfs_leaf_data(leaf) + \
((type *)(btrfs_leaf_data(leaf) + \
btrfs_item_offset((leaf)->items + (slot))))
btrfs_item_offset((leaf)->items + (slot))))
/* extent-tree.c */
/* extent-tree.c */
int
btrfs_copy_pinned
(
struct
btrfs_root
*
root
,
struct
radix_tree_root
*
copy
);
struct
btrfs_block_group_cache
*
btrfs_lookup_block_group
(
struct
struct
btrfs_block_group_cache
*
btrfs_lookup_block_group
(
struct
btrfs_fs_info
*
info
,
btrfs_fs_info
*
info
,
u64
blocknr
);
u64
blocknr
);
...
@@ -1044,8 +1039,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
...
@@ -1044,8 +1039,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct
buffer_head
*
buf
);
struct
buffer_head
*
buf
);
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
int
btrfs_free_extent
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
);
*
root
,
u64
blocknr
,
u64
num_blocks
,
int
pin
);
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
btrfs_root
*
root
);
struct
btrfs_root
*
root
,
struct
radix_tree_root
*
unpin_radix
);
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
int
btrfs_inc_extent_ref
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
u64
blocknr
,
u64
num_blocks
);
u64
blocknr
,
u64
num_blocks
);
...
...
fs/btrfs/disk-io.c
View file @
ccd467d6
...
@@ -270,14 +270,6 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
...
@@ -270,14 +270,6 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
return
NULL
;
return
NULL
;
}
}
int
dirty_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
)
{
WARN_ON
(
atomic_read
(
&
buf
->
b_count
)
==
0
);
mark_buffer_dirty
(
buf
);
return
0
;
}
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
int
clean_tree_block
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
)
struct
buffer_head
*
buf
)
{
{
...
@@ -621,6 +613,20 @@ int close_ctree(struct btrfs_root *root)
...
@@ -621,6 +613,20 @@ int close_ctree(struct btrfs_root *root)
return
0
;
return
0
;
}
}
void
btrfs_mark_buffer_dirty
(
struct
buffer_head
*
bh
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
bh
->
b_page
->
mapping
->
host
)
->
root
;
u64
transid
=
btrfs_header_generation
(
btrfs_buffer_header
(
bh
));
WARN_ON
(
!
atomic_read
(
&
bh
->
b_count
));
if
(
transid
!=
root
->
fs_info
->
generation
)
{
printk
(
KERN_CRIT
"transid mismatch buffer %llu, found %Lu running %Lu
\n
"
,
(
unsigned
long
long
)
bh
->
b_blocknr
,
transid
,
root
->
fs_info
->
generation
);
WARN_ON
(
1
);
}
mark_buffer_dirty
(
bh
);
}
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
)
void
btrfs_block_release
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
buf
)
{
{
brelse
(
buf
);
brelse
(
buf
);
...
...
fs/btrfs/disk-io.h
View file @
ccd467d6
...
@@ -78,4 +78,5 @@ int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh,
...
@@ -78,4 +78,5 @@ int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh,
int
btrfs_releasepage
(
struct
page
*
page
,
gfp_t
flags
);
int
btrfs_releasepage
(
struct
page
*
page
,
gfp_t
flags
);
void
btrfs_btree_balance_dirty
(
struct
btrfs_root
*
root
);
void
btrfs_btree_balance_dirty
(
struct
btrfs_root
*
root
);
int
btrfs_free_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_root
*
root
);
int
btrfs_free_fs_root
(
struct
btrfs_fs_info
*
fs_info
,
struct
btrfs_root
*
root
);
void
btrfs_mark_buffer_dirty
(
struct
buffer_head
*
bh
);
#endif
#endif
fs/btrfs/extent-tree.c
View file @
ccd467d6
...
@@ -523,6 +523,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
...
@@ -523,6 +523,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
}
}
return
0
;
return
0
;
fail:
fail:
WARN_ON
(
1
);
for
(
i
=
0
;
i
<
faili
;
i
++
)
{
for
(
i
=
0
;
i
<
faili
;
i
++
)
{
if
(
leaf
)
{
if
(
leaf
)
{
u64
disk_blocknr
;
u64
disk_blocknr
;
...
@@ -572,7 +573,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
...
@@ -572,7 +573,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
bi
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
bi
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_block_group_item
);
struct
btrfs_block_group_item
);
memcpy
(
bi
,
&
cache
->
item
,
sizeof
(
*
bi
));
memcpy
(
bi
,
&
cache
->
item
,
sizeof
(
*
bi
));
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_release_path
(
extent_root
,
path
);
btrfs_release_path
(
extent_root
,
path
);
fail:
fail:
finish_current_insert
(
trans
,
extent_root
);
finish_current_insert
(
trans
,
extent_root
);
...
@@ -739,8 +740,30 @@ static int try_remove_page(struct address_space *mapping, unsigned long index)
...
@@ -739,8 +740,30 @@ static int try_remove_page(struct address_space *mapping, unsigned long index)
return
ret
;
return
ret
;
}
}
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
int
btrfs_copy_pinned
(
struct
btrfs_root
*
root
,
struct
radix_tree_root
*
copy
)
btrfs_root
*
root
)
{
unsigned
long
gang
[
8
];
u64
last
=
0
;
struct
radix_tree_root
*
pinned_radix
=
&
root
->
fs_info
->
pinned_radix
;
int
ret
;
int
i
;
while
(
1
)
{
ret
=
find_first_radix_bit
(
pinned_radix
,
gang
,
last
,
ARRAY_SIZE
(
gang
));
if
(
!
ret
)
break
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
set_radix_bit
(
copy
,
gang
[
i
]);
last
=
gang
[
i
]
+
1
;
}
}
return
0
;
}
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
radix_tree_root
*
unpin_radix
)
{
{
unsigned
long
gang
[
8
];
unsigned
long
gang
[
8
];
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
...
@@ -752,7 +775,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
...
@@ -752,7 +775,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
struct
radix_tree_root
*
extent_radix
=
&
root
->
fs_info
->
extent_map_radix
;
struct
radix_tree_root
*
extent_radix
=
&
root
->
fs_info
->
extent_map_radix
;
while
(
1
)
{
while
(
1
)
{
ret
=
find_first_radix_bit
(
pinned
_radix
,
gang
,
0
,
ret
=
find_first_radix_bit
(
unpin
_radix
,
gang
,
0
,
ARRAY_SIZE
(
gang
));
ARRAY_SIZE
(
gang
));
if
(
!
ret
)
if
(
!
ret
)
break
;
break
;
...
@@ -760,6 +783,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
...
@@ -760,6 +783,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
first
=
gang
[
0
];
first
=
gang
[
0
];
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
clear_radix_bit
(
pinned_radix
,
gang
[
i
]);
clear_radix_bit
(
pinned_radix
,
gang
[
i
]);
clear_radix_bit
(
unpin_radix
,
gang
[
i
]);
block_group
=
btrfs_lookup_block_group
(
root
->
fs_info
,
block_group
=
btrfs_lookup_block_group
(
root
->
fs_info
,
gang
[
i
]);
gang
[
i
]);
if
(
block_group
)
{
if
(
block_group
)
{
...
@@ -1309,6 +1333,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
...
@@ -1309,6 +1333,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
if
(
data
)
{
if
(
data
)
{
ret
=
find_free_extent
(
trans
,
root
,
0
,
0
,
ret
=
find_free_extent
(
trans
,
root
,
0
,
0
,
search_end
,
0
,
&
prealloc_key
,
0
,
0
,
0
);
search_end
,
0
,
&
prealloc_key
,
0
,
0
,
0
);
BUG_ON
(
ret
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
exclude_nr
=
info
->
extent_tree_prealloc_nr
;
exclude_nr
=
info
->
extent_tree_prealloc_nr
;
...
@@ -1319,6 +1344,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
...
@@ -1319,6 +1344,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
ret
=
find_free_extent
(
trans
,
root
,
num_blocks
,
search_start
,
ret
=
find_free_extent
(
trans
,
root
,
num_blocks
,
search_start
,
search_end
,
hint_block
,
ins
,
search_end
,
hint_block
,
ins
,
exclude_start
,
exclude_nr
,
data
);
exclude_start
,
exclude_nr
,
data
);
BUG_ON
(
ret
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
...
@@ -1334,10 +1360,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
...
@@ -1334,10 +1360,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
if
(
!
data
)
{
if
(
!
data
)
{
exclude_start
=
ins
->
objectid
;
exclude_start
=
ins
->
objectid
;
exclude_nr
=
ins
->
offset
;
exclude_nr
=
ins
->
offset
;
hint_block
=
exclude_start
+
exclude_nr
;
ret
=
find_free_extent
(
trans
,
root
,
0
,
search_start
,
ret
=
find_free_extent
(
trans
,
root
,
0
,
search_start
,
search_end
,
hint_block
,
search_end
,
hint_block
,
&
prealloc_key
,
exclude_start
,
&
prealloc_key
,
exclude_start
,
exclude_nr
,
0
);
exclude_nr
,
0
);
BUG_ON
(
ret
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
}
}
...
@@ -1348,6 +1376,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
...
@@ -1348,6 +1376,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
ret
=
btrfs_insert_item
(
trans
,
extent_root
,
ins
,
&
extent_item
,
ret
=
btrfs_insert_item
(
trans
,
extent_root
,
ins
,
&
extent_item
,
sizeof
(
extent_item
));
sizeof
(
extent_item
));
BUG_ON
(
ret
);
finish_current_insert
(
trans
,
extent_root
);
finish_current_insert
(
trans
,
extent_root
);
pending_ret
=
del_pending_extents
(
trans
,
extent_root
);
pending_ret
=
del_pending_extents
(
trans
,
extent_root
);
if
(
ret
)
{
if
(
ret
)
{
...
...
fs/btrfs/file.c
View file @
ccd467d6
...
@@ -127,7 +127,7 @@ static int insert_inline_extent(struct btrfs_root *root, struct inode *inode,
...
@@ -127,7 +127,7 @@ static int insert_inline_extent(struct btrfs_root *root, struct inode *inode,
ptr
,
kaddr
+
bh_offset
(
bh
),
ptr
,
kaddr
+
bh_offset
(
bh
),
size
);
size
);
kunmap_atomic
(
kaddr
,
KM_USER0
);
kunmap_atomic
(
kaddr
,
KM_USER0
);
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_
mark_buffer_dirty
(
path
->
nodes
[
0
]);
fail:
fail:
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
ret
=
btrfs_end_transaction
(
trans
,
root
);
ret
=
btrfs_end_transaction
(
trans
,
root
);
...
@@ -211,11 +211,13 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
...
@@ -211,11 +211,13 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
int
found_type
;
int
found_type
;
int
found_extent
;
int
found_extent
;
int
found_inline
;
int
found_inline
;
int
recow
;
path
=
btrfs_alloc_path
();
path
=
btrfs_alloc_path
();
if
(
!
path
)
if
(
!
path
)
return
-
ENOMEM
;
return
-
ENOMEM
;
while
(
1
)
{
while
(
1
)
{
recow
=
0
;
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
ret
=
btrfs_lookup_file_extent
(
trans
,
root
,
path
,
inode
->
i_ino
,
ret
=
btrfs_lookup_file_extent
(
trans
,
root
,
path
,
inode
->
i_ino
,
search_start
,
-
1
);
search_start
,
-
1
);
...
@@ -244,6 +246,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
...
@@ -244,6 +246,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
if
(
btrfs_key_type
(
&
key
)
>
BTRFS_EXTENT_DATA_KEY
)
{
if
(
btrfs_key_type
(
&
key
)
>
BTRFS_EXTENT_DATA_KEY
)
{
goto
out
;
goto
out
;
}
}
if
(
recow
)
{
search_start
=
key
.
offset
;
continue
;
}
if
(
btrfs_key_type
(
&
key
)
==
BTRFS_EXTENT_DATA_KEY
)
{
if
(
btrfs_key_type
(
&
key
)
==
BTRFS_EXTENT_DATA_KEY
)
{
extent
=
btrfs_item_ptr
(
leaf
,
slot
,
extent
=
btrfs_item_ptr
(
leaf
,
slot
,
struct
btrfs_file_extent_item
);
struct
btrfs_file_extent_item
);
...
@@ -274,6 +280,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
...
@@ -274,6 +280,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
nextret
=
btrfs_next_leaf
(
root
,
path
);
nextret
=
btrfs_next_leaf
(
root
,
path
);
if
(
nextret
)
if
(
nextret
)
goto
out
;
goto
out
;
recow
=
1
;
}
else
{
}
else
{
path
->
slots
[
0
]
++
;
path
->
slots
[
0
]
++
;
}
}
...
@@ -321,7 +328,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
...
@@ -321,7 +328,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
}
}
btrfs_set_file_extent_num_blocks
(
extent
,
btrfs_set_file_extent_num_blocks
(
extent
,
new_num
);
new_num
);
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_
mark_buffer_dirty
(
path
->
nodes
[
0
]);
}
else
{
}
else
{
WARN_ON
(
1
);
WARN_ON
(
1
);
}
}
...
@@ -452,6 +459,8 @@ static int prepare_pages(struct btrfs_root *root,
...
@@ -452,6 +459,8 @@ static int prepare_pages(struct btrfs_root *root,
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
failed_release
;
goto
failed_release
;
}
}
cancel_dirty_page
(
pages
[
i
],
PAGE_CACHE_SIZE
);
wait_on_page_writeback
(
pages
[
i
]);
}
}
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
...
@@ -522,8 +531,6 @@ static int prepare_pages(struct btrfs_root *root,
...
@@ -522,8 +531,6 @@ static int prepare_pages(struct btrfs_root *root,
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
for
(
i
=
0
;
i
<
num_pages
;
i
++
)
{
cancel_dirty_page
(
pages
[
i
],
PAGE_CACHE_SIZE
);
wait_on_page_writeback
(
pages
[
i
]);
offset
=
pos
&
(
PAGE_CACHE_SIZE
-
1
);
offset
=
pos
&
(
PAGE_CACHE_SIZE
-
1
);
this_write
=
min
((
size_t
)
PAGE_CACHE_SIZE
-
offset
,
write_bytes
);
this_write
=
min
((
size_t
)
PAGE_CACHE_SIZE
-
offset
,
write_bytes
);
if
(
!
page_has_buffers
(
pages
[
i
]))
{
if
(
!
page_has_buffers
(
pages
[
i
]))
{
...
...
fs/btrfs/inode.c
View file @
ccd467d6
...
@@ -506,7 +506,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
...
@@ -506,7 +506,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
extent_num_blocks
);
extent_num_blocks
);
inode
->
i_blocks
-=
(
orig_num_blocks
-
inode
->
i_blocks
-=
(
orig_num_blocks
-
extent_num_blocks
)
<<
3
;
extent_num_blocks
)
<<
3
;
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_
mark_buffer_dirty
(
path
->
nodes
[
0
]);
}
else
{
}
else
{
extent_start
=
extent_start
=
btrfs_file_extent_disk_blocknr
(
fi
);
btrfs_file_extent_disk_blocknr
(
fi
);
...
@@ -2020,7 +2020,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
...
@@ -2020,7 +2020,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
btrfs_set_header_owner
(
&
leaf
->
header
,
root
->
root_key
.
objectid
);
btrfs_set_header_owner
(
&
leaf
->
header
,
root
->
root_key
.
objectid
);
memcpy
(
leaf
->
header
.
fsid
,
root
->
fs_info
->
disk_super
->
fsid
,
memcpy
(
leaf
->
header
.
fsid
,
root
->
fs_info
->
disk_super
->
fsid
,
sizeof
(
leaf
->
header
.
fsid
));
sizeof
(
leaf
->
header
.
fsid
));
mark_buffer_dirty
(
subvol
);
btrfs_
mark_buffer_dirty
(
subvol
);
inode_item
=
&
root_item
.
inode
;
inode_item
=
&
root_item
.
inode
;
memset
(
inode_item
,
0
,
sizeof
(
*
inode_item
));
memset
(
inode_item
,
0
,
sizeof
(
*
inode_item
));
...
@@ -2497,7 +2497,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
...
@@ -2497,7 +2497,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
ptr
=
btrfs_file_extent_inline_start
(
ei
);
ptr
=
btrfs_file_extent_inline_start
(
ei
);
btrfs_memcpy
(
root
,
path
->
nodes
[
0
]
->
b_data
,
btrfs_memcpy
(
root
,
path
->
nodes
[
0
]
->
b_data
,
ptr
,
symname
,
name_len
);
ptr
,
symname
,
name_len
);
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
inode
->
i_op
=
&
btrfs_symlink_inode_operations
;
inode
->
i_op
=
&
btrfs_symlink_inode_operations
;
inode
->
i_mapping
->
a_ops
=
&
btrfs_symlink_aops
;
inode
->
i_mapping
->
a_ops
=
&
btrfs_symlink_aops
;
...
...
fs/btrfs/transaction.c
View file @
ccd467d6
...
@@ -85,6 +85,8 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
...
@@ -85,6 +85,8 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
if
(
root
!=
root
->
fs_info
->
tree_root
&&
root
->
last_trans
<
if
(
root
!=
root
->
fs_info
->
tree_root
&&
root
->
last_trans
<
running_trans_id
)
{
running_trans_id
)
{
WARN_ON
(
root
==
root
->
fs_info
->
extent_root
);
WARN_ON
(
root
->
ref_cows
!=
1
);
if
(
root
->
root_item
.
refs
!=
0
)
{
if
(
root
->
root_item
.
refs
!=
0
)
{
radix_tree_tag_set
(
&
root
->
fs_info
->
fs_roots_radix
,
radix_tree_tag_set
(
&
root
->
fs_info
->
fs_roots_radix
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
(
unsigned
long
)
root
->
root_key
.
objectid
,
...
@@ -113,10 +115,11 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
...
@@ -113,10 +115,11 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
cur_trans
=
root
->
fs_info
->
running_transaction
;
cur_trans
=
root
->
fs_info
->
running_transaction
;
WARN_ON
(
cur_trans
!=
trans
->
transaction
);
WARN_ON
(
cur_trans
->
num_writers
<
1
);
WARN_ON
(
cur_trans
->
num_writers
<
1
);
cur_trans
->
num_writers
--
;
if
(
waitqueue_active
(
&
cur_trans
->
writer_wait
))
if
(
waitqueue_active
(
&
cur_trans
->
writer_wait
))
wake_up
(
&
cur_trans
->
writer_wait
);
wake_up
(
&
cur_trans
->
writer_wait
);
cur_trans
->
num_writers
--
;
put_transaction
(
cur_trans
);
put_transaction
(
cur_trans
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
memset
(
trans
,
0
,
sizeof
(
*
trans
));
memset
(
trans
,
0
,
sizeof
(
*
trans
));
...
@@ -194,6 +197,7 @@ static int wait_for_commit(struct btrfs_root *root,
...
@@ -194,6 +197,7 @@ static int wait_for_commit(struct btrfs_root *root,
struct
btrfs_transaction
*
commit
)
struct
btrfs_transaction
*
commit
)
{
{
DEFINE_WAIT
(
wait
);
DEFINE_WAIT
(
wait
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
while
(
!
commit
->
commit_done
)
{
while
(
!
commit
->
commit_done
)
{
prepare_to_wait
(
&
commit
->
commit_wait
,
&
wait
,
prepare_to_wait
(
&
commit
->
commit_wait
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
TASK_UNINTERRUPTIBLE
);
...
@@ -203,6 +207,7 @@ static int wait_for_commit(struct btrfs_root *root,
...
@@ -203,6 +207,7 @@ static int wait_for_commit(struct btrfs_root *root,
schedule
();
schedule
();
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
}
}
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
finish_wait
(
&
commit
->
commit_wait
,
&
wait
);
finish_wait
(
&
commit
->
commit_wait
,
&
wait
);
return
0
;
return
0
;
}
}
...
@@ -279,7 +284,6 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
...
@@ -279,7 +284,6 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
&
root
->
root_item
);
&
root
->
root_item
);
if
(
err
)
if
(
err
)
break
;
break
;
refs
=
btrfs_root_refs
(
&
tmp_item
);
refs
=
btrfs_root_refs
(
&
tmp_item
);
btrfs_set_root_refs
(
&
tmp_item
,
refs
-
1
);
btrfs_set_root_refs
(
&
tmp_item
,
refs
-
1
);
err
=
btrfs_update_root
(
trans
,
root
->
fs_info
->
tree_root
,
err
=
btrfs_update_root
(
trans
,
root
->
fs_info
->
tree_root
,
...
@@ -333,31 +337,53 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
...
@@ -333,31 +337,53 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
struct
btrfs_transaction
*
cur_trans
;
struct
btrfs_transaction
*
cur_trans
;
struct
btrfs_transaction
*
prev_trans
=
NULL
;
struct
btrfs_transaction
*
prev_trans
=
NULL
;
struct
list_head
dirty_fs_roots
;
struct
list_head
dirty_fs_roots
;
struct
radix_tree_root
pinned_copy
;
DEFINE_WAIT
(
wait
);
DEFINE_WAIT
(
wait
);
init_bit_radix
(
&
pinned_copy
);
INIT_LIST_HEAD
(
&
dirty_fs_roots
);
INIT_LIST_HEAD
(
&
dirty_fs_roots
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
if
(
trans
->
transaction
->
in_commit
)
{
if
(
trans
->
transaction
->
in_commit
)
{
cur_trans
=
trans
->
transaction
;
cur_trans
=
trans
->
transaction
;
trans
->
transaction
->
use_count
++
;
trans
->
transaction
->
use_count
++
;
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
btrfs_end_transaction
(
trans
,
root
);
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
wait_for_commit
(
root
,
cur_trans
);
ret
=
wait_for_commit
(
root
,
cur_trans
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
put_transaction
(
cur_trans
);
put_transaction
(
cur_trans
);
mutex_
unlock
(
&
root
->
fs_info
->
tran
s_mutex
);
mutex_
lock
(
&
root
->
fs_info
->
f
s_mutex
);
return
0
;
return
0
;
}
}
cur_trans
=
trans
->
transaction
;
trans
->
transaction
->
in_commit
=
1
;
trans
->
transaction
->
in_commit
=
1
;
cur_trans
=
trans
->
transaction
;
if
(
cur_trans
->
list
.
prev
!=
&
root
->
fs_info
->
trans_list
)
{
prev_trans
=
list_entry
(
cur_trans
->
list
.
prev
,
struct
btrfs_transaction
,
list
);
if
(
!
prev_trans
->
commit_done
)
{
prev_trans
->
use_count
++
;
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
wait_for_commit
(
root
,
prev_trans
);
put_transaction
(
prev_trans
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
}
}
while
(
trans
->
transaction
->
num_writers
>
1
)
{
while
(
trans
->
transaction
->
num_writers
>
1
)
{
WARN_ON
(
cur_trans
!=
trans
->
transaction
);
WARN_ON
(
cur_trans
!=
trans
->
transaction
);
prepare_to_wait
(
&
trans
->
transaction
->
writer_wait
,
&
wait
,
prepare_to_wait
(
&
trans
->
transaction
->
writer_wait
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
TASK_UNINTERRUPTIBLE
);
if
(
trans
->
transaction
->
num_writers
<=
1
)
if
(
trans
->
transaction
->
num_writers
<=
1
)
break
;
break
;
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
schedule
();
schedule
();
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
finish_wait
(
&
trans
->
transaction
->
writer_wait
,
&
wait
);
finish_wait
(
&
trans
->
transaction
->
writer_wait
,
&
wait
);
}
}
...
@@ -372,34 +398,22 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
...
@@ -372,34 +398,22 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
cur_trans
=
root
->
fs_info
->
running_transaction
;
cur_trans
=
root
->
fs_info
->
running_transaction
;
root
->
fs_info
->
running_transaction
=
NULL
;
root
->
fs_info
->
running_transaction
=
NULL
;
if
(
cur_trans
->
list
.
prev
!=
&
root
->
fs_info
->
trans_list
)
{
prev_trans
=
list_entry
(
cur_trans
->
list
.
prev
,
struct
btrfs_transaction
,
list
);
if
(
prev_trans
->
commit_done
)
prev_trans
=
NULL
;
else
prev_trans
->
use_count
++
;
}
btrfs_set_super_generation
(
&
root
->
fs_info
->
super_copy
,
btrfs_set_super_generation
(
&
root
->
fs_info
->
super_copy
,
cur_trans
->
transid
);
cur_trans
->
transid
);
btrfs_set_super_root
(
&
root
->
fs_info
->
super_copy
,
btrfs_set_super_root
(
&
root
->
fs_info
->
super_copy
,
bh_blocknr
(
root
->
fs_info
->
tree_root
->
node
));
bh_blocknr
(
root
->
fs_info
->
tree_root
->
node
));
memcpy
(
root
->
fs_info
->
disk_super
,
&
root
->
fs_info
->
super_copy
,
memcpy
(
root
->
fs_info
->
disk_super
,
&
root
->
fs_info
->
super_copy
,
sizeof
(
root
->
fs_info
->
super_copy
));
sizeof
(
root
->
fs_info
->
super_copy
));
btrfs_copy_pinned
(
root
,
&
pinned_copy
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
btrfs_write_and_wait_transaction
(
trans
,
root
);
ret
=
btrfs_write_and_wait_transaction
(
trans
,
root
);
if
(
prev_trans
)
{
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
wait_for_commit
(
root
,
prev_trans
);
put_transaction
(
prev_trans
);
mutex_unlock
(
&
root
->
fs_info
->
trans_mutex
);
}
BUG_ON
(
ret
);
BUG_ON
(
ret
);
write_ctree_super
(
trans
,
root
);
write_ctree_super
(
trans
,
root
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_finish_extent_commit
(
trans
,
root
);
btrfs_finish_extent_commit
(
trans
,
root
,
&
pinned_copy
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
mutex_lock
(
&
root
->
fs_info
->
trans_mutex
);
cur_trans
->
commit_done
=
1
;
cur_trans
->
commit_done
=
1
;
wake_up
(
&
cur_trans
->
commit_wait
);
wake_up
(
&
cur_trans
->
commit_wait
);
...
...
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