Blame view
fs/btrfs/ordered-data.c
31.4 KB
dc17ff8f1 Btrfs: Add data=o... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Copyright (C) 2007 Oracle. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ |
dc17ff8f1 Btrfs: Add data=o... |
18 |
#include <linux/slab.h> |
d6bfde876 Btrfs: Fixes for ... |
19 |
#include <linux/blkdev.h> |
f421950f8 Btrfs: Fix some d... |
20 21 |
#include <linux/writeback.h> #include <linux/pagevec.h> |
dc17ff8f1 Btrfs: Add data=o... |
22 23 24 |
#include "ctree.h" #include "transaction.h" #include "btrfs_inode.h" |
e6dcd2dc9 Btrfs: New data=o... |
25 |
#include "extent_io.h" |
199c2a9c3 Btrfs: introduce ... |
26 |
#include "disk-io.h" |
ebb8765b2 btrfs: move btrfs... |
27 |
#include "compression.h" |
dc17ff8f1 Btrfs: Add data=o... |
28 |
|
6352b91da Btrfs: use a slab... |
29 |
static struct kmem_cache *btrfs_ordered_extent_cache; |
e6dcd2dc9 Btrfs: New data=o... |
30 |
static u64 entry_end(struct btrfs_ordered_extent *entry) |
dc17ff8f1 Btrfs: Add data=o... |
31 |
{ |
e6dcd2dc9 Btrfs: New data=o... |
32 33 34 |
if (entry->file_offset + entry->len < entry->file_offset) return (u64)-1; return entry->file_offset + entry->len; |
dc17ff8f1 Btrfs: Add data=o... |
35 |
} |
d352ac681 Btrfs: add and im... |
36 37 38 |
/* returns NULL if the insertion worked, or it returns the node it did find * in the tree */ |
e6dcd2dc9 Btrfs: New data=o... |
39 40 |
static struct rb_node *tree_insert(struct rb_root *root, u64 file_offset, struct rb_node *node) |
dc17ff8f1 Btrfs: Add data=o... |
41 |
{ |
d397712bc Btrfs: Fix checkp... |
42 43 |
struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; |
e6dcd2dc9 Btrfs: New data=o... |
44 |
struct btrfs_ordered_extent *entry; |
dc17ff8f1 Btrfs: Add data=o... |
45 |
|
d397712bc Btrfs: Fix checkp... |
46 |
while (*p) { |
dc17ff8f1 Btrfs: Add data=o... |
47 |
parent = *p; |
e6dcd2dc9 Btrfs: New data=o... |
48 |
entry = rb_entry(parent, struct btrfs_ordered_extent, rb_node); |
dc17ff8f1 Btrfs: Add data=o... |
49 |
|
e6dcd2dc9 Btrfs: New data=o... |
50 |
if (file_offset < entry->file_offset) |
dc17ff8f1 Btrfs: Add data=o... |
51 |
p = &(*p)->rb_left; |
e6dcd2dc9 Btrfs: New data=o... |
52 |
else if (file_offset >= entry_end(entry)) |
dc17ff8f1 Btrfs: Add data=o... |
53 54 55 56 57 58 59 60 61 |
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... |
62 63 64 65 |
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... |
66 67 |
btrfs_panic(fs_info, errno, "Inconsistency in ordered tree at offset %llu", offset); |
43c04fb1b btrfs: Panic on b... |
68 |
} |
d352ac681 Btrfs: add and im... |
69 70 71 72 |
/* * 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... |
73 74 |
static struct rb_node *__tree_search(struct rb_root *root, u64 file_offset, struct rb_node **prev_ret) |
dc17ff8f1 Btrfs: Add data=o... |
75 |
{ |
d397712bc Btrfs: Fix checkp... |
76 |
struct rb_node *n = root->rb_node; |
dc17ff8f1 Btrfs: Add data=o... |
77 |
struct rb_node *prev = NULL; |
e6dcd2dc9 Btrfs: New data=o... |
78 79 80 |
struct rb_node *test; struct btrfs_ordered_extent *entry; struct btrfs_ordered_extent *prev_entry = NULL; |
dc17ff8f1 Btrfs: Add data=o... |
81 |
|
d397712bc Btrfs: Fix checkp... |
82 |
while (n) { |
e6dcd2dc9 Btrfs: New data=o... |
83 |
entry = rb_entry(n, struct btrfs_ordered_extent, rb_node); |
dc17ff8f1 Btrfs: Add data=o... |
84 85 |
prev = n; prev_entry = entry; |
dc17ff8f1 Btrfs: Add data=o... |
86 |
|
e6dcd2dc9 Btrfs: New data=o... |
87 |
if (file_offset < entry->file_offset) |
dc17ff8f1 Btrfs: Add data=o... |
88 |
n = n->rb_left; |
e6dcd2dc9 Btrfs: New data=o... |
89 |
else if (file_offset >= entry_end(entry)) |
dc17ff8f1 Btrfs: Add data=o... |
90 91 92 93 94 95 |
n = n->rb_right; else return n; } if (!prev_ret) return NULL; |
d397712bc Btrfs: Fix checkp... |
96 |
while (prev && file_offset >= entry_end(prev_entry)) { |
e6dcd2dc9 Btrfs: New data=o... |
97 98 99 100 101 102 103 104 105 106 107 108 109 |
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... |
110 |
while (prev && file_offset < entry_end(prev_entry)) { |
e6dcd2dc9 Btrfs: New data=o... |
111 112 113 114 115 116 |
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... |
117 118 119 120 |
} *prev_ret = prev; return NULL; } |
d352ac681 Btrfs: add and im... |
121 122 123 |
/* * helper to check if a given offset is inside a given entry */ |
e6dcd2dc9 Btrfs: New data=o... |
124 125 126 127 128 129 130 |
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 ... |
131 132 133 134 135 136 137 138 |
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... |
139 140 141 142 |
/* * look find the first ordered struct that has this offset, otherwise * the first one less than this offset */ |
e6dcd2dc9 Btrfs: New data=o... |
143 144 |
static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, u64 file_offset) |
dc17ff8f1 Btrfs: Add data=o... |
145 |
{ |
e6dcd2dc9 Btrfs: New data=o... |
146 |
struct rb_root *root = &tree->tree; |
c87fb6fdc Btrfs: avoid unin... |
147 |
struct rb_node *prev = NULL; |
dc17ff8f1 Btrfs: Add data=o... |
148 |
struct rb_node *ret; |
e6dcd2dc9 Btrfs: New data=o... |
149 150 151 152 153 154 155 156 157 |
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... |
158 |
if (!ret) |
e6dcd2dc9 Btrfs: New data=o... |
159 160 161 |
ret = prev; if (ret) tree->last = ret; |
dc17ff8f1 Btrfs: Add data=o... |
162 163 |
return ret; } |
eb84ae039 Btrfs: Cleanup an... |
164 165 166 167 168 169 170 171 |
/* 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... |
172 173 174 |
* The tree is given a single reference on the ordered extent that was * inserted. */ |
4b46fce23 Btrfs: add basic ... |
175 176 |
static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, u64 start, u64 len, u64 disk_len, |
261507a02 btrfs: Allow to a... |
177 |
int type, int dio, int compress_type) |
dc17ff8f1 Btrfs: Add data=o... |
178 |
{ |
0b246afa6 btrfs: root->fs_i... |
179 |
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
199c2a9c3 Btrfs: introduce ... |
180 |
struct btrfs_root *root = BTRFS_I(inode)->root; |
dc17ff8f1 Btrfs: Add data=o... |
181 |
struct btrfs_ordered_inode_tree *tree; |
e6dcd2dc9 Btrfs: New data=o... |
182 183 |
struct rb_node *node; struct btrfs_ordered_extent *entry; |
dc17ff8f1 Btrfs: Add data=o... |
184 |
|
e6dcd2dc9 Btrfs: New data=o... |
185 |
tree = &BTRFS_I(inode)->ordered_tree; |
6352b91da Btrfs: use a slab... |
186 |
entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS); |
dc17ff8f1 Btrfs: Add data=o... |
187 188 |
if (!entry) return -ENOMEM; |
e6dcd2dc9 Btrfs: New data=o... |
189 190 191 |
entry->file_offset = file_offset; entry->start = start; entry->len = len; |
c8b978188 Btrfs: Add zlib c... |
192 |
entry->disk_len = disk_len; |
8b62b72b2 Btrfs: Use PagePr... |
193 |
entry->bytes_left = len; |
5fd020435 Btrfs: finish ord... |
194 |
entry->inode = igrab(inode); |
261507a02 btrfs: Allow to a... |
195 |
entry->compress_type = compress_type; |
77cef2ec5 Btrfs: allow part... |
196 |
entry->truncated_len = (u64)-1; |
d899e0521 Btrfs: Add falloc... |
197 |
if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE) |
80ff38566 Btrfs: update nod... |
198 |
set_bit(type, &entry->flags); |
3eaa28852 Btrfs: Fix the de... |
199 |
|
4b46fce23 Btrfs: add basic ... |
200 201 |
if (dio) set_bit(BTRFS_ORDERED_DIRECT, &entry->flags); |
e6dcd2dc9 Btrfs: New data=o... |
202 |
/* one ref for the tree */ |
e76edab7f btrfs: convert bt... |
203 |
refcount_set(&entry->refs, 1); |
e6dcd2dc9 Btrfs: New data=o... |
204 205 |
init_waitqueue_head(&entry->wait); INIT_LIST_HEAD(&entry->list); |
3eaa28852 Btrfs: Fix the de... |
206 |
INIT_LIST_HEAD(&entry->root_extent_list); |
9afab8820 Btrfs: make order... |
207 208 |
INIT_LIST_HEAD(&entry->work_list); init_completion(&entry->completion); |
2ab28f322 Btrfs: wait on or... |
209 |
INIT_LIST_HEAD(&entry->log_list); |
50d9aa99b Btrfs: make sure ... |
210 |
INIT_LIST_HEAD(&entry->trans_list); |
dc17ff8f1 Btrfs: Add data=o... |
211 |
|
1abe9b8a1 Btrfs: add initia... |
212 |
trace_btrfs_ordered_extent_add(inode, entry); |
5fd020435 Btrfs: finish ord... |
213 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
214 215 |
node = tree_insert(&tree->tree, file_offset, &entry->rb_node); |
43c04fb1b btrfs: Panic on b... |
216 217 |
if (node) ordered_data_tree_panic(inode, -EEXIST, file_offset); |
5fd020435 Btrfs: finish ord... |
218 |
spin_unlock_irq(&tree->lock); |
d397712bc Btrfs: Fix checkp... |
219 |
|
199c2a9c3 Btrfs: introduce ... |
220 |
spin_lock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
221 |
list_add_tail(&entry->root_extent_list, |
199c2a9c3 Btrfs: introduce ... |
222 223 224 |
&root->ordered_extents); root->nr_ordered_extents++; if (root->nr_ordered_extents == 1) { |
0b246afa6 btrfs: root->fs_i... |
225 |
spin_lock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
226 |
BUG_ON(!list_empty(&root->ordered_root)); |
0b246afa6 btrfs: root->fs_i... |
227 228 |
list_add_tail(&root->ordered_root, &fs_info->ordered_roots); spin_unlock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
229 230 |
} spin_unlock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
231 |
|
dc17ff8f1 Btrfs: Add data=o... |
232 233 |
return 0; } |
4b46fce23 Btrfs: add basic ... |
234 235 236 237 |
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... |
238 239 |
disk_len, type, 0, BTRFS_COMPRESS_NONE); |
4b46fce23 Btrfs: add basic ... |
240 241 242 243 244 245 |
} 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... |
246 247 248 249 250 251 252 253 254 255 256 |
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 ... |
257 |
} |
eb84ae039 Btrfs: Cleanup an... |
258 259 |
/* * Add a struct btrfs_ordered_sum into the list of checksums to be inserted |
3edf7d33f Btrfs: Handle dat... |
260 261 |
* when an ordered extent is finished. If the list covers more than one * ordered extent, it is split across multiples. |
eb84ae039 Btrfs: Cleanup an... |
262 |
*/ |
143bede52 btrfs: return voi... |
263 264 265 |
void btrfs_add_ordered_sum(struct inode *inode, struct btrfs_ordered_extent *entry, 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 |
|
e6dcd2dc9 Btrfs: New data=o... |
269 |
tree = &BTRFS_I(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); |
a83342aa0 btrfs: add commen... |
333 334 335 |
/* * Implicit memory barrier after test_and_set_bit */ |
af7a65097 Btrfs: wake up th... |
336 337 338 |
if (waitqueue_active(&entry->wait)) wake_up(&entry->wait); } else { |
163cf09c2 Btrfs: deal with ... |
339 |
ret = 1; |
af7a65097 Btrfs: wake up th... |
340 |
} |
163cf09c2 Btrfs: deal with ... |
341 342 343 |
out: if (!ret && cached && entry) { *cached = entry; |
e76edab7f btrfs: convert bt... |
344 |
refcount_inc(&entry->refs); |
163cf09c2 Btrfs: deal with ... |
345 |
} |
5fd020435 Btrfs: finish ord... |
346 |
spin_unlock_irqrestore(&tree->lock, flags); |
163cf09c2 Btrfs: deal with ... |
347 348 349 350 351 |
return ret == 0; } /* * this is used to account for finished IO across a given range |
eb84ae039 Btrfs: Cleanup an... |
352 353 354 355 356 357 358 |
* 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... |
359 |
int btrfs_dec_test_ordered_pending(struct inode *inode, |
5a1a3df1f Btrfs: cache orde... |
360 |
struct btrfs_ordered_extent **cached, |
5fd020435 Btrfs: finish ord... |
361 |
u64 file_offset, u64 io_size, int uptodate) |
dc17ff8f1 Btrfs: Add data=o... |
362 |
{ |
e6dcd2dc9 Btrfs: New data=o... |
363 |
struct btrfs_ordered_inode_tree *tree; |
dc17ff8f1 Btrfs: Add data=o... |
364 |
struct rb_node *node; |
5a1a3df1f Btrfs: cache orde... |
365 |
struct btrfs_ordered_extent *entry = NULL; |
5fd020435 Btrfs: finish ord... |
366 |
unsigned long flags; |
e6dcd2dc9 Btrfs: New data=o... |
367 368 369 |
int ret; tree = &BTRFS_I(inode)->ordered_tree; |
5fd020435 Btrfs: finish ord... |
370 371 372 373 374 |
spin_lock_irqsave(&tree->lock, flags); if (cached && *cached) { entry = *cached; goto have_entry; } |
e6dcd2dc9 Btrfs: New data=o... |
375 |
node = tree_search(tree, file_offset); |
dc17ff8f1 Btrfs: Add data=o... |
376 |
if (!node) { |
e6dcd2dc9 Btrfs: New data=o... |
377 378 |
ret = 1; goto out; |
dc17ff8f1 Btrfs: Add data=o... |
379 |
} |
e6dcd2dc9 Btrfs: New data=o... |
380 |
entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
5fd020435 Btrfs: finish ord... |
381 |
have_entry: |
e6dcd2dc9 Btrfs: New data=o... |
382 383 384 |
if (!offset_in_entry(entry, file_offset)) { ret = 1; goto out; |
dc17ff8f1 Btrfs: Add data=o... |
385 |
} |
e6dcd2dc9 Btrfs: New data=o... |
386 |
|
8b62b72b2 Btrfs: Use PagePr... |
387 |
if (io_size > entry->bytes_left) { |
efe120a06 Btrfs: convert pr... |
388 389 |
btrfs_crit(BTRFS_I(inode)->root->fs_info, "bad ordered accounting left %llu size %llu", |
c1c9ff7c9 Btrfs: Remove sup... |
390 |
entry->bytes_left, io_size); |
8b62b72b2 Btrfs: Use PagePr... |
391 392 |
} entry->bytes_left -= io_size; |
5fd020435 Btrfs: finish ord... |
393 394 |
if (!uptodate) set_bit(BTRFS_ORDERED_IOERR, &entry->flags); |
af7a65097 Btrfs: wake up th... |
395 |
if (entry->bytes_left == 0) { |
e6dcd2dc9 Btrfs: New data=o... |
396 |
ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
a83342aa0 btrfs: add commen... |
397 398 399 |
/* * Implicit memory barrier after test_and_set_bit */ |
af7a65097 Btrfs: wake up th... |
400 401 402 |
if (waitqueue_active(&entry->wait)) wake_up(&entry->wait); } else { |
8b62b72b2 Btrfs: Use PagePr... |
403 |
ret = 1; |
af7a65097 Btrfs: wake up th... |
404 |
} |
e6dcd2dc9 Btrfs: New data=o... |
405 |
out: |
5a1a3df1f Btrfs: cache orde... |
406 407 |
if (!ret && cached && entry) { *cached = entry; |
e76edab7f btrfs: convert bt... |
408 |
refcount_inc(&entry->refs); |
5a1a3df1f Btrfs: cache orde... |
409 |
} |
5fd020435 Btrfs: finish ord... |
410 |
spin_unlock_irqrestore(&tree->lock, flags); |
e6dcd2dc9 Btrfs: New data=o... |
411 412 |
return ret == 0; } |
dc17ff8f1 Btrfs: Add data=o... |
413 |
|
2ab28f322 Btrfs: wait on or... |
414 |
/* Needs to either be called under a log transaction or the log_mutex */ |
223466370 btrfs: Make btrfs... |
415 |
void btrfs_get_logged_extents(struct btrfs_inode *inode, |
0870295b2 Btrfs: collect on... |
416 417 418 |
struct list_head *logged_list, const loff_t start, const loff_t end) |
2ab28f322 Btrfs: wait on or... |
419 420 421 422 |
{ struct btrfs_ordered_inode_tree *tree; struct btrfs_ordered_extent *ordered; struct rb_node *n; |
0870295b2 Btrfs: collect on... |
423 |
struct rb_node *prev; |
2ab28f322 Btrfs: wait on or... |
424 |
|
223466370 btrfs: Make btrfs... |
425 |
tree = &inode->ordered_tree; |
2ab28f322 Btrfs: wait on or... |
426 |
spin_lock_irq(&tree->lock); |
0870295b2 Btrfs: collect on... |
427 428 429 430 |
n = __tree_search(&tree->tree, end, &prev); if (!n) n = prev; for (; n; n = rb_prev(n)) { |
2ab28f322 Btrfs: wait on or... |
431 |
ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); |
0870295b2 Btrfs: collect on... |
432 433 434 435 |
if (ordered->file_offset > end) continue; if (entry_end(ordered) <= start) break; |
4d884fcea Btrfs: fix fsync ... |
436 |
if (test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags)) |
50d9aa99b Btrfs: make sure ... |
437 |
continue; |
0870295b2 Btrfs: collect on... |
438 |
list_add(&ordered->log_list, logged_list); |
e76edab7f btrfs: convert bt... |
439 |
refcount_inc(&ordered->refs); |
2ab28f322 Btrfs: wait on or... |
440 441 442 |
} spin_unlock_irq(&tree->lock); } |
827463c49 Btrfs: don't mix ... |
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
void btrfs_put_logged_extents(struct list_head *logged_list) { struct btrfs_ordered_extent *ordered; while (!list_empty(logged_list)) { ordered = list_first_entry(logged_list, struct btrfs_ordered_extent, log_list); list_del_init(&ordered->log_list); btrfs_put_ordered_extent(ordered); } } void btrfs_submit_logged_extents(struct list_head *logged_list, struct btrfs_root *log) { int index = log->log_transid % 2; spin_lock_irq(&log->log_extents_lock[index]); list_splice_tail(logged_list, &log->logged_list[index]); spin_unlock_irq(&log->log_extents_lock[index]); } |
50d9aa99b Btrfs: make sure ... |
465 466 |
void btrfs_wait_logged_extents(struct btrfs_trans_handle *trans, struct btrfs_root *log, u64 transid) |
2ab28f322 Btrfs: wait on or... |
467 468 469 470 471 472 |
{ struct btrfs_ordered_extent *ordered; int index = transid % 2; spin_lock_irq(&log->log_extents_lock[index]); while (!list_empty(&log->logged_list[index])) { |
161c3549b Btrfs: change how... |
473 |
struct inode *inode; |
2ab28f322 Btrfs: wait on or... |
474 475 476 477 |
ordered = list_first_entry(&log->logged_list[index], struct btrfs_ordered_extent, log_list); list_del_init(&ordered->log_list); |
161c3549b Btrfs: change how... |
478 |
inode = ordered->inode; |
2ab28f322 Btrfs: wait on or... |
479 |
spin_unlock_irq(&log->log_extents_lock[index]); |
98ce2deda Btrfs: fix abnorm... |
480 481 482 |
if (!test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags) && !test_bit(BTRFS_ORDERED_DIRECT, &ordered->flags)) { |
98ce2deda Btrfs: fix abnorm... |
483 484 485 486 487 488 |
u64 start = ordered->file_offset; u64 end = ordered->file_offset + ordered->len - 1; WARN_ON(!inode); filemap_fdatawrite_range(inode->i_mapping, start, end); } |
2ab28f322 Btrfs: wait on or... |
489 490 |
wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)); |
98ce2deda Btrfs: fix abnorm... |
491 |
|
7558c8bc1 Btrfs: don't atta... |
492 |
/* |
161c3549b Btrfs: change how... |
493 494 495 496 497 498 |
* In order to keep us from losing our ordered extent * information when committing the transaction we have to make * sure that any logged extents are completed when we go to * commit the transaction. To do this we simply increase the * current transactions pending_ordered counter and decrement it * when the ordered extent completes. |
7558c8bc1 Btrfs: don't atta... |
499 |
*/ |
161c3549b Btrfs: change how... |
500 501 502 503 504 505 506 507 508 509 510 511 |
if (!test_bit(BTRFS_ORDERED_COMPLETE, &ordered->flags)) { struct btrfs_ordered_inode_tree *tree; tree = &BTRFS_I(inode)->ordered_tree; spin_lock_irq(&tree->lock); if (!test_bit(BTRFS_ORDERED_COMPLETE, &ordered->flags)) { set_bit(BTRFS_ORDERED_PENDING, &ordered->flags); atomic_inc(&trans->transaction->pending_ordered); } spin_unlock_irq(&tree->lock); } btrfs_put_ordered_extent(ordered); |
2ab28f322 Btrfs: wait on or... |
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 |
spin_lock_irq(&log->log_extents_lock[index]); } spin_unlock_irq(&log->log_extents_lock[index]); } void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid) { struct btrfs_ordered_extent *ordered; int index = transid % 2; spin_lock_irq(&log->log_extents_lock[index]); while (!list_empty(&log->logged_list[index])) { ordered = list_first_entry(&log->logged_list[index], struct btrfs_ordered_extent, log_list); list_del_init(&ordered->log_list); spin_unlock_irq(&log->log_extents_lock[index]); btrfs_put_ordered_extent(ordered); spin_lock_irq(&log->log_extents_lock[index]); } spin_unlock_irq(&log->log_extents_lock[index]); } |
eb84ae039 Btrfs: Cleanup an... |
534 535 536 537 |
/* * used to drop a reference on an ordered extent. This will free * the extent if the last reference is dropped */ |
143bede52 btrfs: return voi... |
538 |
void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) |
e6dcd2dc9 Btrfs: New data=o... |
539 |
{ |
ba1da2f44 Btrfs: Don't pin ... |
540 541 |
struct list_head *cur; struct btrfs_ordered_sum *sum; |
1abe9b8a1 Btrfs: add initia... |
542 |
trace_btrfs_ordered_extent_put(entry->inode, entry); |
e76edab7f btrfs: convert bt... |
543 |
if (refcount_dec_and_test(&entry->refs)) { |
61de718fc Btrfs: fix memory... |
544 545 546 547 |
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... |
548 549 |
if (entry->inode) btrfs_add_delayed_iput(entry->inode); |
d397712bc Btrfs: Fix checkp... |
550 |
while (!list_empty(&entry->list)) { |
ba1da2f44 Btrfs: Don't pin ... |
551 552 553 554 555 |
cur = entry->list.next; sum = list_entry(cur, struct btrfs_ordered_sum, list); list_del(&sum->list); kfree(sum); } |
6352b91da Btrfs: use a slab... |
556 |
kmem_cache_free(btrfs_ordered_extent_cache, entry); |
ba1da2f44 Btrfs: Don't pin ... |
557 |
} |
dc17ff8f1 Btrfs: Add data=o... |
558 |
} |
cee36a03e Rework btrfs_drop... |
559 |
|
eb84ae039 Btrfs: Cleanup an... |
560 561 |
/* * remove an ordered extent from the tree. No references are dropped |
5fd020435 Btrfs: finish ord... |
562 |
* and waiters are woken up. |
eb84ae039 Btrfs: Cleanup an... |
563 |
*/ |
5fd020435 Btrfs: finish ord... |
564 565 |
void btrfs_remove_ordered_extent(struct inode *inode, struct btrfs_ordered_extent *entry) |
cee36a03e Rework btrfs_drop... |
566 |
{ |
0b246afa6 btrfs: root->fs_i... |
567 |
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
e6dcd2dc9 Btrfs: New data=o... |
568 |
struct btrfs_ordered_inode_tree *tree; |
287a0ab91 Btrfs: kill max_e... |
569 |
struct btrfs_root *root = BTRFS_I(inode)->root; |
cee36a03e Rework btrfs_drop... |
570 |
struct rb_node *node; |
161c3549b Btrfs: change how... |
571 |
bool dec_pending_ordered = false; |
cee36a03e Rework btrfs_drop... |
572 |
|
e6dcd2dc9 Btrfs: New data=o... |
573 |
tree = &BTRFS_I(inode)->ordered_tree; |
5fd020435 Btrfs: finish ord... |
574 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
575 |
node = &entry->rb_node; |
cee36a03e Rework btrfs_drop... |
576 |
rb_erase(node, &tree->tree); |
61de718fc Btrfs: fix memory... |
577 |
RB_CLEAR_NODE(node); |
1b8e7e45e Btrfs: avoid unne... |
578 579 |
if (tree->last == node) tree->last = NULL; |
e6dcd2dc9 Btrfs: New data=o... |
580 |
set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); |
161c3549b Btrfs: change how... |
581 582 |
if (test_and_clear_bit(BTRFS_ORDERED_PENDING, &entry->flags)) dec_pending_ordered = true; |
5fd020435 Btrfs: finish ord... |
583 |
spin_unlock_irq(&tree->lock); |
3eaa28852 Btrfs: Fix the de... |
584 |
|
161c3549b Btrfs: change how... |
585 586 587 588 589 590 591 592 593 594 595 596 597 |
/* * The current running transaction is waiting on us, we need to let it * know that we're complete and wake it up. */ if (dec_pending_ordered) { struct btrfs_transaction *trans; /* * The checks for trans are just a formality, it should be set, * but if it isn't we don't want to deref/assert under the spin * lock, so be nice and check if trans is set, but ASSERT() so * if it isn't set a developer will notice. */ |
0b246afa6 btrfs: root->fs_i... |
598 599 |
spin_lock(&fs_info->trans_lock); trans = fs_info->running_transaction; |
161c3549b Btrfs: change how... |
600 |
if (trans) |
9b64f57dd btrfs: convert bt... |
601 |
refcount_inc(&trans->use_count); |
0b246afa6 btrfs: root->fs_i... |
602 |
spin_unlock(&fs_info->trans_lock); |
161c3549b Btrfs: change how... |
603 604 605 606 607 608 609 610 |
ASSERT(trans); if (trans) { if (atomic_dec_and_test(&trans->pending_ordered)) wake_up(&trans->pending_wait); btrfs_put_transaction(trans); } } |
199c2a9c3 Btrfs: introduce ... |
611 |
spin_lock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
612 |
list_del_init(&entry->root_extent_list); |
199c2a9c3 Btrfs: introduce ... |
613 |
root->nr_ordered_extents--; |
5a3f23d51 Btrfs: add extra ... |
614 |
|
1abe9b8a1 Btrfs: add initia... |
615 |
trace_btrfs_ordered_extent_remove(inode, entry); |
199c2a9c3 Btrfs: introduce ... |
616 |
if (!root->nr_ordered_extents) { |
0b246afa6 btrfs: root->fs_i... |
617 |
spin_lock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
618 619 |
BUG_ON(list_empty(&root->ordered_root)); list_del_init(&root->ordered_root); |
0b246afa6 btrfs: root->fs_i... |
620 |
spin_unlock(&fs_info->ordered_root_lock); |
199c2a9c3 Btrfs: introduce ... |
621 622 |
} spin_unlock(&root->ordered_extent_lock); |
e6dcd2dc9 Btrfs: New data=o... |
623 |
wake_up(&entry->wait); |
cee36a03e Rework btrfs_drop... |
624 |
} |
d458b0540 btrfs: Cleanup th... |
625 |
static void btrfs_run_ordered_extent_work(struct btrfs_work *work) |
9afab8820 Btrfs: make order... |
626 627 628 629 630 631 632 |
{ 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... |
633 634 635 636 |
/* * wait for all the ordered extents in a root. This is done when balancing * space between drives. */ |
6374e57ad btrfs: fix intege... |
637 |
u64 btrfs_wait_ordered_extents(struct btrfs_root *root, u64 nr, |
578def7c5 Btrfs: don't wait... |
638 |
const u64 range_start, const u64 range_len) |
3eaa28852 Btrfs: Fix the de... |
639 |
{ |
0b246afa6 btrfs: root->fs_i... |
640 |
struct btrfs_fs_info *fs_info = root->fs_info; |
578def7c5 Btrfs: don't wait... |
641 642 643 |
LIST_HEAD(splice); LIST_HEAD(skipped); LIST_HEAD(works); |
9afab8820 Btrfs: make order... |
644 |
struct btrfs_ordered_extent *ordered, *next; |
6374e57ad btrfs: fix intege... |
645 |
u64 count = 0; |
578def7c5 Btrfs: don't wait... |
646 |
const u64 range_end = range_start + range_len; |
3eaa28852 Btrfs: Fix the de... |
647 |
|
31f3d255c Btrfs: split the ... |
648 |
mutex_lock(&root->ordered_extent_mutex); |
199c2a9c3 Btrfs: introduce ... |
649 650 |
spin_lock(&root->ordered_extent_lock); list_splice_init(&root->ordered_extents, &splice); |
b02441999 Btrfs: don't wait... |
651 |
while (!list_empty(&splice) && nr) { |
199c2a9c3 Btrfs: introduce ... |
652 653 |
ordered = list_first_entry(&splice, struct btrfs_ordered_extent, root_extent_list); |
578def7c5 Btrfs: don't wait... |
654 655 656 657 658 659 660 |
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 ... |
661 662 |
list_move_tail(&ordered->root_extent_list, &root->ordered_extents); |
e76edab7f btrfs: convert bt... |
663 |
refcount_inc(&ordered->refs); |
199c2a9c3 Btrfs: introduce ... |
664 |
spin_unlock(&root->ordered_extent_lock); |
3eaa28852 Btrfs: Fix the de... |
665 |
|
a44903abe btrfs: Replace fs... |
666 |
btrfs_init_work(&ordered->flush_work, |
9e0af2376 Btrfs: fix task h... |
667 |
btrfs_flush_delalloc_helper, |
a44903abe btrfs: Replace fs... |
668 |
btrfs_run_ordered_extent_work, NULL, NULL); |
199c2a9c3 Btrfs: introduce ... |
669 |
list_add_tail(&ordered->work_list, &works); |
0b246afa6 btrfs: root->fs_i... |
670 |
btrfs_queue_work(fs_info->flush_workers, &ordered->flush_work); |
3eaa28852 Btrfs: Fix the de... |
671 |
|
9afab8820 Btrfs: make order... |
672 |
cond_resched(); |
199c2a9c3 Btrfs: introduce ... |
673 |
spin_lock(&root->ordered_extent_lock); |
6374e57ad btrfs: fix intege... |
674 |
if (nr != U64_MAX) |
b02441999 Btrfs: don't wait... |
675 676 |
nr--; count++; |
3eaa28852 Btrfs: Fix the de... |
677 |
} |
578def7c5 Btrfs: don't wait... |
678 |
list_splice_tail(&skipped, &root->ordered_extents); |
b02441999 Btrfs: don't wait... |
679 |
list_splice_tail(&splice, &root->ordered_extents); |
199c2a9c3 Btrfs: introduce ... |
680 |
spin_unlock(&root->ordered_extent_lock); |
9afab8820 Btrfs: make order... |
681 682 683 684 |
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... |
685 |
btrfs_put_ordered_extent(ordered); |
9afab8820 Btrfs: make order... |
686 687 |
cond_resched(); } |
31f3d255c Btrfs: split the ... |
688 |
mutex_unlock(&root->ordered_extent_mutex); |
b02441999 Btrfs: don't wait... |
689 690 |
return count; |
3eaa28852 Btrfs: Fix the de... |
691 |
} |
6374e57ad btrfs: fix intege... |
692 693 |
u64 btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, u64 nr, const u64 range_start, const u64 range_len) |
199c2a9c3 Btrfs: introduce ... |
694 695 696 |
{ struct btrfs_root *root; struct list_head splice; |
6374e57ad btrfs: fix intege... |
697 698 |
u64 total_done = 0; u64 done; |
199c2a9c3 Btrfs: introduce ... |
699 700 |
INIT_LIST_HEAD(&splice); |
8b9d83cd6 Btrfs: fix early ... |
701 |
mutex_lock(&fs_info->ordered_operations_mutex); |
199c2a9c3 Btrfs: introduce ... |
702 703 |
spin_lock(&fs_info->ordered_root_lock); list_splice_init(&fs_info->ordered_roots, &splice); |
b02441999 Btrfs: don't wait... |
704 |
while (!list_empty(&splice) && nr) { |
199c2a9c3 Btrfs: introduce ... |
705 706 707 708 709 710 711 |
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... |
712 713 |
done = btrfs_wait_ordered_extents(root, nr, range_start, range_len); |
199c2a9c3 Btrfs: introduce ... |
714 |
btrfs_put_fs_root(root); |
f0e9b7d64 Btrfs: fix race s... |
715 |
total_done += done; |
199c2a9c3 Btrfs: introduce ... |
716 717 |
spin_lock(&fs_info->ordered_root_lock); |
6374e57ad btrfs: fix intege... |
718 |
if (nr != U64_MAX) { |
b02441999 Btrfs: don't wait... |
719 |
nr -= done; |
b02441999 Btrfs: don't wait... |
720 |
} |
199c2a9c3 Btrfs: introduce ... |
721 |
} |
931aa8779 Btrfs: fix list d... |
722 |
list_splice_tail(&splice, &fs_info->ordered_roots); |
199c2a9c3 Btrfs: introduce ... |
723 |
spin_unlock(&fs_info->ordered_root_lock); |
8b9d83cd6 Btrfs: fix early ... |
724 |
mutex_unlock(&fs_info->ordered_operations_mutex); |
f0e9b7d64 Btrfs: fix race s... |
725 726 |
return total_done; |
199c2a9c3 Btrfs: introduce ... |
727 |
} |
eb84ae039 Btrfs: Cleanup an... |
728 729 730 731 732 733 734 735 736 737 |
/* * 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... |
738 739 740 |
{ u64 start = entry->file_offset; u64 end = start + entry->len - 1; |
e1b81e676 btrfs delete orde... |
741 |
|
1abe9b8a1 Btrfs: add initia... |
742 |
trace_btrfs_ordered_extent_start(inode, entry); |
eb84ae039 Btrfs: Cleanup an... |
743 744 745 |
/* * 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... |
746 |
* for the flusher thread to find them |
eb84ae039 Btrfs: Cleanup an... |
747 |
*/ |
4b46fce23 Btrfs: add basic ... |
748 749 |
if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) filemap_fdatawrite_range(inode->i_mapping, start, end); |
c8b978188 Btrfs: Add zlib c... |
750 |
if (wait) { |
e6dcd2dc9 Btrfs: New data=o... |
751 752 |
wait_event(entry->wait, test_bit(BTRFS_ORDERED_COMPLETE, &entry->flags)); |
c8b978188 Btrfs: Add zlib c... |
753 |
} |
e6dcd2dc9 Btrfs: New data=o... |
754 |
} |
cee36a03e Rework btrfs_drop... |
755 |
|
eb84ae039 Btrfs: Cleanup an... |
756 757 758 |
/* * Used to wait on ordered extents across a large range of bytes. */ |
0ef8b7260 Btrfs: return an ... |
759 |
int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) |
e6dcd2dc9 Btrfs: New data=o... |
760 |
{ |
0ef8b7260 Btrfs: return an ... |
761 |
int ret = 0; |
28aeeac1d Btrfs: fix panic ... |
762 |
int ret_wb = 0; |
e6dcd2dc9 Btrfs: New data=o... |
763 |
u64 end; |
e5a2217ef Fix btrfs_wait_or... |
764 |
u64 orig_end; |
e6dcd2dc9 Btrfs: New data=o... |
765 |
struct btrfs_ordered_extent *ordered; |
e5a2217ef Fix btrfs_wait_or... |
766 767 |
if (start + len < start) { |
f421950f8 Btrfs: Fix some d... |
768 |
orig_end = INT_LIMIT(loff_t); |
e5a2217ef Fix btrfs_wait_or... |
769 770 |
} else { orig_end = start + len - 1; |
f421950f8 Btrfs: Fix some d... |
771 772 |
if (orig_end > INT_LIMIT(loff_t)) orig_end = INT_LIMIT(loff_t); |
e5a2217ef Fix btrfs_wait_or... |
773 |
} |
551ebb2d3 Btrfs: remove use... |
774 |
|
e5a2217ef Fix btrfs_wait_or... |
775 776 777 |
/* start IO across the range first to instantiate any delalloc * extents */ |
728404dac Btrfs: add helper... |
778 |
ret = btrfs_fdatawrite_range(inode, start, orig_end); |
0ef8b7260 Btrfs: return an ... |
779 780 |
if (ret) return ret; |
728404dac Btrfs: add helper... |
781 |
|
28aeeac1d Btrfs: fix panic ... |
782 783 784 785 786 787 788 789 |
/* * 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... |
790 |
|
f421950f8 Btrfs: Fix some d... |
791 |
end = orig_end; |
d397712bc Btrfs: Fix checkp... |
792 |
while (1) { |
e6dcd2dc9 Btrfs: New data=o... |
793 |
ordered = btrfs_lookup_first_ordered_extent(inode, end); |
d397712bc Btrfs: Fix checkp... |
794 |
if (!ordered) |
e6dcd2dc9 Btrfs: New data=o... |
795 |
break; |
e5a2217ef Fix btrfs_wait_or... |
796 |
if (ordered->file_offset > orig_end) { |
e6dcd2dc9 Btrfs: New data=o... |
797 798 799 |
btrfs_put_ordered_extent(ordered); break; } |
b52abf1e3 Btrfs: don't wait... |
800 |
if (ordered->file_offset + ordered->len <= start) { |
e6dcd2dc9 Btrfs: New data=o... |
801 802 803 |
btrfs_put_ordered_extent(ordered); break; } |
e5a2217ef Fix btrfs_wait_or... |
804 |
btrfs_start_ordered_extent(inode, ordered, 1); |
e6dcd2dc9 Btrfs: New data=o... |
805 |
end = ordered->file_offset; |
0ef8b7260 Btrfs: return an ... |
806 807 |
if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)) ret = -EIO; |
e6dcd2dc9 Btrfs: New data=o... |
808 |
btrfs_put_ordered_extent(ordered); |
0ef8b7260 Btrfs: return an ... |
809 |
if (ret || end == 0 || end == start) |
e6dcd2dc9 Btrfs: New data=o... |
810 811 812 |
break; end--; } |
28aeeac1d Btrfs: fix panic ... |
813 |
return ret_wb ? ret_wb : ret; |
cee36a03e Rework btrfs_drop... |
814 |
} |
eb84ae039 Btrfs: Cleanup an... |
815 816 817 818 |
/* * 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... |
819 820 821 822 823 824 825 826 |
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... |
827 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
828 829 830 831 832 833 834 835 |
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... |
836 |
refcount_inc(&entry->refs); |
e6dcd2dc9 Btrfs: New data=o... |
837 |
out: |
5fd020435 Btrfs: finish ord... |
838 |
spin_unlock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
839 840 |
return entry; } |
4b46fce23 Btrfs: add basic ... |
841 842 843 |
/* 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... |
844 845 |
struct btrfs_ordered_extent *btrfs_lookup_ordered_range( struct btrfs_inode *inode, u64 file_offset, u64 len) |
4b46fce23 Btrfs: add basic ... |
846 847 848 849 |
{ struct btrfs_ordered_inode_tree *tree; struct rb_node *node; struct btrfs_ordered_extent *entry = NULL; |
a776c6fa1 btrfs: Make btrfs... |
850 |
tree = &inode->ordered_tree; |
5fd020435 Btrfs: finish ord... |
851 |
spin_lock_irq(&tree->lock); |
4b46fce23 Btrfs: add basic ... |
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 |
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... |
875 |
refcount_inc(&entry->refs); |
5fd020435 Btrfs: finish ord... |
876 |
spin_unlock_irq(&tree->lock); |
4b46fce23 Btrfs: add basic ... |
877 878 |
return entry; } |
b659ef027 Btrfs: avoid sync... |
879 880 881 882 883 |
bool btrfs_have_ordered_extents_in_range(struct inode *inode, u64 file_offset, u64 len) { struct btrfs_ordered_extent *oe; |
a776c6fa1 btrfs: Make btrfs... |
884 |
oe = btrfs_lookup_ordered_range(BTRFS_I(inode), file_offset, len); |
b659ef027 Btrfs: avoid sync... |
885 886 887 888 889 890 |
if (oe) { btrfs_put_ordered_extent(oe); return true; } return false; } |
eb84ae039 Btrfs: Cleanup an... |
891 892 893 894 |
/* * lookup and return any extent before 'file_offset'. NULL is returned * if none is found */ |
e6dcd2dc9 Btrfs: New data=o... |
895 |
struct btrfs_ordered_extent * |
d397712bc Btrfs: Fix checkp... |
896 |
btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset) |
e6dcd2dc9 Btrfs: New data=o... |
897 898 899 900 901 902 |
{ 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... |
903 |
spin_lock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
904 905 906 907 908 |
node = tree_search(tree, file_offset); if (!node) goto out; entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
e76edab7f btrfs: convert bt... |
909 |
refcount_inc(&entry->refs); |
e6dcd2dc9 Btrfs: New data=o... |
910 |
out: |
5fd020435 Btrfs: finish ord... |
911 |
spin_unlock_irq(&tree->lock); |
e6dcd2dc9 Btrfs: New data=o... |
912 |
return entry; |
81d7ed29f Btrfs: Throttle f... |
913 |
} |
dbe674a99 Btrfs: Update on ... |
914 |
|
eb84ae039 Btrfs: Cleanup an... |
915 916 917 918 |
/* * 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... |
919 |
int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, |
dbe674a99 Btrfs: Update on ... |
920 921 922 |
struct btrfs_ordered_extent *ordered) { struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
dbe674a99 Btrfs: Update on ... |
923 924 |
u64 disk_i_size; u64 new_i_size; |
c21677545 Btrfs: Fix disk_i... |
925 |
u64 i_size = i_size_read(inode); |
dbe674a99 Btrfs: Update on ... |
926 |
struct rb_node *node; |
c21677545 Btrfs: Fix disk_i... |
927 |
struct rb_node *prev = NULL; |
dbe674a99 Btrfs: Update on ... |
928 |
struct btrfs_ordered_extent *test; |
c21677545 Btrfs: Fix disk_i... |
929 |
int ret = 1; |
c0d2f6104 btrfs: fix disk_i... |
930 |
u64 orig_offset = offset; |
c21677545 Btrfs: Fix disk_i... |
931 |
|
77cef2ec5 Btrfs: allow part... |
932 933 |
spin_lock_irq(&tree->lock); if (ordered) { |
c21677545 Btrfs: Fix disk_i... |
934 |
offset = entry_end(ordered); |
77cef2ec5 Btrfs: allow part... |
935 936 937 938 939 |
if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags)) offset = min(offset, ordered->file_offset + ordered->truncated_len); } else { |
da17066c4 btrfs: pull node/... |
940 |
offset = ALIGN(offset, btrfs_inode_sectorsize(inode)); |
77cef2ec5 Btrfs: allow part... |
941 |
} |
dbe674a99 Btrfs: Update on ... |
942 |
disk_i_size = BTRFS_I(inode)->disk_i_size; |
19fd2df5b Btrfs: fix btrfs_... |
943 944 945 946 947 948 949 950 951 952 953 954 |
/* * 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... |
955 |
BTRFS_I(inode)->disk_i_size = orig_offset; |
c21677545 Btrfs: Fix disk_i... |
956 957 958 |
ret = 0; goto out; } |
dbe674a99 Btrfs: Update on ... |
959 960 961 962 |
/* * 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... |
963 964 965 966 967 968 969 970 971 |
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 ... |
972 |
goto out; |
dbe674a99 Btrfs: Update on ... |
973 974 |
/* |
dbe674a99 Btrfs: Update on ... |
975 976 977 978 |
* 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... |
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 |
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... |
994 |
for (; node; node = rb_prev(node)) { |
dbe674a99 Btrfs: Update on ... |
995 |
test = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
5fd020435 Btrfs: finish ord... |
996 |
|
bb7ab3b92 btrfs: Fix misspe... |
997 |
/* We treat this entry as if it doesn't exist */ |
5fd020435 Btrfs: finish ord... |
998 999 |
if (test_bit(BTRFS_ORDERED_UPDATED_ISIZE, &test->flags)) continue; |
62c821a8e Btrfs: clean up b... |
1000 1001 |
if (entry_end(test) <= disk_i_size) |
dbe674a99 Btrfs: Update on ... |
1002 |
break; |
c21677545 Btrfs: Fix disk_i... |
1003 |
if (test->file_offset >= i_size) |
dbe674a99 Btrfs: Update on ... |
1004 |
break; |
62c821a8e Btrfs: clean up b... |
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 |
/* * 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 ... |
1016 |
} |
b9a8cc5be Btrfs: fix file e... |
1017 |
new_i_size = min_t(u64, offset, i_size); |
dbe674a99 Btrfs: Update on ... |
1018 1019 |
/* |
b9a8cc5be Btrfs: fix file e... |
1020 1021 |
* Some ordered extents may completed before the current one, and * we hold the real i_size in ->outstanding_isize. |
dbe674a99 Btrfs: Update on ... |
1022 |
*/ |
b9a8cc5be Btrfs: fix file e... |
1023 1024 |
if (ordered && ordered->outstanding_isize > new_i_size) new_i_size = min_t(u64, ordered->outstanding_isize, i_size); |
dbe674a99 Btrfs: Update on ... |
1025 |
BTRFS_I(inode)->disk_i_size = new_i_size; |
c21677545 Btrfs: Fix disk_i... |
1026 |
ret = 0; |
dbe674a99 Btrfs: Update on ... |
1027 |
out: |
c21677545 Btrfs: Fix disk_i... |
1028 |
/* |
5fd020435 Btrfs: finish ord... |
1029 1030 1031 1032 1033 |
* 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... |
1034 1035 |
*/ if (ordered) |
5fd020435 Btrfs: finish ord... |
1036 1037 |
set_bit(BTRFS_ORDERED_UPDATED_ISIZE, &ordered->flags); spin_unlock_irq(&tree->lock); |
c21677545 Btrfs: Fix disk_i... |
1038 |
return ret; |
dbe674a99 Btrfs: Update on ... |
1039 |
} |
ba1da2f44 Btrfs: Don't pin ... |
1040 |
|
eb84ae039 Btrfs: Cleanup an... |
1041 1042 1043 1044 1045 |
/* * 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 ... |
1046 |
int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, |
e4100d987 Btrfs: improve th... |
1047 |
u32 *sum, int len) |
ba1da2f44 Btrfs: Don't pin ... |
1048 1049 |
{ struct btrfs_ordered_sum *ordered_sum; |
ba1da2f44 Btrfs: Don't pin ... |
1050 1051 |
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
3edf7d33f Btrfs: Handle dat... |
1052 1053 |
unsigned long num_sectors; unsigned long i; |
da17066c4 btrfs: pull node/... |
1054 |
u32 sectorsize = btrfs_inode_sectorsize(inode); |
e4100d987 Btrfs: improve th... |
1055 |
int index = 0; |
ba1da2f44 Btrfs: Don't pin ... |
1056 1057 1058 |
ordered = btrfs_lookup_ordered_extent(inode, offset); if (!ordered) |
e4100d987 Btrfs: improve th... |
1059 |
return 0; |
ba1da2f44 Btrfs: Don't pin ... |
1060 |
|
5fd020435 Btrfs: finish ord... |
1061 |
spin_lock_irq(&tree->lock); |
c6e308713 Btrfs: simplify i... |
1062 |
list_for_each_entry_reverse(ordered_sum, &ordered->list, list) { |
e4100d987 Btrfs: improve th... |
1063 1064 1065 1066 |
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... |
1067 1068 |
num_sectors = ordered_sum->len >> inode->i_sb->s_blocksize_bits; |
f51a4a182 Btrfs: remove btr... |
1069 1070 1071 1072 1073 1074 1075 1076 |
num_sectors = min_t(int, len - index, num_sectors - i); memcpy(sum + index, ordered_sum->sums + i, num_sectors); index += (int)num_sectors; if (index == len) goto out; disk_bytenr += num_sectors * sectorsize; |
ba1da2f44 Btrfs: Don't pin ... |
1077 1078 1079 |
} } out: |
5fd020435 Btrfs: finish ord... |
1080 |
spin_unlock_irq(&tree->lock); |
89642229a Btrfs: Search dat... |
1081 |
btrfs_put_ordered_extent(ordered); |
e4100d987 Btrfs: improve th... |
1082 |
return index; |
ba1da2f44 Btrfs: Don't pin ... |
1083 |
} |
6352b91da Btrfs: use a slab... |
1084 1085 1086 1087 |
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... |
1088 |
SLAB_MEM_SPREAD, |
6352b91da Btrfs: use a slab... |
1089 1090 1091 |
NULL); if (!btrfs_ordered_extent_cache) return -ENOMEM; |
25287e0a1 Btrfs: make order... |
1092 |
|
6352b91da Btrfs: use a slab... |
1093 1094 1095 1096 1097 |
return 0; } void ordered_data_exit(void) { |
5598e9005 btrfs: drop null ... |
1098 |
kmem_cache_destroy(btrfs_ordered_extent_cache); |
6352b91da Btrfs: use a slab... |
1099 |
} |