[stgt] [PATCH 1/2] Add infrastructure for statistics on SCSI device level
FUJITA Tomonori
fujita.tomonori at lab.ntt.co.jp
Wed Jun 27 15:14:09 CEST 2012
On Wed, 20 Jun 2012 19:01:42 +0300
Alexander Nezhinsky <alexandern at mellanox.com> 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 at mellanox.com>
> ---
> 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 at vger.kernel.org
> 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 at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list