Commit c9e2f531 authored by Juergen Gross's avatar Juergen Gross Committed by David Vrabel

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: default avatarJuergen Gross <jgross@suse.com>
Reviewed-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: default avatarDavid Vrabel <david.vrabel@citrix.com>
parent f285aa8d
...@@ -848,6 +848,24 @@ static int scsiback_map(struct vscsibk_info *info) ...@@ -848,6 +848,24 @@ static int scsiback_map(struct vscsibk_info *info)
return scsiback_init_sring(info, ring_ref, evtchn); 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 Add a new translation entry
*/ */
...@@ -855,9 +873,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, ...@@ -855,9 +873,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
char *phy, struct ids_tuple *v) char *phy, struct ids_tuple *v)
{ {
int err = 0; int err = 0;
struct v2p_entry *entry;
struct v2p_entry *new; struct v2p_entry *new;
struct list_head *head = &(info->v2p_entry_lists);
unsigned long flags; unsigned long flags;
char *lunp; char *lunp;
unsigned long long unpacked_lun; unsigned long long unpacked_lun;
...@@ -917,15 +933,10 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, ...@@ -917,15 +933,10 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
spin_lock_irqsave(&info->v2p_lock, flags); spin_lock_irqsave(&info->v2p_lock, flags);
/* Check double assignment to identical virtual ID */ /* Check double assignment to identical virtual ID */
list_for_each_entry(entry, head, l) { if (scsiback_chk_translation_entry(info, v)) {
if ((entry->v.chn == v->chn) && pr_warn("Virtual ID is already used. Assignment was not performed.\n");
(entry->v.tgt == v->tgt) && err = -EEXIST;
(entry->v.lun == v->lun)) { goto out;
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 */ /* Create a new translation entry and add to the list */
...@@ -933,7 +944,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, ...@@ -933,7 +944,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
new->v = *v; new->v = *v;
new->tpg = tpg; new->tpg = tpg;
new->lun = unpacked_lun; new->lun = unpacked_lun;
list_add_tail(&new->l, head); list_add_tail(&new->l, &info->v2p_entry_lists);
out: out:
spin_unlock_irqrestore(&info->v2p_lock, flags); spin_unlock_irqrestore(&info->v2p_lock, flags);
...@@ -956,39 +967,40 @@ static void __scsiback_del_translation_entry(struct v2p_entry *entry) ...@@ -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, static int scsiback_del_translation_entry(struct vscsibk_info *info,
struct ids_tuple *v) struct ids_tuple *v)
{ {
struct v2p_entry *entry; struct v2p_entry *entry;
struct list_head *head = &(info->v2p_entry_lists);
unsigned long flags; unsigned long flags;
int ret = 0;
spin_lock_irqsave(&info->v2p_lock, flags); spin_lock_irqsave(&info->v2p_lock, flags);
/* Find out the translation entry specified */ /* Find out the translation entry specified */
list_for_each_entry(entry, head, l) { entry = scsiback_chk_translation_entry(info, v);
if ((entry->v.chn == v->chn) && if (entry)
(entry->v.tgt == v->tgt) && __scsiback_del_translation_entry(entry);
(entry->v.lun == v->lun)) { else
goto found; 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); spin_unlock_irqrestore(&info->v2p_lock, flags);
return 0; return ret;
} }
static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state,
char *phy, struct ids_tuple *vir, int try) 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 (!scsiback_add_translation_entry(info, phy, vir)) {
if (xenbus_printf(XBT_NIL, info->dev->nodename, state, if (xenbus_printf(XBT_NIL, info->dev->nodename, state,
"%d", XenbusStateInitialised)) { "%d", XenbusStateInitialised)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment