aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/target/Makefile3
-rw-r--r--drivers/target/target_core_configfs.c15
-rw-r--r--drivers/target/target_core_device.c3
-rw-r--r--drivers/target/target_core_mib.c1078
-rw-r--r--drivers/target/target_core_mib.h28
-rw-r--r--drivers/target/target_core_tpg.c29
-rw-r--r--drivers/target/target_core_transport.c42
7 files changed, 56 insertions, 1142 deletions
diff --git a/drivers/target/Makefile b/drivers/target/Makefile
index 5cfd70819f08..973bb190ef57 100644
--- a/drivers/target/Makefile
+++ b/drivers/target/Makefile
@@ -13,8 +13,7 @@ target_core_mod-y := target_core_configfs.o \
13 target_core_transport.o \ 13 target_core_transport.o \
14 target_core_cdb.o \ 14 target_core_cdb.o \
15 target_core_ua.o \ 15 target_core_ua.o \
16 target_core_rd.o \ 16 target_core_rd.o
17 target_core_mib.o
18 17
19obj-$(CONFIG_TARGET_CORE) += target_core_mod.o 18obj-$(CONFIG_TARGET_CORE) += target_core_mod.o
20 19
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 1cb74d57ed5f..e77001b16063 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -37,7 +37,6 @@
37#include <linux/parser.h> 37#include <linux/parser.h>
38#include <linux/syscalls.h> 38#include <linux/syscalls.h>
39#include <linux/configfs.h> 39#include <linux/configfs.h>
40#include <linux/proc_fs.h>
41 40
42#include <target/target_core_base.h> 41#include <target/target_core_base.h>
43#include <target/target_core_device.h> 42#include <target/target_core_device.h>
@@ -3022,7 +3021,6 @@ static int target_core_init_configfs(void)
3022 struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL; 3021 struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL;
3023 struct config_group *lu_gp_cg = NULL; 3022 struct config_group *lu_gp_cg = NULL;
3024 struct configfs_subsystem *subsys; 3023 struct configfs_subsystem *subsys;
3025 struct proc_dir_entry *scsi_target_proc = NULL;
3026 struct t10_alua_lu_gp *lu_gp; 3024 struct t10_alua_lu_gp *lu_gp;
3027 int ret; 3025 int ret;
3028 3026
@@ -3128,21 +3126,10 @@ static int target_core_init_configfs(void)
3128 if (core_dev_setup_virtual_lun0() < 0) 3126 if (core_dev_setup_virtual_lun0() < 0)
3129 goto out; 3127 goto out;
3130 3128
3131 scsi_target_proc = proc_mkdir("scsi_target", 0);
3132 if (!(scsi_target_proc)) {
3133 printk(KERN_ERR "proc_mkdir(scsi_target, 0) failed\n");
3134 goto out;
3135 }
3136 ret = init_scsi_target_mib();
3137 if (ret < 0)
3138 goto out;
3139
3140 return 0; 3129 return 0;
3141 3130
3142out: 3131out:
3143 configfs_unregister_subsystem(subsys); 3132 configfs_unregister_subsystem(subsys);
3144 if (scsi_target_proc)
3145 remove_proc_entry("scsi_target", 0);
3146 core_dev_release_virtual_lun0(); 3133 core_dev_release_virtual_lun0();
3147 rd_module_exit(); 3134 rd_module_exit();
3148out_global: 3135out_global:
@@ -3210,8 +3197,6 @@ static void target_core_exit_configfs(void)
3210 printk(KERN_INFO "TARGET_CORE[0]: Released ConfigFS Fabric" 3197 printk(KERN_INFO "TARGET_CORE[0]: Released ConfigFS Fabric"
3211 " Infrastructure\n"); 3198 " Infrastructure\n");
3212 3199
3213 remove_scsi_target_mib();
3214 remove_proc_entry("scsi_target", 0);
3215 core_dev_release_virtual_lun0(); 3200 core_dev_release_virtual_lun0();
3216 rd_module_exit(); 3201 rd_module_exit();
3217 release_se_global(); 3202 release_se_global();
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 9551ab541f03..5da051a07fa3 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -867,9 +867,6 @@ static void se_dev_stop(struct se_device *dev)
867 } 867 }
868 } 868 }
869 spin_unlock(&hba->device_lock); 869 spin_unlock(&hba->device_lock);
870
871 while (atomic_read(&hba->dev_mib_access_count))
872 cpu_relax();
873} 870}
874 871
875int se_dev_check_online(struct se_device *dev) 872int se_dev_check_online(struct se_device *dev)
diff --git a/drivers/target/target_core_mib.c b/drivers/target/target_core_mib.c
deleted file mode 100644
index d5a48aa0d2d1..000000000000
--- a/drivers/target/target_core_mib.c
+++ /dev/null
@@ -1,1078 +0,0 @@
1/*******************************************************************************
2 * Filename: target_core_mib.c
3 *
4 * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved.
5 * Copyright (c) 2007-2010 Rising Tide Systems
6 * Copyright (c) 2008-2010 Linux-iSCSI.org
7 *
8 * Nicholas A. Bellinger <nab@linux-iscsi.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 *
24 ******************************************************************************/
25
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/delay.h>
30#include <linux/timer.h>
31#include <linux/string.h>
32#include <linux/version.h>
33#include <generated/utsrelease.h>
34#include <linux/utsname.h>
35#include <linux/proc_fs.h>
36#include <linux/seq_file.h>
37#include <linux/blkdev.h>
38#include <scsi/scsi.h>
39#include <scsi/scsi_device.h>
40#include <scsi/scsi_host.h>
41
42#include <target/target_core_base.h>
43#include <target/target_core_transport.h>
44#include <target/target_core_fabric_ops.h>
45#include <target/target_core_configfs.h>
46
47#include "target_core_hba.h"
48#include "target_core_mib.h"
49
50/* SCSI mib table index */
51static struct scsi_index_table scsi_index_table;
52
53#ifndef INITIAL_JIFFIES
54#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
55#endif
56
57/* SCSI Instance Table */
58#define SCSI_INST_SW_INDEX 1
59#define SCSI_TRANSPORT_INDEX 1
60
61#define NONE "None"
62#define ISPRINT(a) ((a >= ' ') && (a <= '~'))
63
64static inline int list_is_first(const struct list_head *list,
65 const struct list_head *head)
66{
67 return list->prev == head;
68}
69
70static void *locate_hba_start(
71 struct seq_file *seq,
72 loff_t *pos)
73{
74 spin_lock(&se_global->g_device_lock);
75 return seq_list_start(&se_global->g_se_dev_list, *pos);
76}
77
78static void *locate_hba_next(
79 struct seq_file *seq,
80 void *v,
81 loff_t *pos)
82{
83 return seq_list_next(v, &se_global->g_se_dev_list, pos);
84}
85
86static void locate_hba_stop(struct seq_file *seq, void *v)
87{
88 spin_unlock(&se_global->g_device_lock);
89}
90
91/****************************************************************************
92 * SCSI MIB Tables
93 ****************************************************************************/
94
95/*
96 * SCSI Instance Table
97 */
98static void *scsi_inst_seq_start(
99 struct seq_file *seq,
100 loff_t *pos)
101{
102 spin_lock(&se_global->hba_lock);
103 return seq_list_start(&se_global->g_hba_list, *pos);
104}
105
106static void *scsi_inst_seq_next(
107 struct seq_file *seq,
108 void *v,
109 loff_t *pos)
110{
111 return seq_list_next(v, &se_global->g_hba_list, pos);
112}
113
114static void scsi_inst_seq_stop(struct seq_file *seq, void *v)
115{
116 spin_unlock(&se_global->hba_lock);
117}
118
119static int scsi_inst_seq_show(struct seq_file *seq, void *v)
120{
121 struct se_hba *hba = list_entry(v, struct se_hba, hba_list);
122
123 if (list_is_first(&hba->hba_list, &se_global->g_hba_list))
124 seq_puts(seq, "inst sw_indx\n");
125
126 seq_printf(seq, "%u %u\n", hba->hba_index, SCSI_INST_SW_INDEX);
127 seq_printf(seq, "plugin: %s version: %s\n",
128 hba->transport->name, TARGET_CORE_VERSION);
129
130 return 0;
131}
132
133static const struct seq_operations scsi_inst_seq_ops = {
134 .start = scsi_inst_seq_start,
135 .next = scsi_inst_seq_next,
136 .stop = scsi_inst_seq_stop,
137 .show = scsi_inst_seq_show
138};
139
140static int scsi_inst_seq_open(struct inode *inode, struct file *file)
141{
142 return seq_open(file, &scsi_inst_seq_ops);
143}
144
145static const struct file_operations scsi_inst_seq_fops = {
146 .owner = THIS_MODULE,
147 .open = scsi_inst_seq_open,
148 .read = seq_read,
149 .llseek = seq_lseek,
150 .release = seq_release,
151};
152
153/*
154 * SCSI Device Table
155 */
156static void *scsi_dev_seq_start(struct seq_file *seq, loff_t *pos)
157{
158 return locate_hba_start(seq, pos);
159}
160
161static void *scsi_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
162{
163 return locate_hba_next(seq, v, pos);
164}
165
166static void scsi_dev_seq_stop(struct seq_file *seq, void *v)
167{
168 locate_hba_stop(seq, v);
169}
170
171static int scsi_dev_seq_show(struct seq_file *seq, void *v)
172{
173 struct se_hba *hba;
174 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
175 g_se_dev_list);
176 struct se_device *dev = se_dev->se_dev_ptr;
177 char str[28];
178 int k;
179
180 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
181 seq_puts(seq, "inst indx role ports\n");
182
183 if (!(dev))
184 return 0;
185
186 hba = dev->se_hba;
187 if (!(hba)) {
188 /* Log error ? */
189 return 0;
190 }
191
192 seq_printf(seq, "%u %u %s %u\n", hba->hba_index,
193 dev->dev_index, "Target", dev->dev_port_count);
194
195 memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
196
197 /* vendor */
198 for (k = 0; k < 8; k++)
199 str[k] = ISPRINT(DEV_T10_WWN(dev)->vendor[k]) ?
200 DEV_T10_WWN(dev)->vendor[k] : 0x20;
201 str[k] = 0x20;
202
203 /* model */
204 for (k = 0; k < 16; k++)
205 str[k+9] = ISPRINT(DEV_T10_WWN(dev)->model[k]) ?
206 DEV_T10_WWN(dev)->model[k] : 0x20;
207 str[k + 9] = 0;
208
209 seq_printf(seq, "dev_alias: %s\n", str);
210
211 return 0;
212}
213
214static const struct seq_operations scsi_dev_seq_ops = {
215 .start = scsi_dev_seq_start,
216 .next = scsi_dev_seq_next,
217 .stop = scsi_dev_seq_stop,
218 .show = scsi_dev_seq_show
219};
220
221static int scsi_dev_seq_open(struct inode *inode, struct file *file)
222{
223 return seq_open(file, &scsi_dev_seq_ops);
224}
225
226static const struct file_operations scsi_dev_seq_fops = {
227 .owner = THIS_MODULE,
228 .open = scsi_dev_seq_open,
229 .read = seq_read,
230 .llseek = seq_lseek,
231 .release = seq_release,
232};
233
234/*
235 * SCSI Port Table
236 */
237static void *scsi_port_seq_start(struct seq_file *seq, loff_t *pos)
238{
239 return locate_hba_start(seq, pos);
240}
241
242static void *scsi_port_seq_next(struct seq_file *seq, void *v, loff_t *pos)
243{
244 return locate_hba_next(seq, v, pos);
245}
246
247static void scsi_port_seq_stop(struct seq_file *seq, void *v)
248{
249 locate_hba_stop(seq, v);
250}
251
252static int scsi_port_seq_show(struct seq_file *seq, void *v)
253{
254 struct se_hba *hba;
255 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
256 g_se_dev_list);
257 struct se_device *dev = se_dev->se_dev_ptr;
258 struct se_port *sep, *sep_tmp;
259
260 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
261 seq_puts(seq, "inst device indx role busy_count\n");
262
263 if (!(dev))
264 return 0;
265
266 hba = dev->se_hba;
267 if (!(hba)) {
268 /* Log error ? */
269 return 0;
270 }
271
272 /* FIXME: scsiPortBusyStatuses count */
273 spin_lock(&dev->se_port_lock);
274 list_for_each_entry_safe(sep, sep_tmp, &dev->dev_sep_list, sep_list) {
275 seq_printf(seq, "%u %u %u %s%u %u\n", hba->hba_index,
276 dev->dev_index, sep->sep_index, "Device",
277 dev->dev_index, 0);
278 }
279 spin_unlock(&dev->se_port_lock);
280
281 return 0;
282}
283
284static const struct seq_operations scsi_port_seq_ops = {
285 .start = scsi_port_seq_start,
286 .next = scsi_port_seq_next,
287 .stop = scsi_port_seq_stop,
288 .show = scsi_port_seq_show
289};
290
291static int scsi_port_seq_open(struct inode *inode, struct file *file)
292{
293 return seq_open(file, &scsi_port_seq_ops);
294}
295
296static const struct file_operations scsi_port_seq_fops = {
297 .owner = THIS_MODULE,
298 .open = scsi_port_seq_open,
299 .read = seq_read,
300 .llseek = seq_lseek,
301 .release = seq_release,
302};
303
304/*
305 * SCSI Transport Table
306 */
307static void *scsi_transport_seq_start(struct seq_file *seq, loff_t *pos)
308{
309 return locate_hba_start(seq, pos);
310}
311
312static void *scsi_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos)
313{
314 return locate_hba_next(seq, v, pos);
315}
316
317static void scsi_transport_seq_stop(struct seq_file *seq, void *v)
318{
319 locate_hba_stop(seq, v);
320}
321
322static int scsi_transport_seq_show(struct seq_file *seq, void *v)
323{
324 struct se_hba *hba;
325 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
326 g_se_dev_list);
327 struct se_device *dev = se_dev->se_dev_ptr;
328 struct se_port *se, *se_tmp;
329 struct se_portal_group *tpg;
330 struct t10_wwn *wwn;
331 char buf[64];
332
333 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
334 seq_puts(seq, "inst device indx dev_name\n");
335
336 if (!(dev))
337 return 0;
338
339 hba = dev->se_hba;
340 if (!(hba)) {
341 /* Log error ? */
342 return 0;
343 }
344
345 wwn = DEV_T10_WWN(dev);
346
347 spin_lock(&dev->se_port_lock);
348 list_for_each_entry_safe(se, se_tmp, &dev->dev_sep_list, sep_list) {
349 tpg = se->sep_tpg;
350 sprintf(buf, "scsiTransport%s",
351 TPG_TFO(tpg)->get_fabric_name());
352
353 seq_printf(seq, "%u %s %u %s+%s\n",
354 hba->hba_index, /* scsiTransportIndex */
355 buf, /* scsiTransportType */
356 (TPG_TFO(tpg)->tpg_get_inst_index != NULL) ?
357 TPG_TFO(tpg)->tpg_get_inst_index(tpg) :
358 0,
359 TPG_TFO(tpg)->tpg_get_wwn(tpg),
360 (strlen(wwn->unit_serial)) ?
361 /* scsiTransportDevName */
362 wwn->unit_serial : wwn->vendor);
363 }
364 spin_unlock(&dev->se_port_lock);
365
366 return 0;
367}
368
369static const struct seq_operations scsi_transport_seq_ops = {
370 .start = scsi_transport_seq_start,
371 .next = scsi_transport_seq_next,
372 .stop = scsi_transport_seq_stop,
373 .show = scsi_transport_seq_show
374};
375
376static int scsi_transport_seq_open(struct inode *inode, struct file *file)
377{
378 return seq_open(file, &scsi_transport_seq_ops);
379}
380
381static const struct file_operations scsi_transport_seq_fops = {
382 .owner = THIS_MODULE,
383 .open = scsi_transport_seq_open,
384 .read = seq_read,
385 .llseek = seq_lseek,
386 .release = seq_release,
387};
388
389/*
390 * SCSI Target Device Table
391 */
392static void *scsi_tgt_dev_seq_start(struct seq_file *seq, loff_t *pos)
393{
394 return locate_hba_start(seq, pos);
395}
396
397static void *scsi_tgt_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
398{
399 return locate_hba_next(seq, v, pos);
400}
401
402static void scsi_tgt_dev_seq_stop(struct seq_file *seq, void *v)
403{
404 locate_hba_stop(seq, v);
405}
406
407
408#define LU_COUNT 1 /* for now */
409static int scsi_tgt_dev_seq_show(struct seq_file *seq, void *v)
410{
411 struct se_hba *hba;
412 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
413 g_se_dev_list);
414 struct se_device *dev = se_dev->se_dev_ptr;
415 int non_accessible_lus = 0;
416 char status[16];
417
418 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
419 seq_puts(seq, "inst indx num_LUs status non_access_LUs"
420 " resets\n");
421
422 if (!(dev))
423 return 0;
424
425 hba = dev->se_hba;
426 if (!(hba)) {
427 /* Log error ? */
428 return 0;
429 }
430
431 switch (dev->dev_status) {
432 case TRANSPORT_DEVICE_ACTIVATED:
433 strcpy(status, "activated");
434 break;
435 case TRANSPORT_DEVICE_DEACTIVATED:
436 strcpy(status, "deactivated");
437 non_accessible_lus = 1;
438 break;
439 case TRANSPORT_DEVICE_SHUTDOWN:
440 strcpy(status, "shutdown");
441 non_accessible_lus = 1;
442 break;
443 case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
444 case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
445 strcpy(status, "offline");
446 non_accessible_lus = 1;
447 break;
448 default:
449 sprintf(status, "unknown(%d)", dev->dev_status);
450 non_accessible_lus = 1;
451 }
452
453 seq_printf(seq, "%u %u %u %s %u %u\n",
454 hba->hba_index, dev->dev_index, LU_COUNT,
455 status, non_accessible_lus, dev->num_resets);
456
457 return 0;
458}
459
460static const struct seq_operations scsi_tgt_dev_seq_ops = {
461 .start = scsi_tgt_dev_seq_start,
462 .next = scsi_tgt_dev_seq_next,
463 .stop = scsi_tgt_dev_seq_stop,
464 .show = scsi_tgt_dev_seq_show
465};
466
467static int scsi_tgt_dev_seq_open(struct inode *inode, struct file *file)
468{
469 return seq_open(file, &scsi_tgt_dev_seq_ops);
470}
471
472static const struct file_operations scsi_tgt_dev_seq_fops = {
473 .owner = THIS_MODULE,
474 .open = scsi_tgt_dev_seq_open,
475 .read = seq_read,
476 .llseek = seq_lseek,
477 .release = seq_release,
478};
479
480/*
481 * SCSI Target Port Table
482 */
483static void *scsi_tgt_port_seq_start(struct seq_file *seq, loff_t *pos)
484{
485 return locate_hba_start(seq, pos);
486}
487
488static void *scsi_tgt_port_seq_next(struct seq_file *seq, void *v, loff_t *pos)
489{
490 return locate_hba_next(seq, v, pos);
491}
492
493static void scsi_tgt_port_seq_stop(struct seq_file *seq, void *v)
494{
495 locate_hba_stop(seq, v);
496}
497
498static int scsi_tgt_port_seq_show(struct seq_file *seq, void *v)
499{
500 struct se_hba *hba;
501 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
502 g_se_dev_list);
503 struct se_device *dev = se_dev->se_dev_ptr;
504 struct se_port *sep, *sep_tmp;
505 struct se_portal_group *tpg;
506 u32 rx_mbytes, tx_mbytes;
507 unsigned long long num_cmds;
508 char buf[64];
509
510 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
511 seq_puts(seq, "inst device indx name port_index in_cmds"
512 " write_mbytes read_mbytes hs_in_cmds\n");
513
514 if (!(dev))
515 return 0;
516
517 hba = dev->se_hba;
518 if (!(hba)) {
519 /* Log error ? */
520 return 0;
521 }
522
523 spin_lock(&dev->se_port_lock);
524 list_for_each_entry_safe(sep, sep_tmp, &dev->dev_sep_list, sep_list) {
525 tpg = sep->sep_tpg;
526 sprintf(buf, "%sPort#",
527 TPG_TFO(tpg)->get_fabric_name());
528
529 seq_printf(seq, "%u %u %u %s%d %s%s%d ",
530 hba->hba_index,
531 dev->dev_index,
532 sep->sep_index,
533 buf, sep->sep_index,
534 TPG_TFO(tpg)->tpg_get_wwn(tpg), "+t+",
535 TPG_TFO(tpg)->tpg_get_tag(tpg));
536
537 spin_lock(&sep->sep_lun->lun_sep_lock);
538 num_cmds = sep->sep_stats.cmd_pdus;
539 rx_mbytes = (sep->sep_stats.rx_data_octets >> 20);
540 tx_mbytes = (sep->sep_stats.tx_data_octets >> 20);
541 spin_unlock(&sep->sep_lun->lun_sep_lock);
542
543 seq_printf(seq, "%llu %u %u %u\n", num_cmds,
544 rx_mbytes, tx_mbytes, 0);
545 }
546 spin_unlock(&dev->se_port_lock);
547
548 return 0;
549}
550
551static const struct seq_operations scsi_tgt_port_seq_ops = {
552 .start = scsi_tgt_port_seq_start,
553 .next = scsi_tgt_port_seq_next,
554 .stop = scsi_tgt_port_seq_stop,
555 .show = scsi_tgt_port_seq_show
556};
557
558static int scsi_tgt_port_seq_open(struct inode *inode, struct file *file)
559{
560 return seq_open(file, &scsi_tgt_port_seq_ops);
561}
562
563static const struct file_operations scsi_tgt_port_seq_fops = {
564 .owner = THIS_MODULE,
565 .open = scsi_tgt_port_seq_open,
566 .read = seq_read,
567 .llseek = seq_lseek,
568 .release = seq_release,
569};
570
571/*
572 * SCSI Authorized Initiator Table:
573 * It contains the SCSI Initiators authorized to be attached to one of the
574 * local Target ports.
575 * Iterates through all active TPGs and extracts the info from the ACLs
576 */
577static void *scsi_auth_intr_seq_start(struct seq_file *seq, loff_t *pos)
578{
579 spin_lock_bh(&se_global->se_tpg_lock);
580 return seq_list_start(&se_global->g_se_tpg_list, *pos);
581}
582
583static void *scsi_auth_intr_seq_next(struct seq_file *seq, void *v,
584 loff_t *pos)
585{
586 return seq_list_next(v, &se_global->g_se_tpg_list, pos);
587}
588
589static void scsi_auth_intr_seq_stop(struct seq_file *seq, void *v)
590{
591 spin_unlock_bh(&se_global->se_tpg_lock);
592}
593
594static int scsi_auth_intr_seq_show(struct seq_file *seq, void *v)
595{
596 struct se_portal_group *se_tpg = list_entry(v, struct se_portal_group,
597 se_tpg_list);
598 struct se_dev_entry *deve;
599 struct se_lun *lun;
600 struct se_node_acl *se_nacl;
601 int j;
602
603 if (list_is_first(&se_tpg->se_tpg_list,
604 &se_global->g_se_tpg_list))
605 seq_puts(seq, "inst dev port indx dev_or_port intr_name "
606 "map_indx att_count num_cmds read_mbytes "
607 "write_mbytes hs_num_cmds creation_time row_status\n");
608
609 if (!(se_tpg))
610 return 0;
611
612 spin_lock(&se_tpg->acl_node_lock);
613 list_for_each_entry(se_nacl, &se_tpg->acl_node_list, acl_list) {
614
615 atomic_inc(&se_nacl->mib_ref_count);
616 smp_mb__after_atomic_inc();
617 spin_unlock(&se_tpg->acl_node_lock);
618
619 spin_lock_irq(&se_nacl->device_list_lock);
620 for (j = 0; j < TRANSPORT_MAX_LUNS_PER_TPG; j++) {
621 deve = &se_nacl->device_list[j];
622 if (!(deve->lun_flags &
623 TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) ||
624 (!deve->se_lun))
625 continue;
626 lun = deve->se_lun;
627 if (!lun->lun_se_dev)
628 continue;
629
630 seq_printf(seq, "%u %u %u %u %u %s %u %u %u %u %u %u"
631 " %u %s\n",
632 /* scsiInstIndex */
633 (TPG_TFO(se_tpg)->tpg_get_inst_index != NULL) ?
634 TPG_TFO(se_tpg)->tpg_get_inst_index(se_tpg) :
635 0,
636 /* scsiDeviceIndex */
637 lun->lun_se_dev->dev_index,
638 /* scsiAuthIntrTgtPortIndex */
639 TPG_TFO(se_tpg)->tpg_get_tag(se_tpg),
640 /* scsiAuthIntrIndex */
641 se_nacl->acl_index,
642 /* scsiAuthIntrDevOrPort */
643 1,
644 /* scsiAuthIntrName */
645 se_nacl->initiatorname[0] ?
646 se_nacl->initiatorname : NONE,
647 /* FIXME: scsiAuthIntrLunMapIndex */
648 0,
649 /* scsiAuthIntrAttachedTimes */
650 deve->attach_count,
651 /* scsiAuthIntrOutCommands */
652 deve->total_cmds,
653 /* scsiAuthIntrReadMegaBytes */
654 (u32)(deve->read_bytes >> 20),
655 /* scsiAuthIntrWrittenMegaBytes */
656 (u32)(deve->write_bytes >> 20),
657 /* FIXME: scsiAuthIntrHSOutCommands */
658 0,
659 /* scsiAuthIntrLastCreation */
660 (u32)(((u32)deve->creation_time -
661 INITIAL_JIFFIES) * 100 / HZ),
662 /* FIXME: scsiAuthIntrRowStatus */
663 "Ready");
664 }
665 spin_unlock_irq(&se_nacl->device_list_lock);
666
667 spin_lock(&se_tpg->acl_node_lock);
668 atomic_dec(&se_nacl->mib_ref_count);
669 smp_mb__after_atomic_dec();
670 }
671 spin_unlock(&se_tpg->acl_node_lock);
672
673 return 0;
674}
675
676static const struct seq_operations scsi_auth_intr_seq_ops = {
677 .start = scsi_auth_intr_seq_start,
678 .next = scsi_auth_intr_seq_next,
679 .stop = scsi_auth_intr_seq_stop,
680 .show = scsi_auth_intr_seq_show
681};
682
683static int scsi_auth_intr_seq_open(struct inode *inode, struct file *file)
684{
685 return seq_open(file, &scsi_auth_intr_seq_ops);
686}
687
688static const struct file_operations scsi_auth_intr_seq_fops = {
689 .owner = THIS_MODULE,
690 .open = scsi_auth_intr_seq_open,
691 .read = seq_read,
692 .llseek = seq_lseek,
693 .release = seq_release,
694};
695
696/*
697 * SCSI Attached Initiator Port Table:
698 * It lists the SCSI Initiators attached to one of the local Target ports.
699 * Iterates through all active TPGs and use active sessions from each TPG
700 * to list the info fo this table.
701 */
702static void *scsi_att_intr_port_seq_start(struct seq_file *seq, loff_t *pos)
703{
704 spin_lock_bh(&se_global->se_tpg_lock);
705 return seq_list_start(&se_global->g_se_tpg_list, *pos);
706}
707
708static void *scsi_att_intr_port_seq_next(struct seq_file *seq, void *v,
709 loff_t *pos)
710{
711 return seq_list_next(v, &se_global->g_se_tpg_list, pos);
712}
713
714static void scsi_att_intr_port_seq_stop(struct seq_file *seq, void *v)
715{
716 spin_unlock_bh(&se_global->se_tpg_lock);
717}
718
719static int scsi_att_intr_port_seq_show(struct seq_file *seq, void *v)
720{
721 struct se_portal_group *se_tpg = list_entry(v, struct se_portal_group,
722 se_tpg_list);
723 struct se_dev_entry *deve;
724 struct se_lun *lun;
725 struct se_node_acl *se_nacl;
726 struct se_session *se_sess;
727 unsigned char buf[64];
728 int j;
729
730 if (list_is_first(&se_tpg->se_tpg_list,
731 &se_global->g_se_tpg_list))
732 seq_puts(seq, "inst dev port indx port_auth_indx port_name"
733 " port_ident\n");
734
735 if (!(se_tpg))
736 return 0;
737
738 spin_lock(&se_tpg->session_lock);
739 list_for_each_entry(se_sess, &se_tpg->tpg_sess_list, sess_list) {
740 if ((TPG_TFO(se_tpg)->sess_logged_in(se_sess)) ||
741 (!se_sess->se_node_acl) ||
742 (!se_sess->se_node_acl->device_list))
743 continue;
744
745 atomic_inc(&se_sess->mib_ref_count);
746 smp_mb__after_atomic_inc();
747 se_nacl = se_sess->se_node_acl;
748 atomic_inc(&se_nacl->mib_ref_count);
749 smp_mb__after_atomic_inc();
750 spin_unlock(&se_tpg->session_lock);
751
752 spin_lock_irq(&se_nacl->device_list_lock);
753 for (j = 0; j < TRANSPORT_MAX_LUNS_PER_TPG; j++) {
754 deve = &se_nacl->device_list[j];
755 if (!(deve->lun_flags &
756 TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) ||
757 (!deve->se_lun))
758 continue;
759
760 lun = deve->se_lun;
761 if (!lun->lun_se_dev)
762 continue;
763
764 memset(buf, 0, 64);
765 if (TPG_TFO(se_tpg)->sess_get_initiator_sid != NULL)
766 TPG_TFO(se_tpg)->sess_get_initiator_sid(
767 se_sess, (unsigned char *)&buf[0], 64);
768
769 seq_printf(seq, "%u %u %u %u %u %s+i+%s\n",
770 /* scsiInstIndex */
771 (TPG_TFO(se_tpg)->tpg_get_inst_index != NULL) ?
772 TPG_TFO(se_tpg)->tpg_get_inst_index(se_tpg) :
773 0,
774 /* scsiDeviceIndex */
775 lun->lun_se_dev->dev_index,
776 /* scsiPortIndex */
777 TPG_TFO(se_tpg)->tpg_get_tag(se_tpg),
778 /* scsiAttIntrPortIndex */
779 (TPG_TFO(se_tpg)->sess_get_index != NULL) ?
780 TPG_TFO(se_tpg)->sess_get_index(se_sess) :
781 0,
782 /* scsiAttIntrPortAuthIntrIdx */
783 se_nacl->acl_index,
784 /* scsiAttIntrPortName */
785 se_nacl->initiatorname[0] ?
786 se_nacl->initiatorname : NONE,
787 /* scsiAttIntrPortIdentifier */
788 buf);
789 }
790 spin_unlock_irq(&se_nacl->device_list_lock);
791
792 spin_lock(&se_tpg->session_lock);
793 atomic_dec(&se_nacl->mib_ref_count);
794 smp_mb__after_atomic_dec();
795 atomic_dec(&se_sess->mib_ref_count);
796 smp_mb__after_atomic_dec();
797 }
798 spin_unlock(&se_tpg->session_lock);
799
800 return 0;
801}
802
803static const struct seq_operations scsi_att_intr_port_seq_ops = {
804 .start = scsi_att_intr_port_seq_start,
805 .next = scsi_att_intr_port_seq_next,
806 .stop = scsi_att_intr_port_seq_stop,
807 .show = scsi_att_intr_port_seq_show
808};
809
810static int scsi_att_intr_port_seq_open(struct inode *inode, struct file *file)
811{
812 return seq_open(file, &scsi_att_intr_port_seq_ops);
813}
814
815static const struct file_operations scsi_att_intr_port_seq_fops = {
816 .owner = THIS_MODULE,
817 .open = scsi_att_intr_port_seq_open,
818 .read = seq_read,
819 .llseek = seq_lseek,
820 .release = seq_release,
821};
822
823/*
824 * SCSI Logical Unit Table
825 */
826static void *scsi_lu_seq_start(struct seq_file *seq, loff_t *pos)
827{
828 return locate_hba_start(seq, pos);
829}
830
831static void *scsi_lu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
832{
833 return locate_hba_next(seq, v, pos);
834}
835
836static void scsi_lu_seq_stop(struct seq_file *seq, void *v)
837{
838 locate_hba_stop(seq, v);
839}
840
841#define SCSI_LU_INDEX 1
842static int scsi_lu_seq_show(struct seq_file *seq, void *v)
843{
844 struct se_hba *hba;
845 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
846 g_se_dev_list);
847 struct se_device *dev = se_dev->se_dev_ptr;
848 int j;
849 char str[28];
850
851 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
852 seq_puts(seq, "inst dev indx LUN lu_name vend prod rev"
853 " dev_type status state-bit num_cmds read_mbytes"
854 " write_mbytes resets full_stat hs_num_cmds creation_time\n");
855
856 if (!(dev))
857 return 0;
858
859 hba = dev->se_hba;
860 if (!(hba)) {
861 /* Log error ? */
862 return 0;
863 }
864
865 /* Fix LU state, if we can read it from the device */
866 seq_printf(seq, "%u %u %u %llu %s", hba->hba_index,
867 dev->dev_index, SCSI_LU_INDEX,
868 (unsigned long long)0, /* FIXME: scsiLuDefaultLun */
869 (strlen(DEV_T10_WWN(dev)->unit_serial)) ?
870 /* scsiLuWwnName */
871 (char *)&DEV_T10_WWN(dev)->unit_serial[0] :
872 "None");
873
874 memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
875 /* scsiLuVendorId */
876 for (j = 0; j < 8; j++)
877 str[j] = ISPRINT(DEV_T10_WWN(dev)->vendor[j]) ?
878 DEV_T10_WWN(dev)->vendor[j] : 0x20;
879 str[8] = 0;
880 seq_printf(seq, " %s", str);
881
882 /* scsiLuProductId */
883 for (j = 0; j < 16; j++)
884 str[j] = ISPRINT(DEV_T10_WWN(dev)->model[j]) ?
885 DEV_T10_WWN(dev)->model[j] : 0x20;
886 str[16] = 0;
887 seq_printf(seq, " %s", str);
888
889 /* scsiLuRevisionId */
890 for (j = 0; j < 4; j++)
891 str[j] = ISPRINT(DEV_T10_WWN(dev)->revision[j]) ?
892 DEV_T10_WWN(dev)->revision[j] : 0x20;
893 str[4] = 0;
894 seq_printf(seq, " %s", str);
895
896 seq_printf(seq, " %u %s %s %llu %u %u %u %u %u %u\n",
897 /* scsiLuPeripheralType */
898 TRANSPORT(dev)->get_device_type(dev),
899 (dev->dev_status == TRANSPORT_DEVICE_ACTIVATED) ?
900 "available" : "notavailable", /* scsiLuStatus */
901 "exposed", /* scsiLuState */
902 (unsigned long long)dev->num_cmds,
903 /* scsiLuReadMegaBytes */
904 (u32)(dev->read_bytes >> 20),
905 /* scsiLuWrittenMegaBytes */
906 (u32)(dev->write_bytes >> 20),
907 dev->num_resets, /* scsiLuInResets */
908 0, /* scsiLuOutTaskSetFullStatus */
909 0, /* scsiLuHSInCommands */
910 (u32)(((u32)dev->creation_time - INITIAL_JIFFIES) *
911 100 / HZ));
912
913 return 0;
914}
915
916static const struct seq_operations scsi_lu_seq_ops = {
917 .start = scsi_lu_seq_start,
918 .next = scsi_lu_seq_next,
919 .stop = scsi_lu_seq_stop,
920 .show = scsi_lu_seq_show
921};
922
923static int scsi_lu_seq_open(struct inode *inode, struct file *file)
924{
925 return seq_open(file, &scsi_lu_seq_ops);
926}
927
928static const struct file_operations scsi_lu_seq_fops = {
929 .owner = THIS_MODULE,
930 .open = scsi_lu_seq_open,
931 .read = seq_read,
932 .llseek = seq_lseek,
933 .release = seq_release,
934};
935
936/****************************************************************************/
937
938/*
939 * Remove proc fs entries
940 */
941void remove_scsi_target_mib(void)
942{
943 remove_proc_entry("scsi_target/mib/scsi_inst", NULL);
944 remove_proc_entry("scsi_target/mib/scsi_dev", NULL);
945 remove_proc_entry("scsi_target/mib/scsi_port", NULL);
946 remove_proc_entry("scsi_target/mib/scsi_transport", NULL);
947 remove_proc_entry("scsi_target/mib/scsi_tgt_dev", NULL);
948 remove_proc_entry("scsi_target/mib/scsi_tgt_port", NULL);
949 remove_proc_entry("scsi_target/mib/scsi_auth_intr", NULL);
950 remove_proc_entry("scsi_target/mib/scsi_att_intr_port", NULL);
951 remove_proc_entry("scsi_target/mib/scsi_lu", NULL);
952 remove_proc_entry("scsi_target/mib", NULL);
953}
954
955/*
956 * Create proc fs entries for the mib tables
957 */
958int init_scsi_target_mib(void)
959{
960 struct proc_dir_entry *dir_entry;
961 struct proc_dir_entry *scsi_inst_entry;
962 struct proc_dir_entry *scsi_dev_entry;
963 struct proc_dir_entry *scsi_port_entry;
964 struct proc_dir_entry *scsi_transport_entry;
965 struct proc_dir_entry *scsi_tgt_dev_entry;
966 struct proc_dir_entry *scsi_tgt_port_entry;
967 struct proc_dir_entry *scsi_auth_intr_entry;
968 struct proc_dir_entry *scsi_att_intr_port_entry;
969 struct proc_dir_entry *scsi_lu_entry;
970
971 dir_entry = proc_mkdir("scsi_target/mib", NULL);
972 if (!(dir_entry)) {
973 printk(KERN_ERR "proc_mkdir() failed.\n");
974 return -1;
975 }
976
977 scsi_inst_entry =
978 create_proc_entry("scsi_target/mib/scsi_inst", 0, NULL);
979 if (scsi_inst_entry)
980 scsi_inst_entry->proc_fops = &scsi_inst_seq_fops;
981 else
982 goto error;
983
984 scsi_dev_entry =
985 create_proc_entry("scsi_target/mib/scsi_dev", 0, NULL);
986 if (scsi_dev_entry)
987 scsi_dev_entry->proc_fops = &scsi_dev_seq_fops;
988 else
989 goto error;
990
991 scsi_port_entry =
992 create_proc_entry("scsi_target/mib/scsi_port", 0, NULL);
993 if (scsi_port_entry)
994 scsi_port_entry->proc_fops = &scsi_port_seq_fops;
995 else
996 goto error;
997
998 scsi_transport_entry =
999 create_proc_entry("scsi_target/mib/scsi_transport", 0, NULL);
1000 if (scsi_transport_entry)
1001 scsi_transport_entry->proc_fops = &scsi_transport_seq_fops;
1002 else
1003 goto error;
1004
1005 scsi_tgt_dev_entry =
1006 create_proc_entry("scsi_target/mib/scsi_tgt_dev", 0, NULL);
1007 if (scsi_tgt_dev_entry)
1008 scsi_tgt_dev_entry->proc_fops = &scsi_tgt_dev_seq_fops;
1009 else
1010 goto error;
1011
1012 scsi_tgt_port_entry =
1013 create_proc_entry("scsi_target/mib/scsi_tgt_port", 0, NULL);
1014 if (scsi_tgt_port_entry)
1015 scsi_tgt_port_entry->proc_fops = &scsi_tgt_port_seq_fops;
1016 else
1017 goto error;
1018
1019 scsi_auth_intr_entry =
1020 create_proc_entry("scsi_target/mib/scsi_auth_intr", 0, NULL);
1021 if (scsi_auth_intr_entry)
1022 scsi_auth_intr_entry->proc_fops = &scsi_auth_intr_seq_fops;
1023 else
1024 goto error;
1025
1026 scsi_att_intr_port_entry =
1027 create_proc_entry("scsi_target/mib/scsi_att_intr_port", 0, NULL);
1028 if (scsi_att_intr_port_entry)
1029 scsi_att_intr_port_entry->proc_fops =
1030 &scsi_att_intr_port_seq_fops;
1031 else
1032 goto error;
1033
1034 scsi_lu_entry = create_proc_entry("scsi_target/mib/scsi_lu", 0, NULL);
1035 if (scsi_lu_entry)
1036 scsi_lu_entry->proc_fops = &scsi_lu_seq_fops;
1037 else
1038 goto error;
1039
1040 return 0;
1041
1042error:
1043 printk(KERN_ERR "create_proc_entry() failed.\n");
1044 remove_scsi_target_mib();
1045 return -1;
1046}
1047
1048/*
1049 * Initialize the index table for allocating unique row indexes to various mib
1050 * tables
1051 */
1052void init_scsi_index_table(void)
1053{
1054 memset(&scsi_index_table, 0, sizeof(struct scsi_index_table));
1055 spin_lock_init(&scsi_index_table.lock);
1056}
1057
1058/*
1059 * Allocate a new row index for the entry type specified
1060 */
1061u32 scsi_get_new_index(scsi_index_t type)
1062{
1063 u32 new_index;
1064
1065 if ((type < 0) || (type >= SCSI_INDEX_TYPE_MAX)) {
1066 printk(KERN_ERR "Invalid index type %d\n", type);
1067 return -1;
1068 }
1069
1070 spin_lock(&scsi_index_table.lock);
1071 new_index = ++scsi_index_table.scsi_mib_index[type];
1072 if (new_index == 0)
1073 new_index = ++scsi_index_table.scsi_mib_index[type];
1074 spin_unlock(&scsi_index_table.lock);
1075
1076 return new_index;
1077}
1078EXPORT_SYMBOL(scsi_get_new_index);
diff --git a/drivers/target/target_core_mib.h b/drivers/target/target_core_mib.h
deleted file mode 100644
index 277204633850..000000000000
--- a/drivers/target/target_core_mib.h
+++ /dev/null
@@ -1,28 +0,0 @@
1#ifndef TARGET_CORE_MIB_H
2#define TARGET_CORE_MIB_H
3
4typedef enum {
5 SCSI_INST_INDEX,
6 SCSI_DEVICE_INDEX,
7 SCSI_AUTH_INTR_INDEX,
8 SCSI_INDEX_TYPE_MAX
9} scsi_index_t;
10
11struct scsi_index_table {
12 spinlock_t lock;
13 u32 scsi_mib_index[SCSI_INDEX_TYPE_MAX];
14} ____cacheline_aligned;
15
16/* SCSI Port stats */
17struct scsi_port_stats {
18 u64 cmd_pdus;
19 u64 tx_data_octets;
20 u64 rx_data_octets;
21} ____cacheline_aligned;
22
23extern int init_scsi_target_mib(void);
24extern void remove_scsi_target_mib(void);
25extern void init_scsi_index_table(void);
26extern u32 scsi_get_new_index(scsi_index_t);
27
28#endif /*** TARGET_CORE_MIB_H ***/
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index abfa81a57115..c26f67467623 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -275,7 +275,6 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
275 spin_lock_init(&acl->device_list_lock); 275 spin_lock_init(&acl->device_list_lock);
276 spin_lock_init(&acl->nacl_sess_lock); 276 spin_lock_init(&acl->nacl_sess_lock);
277 atomic_set(&acl->acl_pr_ref_count, 0); 277 atomic_set(&acl->acl_pr_ref_count, 0);
278 atomic_set(&acl->mib_ref_count, 0);
279 acl->queue_depth = TPG_TFO(tpg)->tpg_get_default_depth(tpg); 278 acl->queue_depth = TPG_TFO(tpg)->tpg_get_default_depth(tpg);
280 snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); 279 snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
281 acl->se_tpg = tpg; 280 acl->se_tpg = tpg;
@@ -318,12 +317,6 @@ void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *nacl)
318 cpu_relax(); 317 cpu_relax();
319} 318}
320 319
321void core_tpg_wait_for_mib_ref(struct se_node_acl *nacl)
322{
323 while (atomic_read(&nacl->mib_ref_count) != 0)
324 cpu_relax();
325}
326
327void core_tpg_clear_object_luns(struct se_portal_group *tpg) 320void core_tpg_clear_object_luns(struct se_portal_group *tpg)
328{ 321{
329 int i, ret; 322 int i, ret;
@@ -480,7 +473,6 @@ int core_tpg_del_initiator_node_acl(
480 spin_unlock_bh(&tpg->session_lock); 473 spin_unlock_bh(&tpg->session_lock);
481 474
482 core_tpg_wait_for_nacl_pr_ref(acl); 475 core_tpg_wait_for_nacl_pr_ref(acl);
483 core_tpg_wait_for_mib_ref(acl);
484 core_clear_initiator_node_from_tpg(acl, tpg); 476 core_clear_initiator_node_from_tpg(acl, tpg);
485 core_free_device_list_for_node(acl, tpg); 477 core_free_device_list_for_node(acl, tpg);
486 478
@@ -701,6 +693,8 @@ EXPORT_SYMBOL(core_tpg_register);
701 693
702int core_tpg_deregister(struct se_portal_group *se_tpg) 694int core_tpg_deregister(struct se_portal_group *se_tpg)
703{ 695{
696 struct se_node_acl *nacl, *nacl_tmp;
697
704 printk(KERN_INFO "TARGET_CORE[%s]: Deallocating %s struct se_portal_group" 698 printk(KERN_INFO "TARGET_CORE[%s]: Deallocating %s struct se_portal_group"
705 " for endpoint: %s Portal Tag %u\n", 699 " for endpoint: %s Portal Tag %u\n",
706 (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ? 700 (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ?
@@ -714,6 +708,25 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
714 708
715 while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0) 709 while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0)
716 cpu_relax(); 710 cpu_relax();
711 /*
712 * Release any remaining demo-mode generated se_node_acl that have
713 * not been released because of TFO->tpg_check_demo_mode_cache() == 1
714 * in transport_deregister_session().
715 */
716 spin_lock_bh(&se_tpg->acl_node_lock);
717 list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list,
718 acl_list) {
719 list_del(&nacl->acl_list);
720 se_tpg->num_node_acls--;
721 spin_unlock_bh(&se_tpg->acl_node_lock);
722
723 core_tpg_wait_for_nacl_pr_ref(nacl);
724 core_free_device_list_for_node(nacl, se_tpg);
725 TPG_TFO(se_tpg)->tpg_release_fabric_acl(se_tpg, nacl);
726
727 spin_lock_bh(&se_tpg->acl_node_lock);
728 }
729 spin_unlock_bh(&se_tpg->acl_node_lock);
717 730
718 if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) 731 if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL)
719 core_tpg_release_virtual_lun0(se_tpg); 732 core_tpg_release_virtual_lun0(se_tpg);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 32dc5163b5a0..236e22d8cfae 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -379,6 +379,40 @@ void release_se_global(void)
379 se_global = NULL; 379 se_global = NULL;
380} 380}
381 381
382/* SCSI statistics table index */
383static struct scsi_index_table scsi_index_table;
384
385/*
386 * Initialize the index table for allocating unique row indexes to various mib
387 * tables.
388 */
389void init_scsi_index_table(void)
390{
391 memset(&scsi_index_table, 0, sizeof(struct scsi_index_table));
392 spin_lock_init(&scsi_index_table.lock);
393}
394
395/*
396 * Allocate a new row index for the entry type specified
397 */
398u32 scsi_get_new_index(scsi_index_t type)
399{
400 u32 new_index;
401
402 if ((type < 0) || (type >= SCSI_INDEX_TYPE_MAX)) {
403 printk(KERN_ERR "Invalid index type %d\n", type);
404 return -EINVAL;
405 }
406
407 spin_lock(&scsi_index_table.lock);
408 new_index = ++scsi_index_table.scsi_mib_index[type];
409 if (new_index == 0)
410 new_index = ++scsi_index_table.scsi_mib_index[type];
411 spin_unlock(&scsi_index_table.lock);
412
413 return new_index;
414}
415
382void transport_init_queue_obj(struct se_queue_obj *qobj) 416void transport_init_queue_obj(struct se_queue_obj *qobj)
383{ 417{
384 atomic_set(&qobj->queue_cnt, 0); 418 atomic_set(&qobj->queue_cnt, 0);
@@ -437,7 +471,6 @@ struct se_session *transport_init_session(void)
437 } 471 }
438 INIT_LIST_HEAD(&se_sess->sess_list); 472 INIT_LIST_HEAD(&se_sess->sess_list);
439 INIT_LIST_HEAD(&se_sess->sess_acl_list); 473 INIT_LIST_HEAD(&se_sess->sess_acl_list);
440 atomic_set(&se_sess->mib_ref_count, 0);
441 474
442 return se_sess; 475 return se_sess;
443} 476}
@@ -546,12 +579,6 @@ void transport_deregister_session(struct se_session *se_sess)
546 transport_free_session(se_sess); 579 transport_free_session(se_sess);
547 return; 580 return;
548 } 581 }
549 /*
550 * Wait for possible reference in drivers/target/target_core_mib.c:
551 * scsi_att_intr_port_seq_show()
552 */
553 while (atomic_read(&se_sess->mib_ref_count) != 0)
554 cpu_relax();
555 582
556 spin_lock_bh(&se_tpg->session_lock); 583 spin_lock_bh(&se_tpg->session_lock);
557 list_del(&se_sess->sess_list); 584 list_del(&se_sess->sess_list);
@@ -574,7 +601,6 @@ void transport_deregister_session(struct se_session *se_sess)
574 spin_unlock_bh(&se_tpg->acl_node_lock); 601 spin_unlock_bh(&se_tpg->acl_node_lock);
575 602
576 core_tpg_wait_for_nacl_pr_ref(se_nacl); 603 core_tpg_wait_for_nacl_pr_ref(se_nacl);
577 core_tpg_wait_for_mib_ref(se_nacl);
578 core_free_device_list_for_node(se_nacl, se_tpg); 604 core_free_device_list_for_node(se_nacl, se_tpg);
579 TPG_TFO(se_tpg)->tpg_release_fabric_acl(se_tpg, 605 TPG_TFO(se_tpg)->tpg_release_fabric_acl(se_tpg,
580 se_nacl); 606 se_nacl);