diff options
author | Juergen Gross <jgross@suse.com> | 2023-03-28 11:46:02 +0300 |
---|---|---|
committer | Juergen Gross <jgross@suse.com> | 2023-04-24 08:27:10 +0300 |
commit | b2c042cc802fe96d431821bf1cf2f0f04a3eda7d (patch) | |
tree | ff10d4244ab77b74b3d4b56003a9e84202a550b0 /drivers/xen | |
parent | fae65ef3a148079103ae935107c62f7830ab52c5 (diff) | |
download | linux-b2c042cc802fe96d431821bf1cf2f0f04a3eda7d.tar.xz |
xen/scsiback: don't call scsiback_free_translation_entry() under lock
scsiback_free_translation_entry() shouldn't be called under spinlock,
as it can sleep.
This requires to split removing a translation entry from the v2p list
from actually calling kref_put() for the entry.
Reported-by: Dan Carpenter <error27@gmail.com>
Link: https://lore.kernel.org/lkml/Y+JUIl64UDmdkboh@kadam/
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Link: https://lore.kernel.org/r/20230328084602.20729-1-jgross@suse.com
Signed-off-by: Juergen Gross <jgross@suse.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/xen-scsiback.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 954188b0b858..294f29cdc7aa 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -1010,12 +1010,6 @@ out_free: return err; } -static void __scsiback_del_translation_entry(struct v2p_entry *entry) -{ - list_del(&entry->l); - kref_put(&entry->kref, scsiback_free_translation_entry); -} - /* Delete the translation entry specified */ @@ -1024,18 +1018,20 @@ static int scsiback_del_translation_entry(struct vscsibk_info *info, { struct v2p_entry *entry; unsigned long flags; - int ret = 0; spin_lock_irqsave(&info->v2p_lock, flags); /* Find out the translation entry specified */ entry = scsiback_chk_translation_entry(info, v); if (entry) - __scsiback_del_translation_entry(entry); - else - ret = -ENOENT; + list_del(&entry->l); spin_unlock_irqrestore(&info->v2p_lock, flags); - return ret; + + if (!entry) + return -ENOENT; + + kref_put(&entry->kref, scsiback_free_translation_entry); + return 0; } static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, @@ -1239,14 +1235,19 @@ static void scsiback_release_translation_entry(struct vscsibk_info *info) { struct v2p_entry *entry, *tmp; struct list_head *head = &(info->v2p_entry_lists); + struct list_head tmp_list; unsigned long flags; spin_lock_irqsave(&info->v2p_lock, flags); - list_for_each_entry_safe(entry, tmp, head, l) - __scsiback_del_translation_entry(entry); + list_cut_before(&tmp_list, head, head); spin_unlock_irqrestore(&info->v2p_lock, flags); + + list_for_each_entry_safe(entry, tmp, &tmp_list, l) { + list_del(&entry->l); + kref_put(&entry->kref, scsiback_free_translation_entry); + } } static void scsiback_remove(struct xenbus_device *dev) |