Revision 393961376566 () - Diff

Link to this snippet: https://friendpaste.com/4zct2A5XQoSVJyMFBU2UkA
Embed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fc6401a..6016500 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -120,30 +120,26 @@ static int btrfs_dirty_inode(struct inode *inode);
static void __endio_write_update_ordered(struct inode *inode,
u64 offset, u64 bytes,
- bool uptodate, bool cleanup);
-
-static inline void btrfs_endio_direct_write_update_ordered(struct inode *inode,
- u64 offset,
- u64 bytes,
- bool uptodate)
-{
- return __endio_write_update_ordered(inode, offset, bytes, uptodate, false);
-}
+ bool uptodate);
/*
- * Cleanup all submitted ordered extents in specified range to handle error
- * in cow_file_range() and run_delalloc_nocow().
- * Compression handles error and ordered extent submission by itself,
- * so no need to call this function.
+ * Cleanup all submitted ordered extents in specified range to handle errors
+ * from the fill_dellaloc() callback.
*
- * NOTE: caller must ensure extent_clear_unlock_delalloc() in error handler
- * doesn't cover any range of submitted ordered extent.
- * Or we will double free metadata for submitted ordered extent.
+ * NOTE: caller must ensure that when an error happens, it can not call
+ * extent_clear_unlock_delalloc() to clear both the bits EXTENT_DO_ACCOUNTING
+ * and EXTENT_DELALLOC simultaneously, because that causes the reserved metadata
+ * to be released, which we want to happen only when finishing the ordered
+ * extent (btrfs_finish_ordered_io()). Also note that the caller of the
+ * fill_dealloc() callback already does proper cleanup for the first page of
+ * the range, that is, it invokes the callback writepage_end_io_hook() for the
+ * range of the first page.
*/
static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
u64 offset, u64 bytes)
{
- return __endio_write_update_ordered(inode, offset, bytes, false, true);
+ return __endio_write_update_ordered(inode, offset + PAGE_SIZE,
+ bytes - PAGE_SIZE, false);
}
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
@@ -958,7 +954,6 @@ static noinline int cow_file_range(struct inode *inode,
u64 disk_num_bytes;
u64 cur_alloc_size;
u64 blocksize = fs_info->sectorsize;
- u64 orig_start = start;
struct btrfs_key ins;
struct extent_map *em;
int ret = 0;
@@ -1100,7 +1095,6 @@ static noinline int cow_file_range(struct inode *inode,
EXTENT_DELALLOC | EXTENT_DEFRAG,
PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK);
- btrfs_cleanup_ordered_extents(inode, orig_start, end - orig_start + 1);
goto out;
}
@@ -1526,8 +1520,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
PAGE_CLEAR_DIRTY |
PAGE_SET_WRITEBACK |
PAGE_END_WRITEBACK);
- if (ret)
- btrfs_cleanup_ordered_extents(inode, start, end - start + 1);
btrfs_free_path(path);
return ret;
}
@@ -1577,6 +1569,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
ret = cow_file_range_async(inode, locked_page, start, end,
page_started, nr_written);
}
+ if (ret)
+ btrfs_cleanup_ordered_extents(inode, start, end - start + 1);
return ret;
}
@@ -8176,7 +8170,7 @@ static void btrfs_endio_direct_read(struct bio *bio)
static void __endio_write_update_ordered(struct inode *inode,
u64 offset, u64 bytes,
- bool uptodate, bool cleanup)
+ bool uptodate)
{
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct btrfs_ordered_extent *ordered = NULL;
@@ -8194,16 +8188,6 @@ static void __endio_write_update_ordered(struct inode *inode,
func = btrfs_endio_write_helper;
}
- /*
- * In cleanup case, the first page of the range will be handled
- * by end_extent_writepage() when called from __extent_writepage()
- *
- * So we must skip first page, or we will underflow ordered->bytes_left
- */
- if (cleanup) {
- ordered_offset += PAGE_SIZE;
- ordered_bytes -= PAGE_SIZE;
- }
again:
ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
&ordered_offset,
@@ -8231,10 +8215,10 @@ static void btrfs_endio_direct_write(struct bio *bio)
struct btrfs_dio_private *dip = bio->bi_private;
struct bio *dio_bio = dip->dio_bio;
- btrfs_endio_direct_write_update_ordered(dip->inode,
- dip->logical_offset,
- dip->bytes,
- !bio->bi_error);
+ __endio_write_update_ordered(dip->inode,
+ dip->logical_offset,
+ dip->bytes,
+ !bio->bi_error);
kfree(dip);
@@ -8595,10 +8579,10 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
io_bio = NULL;
} else {
if (write)
- btrfs_endio_direct_write_update_ordered(inode,
+ __endio_write_update_ordered(inode,
file_offset,
dio_bio->bi_iter.bi_size,
- 0);
+ false);
else
unlock_extent(&BTRFS_I(inode)->io_tree, file_offset,
file_offset + dio_bio->bi_iter.bi_size - 1);
@@ -8733,11 +8717,11 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
*/
if (dio_data.unsubmitted_oe_range_start <
dio_data.unsubmitted_oe_range_end)
- btrfs_endio_direct_write_update_ordered(inode,
+ __endio_write_update_ordered(inode,
dio_data.unsubmitted_oe_range_start,
dio_data.unsubmitted_oe_range_end -
dio_data.unsubmitted_oe_range_start,
- 0);
+ false);
} else if (ret >= 0 && (size_t)ret < count)
btrfs_delalloc_release_space(inode, offset,
count - (size_t)ret);