⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 initiator_proc_iface.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	initiator/initiator_proc_iface.c * *	vi: set autoindent tabstop=8 shiftwidth=8 : * *	This file contains the functions for iscsi initiator code that are *	responsible for interfacing with the /proc filesystem. * *	Copyright (C) 2001-2004 InterOperability Lab (IOL) *	University of New Hampshire (UNH) *	Durham, NH 03824 * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2, or (at your option) *	any later version. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, *	USA. * *	The name IOL and/or UNH may not be used to endorse or promote *	products derived from this software without specific prior * 	written permission.*/#include "iscsi_initiator.h"#include "initiator_utilities.h"#include "initiator_error_rec.h"#include "initiator_proc_iface.h"#include <linux/proc_fs.h>#ifdef ISCSI_STATSstatic int __attribute__ ((no_instrument_function))dump_conn_info(struct connection *, char *);static int __attribute__ ((no_instrument_function))dump_sess_info(struct session *, char *);static int __attribute__ ((no_instrument_function))dump_instance_stats(char *);#endif/* * executed only by command process. * Called only by scan_test_stuff() * returns	>= 0 on success, * 		 < 0 on error */static int __attribute__ ((no_instrument_function))do_test(__u32 target, __u32 cid, __u32 test_no){	unsigned long flags, lock_flags;	int result;	struct connection *conn;	struct session *sess;	/*  When using session list, be sure nobody else accesses it */	UNH_LOCK(&host_data_lock, flags);	/* use target and cid to find session and connection */	result = find_connection(target, cid, global_hostdata, &conn, &sess);	if (result >= 0) {		/* perform the requested test on this connection */		UNH_LOCK(&sess->sess_lock, lock_flags);		UNH_UNLOCK(&host_data_lock, flags);		TRACE(TRACE_ISCSI, "Do test number %u\n", test_no);		switch (test_no) {		case 0:			/* send text request */			result = drive_text_negotiate(conn, sess, 0, 1);			break;		case 1:			/* send text request as immediate cmd */			result = drive_text_negotiate(conn, sess, I_BIT, 1);			break;		case 2:			/* send nop (not immediate, no data) */			result = drive_nopout(conn, sess, 0, 0);			break;		case 3:			/* send nop (immediate, no data) */			result = drive_nopout(conn, sess, I_BIT, 0);			break;		case 4:			/* send nop ping (not immediate, data) */			result = drive_nopout(conn, sess, 0, 1);			break;		case 5:			/* send nop ping (immediate, data) */			result = drive_nopout(conn, sess, I_BIT, 1);			break;		case 6:			/* stop/start responding to nop ping from target */			conn->connection_flags ^= SEND_NO_REPLY_TO_NOP_PING;			break;		case 7:			/* stop/start responding to async logout			 * request from target			 */			conn->connection_flags ^= SEND_NO_REPLY_TO_ASYNC_LOGOUT;			break;		case 8:			/* perform connection re-assignment - SAI */			conn->rec_tests = test_no;			break;		case 9:			/* send session logout request */			result = !drive_logout(sess, conn,					       LOGOUT_CLOSE_SESSION);			break;		case 10:			/* send connection logout request */			result = !drive_logout(sess, conn,					       LOGOUT_CLOSE_CONNECTION);			break;		default:			TRACE_ERROR("Test number %u not implemented yet\n",				    test_no);			result = -EINVAL;			break;		} /* switch */		UNH_UNLOCK(&sess->sess_lock, lock_flags);	} else {		/* release our exclusive access to the iscsi structures */		UNH_UNLOCK(&host_data_lock, flags);	}	return result;}/* * executed only by command process. * host_data_lock MUST be held by the calling process/thread * Called by dump_conn_info() and print_session_info() */static int __attribute__ ((no_instrument_function))print_connection_info( struct connection *conn, char *buffer, int pos ){	const char *ptr;	int lun;	struct session *sess;	char extra[20];	pos += sprintf(buffer + pos, "%16s: %u\n", "Connection CID",		       conn->connection_id);	pos += sprintf(buffer + pos, "%16s: ", "Connection State");	switch (conn->connection_state) {	case CONNECTION_FULL_FEATURE_PHASE:		ptr = "FULL FEATURE PHASE";		break;	case CONNECTION_LOGGED_IN:	case CONNECTION_CONNECTED:		ptr = "LOGIN PHASE";		break;	case CONNECTION_RECOVERING:		ptr = "ERROR RECOVERY";		break;	case CONNECTION_LOGGED_OUT:	case CONNECTION_DISCONNECTED:		ptr = "LOGOUT PHASE";		break;	case CONNECTION_NOT_PRESENT:		ptr = "NOT CONNECTED";		break;	default:		pos += sprintf(buffer + pos, "0x%x", conn->connection_state);		ptr = "";		break;	}	pos += sprintf(buffer + pos, "%s\n", ptr);	if (conn->connection_state == CONNECTION_FULL_FEATURE_PHASE		|| conn->connection_state == CONNECTION_CONNECTED) {		char ip_string[INET6_ADDRSTRLEN+2], port_string[8];		if (cnv_inet_to_string(conn->ip_address, ip_string, port_string)									> 0) {			pos += sprintf(buffer + pos, "%16s: %s:%s\n",				       "Target Address",				       ip_string, port_string);		}		if (cnv_inet_to_string(conn->local_ip_address, ip_string,				       port_string) > 0) {			pos += sprintf(buffer + pos, "%16s: %s:%s\n",				       "Local Address",				       ip_string, port_string);		}		sess = conn->my_session;		if (sess->sched_scheme == CONN_SCHED_LUN ) {			/* LUN assigned to connection scheduling is in effect,			 * print numbers of all luns assigned to this connection			 * (if any)			 */			lun = conn->assigned_lun_count;			sprintf(extra, "%d assigned LUN%s", lun,				lun == 1 ? "" : "s");			pos += sprintf(buffer + pos, "%16s:", extra);			for (lun = 0; lun < MAX_LUNS; lun++) {				if (conn == sess->lun_assignments[lun]) {					pos += sprintf(buffer + pos," %d",lun);				}			}			pos += sprintf(buffer + pos, "\n");		}	}	return pos;}static int __attribute__ ((no_instrument_function))print_ascii(char *buffer, __u8 *ptr, int len, char *mess){	int pos;	pos = sprintf(buffer, "%24s: ", mess);	memcpy(buffer + pos, ptr, len);	pos += len;	pos += sprintf(buffer + pos, "\n");	return pos;}static int __attribute__ ((no_instrument_function))print_ver_descr(char *buffer, __u8 *ptr, __u8 *base){	int pos = 0, i;	for (i = 0; i < 8; i++) {		if (ptr > base)			break;		if (*ptr || *(ptr+1)) {			pos += sprintf(buffer + pos, "%24s: 0x%02x%02x\n",				       "version descriptor", *ptr, *(ptr+1));		}		ptr += 2;	}	return pos;}static int __attribute__ ((no_instrument_function))print_capacity_stuff(char *buffer, struct session *sess, __u32 lun){	int pos = 0;	__u32 lba = sess->capacity_lba[lun];	__u32 len = sess->capacity_len[lun];	if (lba && len) {		if (lba != ALL_ONES)			lba++;		pos = sprintf(buffer + pos,				"%16s: %u %u %u-byte hardware sectors\n",				"capacity for lun", lun, lba, len);	}	return pos;}static int __attribute__ ((no_instrument_function))print_limits_stuff(char *buffer, struct session *sess, __u32 lun){	int pos = 0;	__u32 max = sess->limit_max[lun];	__u32 min = sess->limit_min[lun];	if (max || min) {		pos = sprintf(buffer + pos,				"%16s: %u [%u, %u] bytes per block\n",				"limits for lun", lun, min, max);	}	return pos;}static const char * __attribute__ ((no_instrument_function))printable_dev_type( __u32 dev_type ){	const char *mess;	if (dev_type < MAX_SCSI_DEVICE_CODE) {		mess = scsi_device_types[dev_type];	} else {		mess = "reserved";		switch (dev_type) {		case 0x0e:			mess = "simple-direct-access";			break;		case 0x0f:			mess = "optical card reader/writer";			break;		case 0x11:			mess = "object-based-storage";			break;		case 0x1f:			mess = "unknown";			break;		}	/* switch */	}	return mess;}static int __attribute__ ((no_instrument_function))print_inquiry_stuff(char *buffer, struct session *sess, __u32 lun){	int pos = 0, size = sess->inquiry_size[lun], len;	__u8 *base = sess->inquiry_buf[lun], *ptr;	if ((ptr = base) && size) {		pos += sprintf(buffer + pos, "%16s: %u (bytes 0..%u)\n",				"inquiry for lun", lun, *(ptr + 4) + 4);		if ((*ptr >> 5) == 0)			pos += sprintf(buffer + pos, "%24s: %s\n", "device",				"connected");		else if ((*ptr >> 5) == 1)			pos += sprintf(buffer + pos, "%24s: %s\n", "device",				"not connected");		else			pos += sprintf(buffer + pos, "%24s: %u\n", "qualifier",					*ptr >> 5);		pos += sprintf(buffer + pos, "%24s: %s\n", "device type",				printable_dev_type(*ptr & 0x1f));		ptr += 1;		pos += sprintf(buffer + pos, "%24s: %sremovable\n", "medium",				*ptr & 0x80 ? "" : "not ");		ptr += 1;		pos += sprintf(buffer + pos, "%24s: 0x%02x\n", "version", *ptr);		ptr += 1;		if (*ptr != 2)			pos += sprintf(buffer + pos, "%24s: 0x%02x\n",					"byte 3", *ptr);		ptr += 1;		base += 4 + *ptr++;		if (ptr > base)			goto done;		if (*ptr & 0x80)			pos =+ sprintf(buffer + pos, "%24s: %s\n",					"device contains",					"embedded storage array controller");		ptr += 1;		/* skip byte 5 for now */		if (ptr > base)			goto done;		pos += sprintf(buffer + pos, "%24s: 0x%02x\n", "byte 6", *ptr);		ptr += 1;		if (ptr > base)			goto done;		pos += sprintf(buffer + pos, "%24s: 0x%02x\n", "byte 7", *ptr);		ptr += 1;		if (ptr > base)			goto done;		pos += print_ascii(buffer + pos, ptr, 8, "vendor id");		ptr += 8;		if (ptr > base)			goto done;		pos += print_ascii(buffer + pos, ptr, 16, "product id");		ptr += 16;		if (ptr > base)			goto done;		pos += print_ascii(buffer + pos, ptr, 4, "product revision");		ptr += 4;		if (ptr > base)			goto done;		len = strlen(ptr);		if (len > 0  && len < 20)			pos += sprintf(buffer + pos, "%24s: %s\n",					"vendor specific", ptr);		ptr += 20;		if (ptr > base)			goto done;		pos += sprintf(buffer + pos, "%24s: 0x%02x\n", "byte 56", *ptr);		ptr += 1 + 1;		pos += print_ver_descr(buffer + pos, ptr, base);	}done:	return pos;}/* * executed only by command process. * host_data_lock MUST be held by the calling process/thread * Called by dump_sess_info() and iscsi_initiator_proc_info() * this is for configuring the login parameters */static int __attribute__ ((no_instrument_function))print_session_info( struct session *sess, char *buffer, int pos ){	int i;	struct connection *conn;	const char *ptr;	char extra[12];	pos += sprintf(buffer + pos, "%16s: 0x%p\n", "pointer", sess);	pos += sprintf(buffer + pos, "%16s: %u\n", "target id",		       sess->scsi_target_id);	sprintf(extra, "%u LUN%s", sess->n_luns_in_session,		sess->n_luns_in_session == 1 ? "" : "s");	pos += sprintf(buffer + pos, "%16s:", extra);	for (i = 0; i < global_host->max_lun; i++) {		if (sess->lun_bits & (1 << i)) {			pos += sprintf(buffer + pos, " %d", i);		}	}	pos += sprintf(buffer + pos, "\n");	for (i = 0; i < global_host->max_lun; i++) {		if (sess->lun_bits & (1 << i)) {			pos += print_capacity_stuff(buffer + pos, sess, i);			pos += print_limits_stuff(buffer + pos, sess, i);			pos += print_inquiry_stuff(buffer + pos, sess, i);		}	}	switch (sess->sched_scheme) {	case CONN_SCHED_RR:	ptr = "round-robin"; break;	case CONN_SCHED_LUN:	ptr = "LUN to connection"; break;	default:		ptr = "first connection only"; break;	}	pos += sprintf(buffer + pos, "%16s: %s\n", "conn. scheduling",		       ptr);	pos += sprintf(buffer + pos, "%16s: %u\n", "nop interval",		       sess->nop_period);	pos += sprintf(buffer + pos, "%16s: %u\n", "connections",		       sess->nconnections);	for (conn = sess->connection_head; conn != NULL; conn = conn->next) {		pos = print_connection_info(conn, buffer, pos);	}	return pos;}/* * executed only by command process. * host_data_lock MUST be held by the calling process/thread * Called by iscsi_initiator_proc_info() */static int __attribute__ ((no_instrument_function))print_host_info( struct Scsi_Host *host, char *buffer, int pos ){	pos += sprintf(buffer + pos, "%24s  %u\n",			"host number", host->host_no);	pos += sprintf(buffer + pos, "%24s  %u\n",			"max targets", host->max_id);	pos += sprintf(buffer + pos, "%24s  %u\n",			"max luns per target", host->max_lun);	pos += sprintf(buffer + pos, "%24s  %u\n",			"max bytes per cdb", host->max_cmd_len);	pos += sprintf(buffer + pos, "%24s  %d\n",			"max outstanding commands", host->can_queue);	pos += sprintf(buffer + pos, "%24s  %d\n",			"max commands per lun", host->cmd_per_lun);	pos += sprintf(buffer + pos, "%24s  %u\n",			"max sg size per command", host->sg_tablesize);	pos += sprintf(buffer + pos, "%24s  %u\n",			"max sectors per command", host->max_sectors);	pos += sprintf(buffer + pos, "\n");	return pos;}/* scans the unsigned integer starting at ptr. * if result is <= max and only white space follows, return the result * otherwise set err */static void __attribute__ ((no_instrument_function))scan_numeric(char *ptr, __u32 max, __u32 *result, int *err){	__u32 temp;	temp = simple_strtoul(ptr, &ptr, 0);	if (temp > max || strspn(ptr, WHITE_SPACE) != strlen(ptr))		*err = -EINVAL;	else		*result = temp;}/* * executed only by command process. * Called only by scan_manage_stuff() */static int __attribute__ ((no_instrument_function))scan_force_stuff(char *ptr, struct iscsi_targetdata *targ_data, int result){	__u32 c_len, trace_info;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -