diff options
author | Josef Bacik <josef@redhat.com> | 2010-06-21 14:48:16 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2010-10-28 15:59:09 -0400 |
commit | 0af3d00bad38d3bb9912a60928ad0669f17bdb76 (patch) | |
tree | abbf4c773138a33dcde483ac60f016c4b5e55dcc /fs/btrfs/transaction.c | |
parent | f6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff) |
Btrfs: create special free space cache inode
In order to save free space cache, we need an inode to hold the data, and we
need a special item to point at the right inode for the right block group. So
first, create a special item that will point to the right inode, and the number
of extent entries we will have and the number of bitmaps we will have. We
truncate and pre-allocate space everytime to make sure it's uptodate.
This feature will be turned on as soon as you mount with -o space_cache, however
it is safe to boot into old kernels, they will just generate the cache the old
fashion way. When you boot back into a newer kernel we will notice that we
modified and not the cache and automatically discard the cache.
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 66e4c66cc63b..e7144c48ed79 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -163,6 +163,7 @@ enum btrfs_trans_type { | |||
163 | TRANS_START, | 163 | TRANS_START, |
164 | TRANS_JOIN, | 164 | TRANS_JOIN, |
165 | TRANS_USERSPACE, | 165 | TRANS_USERSPACE, |
166 | TRANS_JOIN_NOLOCK, | ||
166 | }; | 167 | }; |
167 | 168 | ||
168 | static int may_wait_transaction(struct btrfs_root *root, int type) | 169 | static int may_wait_transaction(struct btrfs_root *root, int type) |
@@ -186,7 +187,8 @@ again: | |||
186 | if (!h) | 187 | if (!h) |
187 | return ERR_PTR(-ENOMEM); | 188 | return ERR_PTR(-ENOMEM); |
188 | 189 | ||
189 | mutex_lock(&root->fs_info->trans_mutex); | 190 | if (type != TRANS_JOIN_NOLOCK) |
191 | mutex_lock(&root->fs_info->trans_mutex); | ||
190 | if (may_wait_transaction(root, type)) | 192 | if (may_wait_transaction(root, type)) |
191 | wait_current_trans(root); | 193 | wait_current_trans(root); |
192 | 194 | ||
@@ -195,7 +197,8 @@ again: | |||
195 | 197 | ||
196 | cur_trans = root->fs_info->running_transaction; | 198 | cur_trans = root->fs_info->running_transaction; |
197 | cur_trans->use_count++; | 199 | cur_trans->use_count++; |
198 | mutex_unlock(&root->fs_info->trans_mutex); | 200 | if (type != TRANS_JOIN_NOLOCK) |
201 | mutex_unlock(&root->fs_info->trans_mutex); | ||
199 | 202 | ||
200 | h->transid = cur_trans->transid; | 203 | h->transid = cur_trans->transid; |
201 | h->transaction = cur_trans; | 204 | h->transaction = cur_trans; |
@@ -224,9 +227,11 @@ again: | |||
224 | } | 227 | } |
225 | } | 228 | } |
226 | 229 | ||
227 | mutex_lock(&root->fs_info->trans_mutex); | 230 | if (type != TRANS_JOIN_NOLOCK) |
231 | mutex_lock(&root->fs_info->trans_mutex); | ||
228 | record_root_in_trans(h, root); | 232 | record_root_in_trans(h, root); |
229 | mutex_unlock(&root->fs_info->trans_mutex); | 233 | if (type != TRANS_JOIN_NOLOCK) |
234 | mutex_unlock(&root->fs_info->trans_mutex); | ||
230 | 235 | ||
231 | if (!current->journal_info && type != TRANS_USERSPACE) | 236 | if (!current->journal_info && type != TRANS_USERSPACE) |
232 | current->journal_info = h; | 237 | current->journal_info = h; |
@@ -244,6 +249,12 @@ struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, | |||
244 | return start_transaction(root, 0, TRANS_JOIN); | 249 | return start_transaction(root, 0, TRANS_JOIN); |
245 | } | 250 | } |
246 | 251 | ||
252 | struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root, | ||
253 | int num_blocks) | ||
254 | { | ||
255 | return start_transaction(root, 0, TRANS_JOIN_NOLOCK); | ||
256 | } | ||
257 | |||
247 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, | 258 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, |
248 | int num_blocks) | 259 | int num_blocks) |
249 | { | 260 | { |
@@ -348,7 +359,7 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | |||
348 | } | 359 | } |
349 | 360 | ||
350 | static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | 361 | static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, |
351 | struct btrfs_root *root, int throttle) | 362 | struct btrfs_root *root, int throttle, int lock) |
352 | { | 363 | { |
353 | struct btrfs_transaction *cur_trans = trans->transaction; | 364 | struct btrfs_transaction *cur_trans = trans->transaction; |
354 | struct btrfs_fs_info *info = root->fs_info; | 365 | struct btrfs_fs_info *info = root->fs_info; |
@@ -376,18 +387,19 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
376 | 387 | ||
377 | btrfs_trans_release_metadata(trans, root); | 388 | btrfs_trans_release_metadata(trans, root); |
378 | 389 | ||
379 | if (!root->fs_info->open_ioctl_trans && | 390 | if (lock && !root->fs_info->open_ioctl_trans && |
380 | should_end_transaction(trans, root)) | 391 | should_end_transaction(trans, root)) |
381 | trans->transaction->blocked = 1; | 392 | trans->transaction->blocked = 1; |
382 | 393 | ||
383 | if (cur_trans->blocked && !cur_trans->in_commit) { | 394 | if (lock && cur_trans->blocked && !cur_trans->in_commit) { |
384 | if (throttle) | 395 | if (throttle) |
385 | return btrfs_commit_transaction(trans, root); | 396 | return btrfs_commit_transaction(trans, root); |
386 | else | 397 | else |
387 | wake_up_process(info->transaction_kthread); | 398 | wake_up_process(info->transaction_kthread); |
388 | } | 399 | } |
389 | 400 | ||
390 | mutex_lock(&info->trans_mutex); | 401 | if (lock) |
402 | mutex_lock(&info->trans_mutex); | ||
391 | WARN_ON(cur_trans != info->running_transaction); | 403 | WARN_ON(cur_trans != info->running_transaction); |
392 | WARN_ON(cur_trans->num_writers < 1); | 404 | WARN_ON(cur_trans->num_writers < 1); |
393 | cur_trans->num_writers--; | 405 | cur_trans->num_writers--; |
@@ -395,7 +407,8 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
395 | if (waitqueue_active(&cur_trans->writer_wait)) | 407 | if (waitqueue_active(&cur_trans->writer_wait)) |
396 | wake_up(&cur_trans->writer_wait); | 408 | wake_up(&cur_trans->writer_wait); |
397 | put_transaction(cur_trans); | 409 | put_transaction(cur_trans); |
398 | mutex_unlock(&info->trans_mutex); | 410 | if (lock) |
411 | mutex_unlock(&info->trans_mutex); | ||
399 | 412 | ||
400 | if (current->journal_info == trans) | 413 | if (current->journal_info == trans) |
401 | current->journal_info = NULL; | 414 | current->journal_info = NULL; |
@@ -411,13 +424,19 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
411 | int btrfs_end_transaction(struct btrfs_trans_handle *trans, | 424 | int btrfs_end_transaction(struct btrfs_trans_handle *trans, |
412 | struct btrfs_root *root) | 425 | struct btrfs_root *root) |
413 | { | 426 | { |
414 | return __btrfs_end_transaction(trans, root, 0); | 427 | return __btrfs_end_transaction(trans, root, 0, 1); |
415 | } | 428 | } |
416 | 429 | ||
417 | int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, | 430 | int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, |
418 | struct btrfs_root *root) | 431 | struct btrfs_root *root) |
419 | { | 432 | { |
420 | return __btrfs_end_transaction(trans, root, 1); | 433 | return __btrfs_end_transaction(trans, root, 1, 1); |
434 | } | ||
435 | |||
436 | int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans, | ||
437 | struct btrfs_root *root) | ||
438 | { | ||
439 | return __btrfs_end_transaction(trans, root, 0, 0); | ||
421 | } | 440 | } |
422 | 441 | ||
423 | /* | 442 | /* |
@@ -966,6 +985,8 @@ static void update_super_roots(struct btrfs_root *root) | |||
966 | super->root = root_item->bytenr; | 985 | super->root = root_item->bytenr; |
967 | super->generation = root_item->generation; | 986 | super->generation = root_item->generation; |
968 | super->root_level = root_item->level; | 987 | super->root_level = root_item->level; |
988 | if (super->cache_generation != 0 || btrfs_test_opt(root, SPACE_CACHE)) | ||
989 | super->cache_generation = root_item->generation; | ||
969 | } | 990 | } |
970 | 991 | ||
971 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info) | 992 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info) |