Skip to content

Commit a879719

Browse files
committed
Btrfs: send, don't BUG_ON() when an empty symlink is found
When a symlink is successfully created it always has an inline extent containing the source path. However if an error happens when creating the symlink, we can leave in the subvolume's tree a symlink inode without any such inline extent item - this happens if after btrfs_symlink() calls btrfs_end_transaction() and before it calls the inode eviction handler (through the final iput() call), the transaction gets committed and a crash happens before the eviction handler gets called, or if a snapshot of the subvolume is made before the eviction handler gets called. Sadly we can't just avoid this by making btrfs_symlink() call btrfs_end_transaction() after it calls the eviction handler, because the later can commit the current transaction before it removes any items from the subvolume tree (if it encounters ENOSPC errors while reserving space for removing all the items). So make send fail more gracefully, with an -EIO error, and print a message to dmesg/syslog informing that there's an empty symlink inode, so that the user can delete the empty symlink or do something else about it. Reported-by: Stephen R. van den Berg <[email protected]> Signed-off-by: Filipe Manana <[email protected]>
1 parent 2bc0bb5 commit a879719

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

fs/btrfs/send.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1469,7 +1469,21 @@ static int read_symlink(struct btrfs_root *root,
14691469
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
14701470
if (ret < 0)
14711471
goto out;
1472-
BUG_ON(ret);
1472+
if (ret) {
1473+
/*
1474+
* An empty symlink inode. Can happen in rare error paths when
1475+
* creating a symlink (transaction committed before the inode
1476+
* eviction handler removed the symlink inode items and a crash
1477+
* happened in between or the subvol was snapshoted in between).
1478+
* Print an informative message to dmesg/syslog so that the user
1479+
* can delete the symlink.
1480+
*/
1481+
btrfs_err(root->fs_info,
1482+
"Found empty symlink inode %llu at root %llu",
1483+
ino, root->root_key.objectid);
1484+
ret = -EIO;
1485+
goto out;
1486+
}
14731487

14741488
ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
14751489
struct btrfs_file_extent_item);

0 commit comments

Comments
 (0)