Blame view
fs/btrfs/transaction.c
36.3 KB
6cbd55707 Btrfs: add GPLv2 |
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. */ |
79154b1b5 Btrfs: transactio... |
18 |
#include <linux/fs.h> |
5a0e3ad6a include cleanup: ... |
19 |
#include <linux/slab.h> |
340887809 Btrfs: i386 fixes... |
20 |
#include <linux/sched.h> |
d3c2fdcf7 Btrfs: Use balanc... |
21 |
#include <linux/writeback.h> |
5f39d397d Btrfs: Create ext... |
22 |
#include <linux/pagemap.h> |
5f2cc086c Btrfs: Avoid unpl... |
23 |
#include <linux/blkdev.h> |
79154b1b5 Btrfs: transactio... |
24 25 26 |
#include "ctree.h" #include "disk-io.h" #include "transaction.h" |
925baeddc Btrfs: Start btre... |
27 |
#include "locking.h" |
e02119d5a Btrfs: Add a writ... |
28 |
#include "tree-log.h" |
581bb0509 Btrfs: Cache free... |
29 |
#include "inode-map.h" |
79154b1b5 Btrfs: transactio... |
30 |
|
0f7d52f44 Btrfs: groundwork... |
31 |
#define BTRFS_ROOT_TRANS_TAG 0 |
80b6794d1 Btrfs: Lower stac... |
32 |
static noinline void put_transaction(struct btrfs_transaction *transaction) |
79154b1b5 Btrfs: transactio... |
33 |
{ |
13c5a93e7 Btrfs: avoid taki... |
34 35 |
WARN_ON(atomic_read(&transaction->use_count) == 0); if (atomic_dec_and_test(&transaction->use_count)) { |
a4abeea41 Btrfs: kill trans... |
36 |
BUG_ON(!list_empty(&transaction->list)); |
2c90e5d65 Btrfs: still corr... |
37 38 |
memset(transaction, 0, sizeof(*transaction)); kmem_cache_free(btrfs_transaction_cachep, transaction); |
78fae27eb Btrfs: leak fixes... |
39 |
} |
79154b1b5 Btrfs: transactio... |
40 |
} |
817d52f8d Btrfs: async bloc... |
41 42 |
static noinline void switch_commit_root(struct btrfs_root *root) { |
817d52f8d Btrfs: async bloc... |
43 44 |
free_extent_buffer(root->commit_root); root->commit_root = btrfs_root_node(root); |
817d52f8d Btrfs: async bloc... |
45 |
} |
d352ac681 Btrfs: add and im... |
46 47 48 |
/* * either allocate a new transaction or hop into the existing one */ |
a4abeea41 Btrfs: kill trans... |
49 |
static noinline int join_transaction(struct btrfs_root *root, int nofail) |
79154b1b5 Btrfs: transactio... |
50 51 |
{ struct btrfs_transaction *cur_trans; |
a4abeea41 Btrfs: kill trans... |
52 53 |
spin_lock(&root->fs_info->trans_lock); |
d43317dcd Btrfs: fix race d... |
54 |
loop: |
a4abeea41 Btrfs: kill trans... |
55 56 57 58 59 60 |
if (root->fs_info->trans_no_join) { if (!nofail) { spin_unlock(&root->fs_info->trans_lock); return -EBUSY; } } |
79154b1b5 Btrfs: transactio... |
61 |
cur_trans = root->fs_info->running_transaction; |
a4abeea41 Btrfs: kill trans... |
62 63 |
if (cur_trans) { atomic_inc(&cur_trans->use_count); |
13c5a93e7 Btrfs: avoid taki... |
64 |
atomic_inc(&cur_trans->num_writers); |
15ee9bc7e Btrfs: delay comm... |
65 |
cur_trans->num_joined++; |
a4abeea41 Btrfs: kill trans... |
66 67 |
spin_unlock(&root->fs_info->trans_lock); return 0; |
79154b1b5 Btrfs: transactio... |
68 |
} |
a4abeea41 Btrfs: kill trans... |
69 70 71 72 73 |
spin_unlock(&root->fs_info->trans_lock); cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); if (!cur_trans) return -ENOMEM; |
d43317dcd Btrfs: fix race d... |
74 |
|
a4abeea41 Btrfs: kill trans... |
75 76 |
spin_lock(&root->fs_info->trans_lock); if (root->fs_info->running_transaction) { |
d43317dcd Btrfs: fix race d... |
77 78 79 80 |
/* * someone started a transaction after we unlocked. Make sure * to redo the trans_no_join checks above */ |
a4abeea41 Btrfs: kill trans... |
81 82 |
kmem_cache_free(btrfs_transaction_cachep, cur_trans); cur_trans = root->fs_info->running_transaction; |
d43317dcd Btrfs: fix race d... |
83 |
goto loop; |
79154b1b5 Btrfs: transactio... |
84 |
} |
d43317dcd Btrfs: fix race d... |
85 |
|
a4abeea41 Btrfs: kill trans... |
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
atomic_set(&cur_trans->num_writers, 1); cur_trans->num_joined = 0; init_waitqueue_head(&cur_trans->writer_wait); init_waitqueue_head(&cur_trans->commit_wait); cur_trans->in_commit = 0; cur_trans->blocked = 0; /* * One for this trans handle, one so it will live on until we * commit the transaction. */ atomic_set(&cur_trans->use_count, 2); cur_trans->commit_done = 0; cur_trans->start_time = get_seconds(); cur_trans->delayed_refs.root = RB_ROOT; cur_trans->delayed_refs.num_entries = 0; cur_trans->delayed_refs.num_heads_ready = 0; cur_trans->delayed_refs.num_heads = 0; cur_trans->delayed_refs.flushing = 0; cur_trans->delayed_refs.run_delayed_start = 0; spin_lock_init(&cur_trans->commit_lock); spin_lock_init(&cur_trans->delayed_refs.lock); INIT_LIST_HEAD(&cur_trans->pending_snapshots); list_add_tail(&cur_trans->list, &root->fs_info->trans_list); extent_io_tree_init(&cur_trans->dirty_pages, |
ff5714cca Merge branch 'for... |
112 |
root->fs_info->btree_inode->i_mapping); |
a4abeea41 Btrfs: kill trans... |
113 114 115 116 |
root->fs_info->generation++; cur_trans->transid = root->fs_info->generation; root->fs_info->running_transaction = cur_trans; spin_unlock(&root->fs_info->trans_lock); |
15ee9bc7e Btrfs: delay comm... |
117 |
|
79154b1b5 Btrfs: transactio... |
118 119 |
return 0; } |
d352ac681 Btrfs: add and im... |
120 |
/* |
d397712bc Btrfs: Fix checkp... |
121 122 123 124 |
* this does all the record keeping required to make sure that a reference * counted root is properly recorded in a given transaction. This is required * to make sure the old root from before we joined the transaction is deleted * when the transaction commits |
d352ac681 Btrfs: add and im... |
125 |
*/ |
7585717f3 Btrfs: fix reloca... |
126 |
static int record_root_in_trans(struct btrfs_trans_handle *trans, |
a4abeea41 Btrfs: kill trans... |
127 |
struct btrfs_root *root) |
6702ed490 Btrfs: Add run ti... |
128 |
{ |
5d4f98a28 Btrfs: Mixed back... |
129 |
if (root->ref_cows && root->last_trans < trans->transid) { |
6702ed490 Btrfs: Add run ti... |
130 |
WARN_ON(root == root->fs_info->extent_root); |
5d4f98a28 Btrfs: Mixed back... |
131 |
WARN_ON(root->commit_root != root->node); |
7585717f3 Btrfs: fix reloca... |
132 133 134 135 136 137 138 139 140 141 142 |
/* * see below for in_trans_setup usage rules * we have the reloc mutex held now, so there * is only one writer in this function */ root->in_trans_setup = 1; /* make sure readers find in_trans_setup before * they find our root->last_trans update */ smp_wmb(); |
a4abeea41 Btrfs: kill trans... |
143 144 145 146 147 |
spin_lock(&root->fs_info->fs_roots_radix_lock); if (root->last_trans == trans->transid) { spin_unlock(&root->fs_info->fs_roots_radix_lock); return 0; } |
5d4f98a28 Btrfs: Mixed back... |
148 149 150 |
radix_tree_tag_set(&root->fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); |
a4abeea41 Btrfs: kill trans... |
151 |
spin_unlock(&root->fs_info->fs_roots_radix_lock); |
7585717f3 Btrfs: fix reloca... |
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
root->last_trans = trans->transid; /* this is pretty tricky. We don't want to * take the relocation lock in btrfs_record_root_in_trans * unless we're really doing the first setup for this root in * this transaction. * * Normally we'd use root->last_trans as a flag to decide * if we want to take the expensive mutex. * * But, we have to set root->last_trans before we * init the relocation root, otherwise, we trip over warnings * in ctree.c. The solution used here is to flag ourselves * with root->in_trans_setup. When this is 1, we're still * fixing up the reloc trees and everyone must wait. * * When this is zero, they can trust root->last_trans and fly * through btrfs_record_root_in_trans without having to take the * lock. smp_wmb() makes sure that all the writes above are * done before we pop in the zero below */ |
5d4f98a28 Btrfs: Mixed back... |
173 |
btrfs_init_reloc_root(trans, root); |
7585717f3 Btrfs: fix reloca... |
174 175 |
smp_wmb(); root->in_trans_setup = 0; |
5d4f98a28 Btrfs: Mixed back... |
176 177 178 |
} return 0; } |
bcc63abbf Btrfs: implement ... |
179 |
|
7585717f3 Btrfs: fix reloca... |
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root) { if (!root->ref_cows) return 0; /* * see record_root_in_trans for comments about in_trans_setup usage * and barriers */ smp_rmb(); if (root->last_trans == trans->transid && !root->in_trans_setup) return 0; mutex_lock(&root->fs_info->reloc_mutex); record_root_in_trans(trans, root); mutex_unlock(&root->fs_info->reloc_mutex); return 0; } |
d352ac681 Btrfs: add and im... |
202 203 204 205 |
/* wait for commit against the current transaction to become unblocked * when this is done, it is safe to start a new transaction, but the current * transaction might not be fully on disk. */ |
37d1aeee3 Btrfs: Throttle t... |
206 |
static void wait_current_trans(struct btrfs_root *root) |
79154b1b5 Btrfs: transactio... |
207 |
{ |
f92957493 btrfs_start_trans... |
208 |
struct btrfs_transaction *cur_trans; |
79154b1b5 Btrfs: transactio... |
209 |
|
a4abeea41 Btrfs: kill trans... |
210 |
spin_lock(&root->fs_info->trans_lock); |
f92957493 btrfs_start_trans... |
211 |
cur_trans = root->fs_info->running_transaction; |
37d1aeee3 Btrfs: Throttle t... |
212 |
if (cur_trans && cur_trans->blocked) { |
13c5a93e7 Btrfs: avoid taki... |
213 |
atomic_inc(&cur_trans->use_count); |
a4abeea41 Btrfs: kill trans... |
214 |
spin_unlock(&root->fs_info->trans_lock); |
72d63ed64 Btrfs: use wait_e... |
215 216 217 |
wait_event(root->fs_info->transaction_wait, !cur_trans->blocked); |
f92957493 btrfs_start_trans... |
218 |
put_transaction(cur_trans); |
a4abeea41 Btrfs: kill trans... |
219 220 |
} else { spin_unlock(&root->fs_info->trans_lock); |
f92957493 btrfs_start_trans... |
221 |
} |
37d1aeee3 Btrfs: Throttle t... |
222 |
} |
249ac1e55 Btrfs: cleanup tr... |
223 224 225 226 |
enum btrfs_trans_type { TRANS_START, TRANS_JOIN, TRANS_USERSPACE, |
0af3d00ba Btrfs: create spe... |
227 |
TRANS_JOIN_NOLOCK, |
249ac1e55 Btrfs: cleanup tr... |
228 |
}; |
a22285a6a Btrfs: Integrate ... |
229 230 |
static int may_wait_transaction(struct btrfs_root *root, int type) { |
a4abeea41 Btrfs: kill trans... |
231 232 233 234 235 236 237 238 |
if (root->fs_info->log_root_recovering) return 0; if (type == TRANS_USERSPACE) return 1; if (type == TRANS_START && !atomic_read(&root->fs_info->open_ioctl_trans)) |
a22285a6a Btrfs: Integrate ... |
239 |
return 1; |
a4abeea41 Btrfs: kill trans... |
240 |
|
a22285a6a Btrfs: Integrate ... |
241 242 |
return 0; } |
e02119d5a Btrfs: Add a writ... |
243 |
static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, |
a22285a6a Btrfs: Integrate ... |
244 |
u64 num_items, int type) |
37d1aeee3 Btrfs: Throttle t... |
245 |
{ |
a22285a6a Btrfs: Integrate ... |
246 247 |
struct btrfs_trans_handle *h; struct btrfs_transaction *cur_trans; |
b5009945b Btrfs: do transac... |
248 |
u64 num_bytes = 0; |
37d1aeee3 Btrfs: Throttle t... |
249 |
int ret; |
acce952b0 Btrfs: forced rea... |
250 251 252 |
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) return ERR_PTR(-EROFS); |
2a1eb4614 Btrfs: if we've a... |
253 254 255 256 257 258 259 260 261 |
if (current->journal_info) { WARN_ON(type != TRANS_JOIN && type != TRANS_JOIN_NOLOCK); h = current->journal_info; h->use_count++; h->orig_rsv = h->block_rsv; h->block_rsv = NULL; goto got_it; } |
b5009945b Btrfs: do transac... |
262 263 264 265 266 267 268 |
/* * Do the reservation before we join the transaction so we can do all * the appropriate flushing if need be. */ if (num_items > 0 && root != root->fs_info->chunk_root) { num_bytes = btrfs_calc_trans_metadata_size(root, num_items); |
4a92b1b8d Btrfs: stop passi... |
269 |
ret = btrfs_block_rsv_add(root, |
b5009945b Btrfs: do transac... |
270 271 272 273 274 |
&root->fs_info->trans_block_rsv, num_bytes); if (ret) return ERR_PTR(ret); } |
a22285a6a Btrfs: Integrate ... |
275 276 277 278 |
again: h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); if (!h) return ERR_PTR(-ENOMEM); |
37d1aeee3 Btrfs: Throttle t... |
279 |
|
a22285a6a Btrfs: Integrate ... |
280 |
if (may_wait_transaction(root, type)) |
37d1aeee3 Btrfs: Throttle t... |
281 |
wait_current_trans(root); |
a22285a6a Btrfs: Integrate ... |
282 |
|
a4abeea41 Btrfs: kill trans... |
283 284 285 286 287 |
do { ret = join_transaction(root, type == TRANS_JOIN_NOLOCK); if (ret == -EBUSY) wait_current_trans(root); } while (ret == -EBUSY); |
db5b493ac Btrfs: cleanup so... |
288 |
if (ret < 0) { |
6e8df2ae8 Btrfs: fix memory... |
289 |
kmem_cache_free(btrfs_trans_handle_cachep, h); |
db5b493ac Btrfs: cleanup so... |
290 291 |
return ERR_PTR(ret); } |
0f7d52f44 Btrfs: groundwork... |
292 |
|
a22285a6a Btrfs: Integrate ... |
293 |
cur_trans = root->fs_info->running_transaction; |
a22285a6a Btrfs: Integrate ... |
294 295 296 |
h->transid = cur_trans->transid; h->transaction = cur_trans; |
79154b1b5 Btrfs: transactio... |
297 |
h->blocks_used = 0; |
a22285a6a Btrfs: Integrate ... |
298 |
h->bytes_reserved = 0; |
56bec294d Btrfs: do extent ... |
299 |
h->delayed_ref_updates = 0; |
2a1eb4614 Btrfs: if we've a... |
300 |
h->use_count = 1; |
f0486c68e Btrfs: Introduce ... |
301 |
h->block_rsv = NULL; |
2a1eb4614 Btrfs: if we've a... |
302 |
h->orig_rsv = NULL; |
b7ec40d78 Btrfs: reduce sta... |
303 |
|
a22285a6a Btrfs: Integrate ... |
304 305 306 307 308 |
smp_mb(); if (cur_trans->blocked && may_wait_transaction(root, type)) { btrfs_commit_transaction(h, root); goto again; } |
b5009945b Btrfs: do transac... |
309 310 311 |
if (num_bytes) { h->block_rsv = &root->fs_info->trans_block_rsv; h->bytes_reserved = num_bytes; |
a22285a6a Btrfs: Integrate ... |
312 |
} |
9ed74f2db Btrfs: proper -EN... |
313 |
|
2a1eb4614 Btrfs: if we've a... |
314 |
got_it: |
a4abeea41 Btrfs: kill trans... |
315 |
btrfs_record_root_in_trans(h, root); |
a22285a6a Btrfs: Integrate ... |
316 317 318 |
if (!current->journal_info && type != TRANS_USERSPACE) current->journal_info = h; |
79154b1b5 Btrfs: transactio... |
319 320 |
return h; } |
f92957493 btrfs_start_trans... |
321 |
struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |
a22285a6a Btrfs: Integrate ... |
322 |
int num_items) |
f92957493 btrfs_start_trans... |
323 |
{ |
a22285a6a Btrfs: Integrate ... |
324 |
return start_transaction(root, num_items, TRANS_START); |
f92957493 btrfs_start_trans... |
325 |
} |
7a7eaa40a Btrfs: take away ... |
326 |
struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root) |
f92957493 btrfs_start_trans... |
327 |
{ |
a22285a6a Btrfs: Integrate ... |
328 |
return start_transaction(root, 0, TRANS_JOIN); |
f92957493 btrfs_start_trans... |
329 |
} |
7a7eaa40a Btrfs: take away ... |
330 |
struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root) |
0af3d00ba Btrfs: create spe... |
331 332 333 |
{ return start_transaction(root, 0, TRANS_JOIN_NOLOCK); } |
7a7eaa40a Btrfs: take away ... |
334 |
struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root) |
9ca9ee09c Btrfs: fix ioctl-... |
335 |
{ |
7a7eaa40a Btrfs: take away ... |
336 |
return start_transaction(root, 0, TRANS_USERSPACE); |
9ca9ee09c Btrfs: fix ioctl-... |
337 |
} |
d352ac681 Btrfs: add and im... |
338 |
/* wait for a transaction commit to be fully complete */ |
b9c8300c2 Btrfs: remove a B... |
339 |
static noinline void wait_for_commit(struct btrfs_root *root, |
89ce8a63d Add btrfs_end_tra... |
340 341 |
struct btrfs_transaction *commit) { |
72d63ed64 Btrfs: use wait_e... |
342 |
wait_event(commit->commit_wait, commit->commit_done); |
89ce8a63d Add btrfs_end_tra... |
343 |
} |
462045928 Btrfs: add START_... |
344 345 346 347 |
int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) { struct btrfs_transaction *cur_trans = NULL, *t; int ret; |
462045928 Btrfs: add START_... |
348 349 350 |
ret = 0; if (transid) { if (transid <= root->fs_info->last_trans_committed) |
a4abeea41 Btrfs: kill trans... |
351 |
goto out; |
462045928 Btrfs: add START_... |
352 353 |
/* find specified transaction */ |
a4abeea41 Btrfs: kill trans... |
354 |
spin_lock(&root->fs_info->trans_lock); |
462045928 Btrfs: add START_... |
355 356 357 |
list_for_each_entry(t, &root->fs_info->trans_list, list) { if (t->transid == transid) { cur_trans = t; |
a4abeea41 Btrfs: kill trans... |
358 |
atomic_inc(&cur_trans->use_count); |
462045928 Btrfs: add START_... |
359 360 361 362 363 |
break; } if (t->transid > transid) break; } |
a4abeea41 Btrfs: kill trans... |
364 |
spin_unlock(&root->fs_info->trans_lock); |
462045928 Btrfs: add START_... |
365 366 |
ret = -EINVAL; if (!cur_trans) |
a4abeea41 Btrfs: kill trans... |
367 |
goto out; /* bad transid */ |
462045928 Btrfs: add START_... |
368 369 |
} else { /* find newest transaction that is committing | committed */ |
a4abeea41 Btrfs: kill trans... |
370 |
spin_lock(&root->fs_info->trans_lock); |
462045928 Btrfs: add START_... |
371 372 373 374 |
list_for_each_entry_reverse(t, &root->fs_info->trans_list, list) { if (t->in_commit) { if (t->commit_done) |
3473f3c06 Btrfs: unlock the... |
375 |
break; |
462045928 Btrfs: add START_... |
376 |
cur_trans = t; |
a4abeea41 Btrfs: kill trans... |
377 |
atomic_inc(&cur_trans->use_count); |
462045928 Btrfs: add START_... |
378 379 380 |
break; } } |
a4abeea41 Btrfs: kill trans... |
381 |
spin_unlock(&root->fs_info->trans_lock); |
462045928 Btrfs: add START_... |
382 |
if (!cur_trans) |
a4abeea41 Btrfs: kill trans... |
383 |
goto out; /* nothing committing|committed */ |
462045928 Btrfs: add START_... |
384 |
} |
462045928 Btrfs: add START_... |
385 |
wait_for_commit(root, cur_trans); |
462045928 Btrfs: add START_... |
386 387 |
put_transaction(cur_trans); ret = 0; |
a4abeea41 Btrfs: kill trans... |
388 |
out: |
462045928 Btrfs: add START_... |
389 390 |
return ret; } |
37d1aeee3 Btrfs: Throttle t... |
391 392 |
void btrfs_throttle(struct btrfs_root *root) { |
a4abeea41 Btrfs: kill trans... |
393 |
if (!atomic_read(&root->fs_info->open_ioctl_trans)) |
9ca9ee09c Btrfs: fix ioctl-... |
394 |
wait_current_trans(root); |
37d1aeee3 Btrfs: Throttle t... |
395 |
} |
8929ecfa5 Btrfs: Introduce ... |
396 397 398 399 |
static int should_end_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root) { int ret; |
36ba022ac Btrfs: seperate o... |
400 401 |
ret = btrfs_block_rsv_check(root, &root->fs_info->global_block_rsv, 5); |
8929ecfa5 Btrfs: Introduce ... |
402 403 404 405 406 407 408 |
return ret ? 1 : 0; } int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root) { struct btrfs_transaction *cur_trans = trans->transaction; |
9c8d86db9 Btrfs: make sure ... |
409 |
struct btrfs_block_rsv *rsv = trans->block_rsv; |
8929ecfa5 Btrfs: Introduce ... |
410 |
int updates; |
a4abeea41 Btrfs: kill trans... |
411 |
smp_mb(); |
8929ecfa5 Btrfs: Introduce ... |
412 413 |
if (cur_trans->blocked || cur_trans->delayed_refs.flushing) return 1; |
9c8d86db9 Btrfs: make sure ... |
414 415 416 417 418 |
/* * We need to do this in case we're deleting csums so the global block * rsv get's used instead of the csum block rsv. */ trans->block_rsv = NULL; |
8929ecfa5 Btrfs: Introduce ... |
419 420 421 422 |
updates = trans->delayed_ref_updates; trans->delayed_ref_updates = 0; if (updates) btrfs_run_delayed_refs(trans, root, updates); |
9c8d86db9 Btrfs: make sure ... |
423 |
trans->block_rsv = rsv; |
8929ecfa5 Btrfs: Introduce ... |
424 425 |
return should_end_transaction(trans, root); } |
89ce8a63d Add btrfs_end_tra... |
426 |
static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, |
0af3d00ba Btrfs: create spe... |
427 |
struct btrfs_root *root, int throttle, int lock) |
79154b1b5 Btrfs: transactio... |
428 |
{ |
8929ecfa5 Btrfs: Introduce ... |
429 |
struct btrfs_transaction *cur_trans = trans->transaction; |
ab78c84de Btrfs: Throttle o... |
430 |
struct btrfs_fs_info *info = root->fs_info; |
c3e69d58e Btrfs: process th... |
431 |
int count = 0; |
2a1eb4614 Btrfs: if we've a... |
432 433 434 435 |
if (--trans->use_count) { trans->block_rsv = trans->orig_rsv; return 0; } |
b24e03db0 Btrfs: release tr... |
436 |
btrfs_trans_release_metadata(trans, root); |
4c13d758b Btrfs: use the tr... |
437 |
trans->block_rsv = NULL; |
c3e69d58e Btrfs: process th... |
438 439 440 441 442 443 |
while (count < 4) { unsigned long cur = trans->delayed_ref_updates; trans->delayed_ref_updates = 0; if (cur && trans->transaction->delayed_refs.num_heads_ready > 64) { trans->delayed_ref_updates = 0; |
b7ec40d78 Btrfs: reduce sta... |
444 445 446 447 448 449 450 |
/* * do a full flush if the transaction is trying * to close */ if (trans->transaction->delayed_refs.flushing) cur = 0; |
c3e69d58e Btrfs: process th... |
451 452 453 454 455 |
btrfs_run_delayed_refs(trans, root, cur); } else { break; } count++; |
56bec294d Btrfs: do extent ... |
456 |
} |
a4abeea41 Btrfs: kill trans... |
457 458 |
if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) && should_end_transaction(trans, root)) { |
8929ecfa5 Btrfs: Introduce ... |
459 |
trans->transaction->blocked = 1; |
a4abeea41 Btrfs: kill trans... |
460 461 |
smp_wmb(); } |
8929ecfa5 Btrfs: Introduce ... |
462 |
|
0af3d00ba Btrfs: create spe... |
463 |
if (lock && cur_trans->blocked && !cur_trans->in_commit) { |
81317fded Btrfs: fix deadlo... |
464 465 466 467 468 469 470 |
if (throttle) { /* * We may race with somebody else here so end up having * to call end_transaction on ourselves again, so inc * our use_count. */ trans->use_count++; |
8929ecfa5 Btrfs: Introduce ... |
471 |
return btrfs_commit_transaction(trans, root); |
81317fded Btrfs: fix deadlo... |
472 |
} else { |
8929ecfa5 Btrfs: Introduce ... |
473 |
wake_up_process(info->transaction_kthread); |
81317fded Btrfs: fix deadlo... |
474 |
} |
8929ecfa5 Btrfs: Introduce ... |
475 |
} |
8929ecfa5 Btrfs: Introduce ... |
476 |
WARN_ON(cur_trans != info->running_transaction); |
13c5a93e7 Btrfs: avoid taki... |
477 478 |
WARN_ON(atomic_read(&cur_trans->num_writers) < 1); atomic_dec(&cur_trans->num_writers); |
89ce8a63d Add btrfs_end_tra... |
479 |
|
99d16cbca Btrfs: fix deadlo... |
480 |
smp_mb(); |
79154b1b5 Btrfs: transactio... |
481 482 |
if (waitqueue_active(&cur_trans->writer_wait)) wake_up(&cur_trans->writer_wait); |
79154b1b5 Btrfs: transactio... |
483 |
put_transaction(cur_trans); |
9ed74f2db Btrfs: proper -EN... |
484 485 486 |
if (current->journal_info == trans) current->journal_info = NULL; |
d60255795 Btrfs: corruption... |
487 |
memset(trans, 0, sizeof(*trans)); |
2c90e5d65 Btrfs: still corr... |
488 |
kmem_cache_free(btrfs_trans_handle_cachep, trans); |
ab78c84de Btrfs: Throttle o... |
489 |
|
24bbcf044 Btrfs: Add delaye... |
490 491 |
if (throttle) btrfs_run_delayed_iputs(root); |
79154b1b5 Btrfs: transactio... |
492 493 |
return 0; } |
89ce8a63d Add btrfs_end_tra... |
494 495 496 |
int btrfs_end_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root) { |
16cdcec73 btrfs: implement ... |
497 498 499 500 501 502 |
int ret; ret = __btrfs_end_transaction(trans, root, 0, 1); if (ret) return ret; return 0; |
89ce8a63d Add btrfs_end_tra... |
503 504 505 506 507 |
} int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, struct btrfs_root *root) { |
16cdcec73 btrfs: implement ... |
508 509 510 511 512 513 |
int ret; ret = __btrfs_end_transaction(trans, root, 1, 1); if (ret) return ret; return 0; |
0af3d00ba Btrfs: create spe... |
514 515 516 517 518 |
} int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans, struct btrfs_root *root) { |
16cdcec73 btrfs: implement ... |
519 520 521 522 523 524 525 526 527 528 529 530 |
int ret; ret = __btrfs_end_transaction(trans, root, 0, 0); if (ret) return ret; return 0; } int btrfs_end_transaction_dmeta(struct btrfs_trans_handle *trans, struct btrfs_root *root) { return __btrfs_end_transaction(trans, root, 1, 1); |
89ce8a63d Add btrfs_end_tra... |
531 |
} |
d352ac681 Btrfs: add and im... |
532 533 534 |
/* * when btree blocks are allocated, they have some corresponding bits set for * them in one of two extent_io trees. This is used to make sure all of |
690587d10 Btrfs: streamline... |
535 |
* those extents are sent to disk but does not wait on them |
d352ac681 Btrfs: add and im... |
536 |
*/ |
690587d10 Btrfs: streamline... |
537 |
int btrfs_write_marked_extents(struct btrfs_root *root, |
8cef4e160 Btrfs: Avoid supe... |
538 |
struct extent_io_tree *dirty_pages, int mark) |
79154b1b5 Btrfs: transactio... |
539 |
{ |
777e6bd70 Btrfs: Transactio... |
540 |
int err = 0; |
7c4452b9a Btrfs: smarter tr... |
541 |
int werr = 0; |
1728366ef Btrfs: stop using... |
542 |
struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
777e6bd70 Btrfs: Transactio... |
543 |
u64 start = 0; |
5f39d397d Btrfs: Create ext... |
544 |
u64 end; |
7c4452b9a Btrfs: smarter tr... |
545 |
|
1728366ef Btrfs: stop using... |
546 547 548 549 550 551 552 553 554 |
while (!find_first_extent_bit(dirty_pages, start, &start, &end, mark)) { convert_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT, mark, GFP_NOFS); err = filemap_fdatawrite_range(mapping, start, end); if (err) werr = err; cond_resched(); start = end + 1; |
7c4452b9a Btrfs: smarter tr... |
555 |
} |
690587d10 Btrfs: streamline... |
556 557 558 559 560 561 562 563 564 565 566 567 |
if (err) werr = err; return werr; } /* * when btree blocks are allocated, they have some corresponding bits set for * them in one of two extent_io trees. This is used to make sure all of * those extents are on disk for transaction or log commit. We wait * on all the pages and clear them from the dirty pages state tree */ int btrfs_wait_marked_extents(struct btrfs_root *root, |
8cef4e160 Btrfs: Avoid supe... |
568 |
struct extent_io_tree *dirty_pages, int mark) |
690587d10 Btrfs: streamline... |
569 |
{ |
690587d10 Btrfs: streamline... |
570 571 |
int err = 0; int werr = 0; |
1728366ef Btrfs: stop using... |
572 |
struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
690587d10 Btrfs: streamline... |
573 574 |
u64 start = 0; u64 end; |
777e6bd70 Btrfs: Transactio... |
575 |
|
1728366ef Btrfs: stop using... |
576 577 578 579 580 581 582 583 |
while (!find_first_extent_bit(dirty_pages, start, &start, &end, EXTENT_NEED_WAIT)) { clear_extent_bits(dirty_pages, start, end, EXTENT_NEED_WAIT, GFP_NOFS); err = filemap_fdatawait_range(mapping, start, end); if (err) werr = err; cond_resched(); start = end + 1; |
777e6bd70 Btrfs: Transactio... |
584 |
} |
7c4452b9a Btrfs: smarter tr... |
585 586 587 |
if (err) werr = err; return werr; |
79154b1b5 Btrfs: transactio... |
588 |
} |
690587d10 Btrfs: streamline... |
589 590 591 592 593 594 |
/* * when btree blocks are allocated, they have some corresponding bits set for * them in one of two extent_io trees. This is used to make sure all of * those extents are on disk for transaction or log commit */ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, |
8cef4e160 Btrfs: Avoid supe... |
595 |
struct extent_io_tree *dirty_pages, int mark) |
690587d10 Btrfs: streamline... |
596 597 598 |
{ int ret; int ret2; |
8cef4e160 Btrfs: Avoid supe... |
599 600 |
ret = btrfs_write_marked_extents(root, dirty_pages, mark); ret2 = btrfs_wait_marked_extents(root, dirty_pages, mark); |
bf0da8c18 Btrfs: ClearPageE... |
601 602 603 604 605 606 |
if (ret) return ret; if (ret2) return ret2; return 0; |
690587d10 Btrfs: streamline... |
607 |
} |
d0c803c40 Btrfs: Record dir... |
608 609 610 611 612 613 614 615 616 |
int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root) { if (!trans || !trans->transaction) { struct inode *btree_inode; btree_inode = root->fs_info->btree_inode; return filemap_write_and_wait(btree_inode->i_mapping); } return btrfs_write_and_wait_marked_extents(root, |
8cef4e160 Btrfs: Avoid supe... |
617 618 |
&trans->transaction->dirty_pages, EXTENT_DIRTY); |
d0c803c40 Btrfs: Record dir... |
619 |
} |
d352ac681 Btrfs: add and im... |
620 621 622 623 624 625 626 627 628 629 |
/* * this is used to update the root pointer in the tree of tree roots. * * But, in the case of the extent allocation tree, updating the root * pointer may allocate blocks which may change the root of the extent * allocation tree. * * So, this loops and repeats and makes sure the cowonly root didn't * change while the root pointer was being updated in the metadata. */ |
0b86a832a Btrfs: Add suppor... |
630 631 |
static int update_cowonly_root(struct btrfs_trans_handle *trans, struct btrfs_root *root) |
79154b1b5 Btrfs: transactio... |
632 633 |
{ int ret; |
0b86a832a Btrfs: Add suppor... |
634 |
u64 old_root_bytenr; |
86b9f2eca Btrfs: Fix per ro... |
635 |
u64 old_root_used; |
0b86a832a Btrfs: Add suppor... |
636 |
struct btrfs_root *tree_root = root->fs_info->tree_root; |
79154b1b5 Btrfs: transactio... |
637 |
|
86b9f2eca Btrfs: Fix per ro... |
638 |
old_root_used = btrfs_root_used(&root->root_item); |
0b86a832a Btrfs: Add suppor... |
639 |
btrfs_write_dirty_block_groups(trans, root); |
56bec294d Btrfs: do extent ... |
640 |
|
d397712bc Btrfs: Fix checkp... |
641 |
while (1) { |
0b86a832a Btrfs: Add suppor... |
642 |
old_root_bytenr = btrfs_root_bytenr(&root->root_item); |
86b9f2eca Btrfs: Fix per ro... |
643 644 |
if (old_root_bytenr == root->node->start && old_root_used == btrfs_root_used(&root->root_item)) |
79154b1b5 Btrfs: transactio... |
645 |
break; |
87ef2bb46 Btrfs: prevent lo... |
646 |
|
5d4f98a28 Btrfs: Mixed back... |
647 |
btrfs_set_root_node(&root->root_item, root->node); |
79154b1b5 Btrfs: transactio... |
648 |
ret = btrfs_update_root(trans, tree_root, |
0b86a832a Btrfs: Add suppor... |
649 650 |
&root->root_key, &root->root_item); |
79154b1b5 Btrfs: transactio... |
651 |
BUG_ON(ret); |
56bec294d Btrfs: do extent ... |
652 |
|
86b9f2eca Btrfs: Fix per ro... |
653 |
old_root_used = btrfs_root_used(&root->root_item); |
4a8c9a62d Btrfs: make sure ... |
654 |
ret = btrfs_write_dirty_block_groups(trans, root); |
56bec294d Btrfs: do extent ... |
655 |
BUG_ON(ret); |
0b86a832a Btrfs: Add suppor... |
656 |
} |
276e680d1 Btrfs: preserve c... |
657 658 659 |
if (root != root->fs_info->extent_root) switch_commit_root(root); |
0b86a832a Btrfs: Add suppor... |
660 661 |
return 0; } |
d352ac681 Btrfs: add and im... |
662 663 664 |
/* * update all the cowonly tree roots on disk */ |
5d4f98a28 Btrfs: Mixed back... |
665 666 |
static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, struct btrfs_root *root) |
0b86a832a Btrfs: Add suppor... |
667 668 669 |
{ struct btrfs_fs_info *fs_info = root->fs_info; struct list_head *next; |
84234f3a1 Btrfs: Add root t... |
670 |
struct extent_buffer *eb; |
56bec294d Btrfs: do extent ... |
671 |
int ret; |
84234f3a1 Btrfs: Add root t... |
672 |
|
56bec294d Btrfs: do extent ... |
673 674 |
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); BUG_ON(ret); |
87ef2bb46 Btrfs: prevent lo... |
675 |
|
84234f3a1 Btrfs: Add root t... |
676 |
eb = btrfs_lock_root_node(fs_info->tree_root); |
9fa8cfe70 Btrfs: don't prea... |
677 |
btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb); |
84234f3a1 Btrfs: Add root t... |
678 679 |
btrfs_tree_unlock(eb); free_extent_buffer(eb); |
0b86a832a Btrfs: Add suppor... |
680 |
|
56bec294d Btrfs: do extent ... |
681 682 |
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); BUG_ON(ret); |
87ef2bb46 Btrfs: prevent lo... |
683 |
|
d397712bc Btrfs: Fix checkp... |
684 |
while (!list_empty(&fs_info->dirty_cowonly_roots)) { |
0b86a832a Btrfs: Add suppor... |
685 686 687 |
next = fs_info->dirty_cowonly_roots.next; list_del_init(next); root = list_entry(next, struct btrfs_root, dirty_list); |
87ef2bb46 Btrfs: prevent lo... |
688 |
|
0b86a832a Btrfs: Add suppor... |
689 |
update_cowonly_root(trans, root); |
79154b1b5 Btrfs: transactio... |
690 |
} |
276e680d1 Btrfs: preserve c... |
691 692 693 694 |
down_write(&fs_info->extent_commit_sem); switch_commit_root(fs_info->extent_root); up_write(&fs_info->extent_commit_sem); |
79154b1b5 Btrfs: transactio... |
695 696 |
return 0; } |
d352ac681 Btrfs: add and im... |
697 698 699 700 701 |
/* * dead roots are old snapshots that need to be deleted. This allocates * a dirty root struct and adds it into the list of dead roots that need to * be deleted */ |
5d4f98a28 Btrfs: Mixed back... |
702 |
int btrfs_add_dead_root(struct btrfs_root *root) |
5eda7b5e9 Btrfs: Add the ab... |
703 |
{ |
a4abeea41 Btrfs: kill trans... |
704 |
spin_lock(&root->fs_info->trans_lock); |
5d4f98a28 Btrfs: Mixed back... |
705 |
list_add(&root->root_list, &root->fs_info->dead_roots); |
a4abeea41 Btrfs: kill trans... |
706 |
spin_unlock(&root->fs_info->trans_lock); |
5eda7b5e9 Btrfs: Add the ab... |
707 708 |
return 0; } |
d352ac681 Btrfs: add and im... |
709 |
/* |
5d4f98a28 Btrfs: Mixed back... |
710 |
* update all the cowonly tree roots on disk |
d352ac681 Btrfs: add and im... |
711 |
*/ |
5d4f98a28 Btrfs: Mixed back... |
712 713 |
static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, struct btrfs_root *root) |
0f7d52f44 Btrfs: groundwork... |
714 |
{ |
0f7d52f44 Btrfs: groundwork... |
715 |
struct btrfs_root *gang[8]; |
5d4f98a28 Btrfs: Mixed back... |
716 |
struct btrfs_fs_info *fs_info = root->fs_info; |
0f7d52f44 Btrfs: groundwork... |
717 718 |
int i; int ret; |
54aa1f4df Btrfs: Audit call... |
719 |
int err = 0; |
a4abeea41 Btrfs: kill trans... |
720 |
spin_lock(&fs_info->fs_roots_radix_lock); |
d397712bc Btrfs: Fix checkp... |
721 |
while (1) { |
5d4f98a28 Btrfs: Mixed back... |
722 723 |
ret = radix_tree_gang_lookup_tag(&fs_info->fs_roots_radix, (void **)gang, 0, |
0f7d52f44 Btrfs: groundwork... |
724 725 726 727 728 729 |
ARRAY_SIZE(gang), BTRFS_ROOT_TRANS_TAG); if (ret == 0) break; for (i = 0; i < ret; i++) { root = gang[i]; |
5d4f98a28 Btrfs: Mixed back... |
730 731 732 |
radix_tree_tag_clear(&fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); |
a4abeea41 Btrfs: kill trans... |
733 |
spin_unlock(&fs_info->fs_roots_radix_lock); |
31153d812 Btrfs: Add a leaf... |
734 |
|
e02119d5a Btrfs: Add a writ... |
735 |
btrfs_free_log(trans, root); |
5d4f98a28 Btrfs: Mixed back... |
736 |
btrfs_update_reloc_root(trans, root); |
d68fc57b7 Btrfs: Metadata r... |
737 |
btrfs_orphan_commit_root(trans, root); |
bcc63abbf Btrfs: implement ... |
738 |
|
82d5902d9 Btrfs: Support re... |
739 |
btrfs_save_ino_cache(root, trans); |
f1ebcc74d Btrfs: fix tree c... |
740 741 742 |
/* see comments in should_cow_block() */ root->force_cow = 0; smp_wmb(); |
978d910d3 Btrfs: always upd... |
743 |
if (root->commit_root != root->node) { |
581bb0509 Btrfs: Cache free... |
744 |
mutex_lock(&root->fs_commit_mutex); |
817d52f8d Btrfs: async bloc... |
745 |
switch_commit_root(root); |
581bb0509 Btrfs: Cache free... |
746 747 |
btrfs_unpin_free_ino(root); mutex_unlock(&root->fs_commit_mutex); |
978d910d3 Btrfs: always upd... |
748 749 750 |
btrfs_set_root_node(&root->root_item, root->node); } |
5d4f98a28 Btrfs: Mixed back... |
751 |
|
5d4f98a28 Btrfs: Mixed back... |
752 |
err = btrfs_update_root(trans, fs_info->tree_root, |
0f7d52f44 Btrfs: groundwork... |
753 754 |
&root->root_key, &root->root_item); |
a4abeea41 Btrfs: kill trans... |
755 |
spin_lock(&fs_info->fs_roots_radix_lock); |
54aa1f4df Btrfs: Audit call... |
756 757 |
if (err) break; |
0f7d52f44 Btrfs: groundwork... |
758 759 |
} } |
a4abeea41 Btrfs: kill trans... |
760 |
spin_unlock(&fs_info->fs_roots_radix_lock); |
54aa1f4df Btrfs: Audit call... |
761 |
return err; |
0f7d52f44 Btrfs: groundwork... |
762 |
} |
d352ac681 Btrfs: add and im... |
763 764 765 766 |
/* * defrag a given btree. If cacheonly == 1, this won't read from the disk, * otherwise every leaf in the btree is read and defragged. */ |
e9d0b13b5 Btrfs: Btree defr... |
767 768 769 |
int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) { struct btrfs_fs_info *info = root->fs_info; |
e9d0b13b5 Btrfs: Btree defr... |
770 |
struct btrfs_trans_handle *trans; |
8929ecfa5 Btrfs: Introduce ... |
771 |
int ret; |
d3c2fdcf7 Btrfs: Use balanc... |
772 |
unsigned long nr; |
e9d0b13b5 Btrfs: Btree defr... |
773 |
|
8929ecfa5 Btrfs: Introduce ... |
774 |
if (xchg(&root->defrag_running, 1)) |
e9d0b13b5 Btrfs: Btree defr... |
775 |
return 0; |
8929ecfa5 Btrfs: Introduce ... |
776 |
|
6b80053d0 Btrfs: Add back t... |
777 |
while (1) { |
8929ecfa5 Btrfs: Introduce ... |
778 779 780 |
trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) return PTR_ERR(trans); |
e9d0b13b5 Btrfs: Btree defr... |
781 |
ret = btrfs_defrag_leaves(trans, root, cacheonly); |
8929ecfa5 Btrfs: Introduce ... |
782 |
|
d3c2fdcf7 Btrfs: Use balanc... |
783 |
nr = trans->blocks_used; |
e9d0b13b5 Btrfs: Btree defr... |
784 |
btrfs_end_transaction(trans, root); |
d3c2fdcf7 Btrfs: Use balanc... |
785 |
btrfs_btree_balance_dirty(info->tree_root, nr); |
e9d0b13b5 Btrfs: Btree defr... |
786 |
cond_resched(); |
7841cb289 btrfs: add helper... |
787 |
if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN) |
e9d0b13b5 Btrfs: Btree defr... |
788 789 790 |
break; } root->defrag_running = 0; |
8929ecfa5 Btrfs: Introduce ... |
791 |
return ret; |
e9d0b13b5 Btrfs: Btree defr... |
792 |
} |
d352ac681 Btrfs: add and im... |
793 794 795 796 |
/* * new snapshots need to be created at a very specific time in the * transaction commit. This does the actual creation */ |
80b6794d1 Btrfs: Lower stac... |
797 |
static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, |
3063d29f2 Btrfs: Move snaps... |
798 799 800 801 |
struct btrfs_fs_info *fs_info, struct btrfs_pending_snapshot *pending) { struct btrfs_key key; |
80b6794d1 Btrfs: Lower stac... |
802 |
struct btrfs_root_item *new_root_item; |
3063d29f2 Btrfs: Move snaps... |
803 804 |
struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *root = pending->root; |
6bdb72ded Btrfs: create sna... |
805 |
struct btrfs_root *parent_root; |
98c9942ac Btrfs: fix misuse... |
806 |
struct btrfs_block_rsv *rsv; |
6bdb72ded Btrfs: create sna... |
807 |
struct inode *parent_inode; |
6a9122130 Btrfs: use dget_p... |
808 |
struct dentry *parent; |
a22285a6a Btrfs: Integrate ... |
809 |
struct dentry *dentry; |
3063d29f2 Btrfs: Move snaps... |
810 |
struct extent_buffer *tmp; |
925baeddc Btrfs: Start btre... |
811 |
struct extent_buffer *old; |
3063d29f2 Btrfs: Move snaps... |
812 |
int ret; |
d68fc57b7 Btrfs: Metadata r... |
813 |
u64 to_reserve = 0; |
6bdb72ded Btrfs: create sna... |
814 |
u64 index = 0; |
a22285a6a Btrfs: Integrate ... |
815 |
u64 objectid; |
b83cc9693 Btrfs: Add readon... |
816 |
u64 root_flags; |
3063d29f2 Btrfs: Move snaps... |
817 |
|
98c9942ac Btrfs: fix misuse... |
818 |
rsv = trans->block_rsv; |
80b6794d1 Btrfs: Lower stac... |
819 820 |
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); if (!new_root_item) { |
a22285a6a Btrfs: Integrate ... |
821 |
pending->error = -ENOMEM; |
80b6794d1 Btrfs: Lower stac... |
822 823 |
goto fail; } |
a22285a6a Btrfs: Integrate ... |
824 |
|
581bb0509 Btrfs: Cache free... |
825 |
ret = btrfs_find_free_objectid(tree_root, &objectid); |
a22285a6a Btrfs: Integrate ... |
826 827 |
if (ret) { pending->error = ret; |
3063d29f2 Btrfs: Move snaps... |
828 |
goto fail; |
a22285a6a Btrfs: Integrate ... |
829 |
} |
3063d29f2 Btrfs: Move snaps... |
830 |
|
3fd0a5585 Btrfs: Metadata E... |
831 |
btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); |
d68fc57b7 Btrfs: Metadata r... |
832 833 |
if (to_reserve > 0) { |
62f30c546 Btrfs: fix deadlo... |
834 835 |
ret = btrfs_block_rsv_add_noflush(root, &pending->block_rsv, to_reserve); |
d68fc57b7 Btrfs: Metadata r... |
836 837 838 839 840 |
if (ret) { pending->error = ret; goto fail; } } |
3063d29f2 Btrfs: Move snaps... |
841 |
key.objectid = objectid; |
a22285a6a Btrfs: Integrate ... |
842 843 |
key.offset = (u64)-1; key.type = BTRFS_ROOT_ITEM_KEY; |
3063d29f2 Btrfs: Move snaps... |
844 |
|
a22285a6a Btrfs: Integrate ... |
845 |
trans->block_rsv = &pending->block_rsv; |
3de4586c5 Btrfs: Allow subv... |
846 |
|
a22285a6a Btrfs: Integrate ... |
847 |
dentry = pending->dentry; |
6a9122130 Btrfs: use dget_p... |
848 849 |
parent = dget_parent(dentry); parent_inode = parent->d_inode; |
a22285a6a Btrfs: Integrate ... |
850 |
parent_root = BTRFS_I(parent_inode)->root; |
7585717f3 Btrfs: fix reloca... |
851 |
record_root_in_trans(trans, parent_root); |
a22285a6a Btrfs: Integrate ... |
852 |
|
3063d29f2 Btrfs: Move snaps... |
853 854 855 |
/* * insert the directory item */ |
3de4586c5 Btrfs: Allow subv... |
856 |
ret = btrfs_set_inode_index(parent_inode, &index); |
6bdb72ded Btrfs: create sna... |
857 |
BUG_ON(ret); |
0660b5af3 Btrfs: Add backre... |
858 |
ret = btrfs_insert_dir_item(trans, parent_root, |
a22285a6a Btrfs: Integrate ... |
859 |
dentry->d_name.name, dentry->d_name.len, |
16cdcec73 btrfs: implement ... |
860 |
parent_inode, &key, |
a22285a6a Btrfs: Integrate ... |
861 |
BTRFS_FT_DIR, index); |
6bdb72ded Btrfs: create sna... |
862 |
BUG_ON(ret); |
0660b5af3 Btrfs: Add backre... |
863 |
|
a22285a6a Btrfs: Integrate ... |
864 865 |
btrfs_i_size_write(parent_inode, parent_inode->i_size + dentry->d_name.len * 2); |
52c261799 Btrfs: update dir... |
866 867 |
ret = btrfs_update_inode(trans, parent_root, parent_inode); BUG_ON(ret); |
e999376f0 Btrfs: avoid dela... |
868 869 870 871 872 873 874 875 |
/* * pull in the delayed directory update * and the delayed inode item * otherwise we corrupt the FS during * snapshot */ ret = btrfs_run_delayed_items(trans, root); BUG_ON(ret); |
7585717f3 Btrfs: fix reloca... |
876 |
record_root_in_trans(trans, root); |
6bdb72ded Btrfs: create sna... |
877 878 |
btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); |
08fe4db17 Btrfs: Fix uninit... |
879 |
btrfs_check_and_init_root_item(new_root_item); |
6bdb72ded Btrfs: create sna... |
880 |
|
b83cc9693 Btrfs: Add readon... |
881 882 883 884 885 886 |
root_flags = btrfs_root_flags(new_root_item); if (pending->readonly) root_flags |= BTRFS_ROOT_SUBVOL_RDONLY; else root_flags &= ~BTRFS_ROOT_SUBVOL_RDONLY; btrfs_set_root_flags(new_root_item, root_flags); |
6bdb72ded Btrfs: create sna... |
887 888 889 890 891 892 893 |
old = btrfs_lock_root_node(root); btrfs_cow_block(trans, root, old, NULL, 0, &old); btrfs_set_lock_blocking(old); btrfs_copy_root(trans, root, old, &tmp, objectid); btrfs_tree_unlock(old); free_extent_buffer(old); |
f1ebcc74d Btrfs: fix tree c... |
894 895 896 |
/* see comments in should_cow_block() */ root->force_cow = 1; smp_wmb(); |
6bdb72ded Btrfs: create sna... |
897 |
btrfs_set_root_node(new_root_item, tmp); |
a22285a6a Btrfs: Integrate ... |
898 899 900 |
/* record when the snapshot was created in key.offset */ key.offset = trans->transid; ret = btrfs_insert_root(trans, tree_root, &key, new_root_item); |
6bdb72ded Btrfs: create sna... |
901 902 |
btrfs_tree_unlock(tmp); free_extent_buffer(tmp); |
a22285a6a Btrfs: Integrate ... |
903 |
BUG_ON(ret); |
6bdb72ded Btrfs: create sna... |
904 |
|
a22285a6a Btrfs: Integrate ... |
905 906 907 908 |
/* * insert root back/forward references */ ret = btrfs_add_root_ref(trans, tree_root, objectid, |
0660b5af3 Btrfs: Add backre... |
909 |
parent_root->root_key.objectid, |
33345d015 Btrfs: Always use... |
910 |
btrfs_ino(parent_inode), index, |
a22285a6a Btrfs: Integrate ... |
911 |
dentry->d_name.name, dentry->d_name.len); |
0660b5af3 Btrfs: Add backre... |
912 |
BUG_ON(ret); |
6a9122130 Btrfs: use dget_p... |
913 |
dput(parent); |
0660b5af3 Btrfs: Add backre... |
914 |
|
a22285a6a Btrfs: Integrate ... |
915 916 917 |
key.offset = (u64)-1; pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); BUG_ON(IS_ERR(pending->snap)); |
d68fc57b7 Btrfs: Metadata r... |
918 |
|
3fd0a5585 Btrfs: Metadata E... |
919 |
btrfs_reloc_post_snapshot(trans, pending); |
3063d29f2 Btrfs: Move snaps... |
920 |
fail: |
6bdb72ded Btrfs: create sna... |
921 |
kfree(new_root_item); |
98c9942ac Btrfs: fix misuse... |
922 |
trans->block_rsv = rsv; |
a22285a6a Btrfs: Integrate ... |
923 924 |
btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); return 0; |
3063d29f2 Btrfs: Move snaps... |
925 |
} |
d352ac681 Btrfs: add and im... |
926 927 928 |
/* * create all the snapshots we've scheduled for creation */ |
80b6794d1 Btrfs: Lower stac... |
929 930 |
static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info) |
3063d29f2 Btrfs: Move snaps... |
931 932 933 |
{ struct btrfs_pending_snapshot *pending; struct list_head *head = &trans->transaction->pending_snapshots; |
3de4586c5 Btrfs: Allow subv... |
934 |
int ret; |
c6e308713 Btrfs: simplify i... |
935 |
list_for_each_entry(pending, head, list) { |
3de4586c5 Btrfs: Allow subv... |
936 937 938 939 940 |
ret = create_pending_snapshot(trans, fs_info, pending); BUG_ON(ret); } return 0; } |
5d4f98a28 Btrfs: Mixed back... |
941 942 943 944 |
static void update_super_roots(struct btrfs_root *root) { struct btrfs_root_item *root_item; struct btrfs_super_block *super; |
6c41761fc btrfs: separate s... |
945 |
super = root->fs_info->super_copy; |
5d4f98a28 Btrfs: Mixed back... |
946 947 948 949 950 951 952 953 954 955 |
root_item = &root->fs_info->chunk_root->root_item; super->chunk_root = root_item->bytenr; super->chunk_root_generation = root_item->generation; super->chunk_root_level = root_item->level; root_item = &root->fs_info->tree_root->root_item; super->root = root_item->bytenr; super->generation = root_item->generation; super->root_level = root_item->level; |
73bc18768 Btrfs: introduce ... |
956 |
if (btrfs_test_opt(root, SPACE_CACHE)) |
0af3d00ba Btrfs: create spe... |
957 |
super->cache_generation = root_item->generation; |
5d4f98a28 Btrfs: Mixed back... |
958 |
} |
f36f3042e Btrfs: be more po... |
959 960 961 |
int btrfs_transaction_in_commit(struct btrfs_fs_info *info) { int ret = 0; |
a4abeea41 Btrfs: kill trans... |
962 |
spin_lock(&info->trans_lock); |
f36f3042e Btrfs: be more po... |
963 964 |
if (info->running_transaction) ret = info->running_transaction->in_commit; |
a4abeea41 Btrfs: kill trans... |
965 |
spin_unlock(&info->trans_lock); |
f36f3042e Btrfs: be more po... |
966 967 |
return ret; } |
8929ecfa5 Btrfs: Introduce ... |
968 969 970 |
int btrfs_transaction_blocked(struct btrfs_fs_info *info) { int ret = 0; |
a4abeea41 Btrfs: kill trans... |
971 |
spin_lock(&info->trans_lock); |
8929ecfa5 Btrfs: Introduce ... |
972 973 |
if (info->running_transaction) ret = info->running_transaction->blocked; |
a4abeea41 Btrfs: kill trans... |
974 |
spin_unlock(&info->trans_lock); |
8929ecfa5 Btrfs: Introduce ... |
975 976 |
return ret; } |
bb9c12c94 Btrfs: async tran... |
977 978 979 980 981 982 983 |
/* * wait for the current transaction commit to start and block subsequent * transaction joins */ static void wait_current_trans_commit_start(struct btrfs_root *root, struct btrfs_transaction *trans) { |
72d63ed64 Btrfs: use wait_e... |
984 |
wait_event(root->fs_info->transaction_blocked_wait, trans->in_commit); |
bb9c12c94 Btrfs: async tran... |
985 986 987 988 989 990 991 992 993 |
} /* * wait for the current transaction to start and then become unblocked. * caller holds ref. */ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root, struct btrfs_transaction *trans) { |
72d63ed64 Btrfs: use wait_e... |
994 995 |
wait_event(root->fs_info->transaction_wait, trans->commit_done || (trans->in_commit && !trans->blocked)); |
bb9c12c94 Btrfs: async tran... |
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 |
} /* * commit transactions asynchronously. once btrfs_commit_transaction_async * returns, any subsequent transaction will not be allowed to join. */ struct btrfs_async_commit { struct btrfs_trans_handle *newtrans; struct btrfs_root *root; struct delayed_work work; }; static void do_async_commit(struct work_struct *work) { struct btrfs_async_commit *ac = container_of(work, struct btrfs_async_commit, work.work); btrfs_commit_transaction(ac->newtrans, ac->root); kfree(ac); } int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, struct btrfs_root *root, int wait_for_unblock) { struct btrfs_async_commit *ac; struct btrfs_transaction *cur_trans; ac = kmalloc(sizeof(*ac), GFP_NOFS); |
db5b493ac Btrfs: cleanup so... |
1025 1026 |
if (!ac) return -ENOMEM; |
bb9c12c94 Btrfs: async tran... |
1027 1028 1029 |
INIT_DELAYED_WORK(&ac->work, do_async_commit); ac->root = root; |
7a7eaa40a Btrfs: take away ... |
1030 |
ac->newtrans = btrfs_join_transaction(root); |
3612b4959 btrfs: fix return... |
1031 1032 1033 1034 1035 |
if (IS_ERR(ac->newtrans)) { int err = PTR_ERR(ac->newtrans); kfree(ac); return err; } |
bb9c12c94 Btrfs: async tran... |
1036 1037 |
/* take transaction reference */ |
bb9c12c94 Btrfs: async tran... |
1038 |
cur_trans = trans->transaction; |
13c5a93e7 Btrfs: avoid taki... |
1039 |
atomic_inc(&cur_trans->use_count); |
bb9c12c94 Btrfs: async tran... |
1040 1041 1042 1043 1044 |
btrfs_end_transaction(trans, root); schedule_delayed_work(&ac->work, 0); /* wait for transaction to start and unblock */ |
bb9c12c94 Btrfs: async tran... |
1045 1046 1047 1048 |
if (wait_for_unblock) wait_current_trans_commit_start_and_unblock(root, cur_trans); else wait_current_trans_commit_start(root, cur_trans); |
bb9c12c94 Btrfs: async tran... |
1049 |
|
38e880540 Btrfs: clear curr... |
1050 1051 1052 1053 |
if (current->journal_info == trans) current->journal_info = NULL; put_transaction(cur_trans); |
bb9c12c94 Btrfs: async tran... |
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 |
return 0; } /* * btrfs_transaction state sequence: * in_commit = 0, blocked = 0 (initial) * in_commit = 1, blocked = 1 * blocked = 0 * commit_done = 1 */ |
79154b1b5 Btrfs: transactio... |
1064 1065 1066 |
int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_root *root) { |
15ee9bc7e Btrfs: delay comm... |
1067 |
unsigned long joined = 0; |
79154b1b5 Btrfs: transactio... |
1068 |
struct btrfs_transaction *cur_trans; |
8fd17795b Btrfs: early fsyn... |
1069 |
struct btrfs_transaction *prev_trans = NULL; |
79154b1b5 Btrfs: transactio... |
1070 |
DEFINE_WAIT(wait); |
15ee9bc7e Btrfs: delay comm... |
1071 |
int ret; |
89573b9c5 Btrfs: Only let v... |
1072 1073 |
int should_grow = 0; unsigned long now = get_seconds(); |
dccae9999 Btrfs: add flusho... |
1074 |
int flush_on_commit = btrfs_test_opt(root, FLUSHONCOMMIT); |
79154b1b5 Btrfs: transactio... |
1075 |
|
5a3f23d51 Btrfs: add extra ... |
1076 |
btrfs_run_ordered_operations(root, 0); |
b24e03db0 Btrfs: release tr... |
1077 |
btrfs_trans_release_metadata(trans, root); |
9c8d86db9 Btrfs: make sure ... |
1078 |
trans->block_rsv = NULL; |
56bec294d Btrfs: do extent ... |
1079 1080 1081 1082 1083 |
/* make a pass through all the delayed refs we have so far * any runnings procs may add more while we are here */ ret = btrfs_run_delayed_refs(trans, root, 0); BUG_ON(ret); |
b7ec40d78 Btrfs: reduce sta... |
1084 |
cur_trans = trans->transaction; |
56bec294d Btrfs: do extent ... |
1085 1086 1087 1088 |
/* * set the flushing flag so procs in this transaction have to * start sending their work down. */ |
b7ec40d78 Btrfs: reduce sta... |
1089 |
cur_trans->delayed_refs.flushing = 1; |
56bec294d Btrfs: do extent ... |
1090 |
|
c3e69d58e Btrfs: process th... |
1091 |
ret = btrfs_run_delayed_refs(trans, root, 0); |
56bec294d Btrfs: do extent ... |
1092 |
BUG_ON(ret); |
a4abeea41 Btrfs: kill trans... |
1093 |
spin_lock(&cur_trans->commit_lock); |
b7ec40d78 Btrfs: reduce sta... |
1094 |
if (cur_trans->in_commit) { |
a4abeea41 Btrfs: kill trans... |
1095 |
spin_unlock(&cur_trans->commit_lock); |
13c5a93e7 Btrfs: avoid taki... |
1096 |
atomic_inc(&cur_trans->use_count); |
79154b1b5 Btrfs: transactio... |
1097 |
btrfs_end_transaction(trans, root); |
ccd467d60 Btrfs: crash reco... |
1098 |
|
b9c8300c2 Btrfs: remove a B... |
1099 |
wait_for_commit(root, cur_trans); |
15ee9bc7e Btrfs: delay comm... |
1100 |
|
79154b1b5 Btrfs: transactio... |
1101 |
put_transaction(cur_trans); |
15ee9bc7e Btrfs: delay comm... |
1102 |
|
79154b1b5 Btrfs: transactio... |
1103 1104 |
return 0; } |
4313b3994 Btrfs: Reduce sta... |
1105 |
|
2c90e5d65 Btrfs: still corr... |
1106 |
trans->transaction->in_commit = 1; |
f92957493 btrfs_start_trans... |
1107 |
trans->transaction->blocked = 1; |
a4abeea41 Btrfs: kill trans... |
1108 |
spin_unlock(&cur_trans->commit_lock); |
bb9c12c94 Btrfs: async tran... |
1109 |
wake_up(&root->fs_info->transaction_blocked_wait); |
a4abeea41 Btrfs: kill trans... |
1110 |
spin_lock(&root->fs_info->trans_lock); |
ccd467d60 Btrfs: crash reco... |
1111 1112 1113 1114 |
if (cur_trans->list.prev != &root->fs_info->trans_list) { prev_trans = list_entry(cur_trans->list.prev, struct btrfs_transaction, list); if (!prev_trans->commit_done) { |
13c5a93e7 Btrfs: avoid taki... |
1115 |
atomic_inc(&prev_trans->use_count); |
a4abeea41 Btrfs: kill trans... |
1116 |
spin_unlock(&root->fs_info->trans_lock); |
ccd467d60 Btrfs: crash reco... |
1117 1118 |
wait_for_commit(root, prev_trans); |
ccd467d60 Btrfs: crash reco... |
1119 |
|
15ee9bc7e Btrfs: delay comm... |
1120 |
put_transaction(prev_trans); |
a4abeea41 Btrfs: kill trans... |
1121 1122 |
} else { spin_unlock(&root->fs_info->trans_lock); |
ccd467d60 Btrfs: crash reco... |
1123 |
} |
a4abeea41 Btrfs: kill trans... |
1124 1125 |
} else { spin_unlock(&root->fs_info->trans_lock); |
ccd467d60 Btrfs: crash reco... |
1126 |
} |
15ee9bc7e Btrfs: delay comm... |
1127 |
|
89573b9c5 Btrfs: Only let v... |
1128 1129 |
if (now < cur_trans->start_time || now - cur_trans->start_time < 1) should_grow = 1; |
15ee9bc7e Btrfs: delay comm... |
1130 |
do { |
7ea394f11 Btrfs: Fix nodata... |
1131 |
int snap_pending = 0; |
a4abeea41 Btrfs: kill trans... |
1132 |
|
15ee9bc7e Btrfs: delay comm... |
1133 |
joined = cur_trans->num_joined; |
7ea394f11 Btrfs: Fix nodata... |
1134 1135 |
if (!list_empty(&trans->transaction->pending_snapshots)) snap_pending = 1; |
2c90e5d65 Btrfs: still corr... |
1136 |
WARN_ON(cur_trans != trans->transaction); |
15ee9bc7e Btrfs: delay comm... |
1137 |
|
0bdb1db29 Btrfs: flush data... |
1138 |
if (flush_on_commit || snap_pending) { |
24bbcf044 Btrfs: Add delaye... |
1139 1140 |
btrfs_start_delalloc_inodes(root, 1); ret = btrfs_wait_ordered_extents(root, 0, 1); |
ebecd3d9d Btrfs: make flush... |
1141 |
BUG_ON(ret); |
7ea394f11 Btrfs: Fix nodata... |
1142 |
} |
16cdcec73 btrfs: implement ... |
1143 1144 |
ret = btrfs_run_delayed_items(trans, root); BUG_ON(ret); |
5a3f23d51 Btrfs: add extra ... |
1145 1146 1147 1148 1149 1150 1151 1152 |
/* * rename don't use btrfs_join_transaction, so, once we * set the transaction to blocked above, we aren't going * to get any new ordered operations. We can safely run * it here and no for sure that nothing new will be added * to the list */ btrfs_run_ordered_operations(root, 1); |
ed3b3d314 Btrfs: don't walk... |
1153 1154 |
prepare_to_wait(&cur_trans->writer_wait, &wait, TASK_UNINTERRUPTIBLE); |
13c5a93e7 Btrfs: avoid taki... |
1155 |
if (atomic_read(&cur_trans->num_writers) > 1) |
99d16cbca Btrfs: fix deadlo... |
1156 1157 1158 |
schedule_timeout(MAX_SCHEDULE_TIMEOUT); else if (should_grow) schedule_timeout(1); |
15ee9bc7e Btrfs: delay comm... |
1159 |
|
15ee9bc7e Btrfs: delay comm... |
1160 |
finish_wait(&cur_trans->writer_wait, &wait); |
13c5a93e7 Btrfs: avoid taki... |
1161 |
} while (atomic_read(&cur_trans->num_writers) > 1 || |
89573b9c5 Btrfs: Only let v... |
1162 |
(should_grow && cur_trans->num_joined != joined)); |
15ee9bc7e Btrfs: delay comm... |
1163 |
|
7585717f3 Btrfs: fix reloca... |
1164 |
/* |
ed0ca1402 Btrfs: set no_tra... |
1165 1166 1167 1168 1169 1170 1171 1172 1173 |
* Ok now we need to make sure to block out any other joins while we * commit the transaction. We could have started a join before setting * no_join so make sure to wait for num_writers to == 1 again. */ spin_lock(&root->fs_info->trans_lock); root->fs_info->trans_no_join = 1; spin_unlock(&root->fs_info->trans_lock); wait_event(cur_trans->writer_wait, atomic_read(&cur_trans->num_writers) == 1); |
e038dca80 Merge branch 'for... |
1174 |
/* |
7585717f3 Btrfs: fix reloca... |
1175 1176 1177 1178 1179 |
* the reloc mutex makes sure that we stop * the balancing code from coming in and moving * extents around in the middle of the commit */ mutex_lock(&root->fs_info->reloc_mutex); |
e999376f0 Btrfs: avoid dela... |
1180 |
ret = btrfs_run_delayed_items(trans, root); |
3063d29f2 Btrfs: Move snaps... |
1181 |
BUG_ON(ret); |
e999376f0 Btrfs: avoid dela... |
1182 |
ret = create_pending_snapshots(trans, root->fs_info); |
16cdcec73 btrfs: implement ... |
1183 |
BUG_ON(ret); |
56bec294d Btrfs: do extent ... |
1184 1185 |
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); BUG_ON(ret); |
e999376f0 Btrfs: avoid dela... |
1186 1187 1188 1189 1190 |
/* * make sure none of the code above managed to slip in a * delayed item */ btrfs_assert_delayed_root_empty(root); |
2c90e5d65 Btrfs: still corr... |
1191 |
WARN_ON(cur_trans != trans->transaction); |
dc17ff8f1 Btrfs: Add data=o... |
1192 |
|
a2de733c7 btrfs: scrub |
1193 |
btrfs_scrub_pause(root); |
e02119d5a Btrfs: Add a writ... |
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 |
/* btrfs_commit_tree_roots is responsible for getting the * various roots consistent with each other. Every pointer * in the tree of tree roots has to point to the most up to date * root for every subvolume and other tree. So, we have to keep * the tree logging code from jumping in and changing any * of the trees. * * At this point in the commit, there can't be any tree-log * writers, but a little lower down we drop the trans mutex * and let new people in. By holding the tree_log_mutex * from now until after the super is written, we avoid races * with the tree-log code. */ mutex_lock(&root->fs_info->tree_log_mutex); |
5d4f98a28 Btrfs: Mixed back... |
1208 |
ret = commit_fs_roots(trans, root); |
54aa1f4df Btrfs: Audit call... |
1209 |
BUG_ON(ret); |
5d4f98a28 Btrfs: Mixed back... |
1210 |
/* commit_fs_roots gets rid of all the tree log roots, it is now |
e02119d5a Btrfs: Add a writ... |
1211 1212 1213 |
* safe to free the root of tree log roots */ btrfs_free_log_root_tree(trans, root->fs_info); |
5d4f98a28 Btrfs: Mixed back... |
1214 |
ret = commit_cowonly_roots(trans, root); |
79154b1b5 Btrfs: transactio... |
1215 |
BUG_ON(ret); |
54aa1f4df Btrfs: Audit call... |
1216 |
|
11833d66b Btrfs: improve as... |
1217 |
btrfs_prepare_extent_commit(trans, root); |
78fae27eb Btrfs: leak fixes... |
1218 |
cur_trans = root->fs_info->running_transaction; |
5d4f98a28 Btrfs: Mixed back... |
1219 1220 1221 |
btrfs_set_root_node(&root->fs_info->tree_root->root_item, root->fs_info->tree_root->node); |
817d52f8d Btrfs: async bloc... |
1222 |
switch_commit_root(root->fs_info->tree_root); |
5d4f98a28 Btrfs: Mixed back... |
1223 1224 1225 |
btrfs_set_root_node(&root->fs_info->chunk_root->root_item, root->fs_info->chunk_root->node); |
817d52f8d Btrfs: async bloc... |
1226 |
switch_commit_root(root->fs_info->chunk_root); |
5d4f98a28 Btrfs: Mixed back... |
1227 1228 |
update_super_roots(root); |
e02119d5a Btrfs: Add a writ... |
1229 1230 |
if (!root->fs_info->log_root_recovering) { |
6c41761fc btrfs: separate s... |
1231 1232 |
btrfs_set_super_log_root(root->fs_info->super_copy, 0); btrfs_set_super_log_root_level(root->fs_info->super_copy, 0); |
e02119d5a Btrfs: Add a writ... |
1233 |
} |
6c41761fc btrfs: separate s... |
1234 1235 |
memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy, sizeof(*root->fs_info->super_copy)); |
ccd467d60 Btrfs: crash reco... |
1236 |
|
f92957493 btrfs_start_trans... |
1237 |
trans->transaction->blocked = 0; |
a4abeea41 Btrfs: kill trans... |
1238 1239 1240 1241 |
spin_lock(&root->fs_info->trans_lock); root->fs_info->running_transaction = NULL; root->fs_info->trans_no_join = 0; spin_unlock(&root->fs_info->trans_lock); |
7585717f3 Btrfs: fix reloca... |
1242 |
mutex_unlock(&root->fs_info->reloc_mutex); |
b7ec40d78 Btrfs: reduce sta... |
1243 |
|
f92957493 btrfs_start_trans... |
1244 |
wake_up(&root->fs_info->transaction_wait); |
e6dcd2dc9 Btrfs: New data=o... |
1245 |
|
79154b1b5 Btrfs: transactio... |
1246 1247 |
ret = btrfs_write_and_wait_transaction(trans, root); BUG_ON(ret); |
a512bbf85 Btrfs: superblock... |
1248 |
write_ctree_super(trans, root, 0); |
4313b3994 Btrfs: Reduce sta... |
1249 |
|
e02119d5a Btrfs: Add a writ... |
1250 1251 1252 1253 1254 |
/* * the super is written, we can safely allow the tree-loggers * to go about their business */ mutex_unlock(&root->fs_info->tree_log_mutex); |
11833d66b Btrfs: improve as... |
1255 |
btrfs_finish_extent_commit(trans, root); |
4313b3994 Btrfs: Reduce sta... |
1256 |
|
2c90e5d65 Btrfs: still corr... |
1257 |
cur_trans->commit_done = 1; |
b7ec40d78 Btrfs: reduce sta... |
1258 |
|
15ee9bc7e Btrfs: delay comm... |
1259 |
root->fs_info->last_trans_committed = cur_trans->transid; |
817d52f8d Btrfs: async bloc... |
1260 |
|
2c90e5d65 Btrfs: still corr... |
1261 |
wake_up(&cur_trans->commit_wait); |
3de4586c5 Btrfs: Allow subv... |
1262 |
|
a4abeea41 Btrfs: kill trans... |
1263 |
spin_lock(&root->fs_info->trans_lock); |
13c5a93e7 Btrfs: avoid taki... |
1264 |
list_del_init(&cur_trans->list); |
a4abeea41 Btrfs: kill trans... |
1265 |
spin_unlock(&root->fs_info->trans_lock); |
78fae27eb Btrfs: leak fixes... |
1266 |
put_transaction(cur_trans); |
79154b1b5 Btrfs: transactio... |
1267 |
put_transaction(cur_trans); |
58176a960 Btrfs: Add per-ro... |
1268 |
|
1abe9b8a1 Btrfs: add initia... |
1269 |
trace_btrfs_transaction_commit(root); |
a2de733c7 btrfs: scrub |
1270 |
btrfs_scrub_continue(root); |
9ed74f2db Btrfs: proper -EN... |
1271 1272 |
if (current->journal_info == trans) current->journal_info = NULL; |
2c90e5d65 Btrfs: still corr... |
1273 |
kmem_cache_free(btrfs_trans_handle_cachep, trans); |
24bbcf044 Btrfs: Add delaye... |
1274 1275 1276 |
if (current != root->fs_info->transaction_kthread) btrfs_run_delayed_iputs(root); |
79154b1b5 Btrfs: transactio... |
1277 1278 |
return ret; } |
d352ac681 Btrfs: add and im... |
1279 1280 1281 |
/* * interface function to delete all the snapshots we have scheduled for deletion */ |
e9d0b13b5 Btrfs: Btree defr... |
1282 1283 |
int btrfs_clean_old_snapshots(struct btrfs_root *root) { |
5d4f98a28 Btrfs: Mixed back... |
1284 1285 |
LIST_HEAD(list); struct btrfs_fs_info *fs_info = root->fs_info; |
a4abeea41 Btrfs: kill trans... |
1286 |
spin_lock(&fs_info->trans_lock); |
5d4f98a28 Btrfs: Mixed back... |
1287 |
list_splice_init(&fs_info->dead_roots, &list); |
a4abeea41 Btrfs: kill trans... |
1288 |
spin_unlock(&fs_info->trans_lock); |
e9d0b13b5 Btrfs: Btree defr... |
1289 |
|
5d4f98a28 Btrfs: Mixed back... |
1290 1291 |
while (!list_empty(&list)) { root = list_entry(list.next, struct btrfs_root, root_list); |
76dda93c6 Btrfs: add snapsh... |
1292 |
list_del(&root->root_list); |
16cdcec73 btrfs: implement ... |
1293 |
btrfs_kill_all_delayed_nodes(root); |
76dda93c6 Btrfs: add snapsh... |
1294 1295 |
if (btrfs_header_backref_rev(root->node) < BTRFS_MIXED_BACKREF_REV) |
3fd0a5585 Btrfs: Metadata E... |
1296 |
btrfs_drop_snapshot(root, NULL, 0); |
76dda93c6 Btrfs: add snapsh... |
1297 |
else |
3fd0a5585 Btrfs: Metadata E... |
1298 |
btrfs_drop_snapshot(root, NULL, 1); |
e9d0b13b5 Btrfs: Btree defr... |
1299 1300 1301 |
} return 0; } |