mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
btrfs: handle lack of space when cleaning up verity items
When enable_verity() hits the qgroup limit, rollback_verity() needs its
own metadata reservation. When the qgroup limit or lack of space refuses
the rollback, the whole filesystem is forced read-only even though the
qgroup limit was for one subvolume only. Also orphan cleanup at the next
mount fails the same way, so the leftover items are never removed: with
-EDQUOT the subvolume stays unreachable, and with -ENOSPC on a full
filesystem the next read-write mount fails.
Start transactions with btrfs_start_transaction_fallback_global_rsv() in
btrfs_orphan_cleanup(), drop_verity_items() and rollback_verity(). Those
calls only delete items and free the space in the end, so they may use
the global reserve and skip the qgroup limit, which avoids -ENOSPC and
-EDQUOT.
Fixes: 146054090b ("btrfs: initial fsverity support")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Daniel Linjama <daniel@dev.linjama.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
cc337324cc
commit
76bf149cd0
|
|
@ -3892,7 +3892,8 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
|
|||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
/* Only deletes the orphan. */
|
||||
trans = btrfs_start_transaction_fallback_global_rsv(root, 1);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,20 @@ static loff_t merkle_file_pos(const struct inode *inode)
|
|||
return rounded;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a transaction for removing verity items or the verity orphan.
|
||||
*
|
||||
* Like unlink, this only deletes items and frees space in the end, so the
|
||||
* reservation may come from the global reserve when the filesystem is full
|
||||
* (-ENOSPC) and is not subject to the qgroup limit (-EDQUOT). Otherwise a
|
||||
* failed enable could never be cleaned up in either situation.
|
||||
*/
|
||||
static struct btrfs_trans_handle *start_verity_cleanup_trans(struct btrfs_root *root,
|
||||
unsigned int num_items)
|
||||
{
|
||||
return btrfs_start_transaction_fallback_global_rsv(root, num_items);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop all the items for this inode with this key_type.
|
||||
*
|
||||
|
|
@ -120,7 +134,7 @@ static int drop_verity_items(struct btrfs_inode *inode, u8 key_type)
|
|||
|
||||
while (1) {
|
||||
/* 1 for the item being dropped */
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
trans = start_verity_cleanup_trans(root, 1);
|
||||
if (IS_ERR(trans))
|
||||
return PTR_ERR(trans);
|
||||
|
||||
|
|
@ -466,7 +480,7 @@ static int rollback_verity(struct btrfs_inode *inode)
|
|||
* 1 for updating the inode flag
|
||||
* 1 for deleting the orphan
|
||||
*/
|
||||
trans = btrfs_start_transaction(root, 2);
|
||||
trans = start_verity_cleanup_trans(root, 2);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
trans = NULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user