diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-02-20 05:08:51 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fb.com> | 2014-03-10 15:16:39 -0400 |
commit | 5c902ba6223f6a6575054226931fafc51314a25f (patch) | |
tree | dc43b931ac9d6ad7006093db05a8517fadba9320 /fs/btrfs/tree-log.c | |
parent | 7813b3db0a9ec77ff1f4b3ee3fb4925848395d59 (diff) |
Btrfs: use ACCESS_ONCE to prevent the optimize accesses to ->last_trans_log_full_commit
->last_trans_log_full_commit may be changed by the other tasks without lock,
so we need prevent the compiler from the optimize access just like
tmp = fs_info->last_trans_log_full_commit
if (tmp == ...)
...
<do something>
if (tmp == ...)
...
In fact, we need get the new value of ->last_trans_log_full_commit during
the second access. Fix it by ACCESS_ONCE().
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 7c449c699bed..5a4e10b9ac3e 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2375,14 +2375,14 @@ static int wait_log_commit(struct btrfs_trans_handle *trans, | |||
2375 | &wait, TASK_UNINTERRUPTIBLE); | 2375 | &wait, TASK_UNINTERRUPTIBLE); |
2376 | mutex_unlock(&root->log_mutex); | 2376 | mutex_unlock(&root->log_mutex); |
2377 | 2377 | ||
2378 | if (root->fs_info->last_trans_log_full_commit != | 2378 | if (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) != |
2379 | trans->transid && root->log_transid < transid + 2 && | 2379 | trans->transid && root->log_transid < transid + 2 && |
2380 | atomic_read(&root->log_commit[index])) | 2380 | atomic_read(&root->log_commit[index])) |
2381 | schedule(); | 2381 | schedule(); |
2382 | 2382 | ||
2383 | finish_wait(&root->log_commit_wait[index], &wait); | 2383 | finish_wait(&root->log_commit_wait[index], &wait); |
2384 | mutex_lock(&root->log_mutex); | 2384 | mutex_lock(&root->log_mutex); |
2385 | } while (root->fs_info->last_trans_log_full_commit != | 2385 | } while (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) != |
2386 | trans->transid && root->log_transid < transid + 2 && | 2386 | trans->transid && root->log_transid < transid + 2 && |
2387 | atomic_read(&root->log_commit[index])); | 2387 | atomic_read(&root->log_commit[index])); |
2388 | return 0; | 2388 | return 0; |
@@ -2392,12 +2392,12 @@ static void wait_for_writer(struct btrfs_trans_handle *trans, | |||
2392 | struct btrfs_root *root) | 2392 | struct btrfs_root *root) |
2393 | { | 2393 | { |
2394 | DEFINE_WAIT(wait); | 2394 | DEFINE_WAIT(wait); |
2395 | while (root->fs_info->last_trans_log_full_commit != | 2395 | while (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) != |
2396 | trans->transid && atomic_read(&root->log_writers)) { | 2396 | trans->transid && atomic_read(&root->log_writers)) { |
2397 | prepare_to_wait(&root->log_writer_wait, | 2397 | prepare_to_wait(&root->log_writer_wait, |
2398 | &wait, TASK_UNINTERRUPTIBLE); | 2398 | &wait, TASK_UNINTERRUPTIBLE); |
2399 | mutex_unlock(&root->log_mutex); | 2399 | mutex_unlock(&root->log_mutex); |
2400 | if (root->fs_info->last_trans_log_full_commit != | 2400 | if (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) != |
2401 | trans->transid && atomic_read(&root->log_writers)) | 2401 | trans->transid && atomic_read(&root->log_writers)) |
2402 | schedule(); | 2402 | schedule(); |
2403 | mutex_lock(&root->log_mutex); | 2403 | mutex_lock(&root->log_mutex); |
@@ -2456,7 +2456,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2456 | } | 2456 | } |
2457 | 2457 | ||
2458 | /* bail out if we need to do a full commit */ | 2458 | /* bail out if we need to do a full commit */ |
2459 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2459 | if (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) == |
2460 | trans->transid) { | ||
2460 | ret = -EAGAIN; | 2461 | ret = -EAGAIN; |
2461 | btrfs_free_logged_extents(log, log_transid); | 2462 | btrfs_free_logged_extents(log, log_transid); |
2462 | mutex_unlock(&root->log_mutex); | 2463 | mutex_unlock(&root->log_mutex); |
@@ -2515,7 +2516,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2515 | mutex_unlock(&log_root_tree->log_mutex); | 2516 | mutex_unlock(&log_root_tree->log_mutex); |
2516 | goto out; | 2517 | goto out; |
2517 | } | 2518 | } |
2518 | root->fs_info->last_trans_log_full_commit = trans->transid; | 2519 | ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) = |
2520 | trans->transid; | ||
2519 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2521 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2520 | btrfs_free_logged_extents(log, log_transid); | 2522 | btrfs_free_logged_extents(log, log_transid); |
2521 | mutex_unlock(&log_root_tree->log_mutex); | 2523 | mutex_unlock(&log_root_tree->log_mutex); |
@@ -2547,7 +2549,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2547 | * now that we've moved on to the tree of log tree roots, | 2549 | * now that we've moved on to the tree of log tree roots, |
2548 | * check the full commit flag again | 2550 | * check the full commit flag again |
2549 | */ | 2551 | */ |
2550 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2552 | if (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) == |
2553 | trans->transid) { | ||
2551 | blk_finish_plug(&plug); | 2554 | blk_finish_plug(&plug); |
2552 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2555 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2553 | btrfs_free_logged_extents(log, log_transid); | 2556 | btrfs_free_logged_extents(log, log_transid); |