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