target_core_mib.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  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. #include <linux/kernel.h>
  26. #include <linux/module.h>
  27. #include <linux/delay.h>
  28. #include <linux/timer.h>
  29. #include <linux/string.h>
  30. #include <linux/version.h>
  31. #include <generated/utsrelease.h>
  32. #include <linux/utsname.h>
  33. #include <linux/proc_fs.h>
  34. #include <linux/seq_file.h>
  35. #include <linux/blkdev.h>
  36. #include <scsi/scsi.h>
  37. #include <scsi/scsi_device.h>
  38. #include <scsi/scsi_host.h>
  39. #include <target/target_core_base.h>
  40. #include <target/target_core_transport.h>
  41. #include <target/target_core_fabric_ops.h>
  42. #include <target/target_core_configfs.h>
  43. #include "target_core_hba.h"
  44. #include "target_core_mib.h"
  45. /* SCSI mib table index */
  46. static struct scsi_index_table scsi_index_table;
  47. #ifndef INITIAL_JIFFIES
  48. #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
  49. #endif
  50. /* SCSI Instance Table */
  51. #define SCSI_INST_SW_INDEX 1
  52. #define SCSI_TRANSPORT_INDEX 1
  53. #define NONE "None"
  54. #define ISPRINT(a) ((a >= ' ') && (a <= '~'))
  55. static inline int list_is_first(const struct list_head *list,
  56. const struct list_head *head)
  57. {
  58. return list->prev == head;
  59. }
  60. static void *locate_hba_start(
  61. struct seq_file *seq,
  62. loff_t *pos)
  63. {
  64. spin_lock(&se_global->g_device_lock);
  65. return seq_list_start(&se_global->g_se_dev_list, *pos);
  66. }
  67. static void *locate_hba_next(
  68. struct seq_file *seq,
  69. void *v,
  70. loff_t *pos)
  71. {
  72. return seq_list_next(v, &se_global->g_se_dev_list, pos);
  73. }
  74. static void locate_hba_stop(struct seq_file *seq, void *v)
  75. {
  76. spin_unlock(&se_global->g_device_lock);
  77. }
  78. /****************************************************************************
  79. * SCSI MIB Tables
  80. ****************************************************************************/
  81. /*
  82. * SCSI Instance Table
  83. */
  84. static void *scsi_inst_seq_start(
  85. struct seq_file *seq,
  86. loff_t *pos)
  87. {
  88. spin_lock(&se_global->hba_lock);
  89. return seq_list_start(&se_global->g_hba_list, *pos);
  90. }
  91. static void *scsi_inst_seq_next(
  92. struct seq_file *seq,
  93. void *v,
  94. loff_t *pos)
  95. {
  96. return seq_list_next(v, &se_global->g_hba_list, pos);
  97. }
  98. static void scsi_inst_seq_stop(struct seq_file *seq, void *v)
  99. {
  100. spin_unlock(&se_global->hba_lock);
  101. }
  102. static int scsi_inst_seq_show(struct seq_file *seq, void *v)
  103. {
  104. struct se_hba *hba = list_entry(v, struct se_hba, hba_list);
  105. if (list_is_first(&hba->hba_list, &se_global->g_hba_list))
  106. seq_puts(seq, "inst sw_indx\n");
  107. seq_printf(seq, "%u %u\n", hba->hba_index, SCSI_INST_SW_INDEX);
  108. seq_printf(seq, "plugin: %s version: %s\n",
  109. hba->transport->name, TARGET_CORE_VERSION);
  110. return 0;
  111. }
  112. static const struct seq_operations scsi_inst_seq_ops = {
  113. .start = scsi_inst_seq_start,
  114. .next = scsi_inst_seq_next,
  115. .stop = scsi_inst_seq_stop,
  116. .show = scsi_inst_seq_show
  117. };
  118. static int scsi_inst_seq_open(struct inode *inode, struct file *file)
  119. {
  120. return seq_open(file, &scsi_inst_seq_ops);
  121. }
  122. static const struct file_operations scsi_inst_seq_fops = {
  123. .owner = THIS_MODULE,
  124. .open = scsi_inst_seq_open,
  125. .read = seq_read,
  126. .llseek = seq_lseek,
  127. .release = seq_release,
  128. };
  129. /*
  130. * SCSI Device Table
  131. */
  132. static void *scsi_dev_seq_start(struct seq_file *seq, loff_t *pos)
  133. {
  134. return locate_hba_start(seq, pos);
  135. }
  136. static void *scsi_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  137. {
  138. return locate_hba_next(seq, v, pos);
  139. }
  140. static void scsi_dev_seq_stop(struct seq_file *seq, void *v)
  141. {
  142. locate_hba_stop(seq, v);
  143. }
  144. static int scsi_dev_seq_show(struct seq_file *seq, void *v)
  145. {
  146. struct se_hba *hba;
  147. struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
  148. g_se_dev_list);
  149. struct se_device *dev = se_dev->se_dev_ptr;
  150. char str[28];
  151. int k;
  152. if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
  153. seq_puts(seq, "inst indx role ports\n");
  154. if (!(dev))
  155. return 0;
  156. hba = dev->se_hba;
  157. if (!(hba)) {
  158. /* Log error ? */
  159. return 0;
  160. }
  161. seq_printf(seq, "%u %u %s %u\n", hba->hba_index,
  162. dev->dev_index, "Target", dev->dev_port_count);
  163. memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
  164. /* vendor */
  165. for (k = 0; k < 8; k++)
  166. str[k] = ISPRINT(DEV_T10_WWN(dev)->vendor[k]) ?
  167. DEV_T10_WWN(dev)->vendor[k] : 0x20;
  168. str[k] = 0x20;
  169. /* model */
  170. for (k = 0; k < 16; k++)
  171. str[k+9] = ISPRINT(DEV_T10_WWN(dev)->model[k]) ?
  172. DEV_T10_WWN(dev)->model[k] : 0x20;
  173. str[k + 9] = 0;
  174. seq_printf(seq, "dev_alias: %s\n", str);
  175. return 0;
  176. }
  177. static const struct seq_operations scsi_dev_seq_ops = {
  178. .start = scsi_dev_seq_start,
  179. .next = scsi_dev_seq_next,
  180. .stop = scsi_dev_seq_stop,
  181. .show = scsi_dev_seq_show
  182. };
  183. static int scsi_dev_seq_open(struct inode *inode, struct file *file)
  184. {
  185. return seq_open(file, &scsi_dev_seq_ops);
  186. }
  187. static const struct file_operations scsi_dev_seq_fops = {
  188. .owner = THIS_MODULE,
  189. .open = scsi_dev_seq_open,
  190. .read = seq_read,
  191. .llseek = seq_lseek,
  192. .release = seq_release,
  193. };
  194. /*
  195. * SCSI Port Table
  196. */
  197. static void *scsi_port_seq_start(struct seq_file *seq, loff_t *pos)
  198. {
  199. return locate_hba_start(seq, pos);
  200. }
  201. static void *scsi_port_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  202. {
  203. return locate_hba_next(seq, v, pos);
  204. }
  205. static void scsi_port_seq_stop(struct seq_file *seq, void *v)
  206. {
  207. locate_hba_stop(seq, v);
  208. }
  209. static int scsi_port_seq_show(struct seq_file *seq, void *v)
  210. {
  211. struct se_hba *hba;
  212. struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
  213. g_se_dev_list);
  214. struct se_device *dev = se_dev->se_dev_ptr;
  215. struct se_port *sep, *sep_tmp;
  216. if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
  217. seq_puts(seq, "inst device indx role busy_count\n");
  218. if (!(dev))
  219. return 0;
  220. hba = dev->se_hba;
  221. if (!(hba)) {
  222. /* Log error ? */
  223. return 0;
  224. }
  225. /* FIXME: scsiPortBusyStatuses count */
  226. spin_lock(&dev->se_port_lock);
  227. list_for_each_entry_safe(sep, sep_tmp, &dev->dev_sep_list, sep_list) {
  228. seq_printf(seq, "%u %u %u %s%u %u\n", hba->hba_index,
  229. dev->dev_index, sep->sep_index, "Device",
  230. dev->dev_index, 0);
  231. }
  232. spin_unlock(&dev->se_port_lock);
  233. return 0;
  234. }
  235. static const struct seq_operations scsi_port_seq_ops = {
  236. .start = scsi_port_seq_start,
  237. .next = scsi_port_seq_next,
  238. .stop = scsi_port_seq_stop,
  239. .show = scsi_port_seq_show
  240. };
  241. static int scsi_port_seq_open(struct inode *inode, struct file *file)
  242. {
  243. return seq_open(file, &scsi_port_seq_ops);
  244. }
  245. static const struct file_operations scsi_port_seq_fops = {
  246. .owner = THIS_MODULE,
  247. .open = scsi_port_seq_open,
  248. .read = seq_read,
  249. .llseek = seq_lseek,
  250. .release = seq_release,
  251. };
  252. /*
  253. * SCSI Transport Table
  254. */
  255. static void *scsi_transport_seq_start(struct seq_file *seq, loff_t *pos)
  256. {
  257. return locate_hba_start(seq, pos);
  258. }
  259. static void *scsi_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  260. {
  261. return locate_hba_next(seq, v, pos);
  262. }
  263. static void scsi_transport_seq_stop(struct seq_file *seq, void *v)
  264. {
  265. locate_hba_stop(seq, v);
  266. }
  267. static int scsi_transport_seq_show(struct seq_file *seq, void *v)
  268. {
  269. struct se_hba *hba;
  270. struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
  271. g_se_dev_list);
  272. struct se_device *dev = se_dev->se_dev_ptr;
  273. struct se_port *se, *se_tmp;
  274. struct se_portal_group *tpg;
  275. struct t10_wwn *wwn;
  276. char buf[64];
  277. if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
  278. seq_puts(seq, "inst device indx dev_name\n");
  279. if (!(dev))
  280. return 0;
  281. hba = dev->se_hba;
  282. if (!(hba)) {
  283. /* Log error ? */
  284. return 0;
  285. }
  286. wwn = DEV_T10_WWN(dev);
  287. spin_lock(&dev->se_port_lock);
  288. list_for_each_entry_safe(se, se_tmp, &dev->dev_sep_list, sep_list) {
  289. tpg = se->sep_tpg;
  290. sprintf(buf, "scsiTransport%s",
  291. TPG_TFO(tpg)->get_fabric_name());
  292. seq_printf(seq, "%u %s %u %s+%s\n",
  293. hba->hba_index, /* scsiTransportIndex */
  294. buf, /* scsiTransportType */
  295. (TPG_TFO(tpg)->tpg_get_inst_index != NULL) ?
  296. TPG_TFO(tpg)->tpg_get_inst_index(tpg) :
  297. 0,
  298. TPG_TFO(tpg)->tpg_get_wwn(tpg),
  299. (strlen(wwn->unit_serial)) ?
  300. /* scsiTransportDevName */
  301. wwn->unit_serial : wwn->vendor);
  302. }
  303. spin_unlock(&dev->se_port_lock);
  304. return 0;
  305. }
  306. static const struct seq_operations scsi_transport_seq_ops = {
  307. .start = scsi_transport_seq_start,
  308. .next = scsi_transport_seq_next,
  309. .stop = scsi_transport_seq_stop,
  310. .show = scsi_transport_seq_show
  311. };
  312. static int scsi_transport_seq_open(struct inode *inode, struct file *file)
  313. {
  314. return seq_open(file, &scsi_transport_seq_ops);
  315. }
  316. static const struct file_operations scsi_transport_seq_fops = {
  317. .owner = THIS_MODULE,
  318. .open = scsi_transport_seq_open,
  319. .read = seq_read,
  320. .llseek = seq_lseek,
  321. .release = seq_release,
  322. };
  323. /*
  324. * SCSI Target Device Table
  325. */
  326. static void *scsi_tgt_dev_seq_start(struct seq_file *seq, loff_t *pos)
  327. {
  328. return locate_hba_start(seq, pos);
  329. }
  330. static void *scsi_tgt_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  331. {
  332. return locate_hba_next(seq, v, pos);
  333. }
  334. static void scsi_tgt_dev_seq_stop(struct seq_file *seq, void *v)
  335. {
  336. locate_hba_stop(seq, v);
  337. }
  338. #define LU_COUNT 1 /* for now */
  339. static int scsi_tgt_dev_seq_show(struct seq_file *seq, void *v)
  340. {
  341. struct se_hba *hba;
  342. struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
  343. g_se_dev_list);
  344. struct se_device *dev = se_dev->se_dev_ptr;
  345. int non_accessible_lus = 0;
  346. char status[16];
  347. if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
  348. seq_puts(seq, "inst indx num_LUs status non_access_LUs"
  349. " resets\n");
  350. if (!(dev))
  351. return 0;
  352. hba = dev->se_hba;
  353. if (!(hba)) {
  354. /* Log error ? */
  355. return 0;
  356. }
  357. switch (dev->dev_status) {
  358. case TRANSPORT_DEVICE_ACTIVATED:
  359. strcpy(status, "activated");
  360. break;
  361. case TRANSPORT_DEVICE_DEACTIVATED:
  362. strcpy(status, "deactivated");
  363. non_accessible_lus = 1;
  364. break;
  365. case TRANSPORT_DEVICE_SHUTDOWN:
  366. strcpy(status, "shutdown");
  367. non_accessible_lus = 1;
  368. break;
  369. case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
  370. case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
  371. strcpy(status, "offline");
  372. non_accessible_lus = 1;
  373. break;
  374. default:
  375. sprintf(status, "unknown(%d)", dev->dev_status);
  376. non_accessible_lus = 1;
  377. }
  378. seq_printf(seq, "%u %u %u %s %u %u\n",
  379. hba->hba_index, dev->dev_index, LU_COUNT,
  380. status, non_accessible_lus, dev->num_resets);
  381. return 0;
  382. }
  383. static const struct seq_operations scsi_tgt_dev_seq_ops = {
  384. .start = scsi_tgt_dev_seq_start,
  385. .next = scsi_tgt_dev_seq_next,
  386. .stop = scsi_tgt_dev_seq_stop,
  387. .show = scsi_tgt_dev_seq_show
  388. };
  389. static int scsi_tgt_dev_seq_open(struct inode *inode, struct file *file)
  390. {
  391. return seq_open(file, &scsi_tgt_dev_seq_ops);
  392. }
  393. static const struct file_operations scsi_tgt_dev_seq_fops = {
  394. .owner = THIS_MODULE,
  395. .open = scsi_tgt_dev_seq_open,
  396. .read = seq_read,
  397. .llseek = seq_lseek,
  398. .release = seq_release,
  399. };
  400. /*
  401. * SCSI Target Port Table
  402. */
  403. static void *scsi_tgt_port_seq_start(struct seq_file *seq, loff_t *pos)
  404. {
  405. return locate_hba_start(seq, pos);
  406. }
  407. static void *scsi_tgt_port_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  408. {
  409. return locate_hba_next(seq, v, pos);
  410. }
  411. static void scsi_tgt_port_seq_stop(struct seq_file *seq, void *v)
  412. {
  413. locate_hba_stop(seq, v);
  414. }
  415. static int scsi_tgt_port_seq_show(struct seq_file *seq, void *v)
  416. {
  417. struct se_hba *hba;
  418. struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
  419. g_se_dev_list);
  420. struct se_device *dev = se_dev->se_dev_ptr;
  421. struct se_port *sep, *sep_tmp;
  422. struct se_portal_group *tpg;
  423. u32 rx_mbytes, tx_mbytes;
  424. unsigned long long num_cmds;
  425. char buf[64];
  426. if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
  427. seq_puts(seq, "inst device indx name port_index in_cmds"
  428. " write_mbytes read_mbytes hs_in_cmds\n");
  429. if (!(dev))
  430. return 0;
  431. hba = dev->se_hba;
  432. if (!(hba)) {
  433. /* Log error ? */
  434. return 0;
  435. }
  436. spin_lock(&dev->se_port_lock);
  437. list_for_each_entry_safe(sep, sep_tmp, &dev->dev_sep_list, sep_list) {
  438. tpg = sep->sep_tpg;
  439. sprintf(buf, "%sPort#",
  440. TPG_TFO(tpg)->get_fabric_name());
  441. seq_printf(seq, "%u %u %u %s%d %s%s%d ",
  442. hba->hba_index,
  443. dev->dev_index,
  444. sep->sep_index,
  445. buf, sep->sep_index,
  446. TPG_TFO(tpg)->tpg_get_wwn(tpg), "+t+",
  447. TPG_TFO(tpg)->tpg_get_tag(tpg));
  448. spin_lock(&sep->sep_lun->lun_sep_lock);
  449. num_cmds = sep->sep_stats.cmd_pdus;
  450. rx_mbytes = (sep->sep_stats.rx_data_octets >> 20);
  451. tx_mbytes = (sep->sep_stats.tx_data_octets >> 20);
  452. spin_unlock(&sep->sep_lun->lun_sep_lock);
  453. seq_printf(seq, "%llu %u %u %u\n", num_cmds,
  454. rx_mbytes, tx_mbytes, 0);
  455. }
  456. spin_unlock(&dev->se_port_lock);
  457. return 0;
  458. }
  459. static const struct seq_operations scsi_tgt_port_seq_ops = {
  460. .start = scsi_tgt_port_seq_start,
  461. .next = scsi_tgt_port_seq_next,
  462. .stop = scsi_tgt_port_seq_stop,
  463. .show = scsi_tgt_port_seq_show
  464. };
  465. static int scsi_tgt_port_seq_open(struct inode *inode, struct file *file)
  466. {
  467. return seq_open(file, &scsi_tgt_port_seq_ops);
  468. }
  469. static const struct file_operations scsi_tgt_port_seq_fops = {
  470. .owner = THIS_MODULE,
  471. .open = scsi_tgt_port_seq_open,
  472. .read = seq_read,
  473. .llseek = seq_lseek,
  474. .release = seq_release,
  475. };
  476. /*
  477. * SCSI Authorized Initiator Table:
  478. * It contains the SCSI Initiators authorized to be attached to one of the
  479. * local Target ports.
  480. * Iterates through all active TPGs and extracts the info from the ACLs
  481. */
  482. static void *scsi_auth_intr_seq_start(struct seq_file *seq, loff_t *pos)
  483. {
  484. spin_lock_bh(&se_global->se_tpg_lock);
  485. return seq_list_start(&se_global->g_se_tpg_list, *pos);
  486. }
  487. static void *scsi_auth_intr_seq_next(struct seq_file *seq, void *v,
  488. loff_t *pos)
  489. {
  490. return seq_list_next(v, &se_global->g_se_tpg_list, pos);
  491. }
  492. static void scsi_auth_intr_seq_stop(struct seq_file *seq, void *v)
  493. {
  494. spin_unlock_bh(&se_global->se_tpg_lock);
  495. }
  496. static int scsi_auth_intr_seq_show(struct seq_file *seq, void *v)
  497. {
  498. struct se_portal_group *se_tpg = list_entry(v, struct se_portal_group,
  499. se_tpg_list);
  500. struct se_dev_entry *deve;
  501. struct se_lun *lun;
  502. struct se_node_acl *se_nacl;
  503. int j;
  504. if (list_is_first(&se_tpg->se_tpg_list,
  505. &se_global->g_se_tpg_list))
  506. seq_puts(seq, "inst dev port indx dev_or_port intr_name "
  507. "map_indx att_count num_cmds read_mbytes "
  508. "write_mbytes hs_num_cmds creation_time row_status\n");
  509. if (!(se_tpg))
  510. return 0;
  511. spin_lock(&se_tpg->acl_node_lock);
  512. list_for_each_entry(se_nacl, &se_tpg->acl_node_list, acl_list) {
  513. atomic_inc(&se_nacl->mib_ref_count);
  514. smp_mb__after_atomic_inc();
  515. spin_unlock(&se_tpg->acl_node_lock);
  516. spin_lock_irq(&se_nacl->device_list_lock);
  517. for (j = 0; j < TRANSPORT_MAX_LUNS_PER_TPG; j++) {
  518. deve = &se_nacl->device_list[j];
  519. if (!(deve->lun_flags &
  520. TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) ||
  521. (!deve->se_lun))
  522. continue;
  523. lun = deve->se_lun;
  524. if (!lun->lun_se_dev)
  525. continue;
  526. seq_printf(seq, "%u %u %u %u %u %s %u %u %u %u %u %u"
  527. " %u %s\n",
  528. /* scsiInstIndex */
  529. (TPG_TFO(se_tpg)->tpg_get_inst_index != NULL) ?
  530. TPG_TFO(se_tpg)->tpg_get_inst_index(se_tpg) :
  531. 0,
  532. /* scsiDeviceIndex */
  533. lun->lun_se_dev->dev_index,
  534. /* scsiAuthIntrTgtPortIndex */
  535. TPG_TFO(se_tpg)->tpg_get_tag(se_tpg),
  536. /* scsiAuthIntrIndex */
  537. se_nacl->acl_index,
  538. /* scsiAuthIntrDevOrPort */
  539. 1,
  540. /* scsiAuthIntrName */
  541. se_nacl->initiatorname[0] ?
  542. se_nacl->initiatorname : NONE,
  543. /* FIXME: scsiAuthIntrLunMapIndex */
  544. 0,
  545. /* scsiAuthIntrAttachedTimes */
  546. deve->attach_count,
  547. /* scsiAuthIntrOutCommands */
  548. deve->total_cmds,
  549. /* scsiAuthIntrReadMegaBytes */
  550. (u32)(deve->read_bytes >> 20),
  551. /* scsiAuthIntrWrittenMegaBytes */
  552. (u32)(deve->write_bytes >> 20),
  553. /* FIXME: scsiAuthIntrHSOutCommands */
  554. 0,
  555. /* scsiAuthIntrLastCreation */
  556. (u32)(((u32)deve->creation_time -
  557. INITIAL_JIFFIES) * 100 / HZ),
  558. /* FIXME: scsiAuthIntrRowStatus */
  559. "Ready");
  560. }
  561. spin_unlock_irq(&se_nacl->device_list_lock);
  562. spin_lock(&se_tpg->acl_node_lock);
  563. atomic_dec(&se_nacl->mib_ref_count);
  564. smp_mb__after_atomic_dec();
  565. }
  566. spin_unlock(&se_tpg->acl_node_lock);
  567. return 0;
  568. }
  569. static const struct seq_operations scsi_auth_intr_seq_ops = {
  570. .start = scsi_auth_intr_seq_start,
  571. .next = scsi_auth_intr_seq_next,
  572. .stop = scsi_auth_intr_seq_stop,
  573. .show = scsi_auth_intr_seq_show
  574. };
  575. static int scsi_auth_intr_seq_open(struct inode *inode, struct file *file)
  576. {
  577. return seq_open(file, &scsi_auth_intr_seq_ops);
  578. }
  579. static const struct file_operations scsi_auth_intr_seq_fops = {
  580. .owner = THIS_MODULE,
  581. .open = scsi_auth_intr_seq_open,
  582. .read = seq_read,
  583. .llseek = seq_lseek,
  584. .release = seq_release,
  585. };
  586. /*
  587. * SCSI Attached Initiator Port Table:
  588. * It lists the SCSI Initiators attached to one of the local Target ports.
  589. * Iterates through all active TPGs and use active sessions from each TPG
  590. * to list the info fo this table.
  591. */
  592. static void *scsi_att_intr_port_seq_start(struct seq_file *seq, loff_t *pos)
  593. {
  594. spin_lock_bh(&se_global->se_tpg_lock);
  595. return seq_list_start(&se_global->g_se_tpg_list, *pos);
  596. }
  597. static void *scsi_att_intr_port_seq_next(struct seq_file *seq, void *v,
  598. loff_t *pos)
  599. {
  600. return seq_list_next(v, &se_global->g_se_tpg_list, pos);
  601. }
  602. static void scsi_att_intr_port_seq_stop(struct seq_file *seq, void *v)
  603. {
  604. spin_unlock_bh(&se_global->se_tpg_lock);
  605. }
  606. static int scsi_att_intr_port_seq_show(struct seq_file *seq, void *v)
  607. {
  608. struct se_portal_group *se_tpg = list_entry(v, struct se_portal_group,
  609. se_tpg_list);
  610. struct se_dev_entry *deve;
  611. struct se_lun *lun;
  612. struct se_node_acl *se_nacl;
  613. struct se_session *se_sess;
  614. unsigned char buf[64];
  615. int j;
  616. if (list_is_first(&se_tpg->se_tpg_list,
  617. &se_global->g_se_tpg_list))
  618. seq_puts(seq, "inst dev port indx port_auth_indx port_name"
  619. " port_ident\n");
  620. if (!(se_tpg))
  621. return 0;
  622. spin_lock(&se_tpg->session_lock);
  623. list_for_each_entry(se_sess, &se_tpg->tpg_sess_list, sess_list) {
  624. if ((TPG_TFO(se_tpg)->sess_logged_in(se_sess)) ||
  625. (!se_sess->se_node_acl) ||
  626. (!se_sess->se_node_acl->device_list))
  627. continue;
  628. atomic_inc(&se_sess->mib_ref_count);
  629. smp_mb__after_atomic_inc();
  630. se_nacl = se_sess->se_node_acl;
  631. atomic_inc(&se_nacl->mib_ref_count);
  632. smp_mb__after_atomic_inc();
  633. spin_unlock(&se_tpg->session_lock);
  634. spin_lock_irq(&se_nacl->device_list_lock);
  635. for (j = 0; j < TRANSPORT_MAX_LUNS_PER_TPG; j++) {
  636. deve = &se_nacl->device_list[j];
  637. if (!(deve->lun_flags &
  638. TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) ||
  639. (!deve->se_lun))
  640. continue;
  641. lun = deve->se_lun;
  642. if (!lun->lun_se_dev)
  643. continue;
  644. memset(buf, 0, 64);
  645. if (TPG_TFO(se_tpg)->sess_get_initiator_sid != NULL)
  646. TPG_TFO(se_tpg)->sess_get_initiator_sid(
  647. se_sess, (unsigned char *)&buf[0], 64);
  648. seq_printf(seq, "%u %u %u %u %u %s+i+%s\n",
  649. /* scsiInstIndex */
  650. (TPG_TFO(se_tpg)->tpg_get_inst_index != NULL) ?
  651. TPG_TFO(se_tpg)->tpg_get_inst_index(se_tpg) :
  652. 0,
  653. /* scsiDeviceIndex */
  654. lun->lun_se_dev->dev_index,
  655. /* scsiPortIndex */
  656. TPG_TFO(se_tpg)->tpg_get_tag(se_tpg),
  657. /* scsiAttIntrPortIndex */
  658. (TPG_TFO(se_tpg)->sess_get_index != NULL) ?
  659. TPG_TFO(se_tpg)->sess_get_index(se_sess) :
  660. 0,
  661. /* scsiAttIntrPortAuthIntrIdx */
  662. se_nacl->acl_index,
  663. /* scsiAttIntrPortName */
  664. se_nacl->initiatorname[0] ?
  665. se_nacl->initiatorname : NONE,
  666. /* scsiAttIntrPortIdentifier */
  667. buf);
  668. }
  669. spin_unlock_irq(&se_nacl->device_list_lock);
  670. spin_lock(&se_tpg->session_lock);
  671. atomic_dec(&se_nacl->mib_ref_count);
  672. smp_mb__after_atomic_dec();
  673. atomic_dec(&se_sess->mib_ref_count);
  674. smp_mb__after_atomic_dec();
  675. }
  676. spin_unlock(&se_tpg->session_lock);
  677. return 0;
  678. }
  679. static const struct seq_operations scsi_att_intr_port_seq_ops = {
  680. .start = scsi_att_intr_port_seq_start,
  681. .next = scsi_att_intr_port_seq_next,
  682. .stop = scsi_att_intr_port_seq_stop,
  683. .show = scsi_att_intr_port_seq_show
  684. };
  685. static int scsi_att_intr_port_seq_open(struct inode *inode, struct file *file)
  686. {
  687. return seq_open(file, &scsi_att_intr_port_seq_ops);
  688. }
  689. static const struct file_operations scsi_att_intr_port_seq_fops = {
  690. .owner = THIS_MODULE,
  691. .open = scsi_att_intr_port_seq_open,
  692. .read = seq_read,
  693. .llseek = seq_lseek,
  694. .release = seq_release,
  695. };
  696. /*
  697. * SCSI Logical Unit Table
  698. */
  699. static void *scsi_lu_seq_start(struct seq_file *seq, loff_t *pos)
  700. {
  701. return locate_hba_start(seq, pos);
  702. }
  703. static void *scsi_lu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  704. {
  705. return locate_hba_next(seq, v, pos);
  706. }
  707. static void scsi_lu_seq_stop(struct seq_file *seq, void *v)
  708. {
  709. locate_hba_stop(seq, v);
  710. }
  711. #define SCSI_LU_INDEX 1
  712. static int scsi_lu_seq_show(struct seq_file *seq, void *v)
  713. {
  714. struct se_hba *hba;
  715. struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
  716. g_se_dev_list);
  717. struct se_device *dev = se_dev->se_dev_ptr;
  718. int j;
  719. char str[28];
  720. if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
  721. seq_puts(seq, "inst dev indx LUN lu_name vend prod rev"
  722. " dev_type status state-bit num_cmds read_mbytes"
  723. " write_mbytes resets full_stat hs_num_cmds creation_time\n");
  724. if (!(dev))
  725. return 0;
  726. hba = dev->se_hba;
  727. if (!(hba)) {
  728. /* Log error ? */
  729. return 0;
  730. }
  731. /* Fix LU state, if we can read it from the device */
  732. seq_printf(seq, "%u %u %u %llu %s", hba->hba_index,
  733. dev->dev_index, SCSI_LU_INDEX,
  734. (unsigned long long)0, /* FIXME: scsiLuDefaultLun */
  735. (strlen(DEV_T10_WWN(dev)->unit_serial)) ?
  736. /* scsiLuWwnName */
  737. (char *)&DEV_T10_WWN(dev)->unit_serial[0] :
  738. "None");
  739. memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
  740. /* scsiLuVendorId */
  741. for (j = 0; j < 8; j++)
  742. str[j] = ISPRINT(DEV_T10_WWN(dev)->vendor[j]) ?
  743. DEV_T10_WWN(dev)->vendor[j] : 0x20;
  744. str[8] = 0;
  745. seq_printf(seq, " %s", str);
  746. /* scsiLuProductId */
  747. for (j = 0; j < 16; j++)
  748. str[j] = ISPRINT(DEV_T10_WWN(dev)->model[j]) ?
  749. DEV_T10_WWN(dev)->model[j] : 0x20;
  750. str[16] = 0;
  751. seq_printf(seq, " %s", str);
  752. /* scsiLuRevisionId */
  753. for (j = 0; j < 4; j++)
  754. str[j] = ISPRINT(DEV_T10_WWN(dev)->revision[j]) ?
  755. DEV_T10_WWN(dev)->revision[j] : 0x20;
  756. str[4] = 0;
  757. seq_printf(seq, " %s", str);
  758. seq_printf(seq, " %u %s %s %llu %u %u %u %u %u %u\n",
  759. /* scsiLuPeripheralType */
  760. TRANSPORT(dev)->get_device_type(dev),
  761. (dev->dev_status == TRANSPORT_DEVICE_ACTIVATED) ?
  762. "available" : "notavailable", /* scsiLuStatus */
  763. "exposed", /* scsiLuState */
  764. (unsigned long long)dev->num_cmds,
  765. /* scsiLuReadMegaBytes */
  766. (u32)(dev->read_bytes >> 20),
  767. /* scsiLuWrittenMegaBytes */
  768. (u32)(dev->write_bytes >> 20),
  769. dev->num_resets, /* scsiLuInResets */
  770. 0, /* scsiLuOutTaskSetFullStatus */
  771. 0, /* scsiLuHSInCommands */
  772. (u32)(((u32)dev->creation_time - INITIAL_JIFFIES) *
  773. 100 / HZ));
  774. return 0;
  775. }
  776. static const struct seq_operations scsi_lu_seq_ops = {
  777. .start = scsi_lu_seq_start,
  778. .next = scsi_lu_seq_next,
  779. .stop = scsi_lu_seq_stop,
  780. .show = scsi_lu_seq_show
  781. };
  782. static int scsi_lu_seq_open(struct inode *inode, struct file *file)
  783. {
  784. return seq_open(file, &scsi_lu_seq_ops);
  785. }
  786. static const struct file_operations scsi_lu_seq_fops = {
  787. .owner = THIS_MODULE,
  788. .open = scsi_lu_seq_open,
  789. .read = seq_read,
  790. .llseek = seq_lseek,
  791. .release = seq_release,
  792. };
  793. /****************************************************************************/
  794. /*
  795. * Remove proc fs entries
  796. */
  797. void remove_scsi_target_mib(void)
  798. {
  799. remove_proc_entry("scsi_target/mib/scsi_inst", NULL);
  800. remove_proc_entry("scsi_target/mib/scsi_dev", NULL);
  801. remove_proc_entry("scsi_target/mib/scsi_port", NULL);
  802. remove_proc_entry("scsi_target/mib/scsi_transport", NULL);
  803. remove_proc_entry("scsi_target/mib/scsi_tgt_dev", NULL);
  804. remove_proc_entry("scsi_target/mib/scsi_tgt_port", NULL);
  805. remove_proc_entry("scsi_target/mib/scsi_auth_intr", NULL);
  806. remove_proc_entry("scsi_target/mib/scsi_att_intr_port", NULL);
  807. remove_proc_entry("scsi_target/mib/scsi_lu", NULL);
  808. remove_proc_entry("scsi_target/mib", NULL);
  809. }
  810. /*
  811. * Create proc fs entries for the mib tables
  812. */
  813. int init_scsi_target_mib(void)
  814. {
  815. struct proc_dir_entry *dir_entry;
  816. struct proc_dir_entry *scsi_inst_entry;
  817. struct proc_dir_entry *scsi_dev_entry;
  818. struct proc_dir_entry *scsi_port_entry;
  819. struct proc_dir_entry *scsi_transport_entry;
  820. struct proc_dir_entry *scsi_tgt_dev_entry;
  821. struct proc_dir_entry *scsi_tgt_port_entry;
  822. struct proc_dir_entry *scsi_auth_intr_entry;
  823. struct proc_dir_entry *scsi_att_intr_port_entry;
  824. struct proc_dir_entry *scsi_lu_entry;
  825. dir_entry = proc_mkdir("scsi_target/mib", NULL);
  826. if (!(dir_entry)) {
  827. printk(KERN_ERR "proc_mkdir() failed.\n");
  828. return -1;
  829. }
  830. scsi_inst_entry =
  831. create_proc_entry("scsi_target/mib/scsi_inst", 0, NULL);
  832. if (scsi_inst_entry)
  833. scsi_inst_entry->proc_fops = &scsi_inst_seq_fops;
  834. else
  835. goto error;
  836. scsi_dev_entry =
  837. create_proc_entry("scsi_target/mib/scsi_dev", 0, NULL);
  838. if (scsi_dev_entry)
  839. scsi_dev_entry->proc_fops = &scsi_dev_seq_fops;
  840. else
  841. goto error;
  842. scsi_port_entry =
  843. create_proc_entry("scsi_target/mib/scsi_port", 0, NULL);
  844. if (scsi_port_entry)
  845. scsi_port_entry->proc_fops = &scsi_port_seq_fops;
  846. else
  847. goto error;
  848. scsi_transport_entry =
  849. create_proc_entry("scsi_target/mib/scsi_transport", 0, NULL);
  850. if (scsi_transport_entry)
  851. scsi_transport_entry->proc_fops = &scsi_transport_seq_fops;
  852. else
  853. goto error;
  854. scsi_tgt_dev_entry =
  855. create_proc_entry("scsi_target/mib/scsi_tgt_dev", 0, NULL);
  856. if (scsi_tgt_dev_entry)
  857. scsi_tgt_dev_entry->proc_fops = &scsi_tgt_dev_seq_fops;
  858. else
  859. goto error;
  860. scsi_tgt_port_entry =
  861. create_proc_entry("scsi_target/mib/scsi_tgt_port", 0, NULL);
  862. if (scsi_tgt_port_entry)
  863. scsi_tgt_port_entry->proc_fops = &scsi_tgt_port_seq_fops;
  864. else
  865. goto error;
  866. scsi_auth_intr_entry =
  867. create_proc_entry("scsi_target/mib/scsi_auth_intr", 0, NULL);
  868. if (scsi_auth_intr_entry)
  869. scsi_auth_intr_entry->proc_fops = &scsi_auth_intr_seq_fops;
  870. else
  871. goto error;
  872. scsi_att_intr_port_entry =
  873. create_proc_entry("scsi_target/mib/scsi_att_intr_port", 0, NULL);
  874. if (scsi_att_intr_port_entry)
  875. scsi_att_intr_port_entry->proc_fops =
  876. &scsi_att_intr_port_seq_fops;
  877. else
  878. goto error;
  879. scsi_lu_entry = create_proc_entry("scsi_target/mib/scsi_lu", 0, NULL);
  880. if (scsi_lu_entry)
  881. scsi_lu_entry->proc_fops = &scsi_lu_seq_fops;
  882. else
  883. goto error;
  884. return 0;
  885. error:
  886. printk(KERN_ERR "create_proc_entry() failed.\n");
  887. remove_scsi_target_mib();
  888. return -1;
  889. }
  890. /*
  891. * Initialize the index table for allocating unique row indexes to various mib
  892. * tables
  893. */
  894. void init_scsi_index_table(void)
  895. {
  896. memset(&scsi_index_table, 0, sizeof(struct scsi_index_table));
  897. spin_lock_init(&scsi_index_table.lock);
  898. }
  899. /*
  900. * Allocate a new row index for the entry type specified
  901. */
  902. u32 scsi_get_new_index(scsi_index_t type)
  903. {
  904. u32 new_index;
  905. if ((type < 0) || (type >= SCSI_INDEX_TYPE_MAX)) {
  906. printk(KERN_ERR "Invalid index type %d\n", type);
  907. return -1;
  908. }
  909. spin_lock(&scsi_index_table.lock);
  910. new_index = ++scsi_index_table.scsi_mib_index[type];
  911. if (new_index == 0)
  912. new_index = ++scsi_index_table.scsi_mib_index[type];
  913. spin_unlock(&scsi_index_table.lock);
  914. return new_index;
  915. }
  916. EXPORT_SYMBOL(scsi_get_new_index);