summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2016-04-25 04:45:02 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-06-07 18:18:55 -0700
commitac5414fc59a48c5a9fb7b1f0e98251dbd4f2f0f4 (patch)
tree6e6381585a1407278c71edad63bf59530dedafac /fs
parentec450cd597ef50e2ebcf8e11ed12130d8a19fec9 (diff)
downloadlwn-ac5414fc59a48c5a9fb7b1f0e98251dbd4f2f0f4.tar.gz
lwn-ac5414fc59a48c5a9fb7b1f0e98251dbd4f2f0f4.zip
Btrfs: fix empty symlink after creating symlink and fsync parent dir
commit 3f9749f6e9edcf8ec569fb542efc3be35e06e84a upstream. If we create a symlink, fsync its parent directory, crash/power fail and mount the filesystem, we end up with an empty symlink, which not only is useless it's also not allowed in linux (the man page symlink(2) is well explicit about that). So we just need to make sure to fully log an inode if it's a symlink, to ensure its inline extent gets logged, ensuring the same behaviour as ext3, ext4, xfs, reiserfs, f2fs, nilfs2, etc. Example reproducer: $ mkfs.btrfs -f /dev/sdb $ mount /dev/sdb /mnt $ mkdir /mnt/testdir $ sync $ ln -s /mnt/foo /mnt/testdir/bar $ xfs_io -c fsync /mnt/testdir <power fail> $ mount /dev/sdb /mnt $ readlink /mnt/testdir/bar <empty string> A test case for fstests follows soon. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/tree-log.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 23df70e7f884..a2cd42107945 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -5157,7 +5157,7 @@ process_leaf:
}
ctx->log_new_dentries = false;
- if (type == BTRFS_FT_DIR)
+ if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK)
log_mode = LOG_INODE_ALL;
btrfs_release_path(path);
ret = btrfs_log_inode(trans, root, di_inode,