|
@@ -422,6 +422,35 @@ struct iscsi_tpg_np *iscsit_tpg_locate_child_np(
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+static bool iscsit_tpg_check_network_portal(
|
|
|
+ struct iscsi_tiqn *tiqn,
|
|
|
+ struct __kernel_sockaddr_storage *sockaddr,
|
|
|
+ int network_transport)
|
|
|
+{
|
|
|
+ struct iscsi_portal_group *tpg;
|
|
|
+ struct iscsi_tpg_np *tpg_np;
|
|
|
+ struct iscsi_np *np;
|
|
|
+ bool match = false;
|
|
|
+
|
|
|
+ spin_lock(&tiqn->tiqn_tpg_lock);
|
|
|
+ list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
|
|
|
+
|
|
|
+ spin_lock(&tpg->tpg_np_lock);
|
|
|
+ list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) {
|
|
|
+ np = tpg_np->tpg_np;
|
|
|
+
|
|
|
+ match = iscsit_check_np_match(sockaddr, np,
|
|
|
+ network_transport);
|
|
|
+ if (match == true)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ spin_unlock(&tpg->tpg_np_lock);
|
|
|
+ }
|
|
|
+ spin_unlock(&tiqn->tiqn_tpg_lock);
|
|
|
+
|
|
|
+ return match;
|
|
|
+}
|
|
|
+
|
|
|
struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
|
|
|
struct iscsi_portal_group *tpg,
|
|
|
struct __kernel_sockaddr_storage *sockaddr,
|
|
@@ -432,6 +461,16 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
|
|
|
struct iscsi_np *np;
|
|
|
struct iscsi_tpg_np *tpg_np;
|
|
|
|
|
|
+ if (!tpg_np_parent) {
|
|
|
+ if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr,
|
|
|
+ network_transport) == true) {
|
|
|
+ pr_err("Network Portal: %s already exists on a"
|
|
|
+ " different TPG on %s\n", ip_str,
|
|
|
+ tpg->tpg_tiqn->tiqn);
|
|
|
+ return ERR_PTR(-EEXIST);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
tpg_np = kzalloc(sizeof(struct iscsi_tpg_np), GFP_KERNEL);
|
|
|
if (!tpg_np) {
|
|
|
pr_err("Unable to allocate memory for"
|