diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 4a04659fded7..6c8297bcfeb7 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -3323,6 +3323,30 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | |||
3323 | } | 3323 | } |
3324 | 3324 | ||
3325 | /* | 3325 | /* |
3326 | * Check if an inode was logged in the current transaction. We can't always rely | ||
3327 | * on an inode's logged_trans value, because it's an in-memory only field and | ||
3328 | * therefore not persisted. This means that its value is lost if the inode gets | ||
3329 | * evicted and loaded again from disk (in which case it has a value of 0, and | ||
3330 | * certainly it is smaller then any possible transaction ID), when that happens | ||
3331 | * the full_sync flag is set in the inode's runtime flags, so on that case we | ||
3332 | * assume eviction happened and ignore the logged_trans value, assuming the | ||
3333 | * worst case, that the inode was logged before in the current transaction. | ||
3334 | */ | ||
3335 | static bool inode_logged(struct btrfs_trans_handle *trans, | ||
3336 | struct btrfs_inode *inode) | ||
3337 | { | ||
3338 | if (inode->logged_trans == trans->transid) | ||
3339 | return true; | ||
3340 | |||
3341 | if (inode->last_trans == trans->transid && | ||
3342 | test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags) && | ||
3343 | !test_bit(BTRFS_FS_LOG_RECOVERING, &trans->fs_info->flags)) | ||
3344 | return true; | ||
3345 | |||
3346 | return false; | ||
3347 | } | ||
3348 | |||
3349 | /* | ||
3326 | * If both a file and directory are logged, and unlinks or renames are | 3350 | * If both a file and directory are logged, and unlinks or renames are |
3327 | * mixed in, we have a few interesting corners: | 3351 | * mixed in, we have a few interesting corners: |
3328 | * | 3352 | * |
@@ -3356,7 +3380,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
3356 | int bytes_del = 0; | 3380 | int bytes_del = 0; |
3357 | u64 dir_ino = btrfs_ino(dir); | 3381 | u64 dir_ino = btrfs_ino(dir); |
3358 | 3382 | ||
3359 | if (dir->logged_trans < trans->transid) | 3383 | if (!inode_logged(trans, dir)) |
3360 | return 0; | 3384 | return 0; |
3361 | 3385 | ||
3362 | ret = join_running_log_trans(root); | 3386 | ret = join_running_log_trans(root); |
@@ -3460,7 +3484,7 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans, | |||
3460 | u64 index; | 3484 | u64 index; |
3461 | int ret; | 3485 | int ret; |
3462 | 3486 | ||
3463 | if (inode->logged_trans < trans->transid) | 3487 | if (!inode_logged(trans, inode)) |
3464 | return 0; | 3488 | return 0; |
3465 | 3489 | ||
3466 | ret = join_running_log_trans(root); | 3490 | ret = join_running_log_trans(root); |