Skip to content

Commit d50866d

Browse files
committed
Btrfs: don't leave dangling dentry if symlink creation failed
When we are creating a symlink we might fail with an error after we created its inode and added the corresponding directory indexes to its parent inode. In this case we end up never removing the directory indexes because the inode eviction handler, called for our symlink inode on the final iput(), only removes items associated with the symlink inode and not with the parent inode. Example: $ mkfs.btrfs -f /dev/sdi $ mount /dev/sdi /mnt $ touch /mnt/foo $ ln -s /mnt/foo /mnt/bar ln: failed to create symbolic link ‘bar’: Cannot allocate memory $ umount /mnt $ btrfsck /dev/sdi Checking filesystem on /dev/sdi UUID: d5acb5ba-31bd-42da-b456-89dca2e716e1 checking extents checking free space cache checking fs roots root 5 inode 258 errors 2001, no inode item, link count wrong unresolved ref dir 256 index 3 namelen 3 name bar filetype 7 errors 4, no inode ref found 131073 bytes used err is 1 total csum bytes: 0 total tree bytes: 131072 total fs tree bytes: 32768 total extent tree bytes: 16384 btree space waste bytes: 124305 file data blocks allocated: 262144 referenced 262144 btrfs-progs v4.2.3 So fix this by adding the directory index entries as the very last step of symlink creation. Signed-off-by: Filipe Manana <[email protected]>
1 parent a879719 commit d50866d

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

fs/btrfs/inode.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9693,10 +9693,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
96939693
if (err)
96949694
goto out_unlock_inode;
96959695

9696-
err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
9697-
if (err)
9698-
goto out_unlock_inode;
9699-
97009696
path = btrfs_alloc_path();
97019697
if (!path) {
97029698
err = -ENOMEM;
@@ -9733,6 +9729,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
97339729
inode_set_bytes(inode, name_len);
97349730
btrfs_i_size_write(inode, name_len);
97359731
err = btrfs_update_inode(trans, root, inode);
9732+
/*
9733+
* Last step, add directory indexes for our symlink inode. This is the
9734+
* last step to avoid extra cleanup of these indexes if an error happens
9735+
* elsewhere above.
9736+
*/
9737+
if (!err)
9738+
err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
97369739
if (err) {
97379740
drop_inode = 1;
97389741
goto out_unlock_inode;

0 commit comments

Comments
 (0)