Skip to content

Commit 125c4cf

Browse files
fdmananamasoncl
authored andcommitted
Btrfs: set inode's logged_trans/last_log_commit after ranged fsync
When a ranged fsync finishes if there are still extent maps in the modified list, still set the inode's logged_trans and last_log_commit. This is important in case an inode is fsync'ed and unlinked in the same transaction, to ensure its inode ref gets deleted from the log and the respective dentries in its parent are deleted too from the log (if the parent directory was fsync'ed in the same transaction). Instead make btrfs_inode_in_log() return false if the list of modified extent maps isn't empty. This is an incremental on top of the v4 version of the patch: "Btrfs: fix fsync data loss after a ranged fsync" which was added to its v5, but didn't make it on time. Signed-off-by: Filipe Manana <[email protected]> Signed-off-by: Chris Mason <[email protected]>
1 parent b0d5d10 commit 125c4cf

File tree

2 files changed

+13
-14
lines changed

2 files changed

+13
-14
lines changed

fs/btrfs/btrfs_inode.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,17 @@ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
234234
BTRFS_I(inode)->last_sub_trans <=
235235
BTRFS_I(inode)->last_log_commit &&
236236
BTRFS_I(inode)->last_sub_trans <=
237-
BTRFS_I(inode)->root->last_log_commit)
238-
return 1;
237+
BTRFS_I(inode)->root->last_log_commit) {
238+
/*
239+
* After a ranged fsync we might have left some extent maps
240+
* (that fall outside the fsync's range). So return false
241+
* here if the list isn't empty, to make sure btrfs_log_inode()
242+
* will be called and process those extent maps.
243+
*/
244+
smp_mb();
245+
if (list_empty(&BTRFS_I(inode)->extent_tree.modified_extents))
246+
return 1;
247+
}
239248
return 0;
240249
}
241250

fs/btrfs/tree-log.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4093,18 +4093,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
40934093
}
40944094
}
40954095

4096-
write_lock(&em_tree->lock);
4097-
/*
4098-
* If we're doing a ranged fsync and there are still modified extents
4099-
* in the list, we must run on the next fsync call as it might cover
4100-
* those extents (a full fsync or an fsync for other range).
4101-
*/
4102-
if (list_empty(&em_tree->modified_extents)) {
4103-
BTRFS_I(inode)->logged_trans = trans->transid;
4104-
BTRFS_I(inode)->last_log_commit =
4105-
BTRFS_I(inode)->last_sub_trans;
4106-
}
4107-
write_unlock(&em_tree->lock);
4096+
BTRFS_I(inode)->logged_trans = trans->transid;
4097+
BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans;
41084098
out_unlock:
41094099
if (unlikely(err))
41104100
btrfs_put_logged_extents(&logged_list);

0 commit comments

Comments
 (0)