diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-16 18:12:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-16 18:12:56 -0400 |
commit | a18f8775419d3df282dd83efdb51c5a64d092f31 (patch) | |
tree | 1e0abc5c1d30e8bc58dc23099017eca496992fd2 /fs/btrfs/tree-log.c | |
parent | 3eb514866f20c5eb74637279774b6d73b855480a (diff) | |
parent | e02d48eaaed77f6c36916a7aa65c451e1f9d9aab (diff) |
Merge tag 'for-5.3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs updates from David Sterba:
"Highlights:
- chunks that have been trimmed and unchanged since last mount are
tracked and skipped on repeated trims
- use hw assissed crc32c on more arches, speedups if native
instructions or optimized implementation is available
- the RAID56 incompat bit is automatically removed when the last
block group of that type is removed
Fixes:
- fsync fix for reflink on NODATACOW files that could lead to ENOSPC
- fix data loss after inode eviction, renaming it, and fsync it
- fix fsync not persisting dentry deletions due to inode evictions
- update ctime/mtime/iversion after hole punching
- fix compression type validation (reported by KASAN)
- send won't be allowed to start when relocation is in progress, this
can cause spurious errors or produce incorrect send stream
Core:
- new tracepoints for space update
- tree-checker: better check for end of extents for some tree items
- preparatory work for more checksum algorithms
- run delayed iput at unlink time and don't push the work to cleaner
thread where it's not properly throttled
- wrap block mapping to structures and helpers, base for further
refactoring
- split large files, part 1:
- space info handling
- block group reservations
- delayed refs
- delayed allocation
- other cleanups and refactoring"
* tag 'for-5.3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (103 commits)
btrfs: fix memory leak of path on error return path
btrfs: move the subvolume reservation stuff out of extent-tree.c
btrfs: migrate the delalloc space stuff to it's own home
btrfs: migrate btrfs_trans_release_chunk_metadata
btrfs: migrate the delayed refs rsv code
btrfs: Evaluate io_tree in find_lock_delalloc_range()
btrfs: migrate the global_block_rsv helpers to block-rsv.c
btrfs: migrate the block-rsv code to block-rsv.c
btrfs: stop using block_rsv_release_bytes everywhere
btrfs: cleanup the target logic in __btrfs_block_rsv_release
btrfs: export __btrfs_block_rsv_release
btrfs: export btrfs_block_rsv_add_bytes
btrfs: move btrfs_block_rsv definitions into it's own header
btrfs: Simplify update of space_info in __reserve_metadata_bytes()
btrfs: unexport can_overcommit
btrfs: move reserve_metadata_bytes and supporting code to space-info.c
btrfs: move dump_space_info to space-info.c
btrfs: export block_rsv_use_bytes
btrfs: move btrfs_space_info_add_*_bytes to space-info.c
btrfs: move the space info update macro to space-info.h
...
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 3fc8d854d7fb..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); |
@@ -5420,9 +5444,19 @@ log_extents: | |||
5420 | } | 5444 | } |
5421 | } | 5445 | } |
5422 | 5446 | ||
5447 | /* | ||
5448 | * Don't update last_log_commit if we logged that an inode exists after | ||
5449 | * it was loaded to memory (full_sync bit set). | ||
5450 | * This is to prevent data loss when we do a write to the inode, then | ||
5451 | * the inode gets evicted after all delalloc was flushed, then we log | ||
5452 | * it exists (due to a rename for example) and then fsync it. This last | ||
5453 | * fsync would do nothing (not logging the extents previously written). | ||
5454 | */ | ||
5423 | spin_lock(&inode->lock); | 5455 | spin_lock(&inode->lock); |
5424 | inode->logged_trans = trans->transid; | 5456 | inode->logged_trans = trans->transid; |
5425 | inode->last_log_commit = inode->last_sub_trans; | 5457 | if (inode_only != LOG_INODE_EXISTS || |
5458 | !test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags)) | ||
5459 | inode->last_log_commit = inode->last_sub_trans; | ||
5426 | spin_unlock(&inode->lock); | 5460 | spin_unlock(&inode->lock); |
5427 | out_unlock: | 5461 | out_unlock: |
5428 | mutex_unlock(&inode->log_mutex); | 5462 | mutex_unlock(&inode->log_mutex); |