diff options
author | Juergen Gross <jgross@suse.com> | 2016-02-08 09:30:19 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@citrix.com> | 2016-02-08 11:51:36 -0500 |
commit | c9e2f531be000af652927ee0af3a0f24f8e9e046 (patch) | |
tree | 8bcf8cefe2dd2c80cfbf9d6a9c627aef2c63cc8c | |
parent | f285aa8db7cc4432c1a03f8b55ff34fe96317c11 (diff) |
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>
-rw-r--r-- | drivers/xen/xen-scsiback.c | 70 |
1 files 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 | |||
@@ -849,15 +849,31 @@ static int scsiback_map(struct vscsibk_info *info) | |||
849 | } | 849 | } |
850 | 850 | ||
851 | /* | 851 | /* |
852 | Check for a translation entry being present | ||
853 | */ | ||
854 | static struct v2p_entry *scsiback_chk_translation_entry( | ||
855 | struct vscsibk_info *info, struct ids_tuple *v) | ||
856 | { | ||
857 | struct list_head *head = &(info->v2p_entry_lists); | ||
858 | struct v2p_entry *entry; | ||
859 | |||
860 | list_for_each_entry(entry, head, l) | ||
861 | if ((entry->v.chn == v->chn) && | ||
862 | (entry->v.tgt == v->tgt) && | ||
863 | (entry->v.lun == v->lun)) | ||
864 | return entry; | ||
865 | |||
866 | return NULL; | ||
867 | } | ||
868 | |||
869 | /* | ||
852 | Add a new translation entry | 870 | Add a new translation entry |
853 | */ | 871 | */ |
854 | static int scsiback_add_translation_entry(struct vscsibk_info *info, | 872 | static int scsiback_add_translation_entry(struct vscsibk_info *info, |
855 | char *phy, struct ids_tuple *v) | 873 | char *phy, struct ids_tuple *v) |
856 | { | 874 | { |
857 | int err = 0; | 875 | int err = 0; |
858 | struct v2p_entry *entry; | ||
859 | struct v2p_entry *new; | 876 | struct v2p_entry *new; |
860 | struct list_head *head = &(info->v2p_entry_lists); | ||
861 | unsigned long flags; | 877 | unsigned long flags; |
862 | char *lunp; | 878 | char *lunp; |
863 | unsigned long long unpacked_lun; | 879 | unsigned long long unpacked_lun; |
@@ -917,15 +933,10 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info, | |||
917 | spin_lock_irqsave(&info->v2p_lock, flags); | 933 | spin_lock_irqsave(&info->v2p_lock, flags); |
918 | 934 | ||
919 | /* Check double assignment to identical virtual ID */ | 935 | /* Check double assignment to identical virtual ID */ |
920 | list_for_each_entry(entry, head, l) { | 936 | if (scsiback_chk_translation_entry(info, v)) { |
921 | if ((entry->v.chn == v->chn) && | 937 | pr_warn("Virtual ID is already used. Assignment was not performed.\n"); |
922 | (entry->v.tgt == v->tgt) && | 938 | err = -EEXIST; |
923 | (entry->v.lun == v->lun)) { | 939 | goto out; |
924 | pr_warn("Virtual ID is already used. Assignment was not performed.\n"); | ||
925 | err = -EEXIST; | ||
926 | goto out; | ||
927 | } | ||
928 | |||
929 | } | 940 | } |
930 | 941 | ||
931 | /* Create a new translation entry and add to the list */ | 942 | /* 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 | new->v = *v; | 944 | new->v = *v; |
934 | new->tpg = tpg; | 945 | new->tpg = tpg; |
935 | new->lun = unpacked_lun; | 946 | new->lun = unpacked_lun; |
936 | list_add_tail(&new->l, head); | 947 | list_add_tail(&new->l, &info->v2p_entry_lists); |
937 | 948 | ||
938 | out: | 949 | out: |
939 | spin_unlock_irqrestore(&info->v2p_lock, flags); | 950 | spin_unlock_irqrestore(&info->v2p_lock, flags); |
@@ -956,39 +967,40 @@ static void __scsiback_del_translation_entry(struct v2p_entry *entry) | |||
956 | } | 967 | } |
957 | 968 | ||
958 | /* | 969 | /* |
959 | Delete the translation entry specfied | 970 | Delete the translation entry specified |
960 | */ | 971 | */ |
961 | static int scsiback_del_translation_entry(struct vscsibk_info *info, | 972 | static int scsiback_del_translation_entry(struct vscsibk_info *info, |
962 | struct ids_tuple *v) | 973 | struct ids_tuple *v) |
963 | { | 974 | { |
964 | struct v2p_entry *entry; | 975 | struct v2p_entry *entry; |
965 | struct list_head *head = &(info->v2p_entry_lists); | ||
966 | unsigned long flags; | 976 | unsigned long flags; |
977 | int ret = 0; | ||
967 | 978 | ||
968 | spin_lock_irqsave(&info->v2p_lock, flags); | 979 | spin_lock_irqsave(&info->v2p_lock, flags); |
969 | /* Find out the translation entry specified */ | 980 | /* Find out the translation entry specified */ |
970 | list_for_each_entry(entry, head, l) { | 981 | entry = scsiback_chk_translation_entry(info, v); |
971 | if ((entry->v.chn == v->chn) && | 982 | if (entry) |
972 | (entry->v.tgt == v->tgt) && | 983 | __scsiback_del_translation_entry(entry); |
973 | (entry->v.lun == v->lun)) { | 984 | else |
974 | goto found; | 985 | ret = -ENOENT; |
975 | } | ||
976 | } | ||
977 | |||
978 | spin_unlock_irqrestore(&info->v2p_lock, flags); | ||
979 | return 1; | ||
980 | |||
981 | found: | ||
982 | /* Delete the translation entry specfied */ | ||
983 | __scsiback_del_translation_entry(entry); | ||
984 | 986 | ||
985 | spin_unlock_irqrestore(&info->v2p_lock, flags); | 987 | spin_unlock_irqrestore(&info->v2p_lock, flags); |
986 | return 0; | 988 | return ret; |
987 | } | 989 | } |
988 | 990 | ||
989 | static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, | 991 | static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, |
990 | char *phy, struct ids_tuple *vir, int try) | 992 | char *phy, struct ids_tuple *vir, int try) |
991 | { | 993 | { |
994 | struct v2p_entry *entry; | ||
995 | unsigned long flags; | ||
996 | |||
997 | if (try) { | ||
998 | spin_lock_irqsave(&info->v2p_lock, flags); | ||
999 | entry = scsiback_chk_translation_entry(info, vir); | ||
1000 | spin_unlock_irqrestore(&info->v2p_lock, flags); | ||
1001 | if (entry) | ||
1002 | return; | ||
1003 | } | ||
992 | if (!scsiback_add_translation_entry(info, phy, vir)) { | 1004 | if (!scsiback_add_translation_entry(info, phy, vir)) { |
993 | if (xenbus_printf(XBT_NIL, info->dev->nodename, state, | 1005 | if (xenbus_printf(XBT_NIL, info->dev->nodename, state, |
994 | "%d", XenbusStateInitialised)) { | 1006 | "%d", XenbusStateInitialised)) { |