summaryrefslogtreecommitdiffstats
path: root/drivers/target/sbp
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2015-05-10 22:31:10 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-06-01 03:24:33 -0400
commit6bb826121be244a5a3c8bd8b7d45c47df18810b7 (patch)
tree7a75624e4801567a4133bc5b373ed67dd1db1cbb /drivers/target/sbp
parent9fcb57f39c0cde70bcccdc1d998d3060297e911c (diff)
target: Convert se_portal_group->tpg_lun_list[] to RCU hlist
This patch converts the fixed size se_portal_group->tpg_lun_list[] to use modern RCU with hlist_head in order to support an arbitary number of se_lun ports per target endpoint. It includes dropping core_tpg_alloc_lun() from core_dev_add_lun(), and calling it directly from target_fabric_make_lun() to allocate a new se_lun. And add a new target_fabric_port_release() configfs item callback to invoke kfree_rcu() to release memory during se_lun->lun_group shutdown. Also now that se_node_acl->lun_entry_hlist is using RCU, convert existing tpg_lun_lock to struct mutex so core_tpg_add_node_to_devs() can perform RCU updater logic without releasing ->tpg_lun_mutex. Also, drop core_tpg_clear_object_luns() and it's single consumer in iscsi-target, which is duplicating TPG LUN shutdown logic and is current code results in a NOP. Finally, sbp-target and xen-scsiback fabric driver conversions are included, which are required due to the non-standard way they use ->tpg_lun_hlist. Reviewed-by: Hannes Reinecke <hare@suse.de> Cc: Christoph Hellwig <hch@lst.de> Cc: Sagi Grimberg <sagig@mellanox.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Chris Boot <bootc@bootc.net> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/sbp')
-rw-r--r--drivers/target/sbp/sbp_target.c97
-rw-r--r--drivers/target/sbp/sbp_target.h2
2 files changed, 43 insertions, 56 deletions
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 5d7755edc668..47fb12fbaf47 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -108,13 +108,13 @@ static struct sbp_session *sbp_session_find_by_guid(
108} 108}
109 109
110static struct sbp_login_descriptor *sbp_login_find_by_lun( 110static struct sbp_login_descriptor *sbp_login_find_by_lun(
111 struct sbp_session *session, struct se_lun *lun) 111 struct sbp_session *session, u32 unpacked_lun)
112{ 112{
113 struct sbp_login_descriptor *login, *found = NULL; 113 struct sbp_login_descriptor *login, *found = NULL;
114 114
115 spin_lock_bh(&session->lock); 115 spin_lock_bh(&session->lock);
116 list_for_each_entry(login, &session->login_list, link) { 116 list_for_each_entry(login, &session->login_list, link) {
117 if (login->lun == lun) 117 if (login->login_lun == unpacked_lun)
118 found = login; 118 found = login;
119 } 119 }
120 spin_unlock_bh(&session->lock); 120 spin_unlock_bh(&session->lock);
@@ -124,7 +124,7 @@ static struct sbp_login_descriptor *sbp_login_find_by_lun(
124 124
125static int sbp_login_count_all_by_lun( 125static int sbp_login_count_all_by_lun(
126 struct sbp_tpg *tpg, 126 struct sbp_tpg *tpg,
127 struct se_lun *lun, 127 u32 unpacked_lun,
128 int exclusive) 128 int exclusive)
129{ 129{
130 struct se_session *se_sess; 130 struct se_session *se_sess;
@@ -138,7 +138,7 @@ static int sbp_login_count_all_by_lun(
138 138
139 spin_lock_bh(&sess->lock); 139 spin_lock_bh(&sess->lock);
140 list_for_each_entry(login, &sess->login_list, link) { 140 list_for_each_entry(login, &sess->login_list, link) {
141 if (login->lun != lun) 141 if (login->login_lun != unpacked_lun)
142 continue; 142 continue;
143 143
144 if (!exclusive || login->exclusive) 144 if (!exclusive || login->exclusive)
@@ -174,23 +174,23 @@ static struct sbp_login_descriptor *sbp_login_find_by_id(
174 return found; 174 return found;
175} 175}
176 176
177static struct se_lun *sbp_get_lun_from_tpg(struct sbp_tpg *tpg, int lun) 177static u32 sbp_get_lun_from_tpg(struct sbp_tpg *tpg, u32 login_lun, int *err)
178{ 178{
179 struct se_portal_group *se_tpg = &tpg->se_tpg; 179 struct se_portal_group *se_tpg = &tpg->se_tpg;
180 struct se_lun *se_lun; 180 struct se_lun *se_lun;
181 181
182 if (lun >= TRANSPORT_MAX_LUNS_PER_TPG) 182 rcu_read_lock();
183 return ERR_PTR(-EINVAL); 183 hlist_for_each_entry_rcu(se_lun, &se_tpg->tpg_lun_hlist, link) {
184 184 if (se_lun->unpacked_lun == login_lun) {
185 spin_lock(&se_tpg->tpg_lun_lock); 185 rcu_read_unlock();
186 se_lun = se_tpg->tpg_lun_list[lun]; 186 *err = 0;
187 187 return login_lun;
188 if (se_lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) 188 }
189 se_lun = ERR_PTR(-ENODEV); 189 }
190 190 rcu_read_unlock();
191 spin_unlock(&se_tpg->tpg_lun_lock);
192 191
193 return se_lun; 192 *err = -ENODEV;
193 return login_lun;
194} 194}
195 195
196static struct sbp_session *sbp_session_create( 196static struct sbp_session *sbp_session_create(
@@ -294,17 +294,16 @@ static void sbp_management_request_login(
294{ 294{
295 struct sbp_tport *tport = agent->tport; 295 struct sbp_tport *tport = agent->tport;
296 struct sbp_tpg *tpg = tport->tpg; 296 struct sbp_tpg *tpg = tport->tpg;
297 struct se_lun *se_lun;
298 int ret;
299 u64 guid;
300 struct sbp_session *sess; 297 struct sbp_session *sess;
301 struct sbp_login_descriptor *login; 298 struct sbp_login_descriptor *login;
302 struct sbp_login_response_block *response; 299 struct sbp_login_response_block *response;
303 int login_response_len; 300 u64 guid;
301 u32 unpacked_lun;
302 int login_response_len, ret;
304 303
305 se_lun = sbp_get_lun_from_tpg(tpg, 304 unpacked_lun = sbp_get_lun_from_tpg(tpg,
306 LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc))); 305 LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc)), &ret);
307 if (IS_ERR(se_lun)) { 306 if (ret) {
308 pr_notice("login to unknown LUN: %d\n", 307 pr_notice("login to unknown LUN: %d\n",
309 LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc))); 308 LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc)));
310 309
@@ -325,11 +324,11 @@ static void sbp_management_request_login(
325 } 324 }
326 325
327 pr_notice("mgt_agent LOGIN to LUN %d from %016llx\n", 326 pr_notice("mgt_agent LOGIN to LUN %d from %016llx\n",
328 se_lun->unpacked_lun, guid); 327 unpacked_lun, guid);
329 328
330 sess = sbp_session_find_by_guid(tpg, guid); 329 sess = sbp_session_find_by_guid(tpg, guid);
331 if (sess) { 330 if (sess) {
332 login = sbp_login_find_by_lun(sess, se_lun); 331 login = sbp_login_find_by_lun(sess, unpacked_lun);
333 if (login) { 332 if (login) {
334 pr_notice("initiator already logged-in\n"); 333 pr_notice("initiator already logged-in\n");
335 334
@@ -357,7 +356,7 @@ static void sbp_management_request_login(
357 * reject with access_denied if any logins present 356 * reject with access_denied if any logins present
358 */ 357 */
359 if (LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)) && 358 if (LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)) &&
360 sbp_login_count_all_by_lun(tpg, se_lun, 0)) { 359 sbp_login_count_all_by_lun(tpg, unpacked_lun, 0)) {
361 pr_warn("refusing exclusive login with other active logins\n"); 360 pr_warn("refusing exclusive login with other active logins\n");
362 361
363 req->status.status = cpu_to_be32( 362 req->status.status = cpu_to_be32(
@@ -370,7 +369,7 @@ static void sbp_management_request_login(
370 * check exclusive bit in any existing login descriptor 369 * check exclusive bit in any existing login descriptor
371 * reject with access_denied if any exclusive logins present 370 * reject with access_denied if any exclusive logins present
372 */ 371 */
373 if (sbp_login_count_all_by_lun(tpg, se_lun, 1)) { 372 if (sbp_login_count_all_by_lun(tpg, unpacked_lun, 1)) {
374 pr_warn("refusing login while another exclusive login present\n"); 373 pr_warn("refusing login while another exclusive login present\n");
375 374
376 req->status.status = cpu_to_be32( 375 req->status.status = cpu_to_be32(
@@ -383,7 +382,7 @@ static void sbp_management_request_login(
383 * check we haven't exceeded the number of allowed logins 382 * check we haven't exceeded the number of allowed logins
384 * reject with resources_unavailable if we have 383 * reject with resources_unavailable if we have
385 */ 384 */
386 if (sbp_login_count_all_by_lun(tpg, se_lun, 0) >= 385 if (sbp_login_count_all_by_lun(tpg, unpacked_lun, 0) >=
387 tport->max_logins_per_lun) { 386 tport->max_logins_per_lun) {
388 pr_warn("max number of logins reached\n"); 387 pr_warn("max number of logins reached\n");
389 388
@@ -439,7 +438,7 @@ static void sbp_management_request_login(
439 } 438 }
440 439
441 login->sess = sess; 440 login->sess = sess;
442 login->lun = se_lun; 441 login->login_lun = unpacked_lun;
443 login->status_fifo_addr = sbp2_pointer_to_addr(&req->orb.status_fifo); 442 login->status_fifo_addr = sbp2_pointer_to_addr(&req->orb.status_fifo);
444 login->exclusive = LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)); 443 login->exclusive = LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc));
445 login->login_id = atomic_inc_return(&login_id); 444 login->login_id = atomic_inc_return(&login_id);
@@ -601,7 +600,7 @@ static void sbp_management_request_logout(
601 } 600 }
602 601
603 pr_info("mgt_agent LOGOUT from LUN %d session %d\n", 602 pr_info("mgt_agent LOGOUT from LUN %d session %d\n",
604 login->lun->unpacked_lun, login->login_id); 603 login->login_lun, login->login_id);
605 604
606 if (req->node_addr != login->sess->node_id) { 605 if (req->node_addr != login->sess->node_id) {
607 pr_warn("logout from different node ID\n"); 606 pr_warn("logout from different node ID\n");
@@ -1227,7 +1226,7 @@ static void sbp_handle_command(struct sbp_target_request *req)
1227 goto err; 1226 goto err;
1228 } 1227 }
1229 1228
1230 unpacked_lun = req->login->lun->unpacked_lun; 1229 unpacked_lun = req->login->login_lun;
1231 sbp_calc_data_length_direction(req, &data_length, &data_dir); 1230 sbp_calc_data_length_direction(req, &data_length, &data_dir);
1232 1231
1233 pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n", 1232 pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n",
@@ -1826,25 +1825,21 @@ static int sbp_check_stop_free(struct se_cmd *se_cmd)
1826 1825
1827static int sbp_count_se_tpg_luns(struct se_portal_group *tpg) 1826static int sbp_count_se_tpg_luns(struct se_portal_group *tpg)
1828{ 1827{
1829 int i, count = 0; 1828 struct se_lun *lun;
1830 1829 int count = 0;
1831 spin_lock(&tpg->tpg_lun_lock);
1832 for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
1833 struct se_lun *se_lun = tpg->tpg_lun_list[i];
1834
1835 if (se_lun->lun_status == TRANSPORT_LUN_STATUS_FREE)
1836 continue;
1837 1830
1831 rcu_read_lock();
1832 hlist_for_each_entry_rcu(lun, &tpg->tpg_lun_hlist, link)
1838 count++; 1833 count++;
1839 } 1834 rcu_read_unlock();
1840 spin_unlock(&tpg->tpg_lun_lock);
1841 1835
1842 return count; 1836 return count;
1843} 1837}
1844 1838
1845static int sbp_update_unit_directory(struct sbp_tport *tport) 1839static int sbp_update_unit_directory(struct sbp_tport *tport)
1846{ 1840{
1847 int num_luns, num_entries, idx = 0, mgt_agt_addr, ret, i; 1841 struct se_lun *lun;
1842 int num_luns, num_entries, idx = 0, mgt_agt_addr, ret;
1848 u32 *data; 1843 u32 *data;
1849 1844
1850 if (tport->unit_directory.data) { 1845 if (tport->unit_directory.data) {
@@ -1906,28 +1901,20 @@ static int sbp_update_unit_directory(struct sbp_tport *tport)
1906 /* unit unique ID (leaf is just after LUNs) */ 1901 /* unit unique ID (leaf is just after LUNs) */
1907 data[idx++] = 0x8d000000 | (num_luns + 1); 1902 data[idx++] = 0x8d000000 | (num_luns + 1);
1908 1903
1909 spin_lock(&tport->tpg->se_tpg.tpg_lun_lock); 1904 rcu_read_lock();
1910 for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 1905 hlist_for_each_entry_rcu(lun, &tport->tpg->se_tpg.tpg_lun_hlist, link) {
1911 struct se_lun *se_lun = tport->tpg->se_tpg.tpg_lun_list[i];
1912 struct se_device *dev; 1906 struct se_device *dev;
1913 int type; 1907 int type;
1914 1908
1915 if (se_lun->lun_status == TRANSPORT_LUN_STATUS_FREE) 1909 dev = lun->lun_se_dev;
1916 continue;
1917
1918 spin_unlock(&tport->tpg->se_tpg.tpg_lun_lock);
1919
1920 dev = se_lun->lun_se_dev;
1921 type = dev->transport->get_device_type(dev); 1910 type = dev->transport->get_device_type(dev);
1922 1911
1923 /* logical_unit_number */ 1912 /* logical_unit_number */
1924 data[idx++] = 0x14000000 | 1913 data[idx++] = 0x14000000 |
1925 ((type << 16) & 0x1f0000) | 1914 ((type << 16) & 0x1f0000) |
1926 (se_lun->unpacked_lun & 0xffff); 1915 (lun->unpacked_lun & 0xffff);
1927
1928 spin_lock(&tport->tpg->se_tpg.tpg_lun_lock);
1929 } 1916 }
1930 spin_unlock(&tport->tpg->se_tpg.tpg_lun_lock); 1917 rcu_read_unlock();
1931 1918
1932 /* unit unique ID leaf */ 1919 /* unit unique ID leaf */
1933 data[idx++] = 2 << 16; 1920 data[idx++] = 2 << 16;
diff --git a/drivers/target/sbp/sbp_target.h b/drivers/target/sbp/sbp_target.h
index e1b0b84f7379..73bcb1208832 100644
--- a/drivers/target/sbp/sbp_target.h
+++ b/drivers/target/sbp/sbp_target.h
@@ -125,7 +125,7 @@ struct sbp_login_descriptor {
125 struct sbp_session *sess; 125 struct sbp_session *sess;
126 struct list_head link; 126 struct list_head link;
127 127
128 struct se_lun *lun; 128 u32 login_lun;
129 129
130 u64 status_fifo_addr; 130 u64 status_fifo_addr;
131 int exclusive; 131 int exclusive;