|
@@ -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,
|
|
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,
|
|
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 ((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 */
|
|
/* 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->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)
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- 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) {
|
|
|
|
- if ((entry->v.chn == v->chn) &&
|
|
|
|
- (entry->v.tgt == v->tgt) &&
|
|
|
|
- (entry->v.lun == v->lun)) {
|
|
|
|
- goto found;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- spin_unlock_irqrestore(&info->v2p_lock, flags);
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
-found:
|
|
|
|
- /* Delete the translation entry specfied */
|
|
|
|
- __scsiback_del_translation_entry(entry);
|
|
|
|
|
|
+ entry = scsiback_chk_translation_entry(info, v);
|
|
|
|
+ if (entry)
|
|
|
|
+ __scsiback_del_translation_entry(entry);
|
|
|
|
+ else
|
|
|
|
+ ret = -ENOENT;
|
|
|
|
|
|
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)) {
|