📄 initiator_proc_iface.c
字号:
pos += print_my_kmemory(buffer + pos); pos += print_iovs(buffer + pos); if (pos < offset) { /* reader already read everything we have to say, * send back EOF */ result = 0; begin = pos; } else { /* reader had not read everything yet, * send back something */ result = pos; begin = 0; } /* Start of wanted data */ *start = buffer + (offset - begin); result -= (offset - begin); if (result > length) result = length; } TRACE(TRACE_ENTER_LEAVE, "Leave iscsi_initiator_proc_info, result %d\n", result); return result;}#ifdef ISCSI_STATSstatic int __attribute__ ((no_instrument_function))dump_instance_stats(char *page){ int len=0; struct iscsi_instance_stats *istats; char ip_string[INET6_ADDRSTRLEN+2], port_string[8]; istats = &(global_hostdata->instance_stats); len += sprintf(page + len, "Session Login Failure = %d\n", istats->iscsi_intr_login_failure); len += sprintf(page + len, "Last Login Failure Target Name= %s\n", (istats->iscsi_intr_last_tgt_failure_name) ? istats->iscsi_intr_last_tgt_failure_name: "<NULL>"); len+=sprintf(page+len, "Last Target Failure Address = "); if (istats->iscsi_intr_last_tgt_failure_address == NULL) len += sprintf(page + len, "<NULL>\n"); else if (cnv_inet_to_string(istats->iscsi_intr_last_tgt_failure_address, ip_string, port_string) > 0) len += sprintf(page +len, "%s:%s\n", ip_string, port_string); len += sprintf( page + len, "Last Login Failure Time = %ld:%ld\n", istats->iscsi_intr_last_failure_time.tv_sec, istats->iscsi_intr_last_failure_time.tv_usec);#if USE_PRINT_DATE len += print_date(page + len, &(istats->iscsi_intr_last_failure_time));#endif len += sprintf(page + len, "Last Login Failure Type = "); switch (istats->iscsi_intr_last_failure_type) { case ACCEPT_RESPONSE: len += sprintf(page + len, "ACCEPT_RESPONSE\n"); break; case REDIRECT_RESPONSE: len += sprintf(page + len, "REDIRECT_RESPONSE\n"); break; case AUTH_FAIL_RESPONSE: len += sprintf(page + len, "AUTH_FAIL_RESPONSE\n"); break; case AUTHENTICATE_FAIL: len += sprintf(page + len, "AUTHENTICATE_FAIL\n"); break; case NEGOTIATE_FAIL: len += sprintf(page + len, "NEGOTIATE_FAIL\n"); break; case OTHER_FAIL: len += sprintf(page + len, "OTHER_FAIL\n"); break; case UNKNOWN_FAILURE: default: if(istats->iscsi_intr_login_failure) len += sprintf(page +len, "<UNKNOWN FAILURE>\n"); else len += sprintf(page +len, "<NULL>\n"); break; } len += sprintf(page +len, "Login Accept Response = %u\n", istats->iscsi_intr_login_accept_rsp); len += sprintf(page +len, "Login Redirect Response = %u\n", istats->iscsi_intr_login_redirect_rsp); len += sprintf(page +len, "Login Authenticate Fail Response = %u\n", istats->iscsi_intr_login_auth_fail_rsp); len += sprintf(page +len, "Login Authentication Failure = %u\n", istats->iscsi_intr_login_auth_fail_rsp); len += sprintf(page +len, "Login Negotiate Failure = %u\n", istats->iscsi_intr_login_negotiate_fails); len += sprintf(page +len, "Login Other Failure = %u\n", istats->iscsi_intr_login_other_fail_rsp); len += sprintf(page +len, "Normal Logouts = %u\n", istats->iscsi_intr_logout_normals); len += sprintf(page +len, "Other Logouts = %u\n", istats->iscsi_intr_logout_others); return len;}static int __attribute__ ((no_instrument_function))read_proc_file(char *page, char **start, off_t off, int count, int *eof, void *data){ unsigned long flags; int len = 0; struct proc_data *proc_data = (struct proc_data *) data; struct session *sess; struct connection *conn; /* When using global session list, be sure nobody else accesses it */ UNH_LOCK(&host_data_lock, flags); if (proc_data == NULL || proc_data->file != STAT) goto out; len = sprintf(page, "%s\n", OUR_NAME); /* find the session for this target_id */ sess = find_session_by_id(proc_data->sess_id, global_hostdata); if (sess != NULL) { /* found the session */ if (proc_data->type & SESSION) { len += dump_sess_info(sess, page+len); } else if (proc_data->type & CONNECTION) { /* find the connection within this session */ for (conn = sess->connection_head; conn != NULL; conn = conn->next) { if (conn->connection_id == proc_data->conn_id) { len += dump_conn_info(conn, page+len); break; } } } }out: /* release our exclusive access to the global structures */ UNH_UNLOCK(&host_data_lock, flags); return len;}/* * executed only by command process. * host_data_lock MUST be held by the calling process/thread * Called only by read_proc_file(). * dump_sess_info() dumps the session specific info. * It dumps the session negotiated values and statistics * such as cmd pdus txd, response pdus txd, data bytes txd, * data bytes rxd, error count etc... */static int __attribute__ ((no_instrument_function))dump_sess_info(struct session *sess, char *page){ int len; struct iscsi_session_stats *sess_stats; if (sess == NULL) return 0; len = print_session_info(sess, page, 0); sess_stats = sess->sess_stats; len += print_session_params(sess->oper_param, *sess->session_params, page + len); len += sprintf(page +len, "\nPDUs Transmitted\n------------------\n"); len += sprintf(page +len, "%12s %12s %12s %12s %12s %12s\n" "%12u %12u %12u %12u %12u %12u\n", "NopOut", "SCSICommand", "TaskMgmtReq", "TextReq", "DataOut", "SNACK", sess_stats->iscsi_ssn_noptx_pdus, sess_stats->iscsi_ssn_scsicmd_pdus, sess_stats->iscsi_ssn_tskmgmtcmd_pdus, sess_stats->iscsi_ssn_text_pdus, sess_stats->iscsi_ssn_dataout_pdus, sess_stats->iscsi_ssn_snack_pdus); len += sprintf(page +len, "PDUs Received\n------------------\n"); len += sprintf(page +len, "%12s %12s %12s %12s %12s %12s %12s %12s\n" "%12u %12u %12u %12u %12u %12u %12u %12u\n", "NopIn", "SCSIResp", "TaskMgmtResp", "TextResp", "DataIn", "R2T", "AsyncMess", "Reject", sess_stats->iscsi_ssn_noprx_pdus, sess_stats->iscsi_ssn_rsp_pdus, sess_stats->iscsi_ssn_tskmgmtrsp_pdus, sess_stats->iscsi_ssn_textrsp_pdus, sess_stats->iscsi_ssn_datain_pdus, sess_stats->iscsi_ssn_r2t_pdus, sess_stats->iscsi_ssn_async_pdus, sess_stats->iscsi_ssn_rjt_pdus); len += sprintf(page +len, "Data Bytes Txd = %lld\nData Bytes Rxd = %llu\n", sess_stats->iscsi_ssn_txdata_octets, sess_stats->iscsi_ssn_rxdata_octets); len += sprintf(page +len, "Input DataDigest Errors = %u\n", sess->sess_stats->iscsi_ssn_digest_err);#if USE_CONTROL_FILE len += sprintf(page +len, "Connection Timeout Error = %u\n", sess->sess_stats->iscsi_ssn_timeout_err);#endif return len;}/* * executed only by command process. * host_data_lock MUST be held by the calling process/thread * Called only by read_proc_file(). * dump_conn_info () prints the connection stats * CID, Connection STATE, Protocol Type, Local Address, Port * Remote Address, Port, Remote Address Type, Max Receive Data * Max Send Data, Receive Marker, Send Marker, Header Digest * Data Digest etc.. */static int __attribute__ ((no_instrument_function))dump_conn_info(struct connection *conn, char *buf){ int len; if (conn == NULL) return 0 ; len = print_connection_info(conn, buf, 0); if(conn->connection_state == CONNECTION_FULL_FEATURE_PHASE || conn->connection_state == CONNECTION_CONNECTED) { len += sprintf(buf + len, "%16s: %s\n", "LUN addressing", conn->connection_flags & USE_FLAT_SPACE_LUN ? "flat space" : "peripheral device"); len += sprintf(buf +len, "%16s: %s\n", "Header Digest", (conn->connection_flags & USE_HEADERDIGEST) ? "CRC32C" : "None"); len += sprintf(buf +len, "%16s: %s\n", "Data Digest", (conn->connection_flags & USE_DATADIGEST) ? "CRC32C" : "None"); len += sprintf(buf +len, "%16s: %u Bytes\n", "Max Send DSL", conn->max_send_length); len += sprintf(buf +len, "%16s: %u Bytes\n", "Max Recv DSL", conn->max_recv_length);#if 0 len += sprintf(buf +len, "%16s: %s\n", "Send Marker", "TODO"); len += sprintf(buf +len, "%16s: %s\n", "Receive Marker", "TODO");#endif len += sprintf(buf +len, "%16s: %lld\n", "Data Bytes Sent", conn->iscsi_conn_txdata_octets); len += sprintf(buf +len, "%16s: %lld\n", "Data Bytes Rcvd", conn->iscsi_conn_rxdata_octets); } return len;}#if USE_CONTROL_FILEstatic int __attribute__ ((no_instrument_function))write_proc_file(struct file *file, const char *buffer, unsigned long count, void *data){ /* Nothing to do here */ return count;}#endif/* * add_iscsi_proc_entry() routine accepts a void pointer, * the void ptr should be either a session ptr or a connection * ptr. The void ptr is typecast to either of them depending upon * "type". * The session proc entries include a "target#"<num> dir and * stat and ctrl file in it. * The connection proc entries include a "conn#"<cid> dir and * stat and ctrl file in it. * Same read and write routines are used for all files, the operation * is distinguished based on the "data" value in proc_data. */intadd_iscsi_proc_entry(void *ptr, int type){ int ret = -1; struct proc_dir_entry *dir = NULL, *stat_file = NULL;#if USE_CONTROL_FILE struct proc_dir_entry *ctrl_file = NULL;#endif struct session *sess = (struct session *) ptr; struct connection *conn = (struct connection *) ptr; char dir_name[32]; struct proc_data *stat_data = (struct proc_data *) kmalloc(sizeof (struct proc_data), GFP_KERNEL);#if USE_CONTROL_FILE struct proc_data *ctrl_data = (struct proc_data *) kmalloc(sizeof (struct proc_data), GFP_KERNEL);#endif sprintf(dir_name, "%s-%d", (type & SESSION) ? TARGET_FNAME : CONNECTION_FNAME, (type & SESSION) ? sess->scsi_target_id : conn->connection_id); dir = proc_mkdir(dir_name, (type & SESSION) ? global_host->hostt->proc_dir : conn->my_session-> proc_dir); if (dir == NULL) { TRACE(TRACE_DEBUG, "add_proc: creation of proc dir %s failed\n", dir_name); ret = -ENOMEM; goto error_out1; } /* set the proc dir entry in session structure */ if (type & SESSION) { sess->proc_dir = dir; stat_data->sess_id = sess->scsi_target_id; } else { /* Create connection specific stat and control files */ conn->proc_dir = dir; stat_data->sess_id = conn->my_session->scsi_target_id; stat_data->conn_id = conn->connection_id; } stat_data->type = type; stat_data->file = STAT; stat_file = create_proc_read_entry(STAT_FNAME, 0444, dir, read_proc_file, (void *) stat_data); if (stat_file == NULL) { TRACE(TRACE_DEBUG, "add_iscsi_proc_entry: creation of proc file %s failed\n", STAT_FNAME); ret = -ENOMEM; goto error_out2; }#if USE_CONTROL_FILE /* For time being, there is nothing that can be written * into a ctrl for connection. For sess level ctrl file, * we can only set the scheduling algo. */ ctrl_file = create_proc_entry(CONTROL_FNAME, 0644, dir); if (ctrl_file == NULL) { TRACE(TRACE_DEBUG, "add_iscsi_proc_entry: creation of proc file %s failed\n", CONTROL_FNAME); ret = -ENOMEM; goto error_out3; } ctrl_data->type = type; ctrl_data->file = CONTROL; if (type & SESSION) { ctrl_data->sess_id = sess->iscsi_target_id; } else { ctrl_data->sess_id = conn->my_session->iscsi_target_id; ctrl_data->conn_id = conn->connection_id; } ctrl_file->data = (void *) ctrl_data; ctrl_file->read_proc = read_proc_file; ctrl_file->write_proc = write_proc_file; ctrl_file->owner = THIS_MODULE;#endif ret = 0; return ret;#if USE_CONTROL_FILEerror_out3: remove_proc_entry(STAT_FNAME, dir);#endiferror_out2: remove_proc_entry(dir_name, global_host->hostt->proc_dir);error_out1: kfree(stat_data);#if USE_CONTROL_FILE kfree(ctrl_data);#endif return ret;}/* * remove_iscsi_proc_entry() accepts a void ptr and type, * The void ptr is typecast to either session or connection * based on the type. */voidremove_iscsi_proc_entry(void *ptr, int type){ struct session *sess = (struct session *) ptr; struct connection *conn = (struct connection *) ptr; char dir_name[32]; remove_proc_entry(STAT_FNAME, (type & SESSION) ? sess->proc_dir : conn->proc_dir); /*not sure if I have to free the "data" mem. */#if USE_CONTROL_FILE remove_proc_entry(CONTROL_FNAME, (type & SESSION) ? sess->proc_dir : conn->proc_dir);#endif sprintf(dir_name, "%s-%d", (type & SESSION) ? TARGET_FNAME : CONNECTION_FNAME, (type & SESSION) ? sess->scsi_target_id : conn->connection_id); remove_proc_entry(dir_name, (type & SESSION) ? global_host->hostt->proc_dir : conn->my_session->proc_dir); if (type & SESSION) sess->proc_dir = NULL; else conn->proc_dir = NULL; return;}#if USE_PRINT_DATE#define SECS_PER_HOUR (60 * 60)#define SECS_PER_DAY (60 * 60 * 24)#define isleap(year) \ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))#define TIMEZONE (-5 * 60 * 60)static int __attribute__ ((no_instrument_function))print_date (char *page, const struct timeval *t){ int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year; static const __u16 mon_yday[2][13] = { /* Normal years. */ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, /* Leap years. */ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; long int days, rem, y; const __u16 *ip; days = t->tv_sec / SECS_PER_DAY; rem = t->tv_sec % SECS_PER_DAY; rem += TIMEZONE; while (rem < 0) { rem += SECS_PER_DAY; --days; } while (rem >= SECS_PER_DAY) { rem -= SECS_PER_DAY; ++days; } tm_hour = rem / SECS_PER_HOUR; rem %= SECS_PER_HOUR; tm_min = rem / 60; tm_sec = rem % 60; y = 1970; while (days < 0 || days >= (isleap (y) ? 366 : 365)) { long int yg = y + days / 365 - (days % 365 < 0); days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1) - LEAPS_THRU_END_OF (y - 1)); y = yg; } tm_year = y - 1900; if (tm_year != y - 1900) return ; ip = mon_yday[isleap(y)]; for (y = 11; days < (long int) ip[y]; --y) continue; days -= ip[y]; tm_mon = y; tm_mday = days + 1; return sprintf(page, "DATE %.2d/%.2d/%d- %.2d:%.2d:%.2d", tm_mday, tm_mon + 1, tm_year + 1900, tm_hour, tm_min, tm_sec);}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -