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 <jgross@suse.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
This commit is contained in:
parent
f285aa8db7
commit
c9e2f531be
|
@ -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)) {
|
||||
|
|
Loading…
Reference in New Issue