aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/iscsi/iscsi_target.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/iscsi/iscsi_target.c')
-rw-r--r--drivers/target/iscsi/iscsi_target.c55
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
253int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg) 252void 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
260int 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(
410int iscsit_reset_np_thread( 417int 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