On Wed, 20 Jun 2012 19:01:42 +0300 Alexander Nezhinsky <alexandern@xxxxxxxxxxxx> wrote: > To introduce statistics on SCSI device level we need to accumulate them > for each ITL (initiator-target-lun) nexus. > > For example in case of iscsi, this is a granularity which is finer than > a session (IT nexus), as it represents access to a specific lun within > the session. > > Statistics counters are added to the ITL object, "struct it_nexus_lu_info". > They need to be shown later in various scopes (connection, device, target etc.) > requiring two-way access, both from a device (lun to all its ITLs) and > from an IT nexus (IT nexus to all its ITLs). You guys really need this fine granularity. I feel that it's too much. Linux kernel doesn't provide such? > Thus a linked list's head called "it_nexus_lu_info_list" is added to both > struct scsi_lu and struct it_nexus, while struct it_nexus_lu_info > becomes a memeber in these two lists, thru the entries called: > itn_siblings and lu_siblings. > > Signed-off-by: Alexander Nezhinsky <alexandern@xxxxxxxxxxxx> > --- > usr/scsi.c | 16 +++++++++++++- > usr/target.c | 67 +++++++++++++++++++++++++++++++++++++++------------------ > usr/tgtd.h | 27 ++++++++++++++++++++++- > 3 files changed, 87 insertions(+), 23 deletions(-) > > diff --git a/usr/scsi.c b/usr/scsi.c > index 5ec3b4d..861d213 100644 > --- a/usr/scsi.c > +++ b/usr/scsi.c > @@ -201,6 +201,20 @@ int scsi_cmd_perform(int host_no, struct scsi_cmd *cmd) > unsigned char op = cmd->scb[0]; > struct it_nexus_lu_info *itn_lu; > > + if (scsi_get_data_dir(cmd) == DATA_WRITE) { > + cmd->itn_lu_info->stat.wr_subm_sect += scsi_get_out_length(cmd) / 512; The sector size is always expected to be 512? > + cmd->itn_lu_info->stat.wr_subm_cmds++; > + } > + else if (scsi_get_data_dir(cmd) == DATA_READ) { > + cmd->itn_lu_info->stat.rd_subm_sect += scsi_get_in_length(cmd) / 512; > + cmd->itn_lu_info->stat.rd_subm_cmds++; > + } > + else if (scsi_get_data_dir(cmd) == DATA_BIDIRECTIONAL) { > + cmd->itn_lu_info->stat.wr_subm_sect += scsi_get_out_length(cmd) / 512; > + cmd->itn_lu_info->stat.rd_subm_sect += scsi_get_in_length(cmd) / 512; > + cmd->itn_lu_info->stat.bidir_subm_cmds++; > + } > + > if (CDB_CONTROL(cmd) & ((1U << 0) | (1U << 2))) { > /* > * We don't support a linked command. SAM-3 say that > @@ -236,7 +250,7 @@ int scsi_cmd_perform(int host_no, struct scsi_cmd *cmd) > case REPORT_LUNS: > list_for_each_entry(itn_lu, > &cmd->it_nexus->it_nexus_lu_info_list, > - lu_info_siblings) > + itn_siblings) > ua_sense_clear(itn_lu, > ASC_REPORTED_LUNS_DATA_HAS_CHANGED); > break; > diff --git a/usr/target.c b/usr/target.c > index 68222a0..9d67195 100644 > --- a/usr/target.c > +++ b/usr/target.c > @@ -81,7 +81,7 @@ static int target_name_lookup(char *name) > return 0; > } > > -static struct it_nexus *it_nexus_lookup(int tid, uint64_t itn_id) > +struct it_nexus *it_nexus_lookup(int tid, uint64_t itn_id) > { > struct target *target; > struct it_nexus *itn; > @@ -199,11 +199,12 @@ static void it_nexus_del_lu_info(struct it_nexus *itn) > while(!list_empty(&itn->it_nexus_lu_info_list)) { > itn_lu = list_first_entry(&itn->it_nexus_lu_info_list, > struct it_nexus_lu_info, > - lu_info_siblings); > + itn_siblings); > > ua_sense_pending_del(itn_lu); > > - list_del(&itn_lu->lu_info_siblings); > + list_del(&itn_lu->itn_siblings); > + list_del(&itn_lu->lu_siblings); > free(itn_lu); > } > } > @@ -221,7 +222,7 @@ void ua_sense_add_other_it_nexus(uint64_t itn_id, struct scsi_lu *lu, > continue; > > list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > > if (itn_lu->lu != lu) > continue; > @@ -245,7 +246,7 @@ void ua_sense_add_it_nexus(uint64_t itn_id, struct scsi_lu *lu, > > if (itn->itn_id == itn_id) { > list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > > if (itn_lu->lu == lu) { > ret = ua_sense_add(itn_lu, asc); > @@ -268,7 +269,7 @@ int lu_prevent_removal(struct scsi_lu *lu) > > list_for_each_entry(itn, &lu->tgt->it_nexus_list, nexus_siblings) { > list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > if (itn_lu->lu == lu) { > if (itn_lu->prevent & PREVENT_REMOVAL) > return 1; > @@ -315,13 +316,17 @@ int it_nexus_create(int tid, uint64_t itn_id, int host_no, char *info) > if (!itn_lu) > goto out; > itn_lu->lu = lu; > + itn_lu->itn_id = itn_id; > INIT_LIST_HEAD(&itn_lu->pending_ua_sense_list); > > ret = ua_sense_add(itn_lu, ASC_POWERON_RESET); > if (ret) > goto out; > > - list_add(&itn_lu->lu_info_siblings, > + list_add_tail(&itn_lu->lu_siblings, > + &lu->it_nexus_lu_info_list); > + > + list_add(&itn_lu->itn_siblings, > &itn->it_nexus_lu_info_list); > } > > @@ -472,7 +477,7 @@ tgtadm_err tgt_device_create(int tid, int dev_type, uint64_t lun, char *params, > struct scsi_lu *lu, *pos; > struct device_type_template *t; > struct backingstore_template *bst; > - struct it_nexus_lu_info *itn_lu; > + struct it_nexus_lu_info *itn_lu, *itn_lu_pos; > struct it_nexus *itn; > char strflags[128]; > > @@ -573,6 +578,7 @@ tgtadm_err tgt_device_create(int tid, int dev_type, uint64_t lun, char *params, > > tgt_cmd_queue_init(&lu->cmd_queue); > INIT_LIST_HEAD(&lu->registration_list); > + INIT_LIST_HEAD(&lu->it_nexus_lu_info_list); > lu->prgeneration = 0; > lu->pr_holder = NULL; > > @@ -635,21 +641,24 @@ tgtadm_err tgt_device_create(int tid, int dev_type, uint64_t lun, char *params, > if (!itn_lu) > break; > itn_lu->lu = lu; > + itn_lu->itn_id = itn->itn_id; > INIT_LIST_HEAD(&itn_lu->pending_ua_sense_list); > > - list_add(&itn_lu->lu_info_siblings, > - &itn->it_nexus_lu_info_list); > - } > - > - list_for_each_entry(itn, &target->it_nexus_list, nexus_siblings) { > - list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + /* signal LUNs info change thru all existing LUNs in the nexus */ > + list_for_each_entry(itn_lu_pos, &itn->it_nexus_lu_info_list, > + itn_siblings) { > > - if (ua_sense_add(itn_lu, ASC_REPORTED_LUNS_DATA_HAS_CHANGED)) { > + if (ua_sense_add(itn_lu_pos, ASC_REPORTED_LUNS_DATA_HAS_CHANGED)) { > adm_err = TGTADM_NOMEM; > goto fail_bs_init; > } > } > + > + list_add_tail(&itn_lu->lu_siblings, > + &lu->it_nexus_lu_info_list); > + > + list_add(&itn_lu->itn_siblings, > + &itn->it_nexus_lu_info_list); > } > > if (backing && !path) > @@ -712,7 +721,7 @@ tgtadm_err tgt_device_destroy(int tid, uint64_t lun, int force) > > list_for_each_entry(itn, &target->it_nexus_list, nexus_siblings) { > list_for_each_entry_safe(itn_lu, next, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > if (itn_lu->lu == lu) { > ua_sense_pending_del(itn_lu); > break; > @@ -731,7 +740,7 @@ tgtadm_err tgt_device_destroy(int tid, uint64_t lun, int force) > > list_for_each_entry(itn, &target->it_nexus_list, nexus_siblings) { > list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > > ret = ua_sense_add(itn_lu, > ASC_REPORTED_LUNS_DATA_HAS_CHANGED); > @@ -952,7 +961,7 @@ static struct it_nexus_lu_info *it_nexus_lu_info_lookup(struct it_nexus *itn, > struct it_nexus_lu_info *itn_lu; > > list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > if (itn_lu->lu->lun == lun) > return itn_lu; > } > @@ -1061,6 +1070,22 @@ int target_cmd_perform_passthrough(int tid, struct scsi_cmd *cmd) > void target_cmd_io_done(struct scsi_cmd *cmd, int result) > { > scsi_set_result(cmd, result); > + if (scsi_get_data_dir(cmd) == DATA_WRITE) { > + cmd->itn_lu_info->stat.wr_done_sect += scsi_get_out_length(cmd) / 512; > + cmd->itn_lu_info->stat.wr_done_cmds++; > + } > + else if (scsi_get_data_dir(cmd) == DATA_READ) { > + cmd->itn_lu_info->stat.rd_done_sect += scsi_get_in_length(cmd) / 512; > + cmd->itn_lu_info->stat.rd_done_cmds++; > + } > + else if (scsi_get_data_dir(cmd) == DATA_BIDIRECTIONAL) { > + cmd->itn_lu_info->stat.wr_done_sect += scsi_get_out_length(cmd) / 512; > + cmd->itn_lu_info->stat.rd_done_sect += scsi_get_in_length(cmd) / 512; > + cmd->itn_lu_info->stat.bidir_done_cmds++; > + } > + if (result != SAM_STAT_GOOD) > + cmd->itn_lu_info->stat.err_num++; > + > tgt_drivers[cmd->c_target->lid]->cmd_end_notify(cmd->cmd_itn_id, > result, cmd); > return; > @@ -1242,7 +1267,7 @@ enum mgmt_req_result target_mgmt_request(int tid, uint64_t itn_id, > > list_for_each_entry(itn, &target->it_nexus_list, nexus_siblings) { > list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > if (itn_lu->lu->lun == lun) { > if (itn->itn_id == itn_id) > asc = ASC_POWERON_RESET; > @@ -1264,7 +1289,7 @@ enum mgmt_req_result target_mgmt_request(int tid, uint64_t itn_id, > > list_for_each_entry(itn, &target->it_nexus_list, nexus_siblings) { > list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list, > - lu_info_siblings) { > + itn_siblings) { > if (itn_lu->lu->lun == lun) { > ua_sense_add(itn_lu, ASC_POWERON_RESET); > break; > diff --git a/usr/tgtd.h b/usr/tgtd.h > index aa9b9d5..e159c05 100644 > --- a/usr/tgtd.h > +++ b/usr/tgtd.h > @@ -92,9 +92,31 @@ struct ua_sense { > int ua_sense_len; > }; > > +struct lu_stat { > + uint64_t rd_subm_sect; > + uint64_t rd_done_sect; > + > + uint64_t wr_subm_sect; > + uint64_t wr_done_sect; > + > + uint32_t rd_subm_cmds; > + uint32_t rd_done_cmds; > + > + uint32_t wr_subm_cmds; > + uint32_t wr_done_cmds; > + > + uint32_t bidir_subm_cmds; > + uint32_t bidir_done_cmds; > + > + uint32_t err_num; > +}; > + > struct it_nexus_lu_info { > struct scsi_lu *lu; > - struct list_head lu_info_siblings; > + uint64_t itn_id; > + struct lu_stat stat; > + struct list_head itn_siblings; > + struct list_head lu_siblings; > struct list_head pending_ua_sense_list; > int prevent; /* prevent removal on this itl nexus ? */ > }; > @@ -174,6 +196,8 @@ struct scsi_lu { > /* the list of devices belonging to a target */ > struct list_head device_siblings; > > + struct list_head it_nexus_lu_info_list; > + > struct tgt_cmd_queue cmd_queue; > > uint64_t reserve_id; > @@ -280,6 +304,7 @@ extern enum mgmt_req_result target_mgmt_request(int tid, uint64_t itn_id, > uint8_t *lun, uint64_t tag, > int host_no); > > +extern struct it_nexus *it_nexus_lookup(int tid, uint64_t itn_id); > extern void target_cmd_io_done(struct scsi_cmd *cmd, int result); > extern int ua_sense_del(struct scsi_cmd *cmd, int del); > extern void ua_sense_clear(struct it_nexus_lu_info *itn_lu, uint16_t asc); > -- > 1.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe stgt" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe stgt" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html