target/iscsi: Fix network portal creation race

When creating network portals rapidly, such as when restoring a
configuration, LIO's code to reuse existing portals can return a false
negative if the thread hasn't run yet and set np_thread_state to
ISCSI_NP_THREAD_ACTIVE. This causes an error in the network stack
when attempting to bind to the same address/port.

This patch sets NP_THREAD_ACTIVE before the np is placed on g_np_list,
so even if the thread hasn't run yet, iscsit_get_np will return the
existing np.

Also, convert np_lock -> np_mutex + hold across adding new net portal
to g_np_list to prevent a race where two threads may attempt to create
the same network portal, resulting in one of them failing.

(nab: Add missing mutex_unlocks in iscsit_add_np failure paths)
(DanC: Fix incorrect spin_unlock -> spin_unlock_bh)

Signed-off-by: Andy Grover <agrover@redhat.com>
Cc: <stable@vger.kernel.org> #3.1+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by Andy Grover and committed by Nicholas Bellinger ee291e63 76736db3

+21 -13
+21 -13
drivers/target/iscsi/iscsi_target.c
··· 52 static LIST_HEAD(g_tiqn_list); 53 static LIST_HEAD(g_np_list); 54 static DEFINE_SPINLOCK(tiqn_lock); 55 - static DEFINE_SPINLOCK(np_lock); 56 57 static struct idr tiqn_idr; 58 struct idr sess_idr; ··· 307 return false; 308 } 309 310 static struct iscsi_np *iscsit_get_np( 311 struct __kernel_sockaddr_storage *sockaddr, 312 int network_transport) ··· 317 struct iscsi_np *np; 318 bool match; 319 320 - spin_lock_bh(&np_lock); 321 list_for_each_entry(np, &g_np_list, np_list) { 322 - spin_lock(&np->np_thread_lock); 323 if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) { 324 - spin_unlock(&np->np_thread_lock); 325 continue; 326 } 327 ··· 332 * while iscsi_tpg_add_network_portal() is called. 333 */ 334 np->np_exports++; 335 - spin_unlock(&np->np_thread_lock); 336 - spin_unlock_bh(&np_lock); 337 return np; 338 } 339 - spin_unlock(&np->np_thread_lock); 340 } 341 - spin_unlock_bh(&np_lock); 342 343 return NULL; 344 } ··· 350 struct sockaddr_in6 *sock_in6; 351 struct iscsi_np *np; 352 int ret; 353 /* 354 * Locate the existing struct iscsi_np if already active.. 355 */ 356 np = iscsit_get_np(sockaddr, network_transport); 357 - if (np) 358 return np; 359 360 np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL); 361 if (!np) { 362 pr_err("Unable to allocate memory for struct iscsi_np\n"); 363 return ERR_PTR(-ENOMEM); 364 } 365 ··· 388 ret = iscsi_target_setup_login_socket(np, sockaddr); 389 if (ret != 0) { 390 kfree(np); 391 return ERR_PTR(ret); 392 } 393 ··· 397 pr_err("Unable to create kthread: iscsi_np\n"); 398 ret = PTR_ERR(np->np_thread); 399 kfree(np); 400 return ERR_PTR(ret); 401 } 402 /* ··· 408 * point because iscsi_np has not been added to g_np_list yet. 409 */ 410 np->np_exports = 1; 411 412 - spin_lock_bh(&np_lock); 413 list_add_tail(&np->np_list, &g_np_list); 414 - spin_unlock_bh(&np_lock); 415 416 pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n", 417 np->np_ip, np->np_port, np->np_transport->name); ··· 477 478 np->np_transport->iscsit_free_np(np); 479 480 - spin_lock_bh(&np_lock); 481 list_del(&np->np_list); 482 - spin_unlock_bh(&np_lock); 483 484 pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n", 485 np->np_ip, np->np_port, np->np_transport->name);
··· 52 static LIST_HEAD(g_tiqn_list); 53 static LIST_HEAD(g_np_list); 54 static DEFINE_SPINLOCK(tiqn_lock); 55 + static DEFINE_MUTEX(np_lock); 56 57 static struct idr tiqn_idr; 58 struct idr sess_idr; ··· 307 return false; 308 } 309 310 + /* 311 + * Called with mutex np_lock held 312 + */ 313 static struct iscsi_np *iscsit_get_np( 314 struct __kernel_sockaddr_storage *sockaddr, 315 int network_transport) ··· 314 struct iscsi_np *np; 315 bool match; 316 317 list_for_each_entry(np, &g_np_list, np_list) { 318 + spin_lock_bh(&np->np_thread_lock); 319 if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) { 320 + spin_unlock_bh(&np->np_thread_lock); 321 continue; 322 } 323 ··· 330 * while iscsi_tpg_add_network_portal() is called. 331 */ 332 np->np_exports++; 333 + spin_unlock_bh(&np->np_thread_lock); 334 return np; 335 } 336 + spin_unlock_bh(&np->np_thread_lock); 337 } 338 339 return NULL; 340 } ··· 350 struct sockaddr_in6 *sock_in6; 351 struct iscsi_np *np; 352 int ret; 353 + 354 + mutex_lock(&np_lock); 355 + 356 /* 357 * Locate the existing struct iscsi_np if already active.. 358 */ 359 np = iscsit_get_np(sockaddr, network_transport); 360 + if (np) { 361 + mutex_unlock(&np_lock); 362 return np; 363 + } 364 365 np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL); 366 if (!np) { 367 pr_err("Unable to allocate memory for struct iscsi_np\n"); 368 + mutex_unlock(&np_lock); 369 return ERR_PTR(-ENOMEM); 370 } 371 ··· 382 ret = iscsi_target_setup_login_socket(np, sockaddr); 383 if (ret != 0) { 384 kfree(np); 385 + mutex_unlock(&np_lock); 386 return ERR_PTR(ret); 387 } 388 ··· 390 pr_err("Unable to create kthread: iscsi_np\n"); 391 ret = PTR_ERR(np->np_thread); 392 kfree(np); 393 + mutex_unlock(&np_lock); 394 return ERR_PTR(ret); 395 } 396 /* ··· 400 * point because iscsi_np has not been added to g_np_list yet. 401 */ 402 np->np_exports = 1; 403 + np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; 404 405 list_add_tail(&np->np_list, &g_np_list); 406 + mutex_unlock(&np_lock); 407 408 pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n", 409 np->np_ip, np->np_port, np->np_transport->name); ··· 469 470 np->np_transport->iscsit_free_np(np); 471 472 + mutex_lock(&np_lock); 473 list_del(&np->np_list); 474 + mutex_unlock(&np_lock); 475 476 pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n", 477 np->np_ip, np->np_port, np->np_transport->name);