Skip to content

Commit 7324f47

Browse files
mikechristiemartinkpetersen
authored andcommitted
scsi: target: Replace lun_tg_pt_gp_lock with rcu in I/O path
We are only holding the lun_tg_pt_gp_lock in target_alua_state_check() to make sure tg_pt_gp is not freed from under us while we copy the state, delay, ID values. We can instead use RCU here to access the tg_pt_gp. With this patch IOPs can increase up to 10% for jobs like: fio --filename=/dev/sdX --direct=1 --rw=randrw --bs=4k \ --ioengine=libaio --iodepth=64 --numjobs=N when there are multiple sessions (running that fio command to each /dev/sdX or using multipath and there are over 8 paths), or more than 8 queues for the loop or vhost with multiple threads case and numjobs > 8. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mike Christie <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 1283c0d commit 7324f47

File tree

2 files changed

+35
-28
lines changed

2 files changed

+35
-28
lines changed

drivers/target/target_core_alua.c

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,11 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
247247
* this CDB was received upon to determine this value individually
248248
* for ALUA target port group.
249249
*/
250-
spin_lock(&cmd->se_lun->lun_tg_pt_gp_lock);
251-
tg_pt_gp = cmd->se_lun->lun_tg_pt_gp;
250+
rcu_read_lock();
251+
tg_pt_gp = rcu_dereference(cmd->se_lun->lun_tg_pt_gp);
252252
if (tg_pt_gp)
253253
buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs;
254-
spin_unlock(&cmd->se_lun->lun_tg_pt_gp_lock);
254+
rcu_read_unlock();
255255
}
256256
transport_kunmap_data_sg(cmd);
257257

@@ -292,24 +292,24 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
292292
* Determine if explicit ALUA via SET_TARGET_PORT_GROUPS is allowed
293293
* for the local tg_pt_gp.
294294
*/
295-
spin_lock(&l_lun->lun_tg_pt_gp_lock);
296-
l_tg_pt_gp = l_lun->lun_tg_pt_gp;
295+
rcu_read_lock();
296+
l_tg_pt_gp = rcu_dereference(l_lun->lun_tg_pt_gp);
297297
if (!l_tg_pt_gp) {
298-
spin_unlock(&l_lun->lun_tg_pt_gp_lock);
298+
rcu_read_unlock();
299299
pr_err("Unable to access l_lun->tg_pt_gp\n");
300300
rc = TCM_UNSUPPORTED_SCSI_OPCODE;
301301
goto out;
302302
}
303303

304304
if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
305-
spin_unlock(&l_lun->lun_tg_pt_gp_lock);
305+
rcu_read_unlock();
306306
pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
307307
" while TPGS_EXPLICIT_ALUA is disabled\n");
308308
rc = TCM_UNSUPPORTED_SCSI_OPCODE;
309309
goto out;
310310
}
311311
valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
312-
spin_unlock(&l_lun->lun_tg_pt_gp_lock);
312+
rcu_read_unlock();
313313

314314
ptr = &buf[4]; /* Skip over RESERVED area in header */
315315

@@ -662,17 +662,17 @@ target_alua_state_check(struct se_cmd *cmd)
662662
" target port\n");
663663
return TCM_ALUA_OFFLINE;
664664
}
665-
666-
if (!lun->lun_tg_pt_gp)
665+
rcu_read_lock();
666+
tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp);
667+
if (!tg_pt_gp) {
668+
rcu_read_unlock();
667669
return 0;
670+
}
668671

669-
spin_lock(&lun->lun_tg_pt_gp_lock);
670-
tg_pt_gp = lun->lun_tg_pt_gp;
671672
out_alua_state = tg_pt_gp->tg_pt_gp_alua_access_state;
672673
nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs;
673674
tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id;
674-
675-
spin_unlock(&lun->lun_tg_pt_gp_lock);
675+
rcu_read_unlock();
676676
/*
677677
* Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional
678678
* statement so the compiler knows explicitly to check this case first.
@@ -1219,10 +1219,10 @@ static int core_alua_set_tg_pt_secondary_state(
12191219
struct t10_alua_tg_pt_gp *tg_pt_gp;
12201220
int trans_delay_msecs;
12211221

1222-
spin_lock(&lun->lun_tg_pt_gp_lock);
1223-
tg_pt_gp = lun->lun_tg_pt_gp;
1222+
rcu_read_lock();
1223+
tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp);
12241224
if (!tg_pt_gp) {
1225-
spin_unlock(&lun->lun_tg_pt_gp_lock);
1225+
rcu_read_unlock();
12261226
pr_err("Unable to complete secondary state"
12271227
" transition\n");
12281228
return -EINVAL;
@@ -1246,7 +1246,7 @@ static int core_alua_set_tg_pt_secondary_state(
12461246
"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
12471247
tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE");
12481248

1249-
spin_unlock(&lun->lun_tg_pt_gp_lock);
1249+
rcu_read_unlock();
12501250
/*
12511251
* Do the optional transition delay after we set the secondary
12521252
* ALUA access state.
@@ -1754,13 +1754,14 @@ void core_alua_free_tg_pt_gp(
17541754
__target_attach_tg_pt_gp(lun,
17551755
dev->t10_alua.default_tg_pt_gp);
17561756
} else
1757-
lun->lun_tg_pt_gp = NULL;
1757+
rcu_assign_pointer(lun->lun_tg_pt_gp, NULL);
17581758
spin_unlock(&lun->lun_tg_pt_gp_lock);
17591759

17601760
spin_lock(&tg_pt_gp->tg_pt_gp_lock);
17611761
}
17621762
spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
17631763

1764+
synchronize_rcu();
17641765
kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp);
17651766
}
17661767

@@ -1805,7 +1806,7 @@ static void __target_attach_tg_pt_gp(struct se_lun *lun,
18051806
assert_spin_locked(&lun->lun_tg_pt_gp_lock);
18061807

18071808
spin_lock(&tg_pt_gp->tg_pt_gp_lock);
1808-
lun->lun_tg_pt_gp = tg_pt_gp;
1809+
rcu_assign_pointer(lun->lun_tg_pt_gp, tg_pt_gp);
18091810
list_add_tail(&lun->lun_tg_pt_gp_link, &tg_pt_gp->tg_pt_gp_lun_list);
18101811
tg_pt_gp->tg_pt_gp_members++;
18111812
spin_lock(&lun->lun_deve_lock);
@@ -1822,6 +1823,7 @@ void target_attach_tg_pt_gp(struct se_lun *lun,
18221823
spin_lock(&lun->lun_tg_pt_gp_lock);
18231824
__target_attach_tg_pt_gp(lun, tg_pt_gp);
18241825
spin_unlock(&lun->lun_tg_pt_gp_lock);
1826+
synchronize_rcu();
18251827
}
18261828

18271829
static void __target_detach_tg_pt_gp(struct se_lun *lun,
@@ -1834,18 +1836,20 @@ static void __target_detach_tg_pt_gp(struct se_lun *lun,
18341836
tg_pt_gp->tg_pt_gp_members--;
18351837
spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
18361838

1837-
lun->lun_tg_pt_gp = NULL;
1839+
rcu_assign_pointer(lun->lun_tg_pt_gp, NULL);
18381840
}
18391841

18401842
void target_detach_tg_pt_gp(struct se_lun *lun)
18411843
{
18421844
struct t10_alua_tg_pt_gp *tg_pt_gp;
18431845

18441846
spin_lock(&lun->lun_tg_pt_gp_lock);
1845-
tg_pt_gp = lun->lun_tg_pt_gp;
1847+
tg_pt_gp = rcu_dereference_check(lun->lun_tg_pt_gp,
1848+
lockdep_is_held(&lun->lun_tg_pt_gp_lock));
18461849
if (tg_pt_gp)
18471850
__target_detach_tg_pt_gp(lun, tg_pt_gp);
18481851
spin_unlock(&lun->lun_tg_pt_gp_lock);
1852+
synchronize_rcu();
18491853
}
18501854

18511855
ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page)
@@ -1854,8 +1858,8 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page)
18541858
struct t10_alua_tg_pt_gp *tg_pt_gp;
18551859
ssize_t len = 0;
18561860

1857-
spin_lock(&lun->lun_tg_pt_gp_lock);
1858-
tg_pt_gp = lun->lun_tg_pt_gp;
1861+
rcu_read_lock();
1862+
tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp);
18591863
if (tg_pt_gp) {
18601864
tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item;
18611865
len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:"
@@ -1871,7 +1875,7 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page)
18711875
"Offline" : "None",
18721876
core_alua_dump_status(lun->lun_tg_pt_secondary_stat));
18731877
}
1874-
spin_unlock(&lun->lun_tg_pt_gp_lock);
1878+
rcu_read_unlock();
18751879

18761880
return len;
18771881
}
@@ -1918,7 +1922,8 @@ ssize_t core_alua_store_tg_pt_gp_info(
19181922
}
19191923

19201924
spin_lock(&lun->lun_tg_pt_gp_lock);
1921-
tg_pt_gp = lun->lun_tg_pt_gp;
1925+
tg_pt_gp = rcu_dereference_check(lun->lun_tg_pt_gp,
1926+
lockdep_is_held(&lun->lun_tg_pt_gp_lock));
19221927
if (tg_pt_gp) {
19231928
/*
19241929
* Clearing an existing tg_pt_gp association, and replacing
@@ -1941,7 +1946,7 @@ ssize_t core_alua_store_tg_pt_gp_info(
19411946
dev->t10_alua.default_tg_pt_gp);
19421947
spin_unlock(&lun->lun_tg_pt_gp_lock);
19431948

1944-
return count;
1949+
goto sync_rcu;
19451950
}
19461951
__target_detach_tg_pt_gp(lun, tg_pt_gp);
19471952
move = 1;
@@ -1958,6 +1963,8 @@ ssize_t core_alua_store_tg_pt_gp_info(
19581963
tg_pt_gp_new->tg_pt_gp_id);
19591964

19601965
core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new);
1966+
sync_rcu:
1967+
synchronize_rcu();
19611968
return count;
19621969
}
19631970

include/target/target_core_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ struct se_lun {
749749

750750
/* ALUA target port group linkage */
751751
struct list_head lun_tg_pt_gp_link;
752-
struct t10_alua_tg_pt_gp *lun_tg_pt_gp;
752+
struct t10_alua_tg_pt_gp __rcu *lun_tg_pt_gp;
753753
spinlock_t lun_tg_pt_gp_lock;
754754

755755
struct se_portal_group *lun_tpg;

0 commit comments

Comments
 (0)