diff options
author | Filipe Manana <fdmanana@suse.com> | 2014-09-06 23:34:39 +0200 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-09-08 22:56:43 +0200 |
commit | 49dae1bc1c665817e434d01eefaa11967f618243 (patch) | |
tree | 4c306620e23a5c0446ce1826919ed5e62f8f0a5c /fs/btrfs/tree-log.h | |
parent | Btrfs: kfree()ing ERR_PTRs (diff) | |
download | linux-49dae1bc1c665817e434d01eefaa11967f618243.tar.xz linux-49dae1bc1c665817e434d01eefaa11967f618243.zip |
Btrfs: fix fsync data loss after a ranged fsync
While we're doing a full fsync (when the inode has the flag
BTRFS_INODE_NEEDS_FULL_SYNC set) that is ranged too (covers only a
portion of the file), we might have ordered operations that are started
before or while we're logging the inode and that fall outside the fsync
range.
Therefore when a full ranged fsync finishes don't remove every extent
map from the list of modified extent maps - as for some of them, that
fall outside our fsync range, their respective ordered operation hasn't
finished yet, meaning the corresponding file extent item wasn't inserted
into the fs/subvol tree yet and therefore we didn't log it, and we must
let the next fast fsync (one that checks only the modified list) see this
extent map and log a matching file extent item to the log btree and wait
for its ordered operation to finish (if it's still ongoing).
A test case for xfstests follows.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/tree-log.h')
-rw-r--r-- | fs/btrfs/tree-log.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/btrfs/tree-log.h b/fs/btrfs/tree-log.h index 7f5b41bd5373..e2e798ae7cd7 100644 --- a/fs/btrfs/tree-log.h +++ b/fs/btrfs/tree-log.h @@ -59,6 +59,8 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, int btrfs_recover_log_trees(struct btrfs_root *tree_root); int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct dentry *dentry, + const loff_t start, + const loff_t end, struct btrfs_log_ctx *ctx); int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, struct btrfs_root *root, |