diff options
Diffstat (limited to 'drivers/target/iscsi/iscsi_target.c')
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index c4aeac314b2e..1dff3e01f92c 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -220,11 +220,6 @@ int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg) | |||
220 | spin_unlock_bh(&np->np_thread_lock); | 220 | spin_unlock_bh(&np->np_thread_lock); |
221 | return -1; | 221 | return -1; |
222 | } | 222 | } |
223 | if (np->np_login_tpg) { | ||
224 | pr_err("np->np_login_tpg() is not NULL!\n"); | ||
225 | spin_unlock_bh(&np->np_thread_lock); | ||
226 | return -1; | ||
227 | } | ||
228 | spin_unlock_bh(&np->np_thread_lock); | 223 | spin_unlock_bh(&np->np_thread_lock); |
229 | /* | 224 | /* |
230 | * Determine if the portal group is accepting storage traffic. | 225 | * Determine if the portal group is accepting storage traffic. |
@@ -239,26 +234,38 @@ int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg) | |||
239 | /* | 234 | /* |
240 | * Here we serialize access across the TIQN+TPG Tuple. | 235 | * Here we serialize access across the TIQN+TPG Tuple. |
241 | */ | 236 | */ |
242 | ret = mutex_lock_interruptible(&tpg->np_login_lock); | 237 | ret = down_interruptible(&tpg->np_login_sem); |
243 | if ((ret != 0) || signal_pending(current)) | 238 | if ((ret != 0) || signal_pending(current)) |
244 | return -1; | 239 | return -1; |
245 | 240 | ||
246 | spin_lock_bh(&np->np_thread_lock); | 241 | spin_lock_bh(&tpg->tpg_state_lock); |
247 | np->np_login_tpg = tpg; | 242 | if (tpg->tpg_state != TPG_STATE_ACTIVE) { |
248 | spin_unlock_bh(&np->np_thread_lock); | 243 | spin_unlock_bh(&tpg->tpg_state_lock); |
244 | up(&tpg->np_login_sem); | ||
245 | return -1; | ||
246 | } | ||
247 | spin_unlock_bh(&tpg->tpg_state_lock); | ||
249 | 248 | ||
250 | return 0; | 249 | return 0; |
251 | } | 250 | } |
252 | 251 | ||
253 | int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg) | 252 | void iscsit_login_kref_put(struct kref *kref) |
253 | { | ||
254 | struct iscsi_tpg_np *tpg_np = container_of(kref, | ||
255 | struct iscsi_tpg_np, tpg_np_kref); | ||
256 | |||
257 | complete(&tpg_np->tpg_np_comp); | ||
258 | } | ||
259 | |||
260 | int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg, | ||
261 | struct iscsi_tpg_np *tpg_np) | ||
254 | { | 262 | { |
255 | struct iscsi_tiqn *tiqn = tpg->tpg_tiqn; | 263 | struct iscsi_tiqn *tiqn = tpg->tpg_tiqn; |
256 | 264 | ||
257 | spin_lock_bh(&np->np_thread_lock); | 265 | up(&tpg->np_login_sem); |
258 | np->np_login_tpg = NULL; | ||
259 | spin_unlock_bh(&np->np_thread_lock); | ||
260 | 266 | ||
261 | mutex_unlock(&tpg->np_login_lock); | 267 | if (tpg_np) |
268 | kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); | ||
262 | 269 | ||
263 | if (tiqn) | 270 | if (tiqn) |
264 | iscsit_put_tiqn_for_login(tiqn); | 271 | iscsit_put_tiqn_for_login(tiqn); |
@@ -410,20 +417,10 @@ struct iscsi_np *iscsit_add_np( | |||
410 | int iscsit_reset_np_thread( | 417 | int iscsit_reset_np_thread( |
411 | struct iscsi_np *np, | 418 | struct iscsi_np *np, |
412 | struct iscsi_tpg_np *tpg_np, | 419 | struct iscsi_tpg_np *tpg_np, |
413 | struct iscsi_portal_group *tpg) | 420 | struct iscsi_portal_group *tpg, |
421 | bool shutdown) | ||
414 | { | 422 | { |
415 | spin_lock_bh(&np->np_thread_lock); | 423 | spin_lock_bh(&np->np_thread_lock); |
416 | if (tpg && tpg_np) { | ||
417 | /* | ||
418 | * The reset operation need only be performed when the | ||
419 | * passed struct iscsi_portal_group has a login in progress | ||
420 | * to one of the network portals. | ||
421 | */ | ||
422 | if (tpg_np->tpg_np->np_login_tpg != tpg) { | ||
423 | spin_unlock_bh(&np->np_thread_lock); | ||
424 | return 0; | ||
425 | } | ||
426 | } | ||
427 | if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) { | 424 | if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) { |
428 | spin_unlock_bh(&np->np_thread_lock); | 425 | spin_unlock_bh(&np->np_thread_lock); |
429 | return 0; | 426 | return 0; |
@@ -438,6 +435,12 @@ int iscsit_reset_np_thread( | |||
438 | } | 435 | } |
439 | spin_unlock_bh(&np->np_thread_lock); | 436 | spin_unlock_bh(&np->np_thread_lock); |
440 | 437 | ||
438 | if (tpg_np && shutdown) { | ||
439 | kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); | ||
440 | |||
441 | wait_for_completion(&tpg_np->tpg_np_comp); | ||
442 | } | ||
443 | |||
441 | return 0; | 444 | return 0; |
442 | } | 445 | } |
443 | 446 | ||