diff options
author | mav <mav@FreeBSD.org> | 2017-01-26 21:00:49 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2017-01-26 21:00:49 +0000 |
commit | cce5ebe6044dbb57219042e8ebe92b059dac6dfc (patch) | |
tree | fe523c65c0b5f09e39a11dcbca403c759e10f1e5 /sys/cam | |
parent | 3b6d406303ea2f842f368051fefb6b4bb26f6aa5 (diff) | |
download | FreeBSD-src-cce5ebe6044dbb57219042e8ebe92b059dac6dfc.zip FreeBSD-src-cce5ebe6044dbb57219042e8ebe92b059dac6dfc.tar.gz |
MFC r311804: Rewrite CTL statistics in more simple and scalable way.
Instead of collecting statistics for each combination of ports and logical
units, that consumed ~45KB per LU with present number of ports, collect
separate statistics for every port and every logical unit separately, that
consume only 176 bytes per each single LU/port. This reduces struct
ctl_lun size down to just 6KB.
Also new IOCTL API/ABI does not hardcode number of LUs/ports, and should
allow handling of very large quantities.
Old API is still enabled in stable branches for compatibility reasons.
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ctl/ctl.c | 188 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend.h | 51 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend.c | 24 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend.h | 5 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_ioctl.h | 97 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_private.h | 7 |
6 files changed, 242 insertions, 130 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 8962f03..30082cb 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2003-2009 Silicon Graphics International Corp. * Copyright (c) 2012 The FreeBSD Foundation - * Copyright (c) 2015 Alexander Motin <mav@FreeBSD.org> + * Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Portions of this software were developed by Edward Tomasz Napierala @@ -2558,6 +2558,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) { struct ctl_softc *softc = dev->si_drv1; + struct ctl_port *port; struct ctl_lun *lun; int retval; @@ -2769,6 +2770,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, #endif /* CTL_IO_DELAY */ break; } +#ifdef CTL_LEGACY_STATS case CTL_GETSTATS: { struct ctl_stats *stats = (struct ctl_stats *)addr; int i; @@ -2781,26 +2783,26 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, stats->status = CTL_SS_OK; stats->fill_len = 0; STAILQ_FOREACH(lun, &softc->lun_list, links) { - if (stats->fill_len + sizeof(lun->stats) > + if (stats->fill_len + sizeof(lun->legacy_stats) > stats->alloc_len) { stats->status = CTL_SS_NEED_MORE_SPACE; break; } - retval = copyout(&lun->stats, &stats->lun_stats[i++], - sizeof(lun->stats)); + retval = copyout(&lun->legacy_stats, &stats->lun_stats[i++], + sizeof(lun->legacy_stats)); if (retval != 0) break; - stats->fill_len += sizeof(lun->stats); + stats->fill_len += sizeof(lun->legacy_stats); } stats->num_luns = softc->num_luns; -#ifdef CTL_TIME_IO - stats->flags = CTL_STATS_FLAG_TIME_VALID; -#else stats->flags = CTL_STATS_FLAG_NONE; +#ifdef CTL_TIME_IO + stats->flags |= CTL_STATS_FLAG_TIME_VALID; #endif getnanouptime(&stats->timestamp); break; } +#endif /* CTL_LEGACY_STATS */ case CTL_ERROR_INJECT: { struct ctl_error_desc *err_desc, *new_err_desc; @@ -3388,6 +3390,72 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, ctl_isc_announce_port(port); break; } + case CTL_GET_LUN_STATS: { + struct ctl_get_io_stats *stats = (struct ctl_get_io_stats *)addr; + int i; + + /* + * XXX KDM no locking here. If the LUN list changes, + * things can blow up. + */ + i = 0; + stats->status = CTL_SS_OK; + stats->fill_len = 0; + STAILQ_FOREACH(lun, &softc->lun_list, links) { + if (lun->lun < stats->first_item) + continue; + if (stats->fill_len + sizeof(lun->stats) > + stats->alloc_len) { + stats->status = CTL_SS_NEED_MORE_SPACE; + break; + } + retval = copyout(&lun->stats, &stats->stats[i++], + sizeof(lun->stats)); + if (retval != 0) + break; + stats->fill_len += sizeof(lun->stats); + } + stats->num_items = softc->num_luns; + stats->flags = CTL_STATS_FLAG_NONE; +#ifdef CTL_TIME_IO + stats->flags |= CTL_STATS_FLAG_TIME_VALID; +#endif + getnanouptime(&stats->timestamp); + break; + } + case CTL_GET_PORT_STATS: { + struct ctl_get_io_stats *stats = (struct ctl_get_io_stats *)addr; + int i; + + /* + * XXX KDM no locking here. If the LUN list changes, + * things can blow up. + */ + i = 0; + stats->status = CTL_SS_OK; + stats->fill_len = 0; + STAILQ_FOREACH(port, &softc->port_list, links) { + if (port->targ_port < stats->first_item) + continue; + if (stats->fill_len + sizeof(port->stats) > + stats->alloc_len) { + stats->status = CTL_SS_NEED_MORE_SPACE; + break; + } + retval = copyout(&port->stats, &stats->stats[i++], + sizeof(port->stats)); + if (retval != 0) + break; + stats->fill_len += sizeof(port->stats); + } + stats->num_items = softc->num_ports; + stats->flags = CTL_STATS_FLAG_NONE; +#ifdef CTL_TIME_IO + stats->flags |= CTL_STATS_FLAG_TIME_VALID; +#endif + getnanouptime(&stats->timestamp); + break; + } default: { /* XXX KDM should we fix this? */ #if 0 @@ -4382,7 +4450,7 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, struct scsi_vpd_id_descriptor *desc; struct scsi_vpd_id_t10 *t10id; const char *eui, *naa, *scsiname, *uuid, *vendor, *value; - int lun_number, i, lun_malloced; + int lun_number, lun_malloced; int devidlen, idlen1, idlen2 = 0, len; if (be_lun == NULL) @@ -4604,13 +4672,16 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, ctl_softc->num_luns++; /* Setup statistics gathering */ - lun->stats.device_type = be_lun->lun_type; - lun->stats.lun_number = lun_number; - lun->stats.blocksize = be_lun->blocksize; +#ifdef CTL_LEGACY_STATS + lun->legacy_stats.device_type = be_lun->lun_type; + lun->legacy_stats.lun_number = lun_number; + lun->legacy_stats.blocksize = be_lun->blocksize; if (be_lun->blocksize == 0) - lun->stats.flags = CTL_LUN_STATS_NO_BLOCKSIZE; - for (i = 0;i < CTL_MAX_PORTS;i++) - lun->stats.ports[i].targ_port = i; + lun->legacy_stats.flags = CTL_LUN_STATS_NO_BLOCKSIZE; + for (len = 0; len < CTL_MAX_PORTS; len++) + lun->legacy_stats.ports[len].targ_port = len; +#endif /* CTL_LEGACY_STATS */ + lun->stats.item = lun_number; mtx_unlock(&ctl_softc->ctl_lock); @@ -6676,9 +6747,7 @@ ctl_sap_log_sense_handler(struct ctl_scsiio *ctsio, { struct ctl_lun *lun = CTL_LUN(ctsio); struct stat_page *data; - uint64_t rn, wn, rb, wb; - struct bintime rt, wt; - int i; + struct bintime *t; data = (struct stat_page *)page_index->page_data; @@ -6686,28 +6755,21 @@ ctl_sap_log_sense_handler(struct ctl_scsiio *ctsio, data->sap.hdr.param_control = SLP_LBIN; data->sap.hdr.param_len = sizeof(struct scsi_log_stat_and_perf) - sizeof(struct scsi_log_param_header); - rn = wn = rb = wb = 0; - bintime_clear(&rt); - bintime_clear(&wt); - for (i = 0; i < CTL_MAX_PORTS; i++) { - rn += lun->stats.ports[i].operations[CTL_STATS_READ]; - wn += lun->stats.ports[i].operations[CTL_STATS_WRITE]; - rb += lun->stats.ports[i].bytes[CTL_STATS_READ]; - wb += lun->stats.ports[i].bytes[CTL_STATS_WRITE]; - bintime_add(&rt, &lun->stats.ports[i].time[CTL_STATS_READ]); - bintime_add(&wt, &lun->stats.ports[i].time[CTL_STATS_WRITE]); - } - scsi_u64to8b(rn, data->sap.read_num); - scsi_u64to8b(wn, data->sap.write_num); - if (lun->stats.blocksize > 0) { - scsi_u64to8b(wb / lun->stats.blocksize, - data->sap.recvieved_lba); - scsi_u64to8b(rb / lun->stats.blocksize, - data->sap.transmitted_lba); - } - scsi_u64to8b((uint64_t)rt.sec * 1000 + rt.frac / (UINT64_MAX / 1000), + scsi_u64to8b(lun->stats.operations[CTL_STATS_READ], + data->sap.read_num); + scsi_u64to8b(lun->stats.operations[CTL_STATS_WRITE], + data->sap.write_num); + if (lun->be_lun->blocksize > 0) { + scsi_u64to8b(lun->stats.bytes[CTL_STATS_WRITE] / + lun->be_lun->blocksize, data->sap.recvieved_lba); + scsi_u64to8b(lun->stats.bytes[CTL_STATS_READ] / + lun->be_lun->blocksize, data->sap.transmitted_lba); + } + t = &lun->stats.time[CTL_STATS_READ]; + scsi_u64to8b((uint64_t)t->sec * 1000 + t->frac / (UINT64_MAX / 1000), data->sap.read_int); - scsi_u64to8b((uint64_t)wt.sec * 1000 + wt.frac / (UINT64_MAX / 1000), + t = &lun->stats.time[CTL_STATS_WRITE]; + scsi_u64to8b((uint64_t)t->sec * 1000 + t->frac / (UINT64_MAX / 1000), data->sap.write_int); scsi_u64to8b(0, data->sap.weighted_num); scsi_u64to8b(0, data->sap.weighted_int); @@ -13044,13 +13106,13 @@ static void ctl_process_done(union ctl_io *io) { struct ctl_softc *softc = CTL_SOFTC(io); + struct ctl_port *port = CTL_PORT(io); struct ctl_lun *lun = CTL_LUN(io); void (*fe_done)(union ctl_io *io); union ctl_ha_msg msg; - uint32_t targ_port = io->io_hdr.nexus.targ_port; CTL_DEBUG_PRINT(("ctl_process_done\n")); - fe_done = softc->ctl_ports[targ_port]->fe_done; + fe_done = port->fe_done; #ifdef CTL_TIME_IO if ((time_uptime - io->io_hdr.start_time) > ctl_time_io_secs) { @@ -13153,11 +13215,13 @@ ctl_process_done(union ctl_io *io) */ if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS && io->io_hdr.io_type == CTL_IO_SCSI) { -#ifdef CTL_TIME_IO - struct bintime cur_bt; -#endif int type; +#ifdef CTL_TIME_IO + struct bintime bt; + getbinuptime(&bt); + bintime_sub(&bt, &io->io_hdr.start_bt); +#endif if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) type = CTL_STATS_READ; @@ -13167,18 +13231,38 @@ ctl_process_done(union ctl_io *io) else type = CTL_STATS_NO_IO; - lun->stats.ports[targ_port].bytes[type] += +#ifdef CTL_LEGACY_STATS + uint32_t targ_port = port->targ_port; + lun->legacy_stats.ports[targ_port].bytes[type] += io->scsiio.kern_total_len; - lun->stats.ports[targ_port].operations[type]++; + lun->legacy_stats.ports[targ_port].operations[type] ++; + lun->legacy_stats.ports[targ_port].num_dmas[type] += + io->io_hdr.num_dmas; #ifdef CTL_TIME_IO - bintime_add(&lun->stats.ports[targ_port].dma_time[type], + bintime_add(&lun->legacy_stats.ports[targ_port].dma_time[type], &io->io_hdr.dma_bt); - getbinuptime(&cur_bt); - bintime_sub(&cur_bt, &io->io_hdr.start_bt); - bintime_add(&lun->stats.ports[targ_port].time[type], &cur_bt); + bintime_add(&lun->legacy_stats.ports[targ_port].time[type], + &bt); #endif - lun->stats.ports[targ_port].num_dmas[type] += - io->io_hdr.num_dmas; +#endif /* CTL_LEGACY_STATS */ + + lun->stats.bytes[type] += io->scsiio.kern_total_len; + lun->stats.operations[type] ++; + lun->stats.dmas[type] += io->io_hdr.num_dmas; +#ifdef CTL_TIME_IO + bintime_add(&lun->stats.dma_time[type], &io->io_hdr.dma_bt); + bintime_add(&lun->stats.time[type], &bt); +#endif + + mtx_lock(&port->port_lock); + port->stats.bytes[type] += io->scsiio.kern_total_len; + port->stats.operations[type] ++; + port->stats.dmas[type] += io->io_hdr.num_dmas; +#ifdef CTL_TIME_IO + bintime_add(&port->stats.dma_time[type], &io->io_hdr.dma_bt); + bintime_add(&port->stats.time[type], &bt); +#endif + mtx_unlock(&port->port_lock); } /* diff --git a/sys/cam/ctl/ctl_backend.h b/sys/cam/ctl/ctl_backend.h index 4177e2d..d8ada83 100644 --- a/sys/cam/ctl/ctl_backend.h +++ b/sys/cam/ctl/ctl_backend.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003 Silicon Graphics International Corp. - * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> + * Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,54 +40,7 @@ #ifndef _CTL_BACKEND_H_ #define _CTL_BACKEND_H_ -/* - * XXX KDM move this to another header file? - */ -#define CTL_BE_NAME_LEN 32 - -/* - * The ID_REQ flag is used to say that the caller has requested a - * particular LUN ID in the req_lun_id field. If we cannot allocate that - * LUN ID, the ctl_add_lun() call will fail. - * - * The STOPPED flag tells us that the LUN should default to the powered - * off state. It will return 0x04,0x02 until it is powered up. ("Logical - * unit not ready, initializing command required.") - * - * The NO_MEDIA flag tells us that the LUN has no media inserted. - * - * The PRIMARY flag tells us that this LUN is registered as a Primary LUN - * which is accessible via the Master shelf controller in an HA. This flag - * being set indicates a Primary LUN. This flag being reset represents a - * Secondary LUN controlled by the Secondary controller in an HA - * configuration. Flag is applicable at this time to T_DIRECT types. - * - * The SERIAL_NUM flag tells us that the serial_num field is filled in and - * valid for use in SCSI INQUIRY VPD page 0x80. - * - * The DEVID flag tells us that the device_id field is filled in and - * valid for use in SCSI INQUIRY VPD page 0x83. - * - * The DEV_TYPE flag tells us that the device_type field is filled in. - * - * The EJECTED flag tells us that the removable LUN has tray open. - * - * The UNMAP flag tells us that this LUN supports UNMAP. - * - * The OFFLINE flag tells us that this LUN can not access backing store. - */ -typedef enum { - CTL_LUN_FLAG_ID_REQ = 0x01, - CTL_LUN_FLAG_STOPPED = 0x02, - CTL_LUN_FLAG_NO_MEDIA = 0x04, - CTL_LUN_FLAG_PRIMARY = 0x08, - CTL_LUN_FLAG_SERIAL_NUM = 0x10, - CTL_LUN_FLAG_DEVID = 0x20, - CTL_LUN_FLAG_DEV_TYPE = 0x40, - CTL_LUN_FLAG_UNMAP = 0x80, - CTL_LUN_FLAG_EJECTED = 0x100, - CTL_LUN_FLAG_READONLY = 0x200 -} ctl_backend_lun_flags; +#include <cam/ctl/ctl_ioctl.h> typedef enum { CTL_LUN_SERSEQ_OFF, diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c index 97f4e0b..03ee9da 100644 --- a/sys/cam/ctl/ctl_frontend.c +++ b/sys/cam/ctl/ctl_frontend.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003 Silicon Graphics International Corp. + * Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -192,13 +193,14 @@ error: mtx_unlock(&softc->ctl_lock); return (retval); } + port->targ_port = port_num; port->ctl_pool_ref = pool; - if (port->options.stqh_first == NULL) STAILQ_INIT(&port->options); + port->stats.item = port_num; + mtx_init(&port->port_lock, "CTL port", NULL, MTX_DEF); mtx_lock(&softc->ctl_lock); - port->targ_port = port_num; STAILQ_INSERT_TAIL(&port->frontend->port_list, port, fe_links); for (tport = NULL, nport = STAILQ_FIRST(&softc->port_list); nport != NULL && nport->targ_port < port_num; @@ -218,17 +220,11 @@ int ctl_port_deregister(struct ctl_port *port) { struct ctl_softc *softc = port->ctl_softc; - struct ctl_io_pool *pool; - int retval, i; - - retval = 0; - - pool = (struct ctl_io_pool *)port->ctl_pool_ref; + struct ctl_io_pool *pool = (struct ctl_io_pool *)port->ctl_pool_ref; + int i; - if (port->targ_port == -1) { - retval = 1; - goto bailout; - } + if (port->targ_port == -1) + return (1); mtx_lock(&softc->ctl_lock); STAILQ_REMOVE(&softc->port_list, port, ctl_port, links); @@ -251,9 +247,9 @@ ctl_port_deregister(struct ctl_port *port) for (i = 0; i < port->max_initiators; i++) free(port->wwpn_iid[i].name, M_CTL); free(port->wwpn_iid, M_CTL); + mtx_destroy(&port->port_lock); -bailout: - return (retval); + return (0); } void diff --git a/sys/cam/ctl/ctl_frontend.h b/sys/cam/ctl/ctl_frontend.h index 3e42ac3..37e6824 100644 --- a/sys/cam/ctl/ctl_frontend.h +++ b/sys/cam/ctl/ctl_frontend.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003 Silicon Graphics International Corp. + * Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +40,8 @@ #ifndef _CTL_FRONTEND_H_ #define _CTL_FRONTEND_H_ +#include <cam/ctl/ctl_ioctl.h> + typedef enum { CTL_PORT_STATUS_NONE = 0x00, CTL_PORT_STATUS_ONLINE = 0x01, @@ -243,6 +246,8 @@ struct ctl_port { struct ctl_devid *port_devid; /* passed to CTL */ struct ctl_devid *target_devid; /* passed to CTL */ struct ctl_devid *init_devid; /* passed to CTL */ + struct ctl_io_stats stats; /* used by CTL */ + struct mtx port_lock; /* used by CTL */ STAILQ_ENTRY(ctl_port) fe_links; /* used by CTL */ STAILQ_ENTRY(ctl_port) links; /* used by CTL */ }; diff --git a/sys/cam/ctl/ctl_ioctl.h b/sys/cam/ctl/ctl_ioctl.h index e8f6b87..ee4ce18 100644 --- a/sys/cam/ctl/ctl_ioctl.h +++ b/sys/cam/ctl/ctl_ioctl.h @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003 Silicon Graphics International Corp. * Copyright (c) 2011 Spectra Logic Corporation + * Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,6 +81,9 @@ /* Hopefully this won't conflict with new misc devices that pop up */ #define CTL_MINOR 225 +/* Legacy statistics accumulated for every port for every LU. */ +#define CTL_LEGACY_STATS 1 + typedef enum { CTL_DELAY_TYPE_NONE, CTL_DELAY_TYPE_CONT, @@ -117,6 +121,18 @@ typedef enum { #define CTL_STATS_NUM_TYPES 3 typedef enum { + CTL_SS_OK, + CTL_SS_NEED_MORE_SPACE, + CTL_SS_ERROR +} ctl_stats_status; + +typedef enum { + CTL_STATS_FLAG_NONE = 0x00, + CTL_STATS_FLAG_TIME_VALID = 0x01 +} ctl_stats_flags; + +#ifdef CTL_LEGACY_STATS +typedef enum { CTL_LUN_STATS_NO_BLOCKSIZE = 0x01 } ctl_lun_stats_flags; @@ -137,17 +153,6 @@ struct ctl_lun_io_stats { struct ctl_lun_io_port_stats ports[CTL_MAX_PORTS]; }; -typedef enum { - CTL_SS_OK, - CTL_SS_NEED_MORE_SPACE, - CTL_SS_ERROR -} ctl_stats_status; - -typedef enum { - CTL_STATS_FLAG_NONE = 0x00, - CTL_STATS_FLAG_TIME_VALID = 0x01 -} ctl_stats_flags; - struct ctl_stats { int alloc_len; /* passed to kernel */ struct ctl_lun_io_stats *lun_stats; /* passed to/from kernel */ @@ -157,6 +162,27 @@ struct ctl_stats { ctl_stats_flags flags; /* passed to userland */ struct timespec timestamp; /* passed to userland */ }; +#endif /* CTL_LEGACY_STATS */ + +struct ctl_io_stats { + uint32_t item; + uint64_t bytes[CTL_STATS_NUM_TYPES]; + uint64_t operations[CTL_STATS_NUM_TYPES]; + uint64_t dmas[CTL_STATS_NUM_TYPES]; + struct bintime time[CTL_STATS_NUM_TYPES]; + struct bintime dma_time[CTL_STATS_NUM_TYPES]; +}; + +struct ctl_get_io_stats { + struct ctl_io_stats *stats; /* passed to/from kernel */ + size_t alloc_len; /* passed to kernel */ + size_t fill_len; /* passed to userland */ + int first_item; /* passed to kernel */ + int num_items; /* passed to userland */ + ctl_stats_status status; /* passed to userland */ + ctl_stats_flags flags; /* passed to userland */ + struct timespec timestamp; /* passed to userland */ +}; /* * The types of errors that can be injected: @@ -342,12 +368,54 @@ typedef enum { CTL_LUNREQ_MODIFY, } ctl_lunreq_type; +/* + * The ID_REQ flag is used to say that the caller has requested a + * particular LUN ID in the req_lun_id field. If we cannot allocate that + * LUN ID, the ctl_add_lun() call will fail. + * + * The STOPPED flag tells us that the LUN should default to the powered + * off state. It will return 0x04,0x02 until it is powered up. ("Logical + * unit not ready, initializing command required.") + * + * The NO_MEDIA flag tells us that the LUN has no media inserted. + * + * The PRIMARY flag tells us that this LUN is registered as a Primary LUN + * which is accessible via the Master shelf controller in an HA. This flag + * being set indicates a Primary LUN. This flag being reset represents a + * Secondary LUN controlled by the Secondary controller in an HA + * configuration. Flag is applicable at this time to T_DIRECT types. + * + * The SERIAL_NUM flag tells us that the serial_num field is filled in and + * valid for use in SCSI INQUIRY VPD page 0x80. + * + * The DEVID flag tells us that the device_id field is filled in and + * valid for use in SCSI INQUIRY VPD page 0x83. + * + * The DEV_TYPE flag tells us that the device_type field is filled in. + * + * The EJECTED flag tells us that the removable LUN has tray open. + * + * The UNMAP flag tells us that this LUN supports UNMAP. + * + * The OFFLINE flag tells us that this LUN can not access backing store. + */ +typedef enum { + CTL_LUN_FLAG_ID_REQ = 0x01, + CTL_LUN_FLAG_STOPPED = 0x02, + CTL_LUN_FLAG_NO_MEDIA = 0x04, + CTL_LUN_FLAG_PRIMARY = 0x08, + CTL_LUN_FLAG_SERIAL_NUM = 0x10, + CTL_LUN_FLAG_DEVID = 0x20, + CTL_LUN_FLAG_DEV_TYPE = 0x40, + CTL_LUN_FLAG_UNMAP = 0x80, + CTL_LUN_FLAG_EJECTED = 0x100, + CTL_LUN_FLAG_READONLY = 0x200 +} ctl_backend_lun_flags; /* * LUN creation parameters: * - * flags: Various LUN flags, see ctl_backend.h for a - * description of the flag values and meanings. + * flags: Various LUN flags, see above. * * device_type: The SCSI device type. e.g. 0 for Direct Access, * 3 for Processor, etc. Only certain backends may @@ -465,6 +533,7 @@ union ctl_lunreq_data { * kern_be_args: For kernel use only. */ struct ctl_lun_req { +#define CTL_BE_NAME_LEN 32 char backend[CTL_BE_NAME_LEN]; ctl_lunreq_type reqtype; union ctl_lunreq_data reqdata; @@ -761,6 +830,8 @@ struct ctl_lun_map { #define CTL_PORT_REQ _IOWR(CTL_MINOR, 0x26, struct ctl_req) #define CTL_PORT_LIST _IOWR(CTL_MINOR, 0x27, struct ctl_lun_list) #define CTL_LUN_MAP _IOW(CTL_MINOR, 0x28, struct ctl_lun_map) +#define CTL_GET_LUN_STATS _IOWR(CTL_MINOR, 0x29, struct ctl_get_io_stats) +#define CTL_GET_PORT_STATS _IOWR(CTL_MINOR, 0x2a, struct ctl_get_io_stats) #endif /* _CTL_IOCTL_H_ */ diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index 5b71f9a..3f46769 100644 --- a/sys/cam/ctl/ctl_private.h +++ b/sys/cam/ctl/ctl_private.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003, 2004, 2005, 2008 Silicon Graphics International Corp. - * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> + * Copyright (c) 2014-2017 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -404,7 +404,10 @@ struct ctl_lun { struct callout ie_callout; /* INTERVAL TIMER */ struct ctl_mode_pages mode_pages; struct ctl_log_pages log_pages; - struct ctl_lun_io_stats stats; +#ifdef CTL_LEGACY_STATS + struct ctl_lun_io_stats legacy_stats; +#endif /* CTL_LEGACY_STATS */ + struct ctl_io_stats stats; uint32_t res_idx; uint32_t pr_generation; uint64_t *pr_keys[CTL_MAX_PORTS]; |