aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2014-09-11 16:22:14 -0400
committerChris Mason <clm@fb.com>2014-09-16 19:12:19 -0400
commit125c4cf9f37c98fed2c08229b31358cfec63dcf6 (patch)
treea5aaaa434b9be066a0b236a5acfe4406c35dfd21 /fs/btrfs
parentb0d5d10f41a0f1cd839408dd94427f2db3553bca (diff)
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 <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/btrfs_inode.h13
-rw-r--r--fs/btrfs/tree-log.c14
2 files changed, 13 insertions, 14 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 43527fd78825..56b8522d5767 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -234,8 +234,17 @@ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
234 BTRFS_I(inode)->last_sub_trans <= 234 BTRFS_I(inode)->last_sub_trans <=
235 BTRFS_I(inode)->last_log_commit && 235 BTRFS_I(inode)->last_log_commit &&
236 BTRFS_I(inode)->last_sub_trans <= 236 BTRFS_I(inode)->last_sub_trans <=
237 BTRFS_I(inode)->root->last_log_commit) 237 BTRFS_I(inode)->root->last_log_commit) {
238 return 1; 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 }
239 return 0; 248 return 0;
240} 249}
241 250
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index d296efe2d3e7..1d1ba083ca6e 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4093,18 +4093,8 @@ log_extents:
4093 } 4093 }
4094 } 4094 }
4095 4095
4096 write_lock(&em_tree->lock); 4096 BTRFS_I(inode)->logged_trans = trans->transid;
4097 /* 4097 BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans;
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);
4108out_unlock: 4098out_unlock:
4109 if (unlikely(err)) 4099 if (unlikely(err))
4110 btrfs_put_logged_extents(&logged_list); 4100 btrfs_put_logged_extents(&logged_list);