From c9e2f531be000af652927ee0af3a0f24f8e9e046 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 8 Feb 2016 15:30:19 +0100 Subject: [PATCH] xen/scsiback: avoid warnings when adding multiple LUNs to a domain When adding more than one LUN to a frontend a warning for a failed assignment is issued in dom0 for each already existing LUN. Avoid this warning by checking for a LUN already existing when existence is allowed (scsiback_do_add_lun() called with try == 1). As the LUN existence check is needed now for a third time, factor it out into a function. This in turn leads to a more or less complete rewrite of scsiback_del_translation_entry() which will now return a proper error code in case of failure. Signed-off-by: Juergen Gross Reviewed-by: Boris Ostrovsky Signed-off-by: David Vrabel --- drivers/xen/xen-scsiback.c | 70 ++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 51387d75c7bf..c46ee189466f 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -848,6 +848,24 @@ static int scsiback_map(struct vscsibk_info *info) return scsiback_init_sring(info, ring_ref, evtchn); } +/* + Check for a translation entry being present +*/ +static struct v2p_entry *scsiback_chk_translation_entry( + struct vscsibk_info *info, struct ids_tuple *v) +{ + struct list_head *head = &(info->v2p_entry_lists); + struct v2p_entry *entry; + + list_for_each_entry(entry, head, l) + if ((entry->v.chn == v->chn) && + (entry->v.tgt == v->tgt) && + (entry->v.lun == v->lun)) + return entry; + + return NULL; +} + /* Add a new translation entry */ @@ -855,9 +873,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, char *phy, struct ids_tuple *v) { int err = 0; - struct v2p_entry *entry; struct v2p_entry *new; - struct list_head *head = &(info->v2p_entry_lists); unsigned long flags; char *lunp; unsigned long long unpacked_lun; @@ -917,15 +933,10 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, spin_lock_irqsave(&info->v2p_lock, flags); /* Check double assignment to identical virtual ID */ - list_for_each_entry(entry, head, l) { - if ((entry->v.chn == v->chn) && - (entry->v.tgt == v->tgt) && - (entry->v.lun == v->lun)) { - pr_warn("Virtual ID is already used. Assignment was not performed.\n"); - err = -EEXIST; - goto out; - } - + if (scsiback_chk_translation_entry(info, v)) { + pr_warn("Virtual ID is already used. Assignment was not performed.\n"); + err = -EEXIST; + goto out; } /* Create a new translation entry and add to the list */ @@ -933,7 +944,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, new->v = *v; new->tpg = tpg; new->lun = unpacked_lun; - list_add_tail(&new->l, head); + list_add_tail(&new->l, &info->v2p_entry_lists); out: spin_unlock_irqrestore(&info->v2p_lock, flags); @@ -956,39 +967,40 @@ static void __scsiback_del_translation_entry(struct v2p_entry *entry) } /* - Delete the translation entry specfied + Delete the translation entry specified */ static int scsiback_del_translation_entry(struct vscsibk_info *info, struct ids_tuple *v) { struct v2p_entry *entry; - struct list_head *head = &(info->v2p_entry_lists); unsigned long flags; + int ret = 0; spin_lock_irqsave(&info->v2p_lock, flags); /* Find out the translation entry specified */ - list_for_each_entry(entry, head, l) { - if ((entry->v.chn == v->chn) && - (entry->v.tgt == v->tgt) && - (entry->v.lun == v->lun)) { - goto found; - } - } + entry = scsiback_chk_translation_entry(info, v); + if (entry) + __scsiback_del_translation_entry(entry); + else + ret = -ENOENT; spin_unlock_irqrestore(&info->v2p_lock, flags); - return 1; - -found: - /* Delete the translation entry specfied */ - __scsiback_del_translation_entry(entry); - - spin_unlock_irqrestore(&info->v2p_lock, flags); - return 0; + return ret; } static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, char *phy, struct ids_tuple *vir, int try) { + struct v2p_entry *entry; + unsigned long flags; + + if (try) { + spin_lock_irqsave(&info->v2p_lock, flags); + entry = scsiback_chk_translation_entry(info, vir); + spin_unlock_irqrestore(&info->v2p_lock, flags); + if (entry) + return; + } if (!scsiback_add_translation_entry(info, phy, vir)) { if (xenbus_printf(XBT_NIL, info->dev->nodename, state, "%d", XenbusStateInitialised)) {