]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/target/target_core_mib.c
Merge branch 'slub/hotplug' into slab/urgent
[mv-sheeva.git] / drivers / target / target_core_mib.c
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 */
51 static 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
64 static inline int list_is_first(const struct list_head *list,
65                                 const struct list_head *head)
66 {
67         return list->prev == head;
68 }
69
70 static 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
78 static 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
86 static 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  */
98 static 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
106 static 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
114 static void scsi_inst_seq_stop(struct seq_file *seq, void *v)
115 {
116         spin_unlock(&se_global->hba_lock);
117 }
118
119 static 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
133 static 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
140 static int scsi_inst_seq_open(struct inode *inode, struct file *file)
141 {
142         return seq_open(file, &scsi_inst_seq_ops);
143 }
144
145 static 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  */
156 static void *scsi_dev_seq_start(struct seq_file *seq, loff_t *pos)
157 {
158         return locate_hba_start(seq, pos);
159 }
160
161 static 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
166 static void scsi_dev_seq_stop(struct seq_file *seq, void *v)
167 {
168         locate_hba_stop(seq, v);
169 }
170
171 static 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
214 static 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
221 static int scsi_dev_seq_open(struct inode *inode, struct file *file)
222 {
223         return seq_open(file, &scsi_dev_seq_ops);
224 }
225
226 static 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  */
237 static void *scsi_port_seq_start(struct seq_file *seq, loff_t *pos)
238 {
239         return locate_hba_start(seq, pos);
240 }
241
242 static 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
247 static void scsi_port_seq_stop(struct seq_file *seq, void *v)
248 {
249         locate_hba_stop(seq, v);
250 }
251
252 static 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
284 static 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
291 static int scsi_port_seq_open(struct inode *inode, struct file *file)
292 {
293         return seq_open(file, &scsi_port_seq_ops);
294 }
295
296 static 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  */
307 static void *scsi_transport_seq_start(struct seq_file *seq, loff_t *pos)
308 {
309         return locate_hba_start(seq, pos);
310 }
311
312 static 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
317 static void scsi_transport_seq_stop(struct seq_file *seq, void *v)
318 {
319         locate_hba_stop(seq, v);
320 }
321
322 static 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
369 static 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
376 static int scsi_transport_seq_open(struct inode *inode, struct file *file)
377 {
378         return seq_open(file, &scsi_transport_seq_ops);
379 }
380
381 static 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  */
392 static void *scsi_tgt_dev_seq_start(struct seq_file *seq, loff_t *pos)
393 {
394         return locate_hba_start(seq, pos);
395 }
396
397 static 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
402 static 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 */
409 static 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
460 static 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
467 static 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
472 static 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  */
483 static void *scsi_tgt_port_seq_start(struct seq_file *seq, loff_t *pos)
484 {
485         return locate_hba_start(seq, pos);
486 }
487
488 static 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
493 static void scsi_tgt_port_seq_stop(struct seq_file *seq, void *v)
494 {
495         locate_hba_stop(seq, v);
496 }
497
498 static 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
551 static 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
558 static 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
563 static 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  */
577 static 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
583 static 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
589 static void scsi_auth_intr_seq_stop(struct seq_file *seq, void *v)
590 {
591         spin_unlock_bh(&se_global->se_tpg_lock);
592 }
593
594 static 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
676 static 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
683 static 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
688 static 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  */
702 static 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
708 static 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
714 static 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
719 static 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
803 static 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
810 static 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
815 static 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  */
826 static void *scsi_lu_seq_start(struct seq_file *seq, loff_t *pos)
827 {
828         return locate_hba_start(seq, pos);
829 }
830
831 static 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
836 static 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
842 static 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
916 static 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
923 static int scsi_lu_seq_open(struct inode *inode, struct file *file)
924 {
925         return seq_open(file, &scsi_lu_seq_ops);
926 }
927
928 static 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  */
941 void 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  */
958 int 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
1042 error:
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  */
1052 void 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  */
1061 u32 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 }
1078 EXPORT_SYMBOL(scsi_get_new_index);