Blame view
fs/btrfs/ordered-data.c
28.4 KB
c1d7c514f btrfs: replace GP... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
dc17ff8f1 Btrfs: Add data=o... |
2 3 |
/* * Copyright (C) 2007 Oracle. All rights reserved. |
dc17ff8f1 Btrfs: Add data=o... |
4 |
*/ |
dc17ff8f1 Btrfs: Add data=o... |
5 |
#include <linux/slab.h> |
d6bfde876 Btrfs: Fixes for ... |
6 |
#include <linux/blkdev.h> |
f421950f8 Btrfs: Fix some d... |
7 |
#include <linux/writeback.h> |
a3d46aea4 btrfs: Switch mem... |
8 |
#include <linux/sched/mm.h> |
602cbe91f btrfs: move cond_... |
9 |
#include "misc.h" |
dc17ff8f1 Btrfs: Add data=o... |
10 11 12 |
#include "ctree.h" #include "transaction.h" #include "btrfs_inode.h" |
e6dcd2dc9 Btrfs: New data=o... |
13 |
#include "extent_io.h" |
199c2a9c3 Btrfs: introduce ... |
14 |
#include "disk-io.h" |
ebb8765b2 btrfs: move btrfs... |
15 |
#include "compression.h" |
867363429 btrfs: migrate th... |
16 |
#include "delalloc-space.h" |
dc17ff8f1 Btrfs: Add data=o... |
17 |
|
6352b91da Btrfs: use a slab... |
18 |
static struct kmem_cache *btrfs_ordered_extent_cache; |
e6dcd2dc9 Btrfs: New data=o... |
19 |
static u64 entry_end(struct btrfs_ordered_extent *entry) |
dc17ff8f1 Btrfs: Add data=o... |
20 |
{ |
e6dcd2dc9 Btrfs: New data=o... |
21 22 23 |
if (entry->file_offset + entry->len < entry->file_offset) return (u64)-1; return entry->file_offset + entry->len; |
dc17ff8f1 Btrfs: Add data=o... |
24 |
} |
d352ac681 Btrfs: add and im... |
25 26 27 |
/* returns NULL if the insertion worked, or it returns the node it did find * in the tree */ |
e6dcd2dc9 Btrfs: New data=o... |
28 29 |
static struct rb_node *tree_insert(struct rb_root *root, u64 file_offset, struct rb_node *node) |
dc17ff8f1 Btrfs: Add data=o... |
30 |
{ |
d397712bc Btrfs: Fix checkp... |
31 32 |
struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; |
e6dcd2dc9 Btrfs: New data=o... |
33 |
struct btrfs_ordered_extent *entry; |
dc17ff8f1 Btrfs: Add data=o... |
34 |
|
d397712bc Btrfs: Fix checkp... |
35 |
while (*p) { |
dc17ff8f1 Btrfs: Add data=o... |
36 |
parent = *p; |
e6dcd2dc9 Btrfs: New data=o... |
37 |
entry = rb_entry(parent, struct btrfs_ordered_extent, rb_node); |
dc17ff8f1 Btrfs: Add data=o... |
38 |
|
e6dcd2dc9 Btrfs: New data=o... |
39 |
if (file_offset < entry->file_offset) |
dc17ff8f1 Btrfs: Add data=o... |
40 |
p = &(*p)->rb_left; |
e6dcd2dc9 Btrfs: New data=o... |
41 |
else if (file_offset >= entry_end(entry)) |
dc17ff8f1 Btrfs: Add data=o... |
42 43 44 45 46 47 48 49 50 |
p = &(*p)->rb_right; else return parent; } rb_link_node(node, parent, p); rb_insert_color(node, root); return NULL; } |
43c04fb1b btrfs: Panic on b... |
51 52 53 54 |
static void ordered_data_tree_panic(struct inode *inode, int errno, u64 offset) { struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
5d163e0e6 btrfs: unsplit pr... |
55 56 |
btrfs_panic(fs_info, errno, "Inconsistency in ordered tree at offset %llu", offset); |
43c04fb1b btrfs: Panic on b... |
57 |
} |
d352ac681 Btrfs: add and im... |
58 59 60 61 |
/* * look for a given offset in the tree, and if it can't be found return the * first lesser offset */ |
e6dcd2dc9 Btrfs: New data=o... |
62 63 |
static struct rb_node *__tree_search(struct rb_root *root, u64 file_offset, struct rb_node **prev_ret) |
dc17ff8f1 Btrfs: Add data=o... |
64 |
{ |
d397712bc Btrfs: Fix checkp... |
65 |
struct rb_node *n = root->rb_node; |
dc17ff8f1 Btrfs: Add data=o... |
66 |
struct rb_node *prev = NULL; |
e6dcd2dc9 Btrfs: New data=o... |
67 68 69 |
struct rb_node *test; struct btrfs_ordered_extent *entry; struct btrfs_ordered_extent *prev_entry = NULL; |
dc17ff8f1 Btrfs: Add data=o... |
70 |
|
d397712bc Btrfs: Fix checkp... |
71 |
while (n) { |
e6dcd2dc9 Btrfs: New data=o... |
72 |
entry = rb_entry(n, struct btrfs_ordered_extent, rb_node); |
dc17ff8f1 Btrfs: Add data=o... |
73 74 |
prev = n; prev_entry = entry; |
dc17ff8f1 Btrfs: Add data=o... |
75 |
|
e6dcd2dc9 Btrfs: New data=o... |
76 |
if (file_offset < entry->file_offset) |
dc17ff8f1 Btrfs: Add data=o... |
77 |
n = n->rb_left; |
e6dcd2dc9 Btrfs: New data=o... |
78 |
else if (file_offset >= entry_end(entry)) |
dc17ff8f1 Btrfs: Add data=o... |
79 80 81 82 83 84 |
n = n->rb_right; else return n; } if (!prev_ret) return NULL; |
d397712bc Btrfs: Fix checkp... |
85 |
while (prev && file_offset >= entry_end(prev_entry)) { |
e6dcd2dc9 Btrfs: New data=o... |
86 87 88 89 90 91 92 93 94 95 96 97 98 |
test = rb_next(prev); if (!test) break; prev_entry = rb_entry(test, struct btrfs_ordered_extent, rb_node); if (file_offset < entry_end(prev_entry)) break; prev = test; } if (prev) prev_entry = rb_entry(prev, struct btrfs_ordered_extent, rb_node); |
d397712bc Btrfs: Fix checkp... |
99 |
while (prev && file_offset < entry_end(prev_entry)) { |
e6dcd2dc9 Btrfs: New data=o... |
100 101 102 103 104 105 |
test = rb_prev(prev); if (!test) break; prev_entry = rb_entry(test, struct btrfs_ordered_extent, rb_node); prev = test; |
dc17ff8f1 Btrfs: Add data=o... |
106 107 108 109 |
} *prev_ret = prev; return NULL; } |
d352ac681 Btrfs: add and im... |
110 111 112 |
/* * helper to check if a given offset is inside a given entry */ |
e6dcd2dc9 Btrfs: New data=o... |
113 114 115 116 117 118 119 |
static int offset_in_entry(struct btrfs_ordered_extent *entry, u64 file_offset) { if (file_offset < entry->file_offset || entry->file_offset + entry->len <= file_offset) return 0; return 1; } |
4b46fce23 Btrfs: add basic ... |
120 121 122 123 124 125 126 127 |
static int range_overlaps(struct btrfs_ordered_extent *entry, u64 file_offset, u64 len) { if (file_offset + len <= entry->file_offset || entry->file_offset + entry->len <= file_offset) return 0; return 1; } |
d352ac681 Btrfs: add and im... |
128 129 130 131 |
/* * look find the first ordered struct that has this offset, otherwise * the first one less than this offset */ |
e6dcd2dc9 Btrfs: New data=o... |
132 133 |
static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, u64 file_offset) |
dc17ff8f1 Btrfs: Add data=o... |
134 |
{ |
e6dcd2dc9 Btrfs: New data=o... |
135 |
struct rb_root *root = &tree->tree; |
c87fb6fdc Btrfs: avoid unin... |
136 |
struct rb_node *prev = NULL; |
dc17ff8f1 Btrfs: Add data=o... |
137 |
struct rb_node *ret; |
e6dcd2dc9 Btrfs: New data=o... |
138 139 140 141 142 143 144 145 146 |
struct btrfs_ordered_extent *entry; if (tree->last) { entry = rb_entry(tree->last, struct btrfs_ordered_extent, rb_node); if (offset_in_entry(entry, file_offset)) return tree->last; } ret = __tree_search(root, file_offset, &prev); |
dc17ff8f1 Btrfs: Add data=o... |
147 |
if (!ret) |
e6dcd2dc9 Btrfs: New data=o... |
148 149 150 |
ret = prev; if (ret) tree->last = ret; |
dc17ff8f1 Btrfs: Add data=o... |
151 152 |
return ret; } |
eb84ae039 Btrfs: Cleanup an... |
153 154 155 156 157 158 159 160 |
/* allocate and add a new ordered_extent into the per-inode tree. * file_offset is the logical offset in the file * * start is the disk block number of an extent already reserved in the * extent allocation tree * * len is the length of the extent * |
eb84ae039 Btrfs: Cleanup an... |
161 162 163 |
* The tree is given a single reference on the ordered extent that was * inserted. */ |
4b46fce23 Btrfs: add basic ... |
164 165 |
static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, u64 start, u64 len, u64 disk_len, |
261507a02 btrfs: Allow to a... |
166 |
int type, int dio, int compress_type) |
dc17ff8f1 Btrfs: Add data=o... |
167 |
{ |
0b246afa6 btrfs: root->fs_i... |
168 |
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
199c2a9c3 Btrfs: introduce ... |
169 |
struct btrfs_root *root = BTRFS_I(inode)->root; |
dc17ff8f1 Btrfs: Add data=o... |
170 |
struct btrfs_ordered_inode_tree *tree; |
e6dcd2dc9 Btrfs: New data=o... |
171 172 |
struct rb_node *node; struct btrfs_ordered_extent *entry; |
dc17ff8f1 Btrfs: Add data=o... |
173 |
|
e6dcd2dc9 Btrfs: New data=o... |
174 |
tree = &BTRFS_I(inode)->ordered_tree; |
6352b91da Btrfs: use a slab... |
175 |
entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS); |
dc17ff8f1 Btrfs: Add data=o... |
176 177 |
if (!entry) return -ENOMEM; |
e6dcd2dc9 Btrfs: New data=o... |
178 179 180 |
entry->file_offset = file_offset; entry->start = start; entry->len = len; |
c8b978188 Btrfs: Add zlib c... |
181 |
entry->disk_len = disk_len; |
8b62b72b2 Btrfs: Use PagePr... |
182 |
entry->bytes_left = len; |
5fd020435 Btrfs: finish ord... |
183 |
entry->inode = igrab(inode); |
261507a02 btrfs: Allow to a... |
184 |
entry->compress_type = compress_type; |
77cef2ec5 Btrfs: allow part... |
185 |
entry->truncated_len = (u64)-1; |
d899e0521 Btrfs: Add falloc... |
186 |
if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE) |
80ff38566 Btrfs: update nod... |
187 |
set_bit(type, &entry->flags); |
3eaa28852 Btrfs: Fix the de... |
188 |
|
4297ff84d btrfs: track DIO ... |
189 190 191 |
if (dio) { percpu_counter_add_batch(&fs_info->dio_bytes, len, fs_info->delalloc_batch); |
4b46fce23 Btrfs: add basic ... |
192 |
set_bit(BTRFS_ORDERED_DIRECT, &entry->flags); |
4297ff84d btrfs: track DIO ... |
193 |
} |
4b46fce23 Btrfs: add basic ... |
194 |
|
e6dcd2dc9 Btrfs: New data=o... |
195 |
/* one ref for the tree */ |
e76edab7f btrfs: convert bt... |
196 |
refcount_set(&entry->refs, 1); |
e6dcd2dc9 Btrfs: New data=o... |
197 198 |
init_waitqueue_head(&entry->wait); INIT_LIST_HEAD(&entry->list); |
3eaa28852 Btrfs: Fix the de... |
199 |
INIT_LIST_HEAD(&entry->root_extent_list); |
9afab8820 Btrfs: make order... |
200 201 |
INIT_LIST_HEAD(&entry->work_list); init_completion(&entry->completion); |
2ab28f322 Btrfs: wait on or... |
202 |
INIT_LIST_HEAD(&entry->log_list); |
50d9aa99b Btrfs: make sure ... |
203 |
INIT_LIST_HEAD(&entry->trans_list); |
dc17ff8f1 Btrfs: Add data=o... |
204 |
|
1abe9b8a1 Btrfs: add initia... |
205 |
trace_btrfs_ordered_extent_add(inode, entry); |
5fd020435 Btrfs: finish ord... |
206 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
207 208 |
node = tree_insert(&tree->tree, file_offset, &entry->rb_node); |
43c04fb1b btrfs: Panic on b... |
209 210 |
if (node) ordered_data_tree_panic(inode, -EEXIST, file_offset); |
5fd020435 Btrfs: finish ord... |
211 |
spin_unlock_irq(&tree->lock); |
d397712bc Btrfs: Fix checkp... |
212 |
|
199c2a9c3 Btrfs: introduce ... |
213 |
spin_lock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
214 |
list_add_tail(&entry->root_extent_list, |
199c2a9c3 Btrfs: introduce ... |
215 216 217 |
&root->ordered_extents); root->nr_ordered_extents++; if (root->nr_ordered_extents == 1) { |
0b246afa6 btrfs: root->fs_i... |
218 |
spin_lock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
219 |
BUG_ON(!list_empty(&root->ordered_root)); |
0b246afa6 btrfs: root->fs_i... |
220 221 |
list_add_tail(&root->ordered_root, &fs_info->ordered_roots); spin_unlock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
222 223 |
} spin_unlock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
224 |
|
8b62f87ba Btrfs: rework out... |
225 226 227 228 229 230 231 232 |
/* * We don't need the count_max_extents here, we can assume that all of * that work has been done at higher layers, so this is truly the * smallest the extent is going to get. */ spin_lock(&BTRFS_I(inode)->lock); btrfs_mod_outstanding_extents(BTRFS_I(inode), 1); spin_unlock(&BTRFS_I(inode)->lock); |
dc17ff8f1 Btrfs: Add data=o... |
233 234 |
return 0; } |
4b46fce23 Btrfs: add basic ... |
235 236 237 238 |
int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, u64 start, u64 len, u64 disk_len, int type) { return __btrfs_add_ordered_extent(inode, file_offset, start, len, |
261507a02 btrfs: Allow to a... |
239 240 |
disk_len, type, 0, BTRFS_COMPRESS_NONE); |
4b46fce23 Btrfs: add basic ... |
241 242 243 244 245 246 |
} int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset, u64 start, u64 len, u64 disk_len, int type) { return __btrfs_add_ordered_extent(inode, file_offset, start, len, |
261507a02 btrfs: Allow to a... |
247 248 249 250 251 252 253 254 255 256 257 |
disk_len, type, 1, BTRFS_COMPRESS_NONE); } int btrfs_add_ordered_extent_compress(struct inode *inode, u64 file_offset, u64 start, u64 len, u64 disk_len, int type, int compress_type) { return __btrfs_add_ordered_extent(inode, file_offset, start, len, disk_len, type, 0, compress_type); |
4b46fce23 Btrfs: add basic ... |
258 |
} |
eb84ae039 Btrfs: Cleanup an... |
259 260 |
/* * Add a struct btrfs_ordered_sum into the list of checksums to be inserted |
3edf7d33f Btrfs: Handle dat... |
261 262 |
* when an ordered extent is finished. If the list covers more than one * ordered extent, it is split across multiples. |
eb84ae039 Btrfs: Cleanup an... |
263 |
*/ |
f9756261c btrfs: Remove red... |
264 |
void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry, |
143bede52 btrfs: return voi... |
265 |
struct btrfs_ordered_sum *sum) |
dc17ff8f1 Btrfs: Add data=o... |
266 |
{ |
e6dcd2dc9 Btrfs: New data=o... |
267 |
struct btrfs_ordered_inode_tree *tree; |
dc17ff8f1 Btrfs: Add data=o... |
268 |
|
f9756261c btrfs: Remove red... |
269 |
tree = &BTRFS_I(entry->inode)->ordered_tree; |
5fd020435 Btrfs: finish ord... |
270 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
271 |
list_add_tail(&sum->list, &entry->list); |
5fd020435 Btrfs: finish ord... |
272 |
spin_unlock_irq(&tree->lock); |
dc17ff8f1 Btrfs: Add data=o... |
273 |
} |
eb84ae039 Btrfs: Cleanup an... |
274 275 |
/* * this is used to account for finished IO across a given range |
163cf09c2 Btrfs: deal with ... |
276 277 278 279 280 281 282 283 284 285 286 287 |
* of the file. The IO may span ordered extents. If * a given ordered_extent is completely done, 1 is returned, otherwise * 0. * * test_and_set_bit on a flag in the struct btrfs_ordered_extent is used * to make sure this function only returns 1 once for a given ordered extent. * * file_offset is updated to one byte past the range that is recorded as * complete. This allows you to walk forward in the file. */ int btrfs_dec_test_first_ordered_pending(struct inode *inode, struct btrfs_ordered_extent **cached, |
5fd020435 Btrfs: finish ord... |
288 |
u64 *file_offset, u64 io_size, int uptodate) |
163cf09c2 Btrfs: deal with ... |
289 |
{ |
0b246afa6 btrfs: root->fs_i... |
290 |
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
163cf09c2 Btrfs: deal with ... |
291 292 293 294 |
struct btrfs_ordered_inode_tree *tree; struct rb_node *node; struct btrfs_ordered_extent *entry = NULL; int ret; |
5fd020435 Btrfs: finish ord... |
295 |
unsigned long flags; |
163cf09c2 Btrfs: deal with ... |
296 297 298 299 300 |
u64 dec_end; u64 dec_start; u64 to_dec; tree = &BTRFS_I(inode)->ordered_tree; |
5fd020435 Btrfs: finish ord... |
301 |
spin_lock_irqsave(&tree->lock, flags); |
163cf09c2 Btrfs: deal with ... |
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
node = tree_search(tree, *file_offset); if (!node) { ret = 1; goto out; } entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); if (!offset_in_entry(entry, *file_offset)) { ret = 1; goto out; } dec_start = max(*file_offset, entry->file_offset); dec_end = min(*file_offset + io_size, entry->file_offset + entry->len); *file_offset = dec_end; if (dec_start > dec_end) { |
0b246afa6 btrfs: root->fs_i... |
319 320 |
btrfs_crit(fs_info, "bad ordering dec_start %llu end %llu", dec_start, dec_end); |
163cf09c2 Btrfs: deal with ... |
321 322 323 |
} to_dec = dec_end - dec_start; if (to_dec > entry->bytes_left) { |
0b246afa6 btrfs: root->fs_i... |
324 325 326 |
btrfs_crit(fs_info, "bad ordered accounting left %llu size %llu", entry->bytes_left, to_dec); |
163cf09c2 Btrfs: deal with ... |
327 328 |
} entry->bytes_left -= to_dec; |
5fd020435 Btrfs: finish ord... |
329 330 |
if (!uptodate) set_bit(BTRFS_ORDERED_IOERR, &entry->flags); |
af7a65097 Btrfs: wake up th... |
331 |
if (entry->bytes_left == 0) { |
163cf09c2 Btrfs: deal with ... |
332 |
ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
093258e6e btrfs: replace wa... |
333 334 |
/* test_and_set_bit implies a barrier */ cond_wake_up_nomb(&entry->wait); |
af7a65097 Btrfs: wake up th... |
335 |
} else { |
163cf09c2 Btrfs: deal with ... |
336 |
ret = 1; |
af7a65097 Btrfs: wake up th... |
337 |
} |
163cf09c2 Btrfs: deal with ... |
338 339 340 |
out: if (!ret && cached && entry) { *cached = entry; |
e76edab7f btrfs: convert bt... |
341 |
refcount_inc(&entry->refs); |
163cf09c2 Btrfs: deal with ... |
342 |
} |
5fd020435 Btrfs: finish ord... |
343 |
spin_unlock_irqrestore(&tree->lock, flags); |
163cf09c2 Btrfs: deal with ... |
344 345 346 347 348 |
return ret == 0; } /* * this is used to account for finished IO across a given range |
eb84ae039 Btrfs: Cleanup an... |
349 350 351 352 353 354 355 |
* of the file. The IO should not span ordered extents. If * a given ordered_extent is completely done, 1 is returned, otherwise * 0. * * test_and_set_bit on a flag in the struct btrfs_ordered_extent is used * to make sure this function only returns 1 once for a given ordered extent. */ |
e6dcd2dc9 Btrfs: New data=o... |
356 |
int btrfs_dec_test_ordered_pending(struct inode *inode, |
5a1a3df1f Btrfs: cache orde... |
357 |
struct btrfs_ordered_extent **cached, |
5fd020435 Btrfs: finish ord... |
358 |
u64 file_offset, u64 io_size, int uptodate) |
dc17ff8f1 Btrfs: Add data=o... |
359 |
{ |
e6dcd2dc9 Btrfs: New data=o... |
360 |
struct btrfs_ordered_inode_tree *tree; |
dc17ff8f1 Btrfs: Add data=o... |
361 |
struct rb_node *node; |
5a1a3df1f Btrfs: cache orde... |
362 |
struct btrfs_ordered_extent *entry = NULL; |
5fd020435 Btrfs: finish ord... |
363 |
unsigned long flags; |
e6dcd2dc9 Btrfs: New data=o... |
364 365 366 |
int ret; tree = &BTRFS_I(inode)->ordered_tree; |
5fd020435 Btrfs: finish ord... |
367 368 369 370 371 |
spin_lock_irqsave(&tree->lock, flags); if (cached && *cached) { entry = *cached; goto have_entry; } |
e6dcd2dc9 Btrfs: New data=o... |
372 |
node = tree_search(tree, file_offset); |
dc17ff8f1 Btrfs: Add data=o... |
373 |
if (!node) { |
e6dcd2dc9 Btrfs: New data=o... |
374 375 |
ret = 1; goto out; |
dc17ff8f1 Btrfs: Add data=o... |
376 |
} |
e6dcd2dc9 Btrfs: New data=o... |
377 |
entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
5fd020435 Btrfs: finish ord... |
378 |
have_entry: |
e6dcd2dc9 Btrfs: New data=o... |
379 380 381 |
if (!offset_in_entry(entry, file_offset)) { ret = 1; goto out; |
dc17ff8f1 Btrfs: Add data=o... |
382 |
} |
e6dcd2dc9 Btrfs: New data=o... |
383 |
|
8b62b72b2 Btrfs: Use PagePr... |
384 |
if (io_size > entry->bytes_left) { |
efe120a06 Btrfs: convert pr... |
385 386 |
btrfs_crit(BTRFS_I(inode)->root->fs_info, "bad ordered accounting left %llu size %llu", |
c1c9ff7c9 Btrfs: Remove sup... |
387 |
entry->bytes_left, io_size); |
8b62b72b2 Btrfs: Use PagePr... |
388 389 |
} entry->bytes_left -= io_size; |
5fd020435 Btrfs: finish ord... |
390 391 |
if (!uptodate) set_bit(BTRFS_ORDERED_IOERR, &entry->flags); |
af7a65097 Btrfs: wake up th... |
392 |
if (entry->bytes_left == 0) { |
e6dcd2dc9 Btrfs: New data=o... |
393 |
ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
093258e6e btrfs: replace wa... |
394 395 |
/* test_and_set_bit implies a barrier */ cond_wake_up_nomb(&entry->wait); |
af7a65097 Btrfs: wake up th... |
396 |
} else { |
8b62b72b2 Btrfs: Use PagePr... |
397 |
ret = 1; |
af7a65097 Btrfs: wake up th... |
398 |
} |
e6dcd2dc9 Btrfs: New data=o... |
399 |
out: |
5a1a3df1f Btrfs: cache orde... |
400 401 |
if (!ret && cached && entry) { *cached = entry; |
e76edab7f btrfs: convert bt... |
402 |
refcount_inc(&entry->refs); |
5a1a3df1f Btrfs: cache orde... |
403 |
} |
5fd020435 Btrfs: finish ord... |
404 |
spin_unlock_irqrestore(&tree->lock, flags); |
e6dcd2dc9 Btrfs: New data=o... |
405 406 |
return ret == 0; } |
dc17ff8f1 Btrfs: Add data=o... |
407 |
|
eb84ae039 Btrfs: Cleanup an... |
408 409 410 411 |
/* * used to drop a reference on an ordered extent. This will free * the extent if the last reference is dropped */ |
143bede52 btrfs: return voi... |
412 |
void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) |
e6dcd2dc9 Btrfs: New data=o... |
413 |
{ |
ba1da2f44 Btrfs: Don't pin ... |
414 415 |
struct list_head *cur; struct btrfs_ordered_sum *sum; |
1abe9b8a1 Btrfs: add initia... |
416 |
trace_btrfs_ordered_extent_put(entry->inode, entry); |
e76edab7f btrfs: convert bt... |
417 |
if (refcount_dec_and_test(&entry->refs)) { |
61de718fc Btrfs: fix memory... |
418 419 420 421 |
ASSERT(list_empty(&entry->log_list)); ASSERT(list_empty(&entry->trans_list)); ASSERT(list_empty(&entry->root_extent_list)); ASSERT(RB_EMPTY_NODE(&entry->rb_node)); |
5fd020435 Btrfs: finish ord... |
422 423 |
if (entry->inode) btrfs_add_delayed_iput(entry->inode); |
d397712bc Btrfs: Fix checkp... |
424 |
while (!list_empty(&entry->list)) { |
ba1da2f44 Btrfs: Don't pin ... |
425 426 427 |
cur = entry->list.next; sum = list_entry(cur, struct btrfs_ordered_sum, list); list_del(&sum->list); |
a3d46aea4 btrfs: Switch mem... |
428 |
kvfree(sum); |
ba1da2f44 Btrfs: Don't pin ... |
429 |
} |
6352b91da Btrfs: use a slab... |
430 |
kmem_cache_free(btrfs_ordered_extent_cache, entry); |
ba1da2f44 Btrfs: Don't pin ... |
431 |
} |
dc17ff8f1 Btrfs: Add data=o... |
432 |
} |
cee36a03e Rework btrfs_drop... |
433 |
|
eb84ae039 Btrfs: Cleanup an... |
434 435 |
/* * remove an ordered extent from the tree. No references are dropped |
5fd020435 Btrfs: finish ord... |
436 |
* and waiters are woken up. |
eb84ae039 Btrfs: Cleanup an... |
437 |
*/ |
5fd020435 Btrfs: finish ord... |
438 439 |
void btrfs_remove_ordered_extent(struct inode *inode, struct btrfs_ordered_extent *entry) |
cee36a03e Rework btrfs_drop... |
440 |
{ |
0b246afa6 btrfs: root->fs_i... |
441 |
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
e6dcd2dc9 Btrfs: New data=o... |
442 |
struct btrfs_ordered_inode_tree *tree; |
8b62f87ba Btrfs: rework out... |
443 444 |
struct btrfs_inode *btrfs_inode = BTRFS_I(inode); struct btrfs_root *root = btrfs_inode->root; |
cee36a03e Rework btrfs_drop... |
445 |
struct rb_node *node; |
cee36a03e Rework btrfs_drop... |
446 |
|
8b62f87ba Btrfs: rework out... |
447 448 449 450 451 |
/* This is paired with btrfs_add_ordered_extent. */ spin_lock(&btrfs_inode->lock); btrfs_mod_outstanding_extents(btrfs_inode, -1); spin_unlock(&btrfs_inode->lock); if (root != fs_info->tree_root) |
43b18595d btrfs: qgroup: Us... |
452 |
btrfs_delalloc_release_metadata(btrfs_inode, entry->len, false); |
8b62f87ba Btrfs: rework out... |
453 |
|
4297ff84d btrfs: track DIO ... |
454 455 456 |
if (test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) percpu_counter_add_batch(&fs_info->dio_bytes, -entry->len, fs_info->delalloc_batch); |
8b62f87ba Btrfs: rework out... |
457 |
tree = &btrfs_inode->ordered_tree; |
5fd020435 Btrfs: finish ord... |
458 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
459 |
node = &entry->rb_node; |
cee36a03e Rework btrfs_drop... |
460 |
rb_erase(node, &tree->tree); |
61de718fc Btrfs: fix memory... |
461 |
RB_CLEAR_NODE(node); |
1b8e7e45e Btrfs: avoid unne... |
462 463 |
if (tree->last == node) tree->last = NULL; |
e6dcd2dc9 Btrfs: New data=o... |
464 |
set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); |
5fd020435 Btrfs: finish ord... |
465 |
spin_unlock_irq(&tree->lock); |
3eaa28852 Btrfs: Fix the de... |
466 |
|
199c2a9c3 Btrfs: introduce ... |
467 |
spin_lock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
468 |
list_del_init(&entry->root_extent_list); |
199c2a9c3 Btrfs: introduce ... |
469 |
root->nr_ordered_extents--; |
5a3f23d51 Btrfs: add extra ... |
470 |
|
1abe9b8a1 Btrfs: add initia... |
471 |
trace_btrfs_ordered_extent_remove(inode, entry); |
199c2a9c3 Btrfs: introduce ... |
472 |
if (!root->nr_ordered_extents) { |
0b246afa6 btrfs: root->fs_i... |
473 |
spin_lock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
474 475 |
BUG_ON(list_empty(&root->ordered_root)); list_del_init(&root->ordered_root); |
0b246afa6 btrfs: root->fs_i... |
476 |
spin_unlock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
477 478 |
} spin_unlock(&root->ordered_extent_lock); |
e6dcd2dc9 Btrfs: New data=o... |
479 |
wake_up(&entry->wait); |
cee36a03e Rework btrfs_drop... |
480 |
} |
d458b0540 btrfs: Cleanup th... |
481 |
static void btrfs_run_ordered_extent_work(struct btrfs_work *work) |
9afab8820 Btrfs: make order... |
482 483 484 485 486 487 488 |
{ struct btrfs_ordered_extent *ordered; ordered = container_of(work, struct btrfs_ordered_extent, flush_work); btrfs_start_ordered_extent(ordered->inode, ordered, 1); complete(&ordered->completion); } |
d352ac681 Btrfs: add and im... |
489 490 491 492 |
/* * wait for all the ordered extents in a root. This is done when balancing * space between drives. */ |
6374e57ad btrfs: fix intege... |
493 |
u64 btrfs_wait_ordered_extents(struct btrfs_root *root, u64 nr, |
578def7c5 Btrfs: don't wait... |
494 |
const u64 range_start, const u64 range_len) |
3eaa28852 Btrfs: Fix the de... |
495 |
{ |
0b246afa6 btrfs: root->fs_i... |
496 |
struct btrfs_fs_info *fs_info = root->fs_info; |
578def7c5 Btrfs: don't wait... |
497 498 499 |
LIST_HEAD(splice); LIST_HEAD(skipped); LIST_HEAD(works); |
9afab8820 Btrfs: make order... |
500 |
struct btrfs_ordered_extent *ordered, *next; |
6374e57ad btrfs: fix intege... |
501 |
u64 count = 0; |
578def7c5 Btrfs: don't wait... |
502 |
const u64 range_end = range_start + range_len; |
3eaa28852 Btrfs: Fix the de... |
503 |
|
31f3d255c Btrfs: split the ... |
504 |
mutex_lock(&root->ordered_extent_mutex); |
199c2a9c3 Btrfs: introduce ... |
505 506 |
spin_lock(&root->ordered_extent_lock); list_splice_init(&root->ordered_extents, &splice); |
b02441999 Btrfs: don't wait... |
507 |
while (!list_empty(&splice) && nr) { |
199c2a9c3 Btrfs: introduce ... |
508 509 |
ordered = list_first_entry(&splice, struct btrfs_ordered_extent, root_extent_list); |
578def7c5 Btrfs: don't wait... |
510 511 512 513 514 515 516 |
if (range_end <= ordered->start || ordered->start + ordered->disk_len <= range_start) { list_move_tail(&ordered->root_extent_list, &skipped); cond_resched_lock(&root->ordered_extent_lock); continue; } |
199c2a9c3 Btrfs: introduce ... |
517 518 |
list_move_tail(&ordered->root_extent_list, &root->ordered_extents); |
e76edab7f btrfs: convert bt... |
519 |
refcount_inc(&ordered->refs); |
199c2a9c3 Btrfs: introduce ... |
520 |
spin_unlock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
521 |
|
a44903abe btrfs: Replace fs... |
522 523 |
btrfs_init_work(&ordered->flush_work, btrfs_run_ordered_extent_work, NULL, NULL); |
199c2a9c3 Btrfs: introduce ... |
524 |
list_add_tail(&ordered->work_list, &works); |
0b246afa6 btrfs: root->fs_i... |
525 |
btrfs_queue_work(fs_info->flush_workers, &ordered->flush_work); |
3eaa28852 Btrfs: Fix the de... |
526 |
|
9afab8820 Btrfs: make order... |
527 |
cond_resched(); |
199c2a9c3 Btrfs: introduce ... |
528 |
spin_lock(&root->ordered_extent_lock); |
6374e57ad btrfs: fix intege... |
529 |
if (nr != U64_MAX) |
b02441999 Btrfs: don't wait... |
530 531 |
nr--; count++; |
3eaa28852 Btrfs: Fix the de... |
532 |
} |
578def7c5 Btrfs: don't wait... |
533 |
list_splice_tail(&skipped, &root->ordered_extents); |
b02441999 Btrfs: don't wait... |
534 |
list_splice_tail(&splice, &root->ordered_extents); |
199c2a9c3 Btrfs: introduce ... |
535 |
spin_unlock(&root->ordered_extent_lock); |
9afab8820 Btrfs: make order... |
536 537 538 539 |
list_for_each_entry_safe(ordered, next, &works, work_list) { list_del_init(&ordered->work_list); wait_for_completion(&ordered->completion); |
9afab8820 Btrfs: make order... |
540 |
btrfs_put_ordered_extent(ordered); |
9afab8820 Btrfs: make order... |
541 542 |
cond_resched(); } |
31f3d255c Btrfs: split the ... |
543 |
mutex_unlock(&root->ordered_extent_mutex); |
b02441999 Btrfs: don't wait... |
544 545 |
return count; |
3eaa28852 Btrfs: Fix the de... |
546 |
} |
6374e57ad btrfs: fix intege... |
547 548 |
u64 btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, u64 nr, const u64 range_start, const u64 range_len) |
199c2a9c3 Btrfs: introduce ... |
549 550 551 |
{ struct btrfs_root *root; struct list_head splice; |
6374e57ad btrfs: fix intege... |
552 553 |
u64 total_done = 0; u64 done; |
199c2a9c3 Btrfs: introduce ... |
554 555 |
INIT_LIST_HEAD(&splice); |
8b9d83cd6 Btrfs: fix early ... |
556 |
mutex_lock(&fs_info->ordered_operations_mutex); |
199c2a9c3 Btrfs: introduce ... |
557 558 |
spin_lock(&fs_info->ordered_root_lock); list_splice_init(&fs_info->ordered_roots, &splice); |
b02441999 Btrfs: don't wait... |
559 |
while (!list_empty(&splice) && nr) { |
199c2a9c3 Btrfs: introduce ... |
560 561 562 563 564 565 566 |
root = list_first_entry(&splice, struct btrfs_root, ordered_root); root = btrfs_grab_fs_root(root); BUG_ON(!root); list_move_tail(&root->ordered_root, &fs_info->ordered_roots); spin_unlock(&fs_info->ordered_root_lock); |
578def7c5 Btrfs: don't wait... |
567 568 |
done = btrfs_wait_ordered_extents(root, nr, range_start, range_len); |
199c2a9c3 Btrfs: introduce ... |
569 |
btrfs_put_fs_root(root); |
f0e9b7d64 Btrfs: fix race s... |
570 |
total_done += done; |
199c2a9c3 Btrfs: introduce ... |
571 572 |
spin_lock(&fs_info->ordered_root_lock); |
6374e57ad btrfs: fix intege... |
573 |
if (nr != U64_MAX) { |
b02441999 Btrfs: don't wait... |
574 |
nr -= done; |
b02441999 Btrfs: don't wait... |
575 |
} |
199c2a9c3 Btrfs: introduce ... |
576 |
} |
931aa8779 Btrfs: fix list d... |
577 |
list_splice_tail(&splice, &fs_info->ordered_roots); |
199c2a9c3 Btrfs: introduce ... |
578 |
spin_unlock(&fs_info->ordered_root_lock); |
8b9d83cd6 Btrfs: fix early ... |
579 |
mutex_unlock(&fs_info->ordered_operations_mutex); |
f0e9b7d64 Btrfs: fix race s... |
580 581 |
return total_done; |
199c2a9c3 Btrfs: introduce ... |
582 |
} |
eb84ae039 Btrfs: Cleanup an... |
583 584 585 586 587 588 589 590 591 592 |
/* * Used to start IO or wait for a given ordered extent to finish. * * If wait is one, this effectively waits on page writeback for all the pages * in the extent, and it waits on the io completion code to insert * metadata into the btree corresponding to the extent */ void btrfs_start_ordered_extent(struct inode *inode, struct btrfs_ordered_extent *entry, int wait) |
e6dcd2dc9 Btrfs: New data=o... |
593 594 595 |
{ u64 start = entry->file_offset; u64 end = start + entry->len - 1; |
e1b81e676 btrfs delete orde... |
596 |
|
1abe9b8a1 Btrfs: add initia... |
597 |
trace_btrfs_ordered_extent_start(inode, entry); |
eb84ae039 Btrfs: Cleanup an... |
598 599 600 |
/* * pages in the range can be dirty, clean or writeback. We * start IO on any dirty ones so the wait doesn't stall waiting |
b25703140 btrfs: nuke pdflu... |
601 |
* for the flusher thread to find them |
eb84ae039 Btrfs: Cleanup an... |
602 |
*/ |
4b46fce23 Btrfs: add basic ... |
603 604 |
if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) filemap_fdatawrite_range(inode->i_mapping, start, end); |
c8b978188 Btrfs: Add zlib c... |
605 |
if (wait) { |
e6dcd2dc9 Btrfs: New data=o... |
606 607 |
wait_event(entry->wait, test_bit(BTRFS_ORDERED_COMPLETE, &entry->flags)); |
c8b978188 Btrfs: Add zlib c... |
608 |
} |
e6dcd2dc9 Btrfs: New data=o... |
609 |
} |
cee36a03e Rework btrfs_drop... |
610 |
|
eb84ae039 Btrfs: Cleanup an... |
611 612 613 |
/* * Used to wait on ordered extents across a large range of bytes. */ |
0ef8b7260 Btrfs: return an ... |
614 |
int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) |
e6dcd2dc9 Btrfs: New data=o... |
615 |
{ |
0ef8b7260 Btrfs: return an ... |
616 |
int ret = 0; |
28aeeac1d Btrfs: fix panic ... |
617 |
int ret_wb = 0; |
e6dcd2dc9 Btrfs: New data=o... |
618 |
u64 end; |
e5a2217ef Fix btrfs_wait_or... |
619 |
u64 orig_end; |
e6dcd2dc9 Btrfs: New data=o... |
620 |
struct btrfs_ordered_extent *ordered; |
e5a2217ef Fix btrfs_wait_or... |
621 622 |
if (start + len < start) { |
f421950f8 Btrfs: Fix some d... |
623 |
orig_end = INT_LIMIT(loff_t); |
e5a2217ef Fix btrfs_wait_or... |
624 625 |
} else { orig_end = start + len - 1; |
f421950f8 Btrfs: Fix some d... |
626 627 |
if (orig_end > INT_LIMIT(loff_t)) orig_end = INT_LIMIT(loff_t); |
e5a2217ef Fix btrfs_wait_or... |
628 |
} |
551ebb2d3 Btrfs: remove use... |
629 |
|
e5a2217ef Fix btrfs_wait_or... |
630 631 632 |
/* start IO across the range first to instantiate any delalloc * extents */ |
728404dac Btrfs: add helper... |
633 |
ret = btrfs_fdatawrite_range(inode, start, orig_end); |
0ef8b7260 Btrfs: return an ... |
634 635 |
if (ret) return ret; |
728404dac Btrfs: add helper... |
636 |
|
28aeeac1d Btrfs: fix panic ... |
637 638 639 640 641 642 643 644 |
/* * If we have a writeback error don't return immediately. Wait first * for any ordered extents that haven't completed yet. This is to make * sure no one can dirty the same page ranges and call writepages() * before the ordered extents complete - to avoid failures (-EEXIST) * when adding the new ordered extents to the ordered tree. */ ret_wb = filemap_fdatawait_range(inode->i_mapping, start, orig_end); |
e5a2217ef Fix btrfs_wait_or... |
645 |
|
f421950f8 Btrfs: Fix some d... |
646 |
end = orig_end; |
d397712bc Btrfs: Fix checkp... |
647 |
while (1) { |
e6dcd2dc9 Btrfs: New data=o... |
648 |
ordered = btrfs_lookup_first_ordered_extent(inode, end); |
d397712bc Btrfs: Fix checkp... |
649 |
if (!ordered) |
e6dcd2dc9 Btrfs: New data=o... |
650 |
break; |
e5a2217ef Fix btrfs_wait_or... |
651 |
if (ordered->file_offset > orig_end) { |
e6dcd2dc9 Btrfs: New data=o... |
652 653 654 |
btrfs_put_ordered_extent(ordered); break; } |
b52abf1e3 Btrfs: don't wait... |
655 |
if (ordered->file_offset + ordered->len <= start) { |
e6dcd2dc9 Btrfs: New data=o... |
656 657 658 |
btrfs_put_ordered_extent(ordered); break; } |
e5a2217ef Fix btrfs_wait_or... |
659 |
btrfs_start_ordered_extent(inode, ordered, 1); |
e6dcd2dc9 Btrfs: New data=o... |
660 |
end = ordered->file_offset; |
c383f8ad2 Btrfs: fix btrfs_... |
661 662 663 664 665 |
/* * If the ordered extent had an error save the error but don't * exit without waiting first for all other ordered extents in * the range to complete. */ |
0ef8b7260 Btrfs: return an ... |
666 667 |
if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)) ret = -EIO; |
e6dcd2dc9 Btrfs: New data=o... |
668 |
btrfs_put_ordered_extent(ordered); |
c383f8ad2 Btrfs: fix btrfs_... |
669 |
if (end == 0 || end == start) |
e6dcd2dc9 Btrfs: New data=o... |
670 671 672 |
break; end--; } |
28aeeac1d Btrfs: fix panic ... |
673 |
return ret_wb ? ret_wb : ret; |
cee36a03e Rework btrfs_drop... |
674 |
} |
eb84ae039 Btrfs: Cleanup an... |
675 676 677 678 |
/* * find an ordered extent corresponding to file_offset. return NULL if * nothing is found, otherwise take a reference on the extent and return it */ |
e6dcd2dc9 Btrfs: New data=o... |
679 680 681 682 683 684 685 686 |
struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct inode *inode, u64 file_offset) { struct btrfs_ordered_inode_tree *tree; struct rb_node *node; struct btrfs_ordered_extent *entry = NULL; tree = &BTRFS_I(inode)->ordered_tree; |
5fd020435 Btrfs: finish ord... |
687 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
688 689 690 691 692 693 694 695 |
node = tree_search(tree, file_offset); if (!node) goto out; entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); if (!offset_in_entry(entry, file_offset)) entry = NULL; if (entry) |
e76edab7f btrfs: convert bt... |
696 |
refcount_inc(&entry->refs); |
e6dcd2dc9 Btrfs: New data=o... |
697 |
out: |
5fd020435 Btrfs: finish ord... |
698 |
spin_unlock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
699 700 |
return entry; } |
4b46fce23 Btrfs: add basic ... |
701 702 703 |
/* Since the DIO code tries to lock a wide area we need to look for any ordered * extents that exist in the range, rather than just the start of the range. */ |
a776c6fa1 btrfs: Make btrfs... |
704 705 |
struct btrfs_ordered_extent *btrfs_lookup_ordered_range( struct btrfs_inode *inode, u64 file_offset, u64 len) |
4b46fce23 Btrfs: add basic ... |
706 707 708 709 |
{ struct btrfs_ordered_inode_tree *tree; struct rb_node *node; struct btrfs_ordered_extent *entry = NULL; |
a776c6fa1 btrfs: Make btrfs... |
710 |
tree = &inode->ordered_tree; |
5fd020435 Btrfs: finish ord... |
711 |
spin_lock_irq(&tree->lock); |
4b46fce23 Btrfs: add basic ... |
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 |
node = tree_search(tree, file_offset); if (!node) { node = tree_search(tree, file_offset + len); if (!node) goto out; } while (1) { entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); if (range_overlaps(entry, file_offset, len)) break; if (entry->file_offset >= file_offset + len) { entry = NULL; break; } entry = NULL; node = rb_next(node); if (!node) break; } out: if (entry) |
e76edab7f btrfs: convert bt... |
735 |
refcount_inc(&entry->refs); |
5fd020435 Btrfs: finish ord... |
736 |
spin_unlock_irq(&tree->lock); |
4b46fce23 Btrfs: add basic ... |
737 738 |
return entry; } |
eb84ae039 Btrfs: Cleanup an... |
739 740 741 742 |
/* * lookup and return any extent before 'file_offset'. NULL is returned * if none is found */ |
e6dcd2dc9 Btrfs: New data=o... |
743 |
struct btrfs_ordered_extent * |
d397712bc Btrfs: Fix checkp... |
744 |
btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset) |
e6dcd2dc9 Btrfs: New data=o... |
745 746 747 748 749 750 |
{ struct btrfs_ordered_inode_tree *tree; struct rb_node *node; struct btrfs_ordered_extent *entry = NULL; tree = &BTRFS_I(inode)->ordered_tree; |
5fd020435 Btrfs: finish ord... |
751 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
752 753 754 755 756 |
node = tree_search(tree, file_offset); if (!node) goto out; entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
e76edab7f btrfs: convert bt... |
757 |
refcount_inc(&entry->refs); |
e6dcd2dc9 Btrfs: New data=o... |
758 |
out: |
5fd020435 Btrfs: finish ord... |
759 |
spin_unlock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
760 |
return entry; |
81d7ed29f Btrfs: Throttle f... |
761 |
} |
dbe674a99 Btrfs: Update on ... |
762 |
|
eb84ae039 Btrfs: Cleanup an... |
763 764 765 766 |
/* * 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. */ |
c21677545 Btrfs: Fix disk_i... |
767 |
int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, |
dbe674a99 Btrfs: Update on ... |
768 769 770 |
struct btrfs_ordered_extent *ordered) { struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
dbe674a99 Btrfs: Update on ... |
771 772 |
u64 disk_i_size; u64 new_i_size; |
c21677545 Btrfs: Fix disk_i... |
773 |
u64 i_size = i_size_read(inode); |
dbe674a99 Btrfs: Update on ... |
774 |
struct rb_node *node; |
c21677545 Btrfs: Fix disk_i... |
775 |
struct rb_node *prev = NULL; |
dbe674a99 Btrfs: Update on ... |
776 |
struct btrfs_ordered_extent *test; |
c21677545 Btrfs: Fix disk_i... |
777 |
int ret = 1; |
c0d2f6104 btrfs: fix disk_i... |
778 |
u64 orig_offset = offset; |
c21677545 Btrfs: Fix disk_i... |
779 |
|
77cef2ec5 Btrfs: allow part... |
780 781 |
spin_lock_irq(&tree->lock); if (ordered) { |
c21677545 Btrfs: Fix disk_i... |
782 |
offset = entry_end(ordered); |
77cef2ec5 Btrfs: allow part... |
783 784 785 786 787 |
if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags)) offset = min(offset, ordered->file_offset + ordered->truncated_len); } else { |
da17066c4 btrfs: pull node/... |
788 |
offset = ALIGN(offset, btrfs_inode_sectorsize(inode)); |
77cef2ec5 Btrfs: allow part... |
789 |
} |
dbe674a99 Btrfs: Update on ... |
790 |
disk_i_size = BTRFS_I(inode)->disk_i_size; |
19fd2df5b Btrfs: fix btrfs_... |
791 792 793 794 795 796 797 798 799 800 801 802 |
/* * truncate file. * If ordered is not NULL, then this is called from endio and * disk_i_size will be updated by either truncate itself or any * in-flight IOs which are inside the disk_i_size. * * Because btrfs_setsize() may set i_size with disk_i_size if truncate * fails somehow, we need to make sure we have a precise disk_i_size by * updating it as usual. * */ if (!ordered && disk_i_size > i_size) { |
c0d2f6104 btrfs: fix disk_i... |
803 |
BTRFS_I(inode)->disk_i_size = orig_offset; |
c21677545 Btrfs: Fix disk_i... |
804 805 806 |
ret = 0; goto out; } |
dbe674a99 Btrfs: Update on ... |
807 808 809 810 |
/* * 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 */ |
5d1f40202 Btrfs: fix missin... |
811 812 813 814 815 816 817 818 819 |
if (disk_i_size == i_size) goto out; /* * We still need to update disk_i_size if outstanding_isize is greater * than disk_i_size. */ if (offset <= disk_i_size && (!ordered || ordered->outstanding_isize <= disk_i_size)) |
dbe674a99 Btrfs: Update on ... |
820 |
goto out; |
dbe674a99 Btrfs: Update on ... |
821 822 |
/* |
dbe674a99 Btrfs: Update on ... |
823 824 825 826 |
* walk backward from this ordered extent to disk_i_size. * if we find an ordered extent then we can't update disk i_size * yet */ |
c21677545 Btrfs: Fix disk_i... |
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 |
if (ordered) { node = rb_prev(&ordered->rb_node); } else { prev = tree_search(tree, offset); /* * 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; } |
5fd020435 Btrfs: finish ord... |
842 |
for (; node; node = rb_prev(node)) { |
dbe674a99 Btrfs: Update on ... |
843 |
test = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
5fd020435 Btrfs: finish ord... |
844 |
|
bb7ab3b92 btrfs: Fix misspe... |
845 |
/* We treat this entry as if it doesn't exist */ |
5fd020435 Btrfs: finish ord... |
846 847 |
if (test_bit(BTRFS_ORDERED_UPDATED_ISIZE, &test->flags)) continue; |
62c821a8e Btrfs: clean up b... |
848 849 |
if (entry_end(test) <= disk_i_size) |
dbe674a99 Btrfs: Update on ... |
850 |
break; |
c21677545 Btrfs: Fix disk_i... |
851 |
if (test->file_offset >= i_size) |
dbe674a99 Btrfs: Update on ... |
852 |
break; |
62c821a8e Btrfs: clean up b... |
853 854 855 856 857 858 859 860 861 862 863 |
/* * We don't update disk_i_size now, so record this undealt * i_size. Or we will not know the real i_size. */ if (test->outstanding_isize < offset) test->outstanding_isize = offset; if (ordered && ordered->outstanding_isize > test->outstanding_isize) test->outstanding_isize = ordered->outstanding_isize; goto out; |
dbe674a99 Btrfs: Update on ... |
864 |
} |
b9a8cc5be Btrfs: fix file e... |
865 |
new_i_size = min_t(u64, offset, i_size); |
dbe674a99 Btrfs: Update on ... |
866 867 |
/* |
b9a8cc5be Btrfs: fix file e... |
868 869 |
* Some ordered extents may completed before the current one, and * we hold the real i_size in ->outstanding_isize. |
dbe674a99 Btrfs: Update on ... |
870 |
*/ |
b9a8cc5be Btrfs: fix file e... |
871 872 |
if (ordered && ordered->outstanding_isize > new_i_size) new_i_size = min_t(u64, ordered->outstanding_isize, i_size); |
dbe674a99 Btrfs: Update on ... |
873 |
BTRFS_I(inode)->disk_i_size = new_i_size; |
c21677545 Btrfs: Fix disk_i... |
874 |
ret = 0; |
dbe674a99 Btrfs: Update on ... |
875 |
out: |
c21677545 Btrfs: Fix disk_i... |
876 |
/* |
5fd020435 Btrfs: finish ord... |
877 878 879 880 881 |
* We need to do this because we can't remove ordered extents until * after the i_disk_size has been updated and then the inode has been * updated to reflect the change, so we need to tell anybody who finds * this ordered extent that we've already done all the real work, we * just haven't completed all the other work. |
c21677545 Btrfs: Fix disk_i... |
882 883 |
*/ if (ordered) |
5fd020435 Btrfs: finish ord... |
884 885 |
set_bit(BTRFS_ORDERED_UPDATED_ISIZE, &ordered->flags); spin_unlock_irq(&tree->lock); |
c21677545 Btrfs: Fix disk_i... |
886 |
return ret; |
dbe674a99 Btrfs: Update on ... |
887 |
} |
ba1da2f44 Btrfs: Don't pin ... |
888 |
|
eb84ae039 Btrfs: Cleanup an... |
889 890 891 892 893 |
/* * search the ordered extents for one corresponding to 'offset' and * try to find a checksum. This is used because we allow pages to * be reclaimed before their checksum is actually put into the btree */ |
d20f7043f Btrfs: move data ... |
894 |
int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, |
1e25a2e3c btrfs: don't assu... |
895 |
u8 *sum, int len) |
ba1da2f44 Btrfs: Don't pin ... |
896 |
{ |
1e25a2e3c btrfs: don't assu... |
897 |
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
ba1da2f44 Btrfs: Don't pin ... |
898 |
struct btrfs_ordered_sum *ordered_sum; |
ba1da2f44 Btrfs: Don't pin ... |
899 900 |
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
3edf7d33f Btrfs: Handle dat... |
901 902 |
unsigned long num_sectors; unsigned long i; |
da17066c4 btrfs: pull node/... |
903 |
u32 sectorsize = btrfs_inode_sectorsize(inode); |
1e25a2e3c btrfs: don't assu... |
904 |
const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); |
e4100d987 Btrfs: improve th... |
905 |
int index = 0; |
ba1da2f44 Btrfs: Don't pin ... |
906 907 908 |
ordered = btrfs_lookup_ordered_extent(inode, offset); if (!ordered) |
e4100d987 Btrfs: improve th... |
909 |
return 0; |
ba1da2f44 Btrfs: Don't pin ... |
910 |
|
5fd020435 Btrfs: finish ord... |
911 |
spin_lock_irq(&tree->lock); |
c6e308713 Btrfs: simplify i... |
912 |
list_for_each_entry_reverse(ordered_sum, &ordered->list, list) { |
e4100d987 Btrfs: improve th... |
913 914 915 916 |
if (disk_bytenr >= ordered_sum->bytenr && disk_bytenr < ordered_sum->bytenr + ordered_sum->len) { i = (disk_bytenr - ordered_sum->bytenr) >> inode->i_sb->s_blocksize_bits; |
e4100d987 Btrfs: improve th... |
917 918 |
num_sectors = ordered_sum->len >> inode->i_sb->s_blocksize_bits; |
f51a4a182 Btrfs: remove btr... |
919 |
num_sectors = min_t(int, len - index, num_sectors - i); |
1e25a2e3c btrfs: don't assu... |
920 921 |
memcpy(sum + index, ordered_sum->sums + i * csum_size, num_sectors * csum_size); |
f51a4a182 Btrfs: remove btr... |
922 |
|
1e25a2e3c btrfs: don't assu... |
923 |
index += (int)num_sectors * csum_size; |
f51a4a182 Btrfs: remove btr... |
924 925 926 |
if (index == len) goto out; disk_bytenr += num_sectors * sectorsize; |
ba1da2f44 Btrfs: Don't pin ... |
927 928 929 |
} } out: |
5fd020435 Btrfs: finish ord... |
930 |
spin_unlock_irq(&tree->lock); |
89642229a Btrfs: Search dat... |
931 |
btrfs_put_ordered_extent(ordered); |
e4100d987 Btrfs: improve th... |
932 |
return index; |
ba1da2f44 Btrfs: Don't pin ... |
933 |
} |
ffa87214c btrfs: add new he... |
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 |
/* * btrfs_flush_ordered_range - Lock the passed range and ensures all pending * ordered extents in it are run to completion. * * @tree: IO tree used for locking out other users of the range * @inode: Inode whose ordered tree is to be searched * @start: Beginning of range to flush * @end: Last byte of range to lock * @cached_state: If passed, will return the extent state responsible for the * locked range. It's the caller's responsibility to free the cached state. * * This function always returns with the given range locked, ensuring after it's * called no order extent can be pending. */ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree, struct btrfs_inode *inode, u64 start, u64 end, struct extent_state **cached_state) { struct btrfs_ordered_extent *ordered; |
a3b46b86c btrfs: fix extent... |
954 955 |
struct extent_state *cache = NULL; struct extent_state **cachedp = &cache; |
bd80d94ef btrfs: Always use... |
956 957 |
if (cached_state) |
a3b46b86c btrfs: fix extent... |
958 |
cachedp = cached_state; |
ffa87214c btrfs: add new he... |
959 960 |
while (1) { |
a3b46b86c btrfs: fix extent... |
961 |
lock_extent_bits(tree, start, end, cachedp); |
ffa87214c btrfs: add new he... |
962 963 |
ordered = btrfs_lookup_ordered_range(inode, start, end - start + 1); |
bd80d94ef btrfs: Always use... |
964 965 966 967 968 969 970 |
if (!ordered) { /* * If no external cached_state has been passed then * decrement the extra ref taken for cachedp since we * aren't exposing it outside of this function */ if (!cached_state) |
a3b46b86c btrfs: fix extent... |
971 |
refcount_dec(&cache->refs); |
ffa87214c btrfs: add new he... |
972 |
break; |
bd80d94ef btrfs: Always use... |
973 |
} |
a3b46b86c btrfs: fix extent... |
974 |
unlock_extent_cached(tree, start, end, cachedp); |
ffa87214c btrfs: add new he... |
975 976 977 978 |
btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1); btrfs_put_ordered_extent(ordered); } } |
6352b91da Btrfs: use a slab... |
979 980 981 982 |
int __init ordered_data_init(void) { btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent", sizeof(struct btrfs_ordered_extent), 0, |
fba4b6977 btrfs: Fix slab a... |
983 |
SLAB_MEM_SPREAD, |
6352b91da Btrfs: use a slab... |
984 985 986 |
NULL); if (!btrfs_ordered_extent_cache) return -ENOMEM; |
25287e0a1 Btrfs: make order... |
987 |
|
6352b91da Btrfs: use a slab... |
988 989 |
return 0; } |
e67c718b5 btrfs: add more _... |
990 |
void __cold ordered_data_exit(void) |
6352b91da Btrfs: use a slab... |
991 |
{ |
5598e9005 btrfs: drop null ... |
992 |
kmem_cache_destroy(btrfs_ordered_extent_cache); |
6352b91da Btrfs: use a slab... |
993 |
} |