From d248cc356200a4df93e92b114fd46f4d94680c88 Mon Sep 17 00:00:00 2001 From: Sriram Patil Date: Mon, 8 May 2017 12:44:59 +0000 Subject: [PATCH] NFS Ganesha global stats are now written into shm to be displayed at runtime Allocating a shared memory in nfs_main to store the global stats. These global stats are written by Ganesha and can be read by a client program display_stats. display_stats binary is created at path support/display_stats. It does not take any arguments as of now. It displays the Ganesha global stats as they happen every second. Change-Id: Idf318d7d6a5c1e660e0a97f8106a69c0b83a3197 Signed-off-by: Sriram Patil --- src/MainNFSD/nfs_main.c | 16 ++ src/include/server_stats.h | 177 ++++++++++++++++++++ src/support/CMakeLists.txt | 13 ++ src/support/display_stats.c | 235 ++++++++++++++++++++++++++ src/support/server_stats.c | 322 ++++++++++++++---------------------- 5 files changed, 563 insertions(+), 200 deletions(-) create mode 100644 src/support/display_stats.c diff --git a/src/MainNFSD/nfs_main.c b/src/MainNFSD/nfs_main.c index 5685dcd11e..f6d408eff3 100644 --- a/src/MainNFSD/nfs_main.c +++ b/src/MainNFSD/nfs_main.c @@ -37,11 +37,14 @@ #include #include /* for sigaction */ #include +#include +#include #include "fsal.h" #include "log.h" #include "nfs_init.h" #include "nfs_exports.h" #include "pnfs_utils.h" +#include "server_stats.h" /** * @brief LTTng trace enabling magic @@ -480,9 +483,22 @@ int main(int argc, char *argv[]) config_Free(config_struct); + int shmid = global_stats_init(); + + if (shmid < 0) { + LogEvent(COMPONENT_INIT, + "***shmget failed, key 2049, errno %d\n", shmid); + LogEvent(COMPONENT_INIT, "global stats allocated with malloc"); + } else { + LogEvent(COMPONENT_INIT, + "***shmget successful, key 2049, shmid %d\n", shmid); + } + /* Everything seems to be OK! We can now start service threads */ nfs_start(&my_nfs_start_info); + global_stats_free(); + return 0; fatal_die: diff --git a/src/include/server_stats.h b/src/include/server_stats.h index 32b2b719b3..055e9a3c0a 100644 --- a/src/include/server_stats.h +++ b/src/include/server_stats.h @@ -41,6 +41,180 @@ #include +#ifdef USE_DBUS + +struct op_name { + char *name; +}; + +/* latency stats + */ +struct op_latency { + uint64_t latency; + uint64_t min; + uint64_t max; +}; + +/* v3 ops + */ +struct nfsv3_ops { + uint64_t op[NFSPROC3_COMMIT+1]; +}; + +/* quota ops + */ +struct qta_ops { + uint64_t op[RQUOTAPROC_SETACTIVEQUOTA+1]; +}; + +/* nlm ops + */ +struct nlm_ops { + uint64_t op[NLMPROC4_FREE_ALL+1]; +}; + +/* mount ops + */ +struct mnt_ops { + uint64_t op[MOUNTPROC3_EXPORT+1]; +}; + +/* v4 ops + */ +struct nfsv4_ops { + uint64_t op[NFS4_OP_LAST_ONE]; +}; + +/* basic op counter + */ + +struct proto_op { + uint64_t total; /* total of any kind */ + uint64_t errors; /* ! NFS_OK */ + uint64_t dups; /* detected dup requests */ + struct op_latency latency; /* either executed ops latency */ + struct op_latency dup_latency; /* or latency (runtime) to replay */ + struct op_latency queue_latency; /* queue wait time */ +}; + +/* basic I/O transfer counter + */ +struct xfer_op { + struct proto_op cmd; + uint64_t requested; + uint64_t transferred; +}; + +/* pNFS Layout counters + */ + +struct layout_op { + uint64_t total; /* total ops */ + uint64_t errors; /* ! NFS4_OK && !NFS4ERR_DELAY */ + uint64_t delays; /* NFS4ERR_DELAY */ +}; + +/* NFSv3 statistics counters + */ + +struct nfsv3_stats { + struct proto_op cmds; /* non-I/O ops = cmds - (read+write) */ + struct xfer_op read; + struct xfer_op write; +}; + +/* Mount statistics counters + */ +struct mnt_stats { + struct proto_op v1_ops; + struct proto_op v3_ops; +}; + +/* lock manager counters + */ + +struct nlmv4_stats { + struct proto_op ops; +}; + +/* Quota counters + */ + +struct rquota_stats { + struct proto_op ops; + struct proto_op ext_ops; +}; + +/* NFSv4 statistics counters + */ + +struct nfsv40_stats { + struct proto_op compounds; + uint64_t ops_per_compound; /* avg = total / ops_per */ + struct xfer_op read; + struct xfer_op write; +}; + +struct nfsv41_stats { + struct proto_op compounds; + uint64_t ops_per_compound; /* for size averaging */ + struct xfer_op read; + struct xfer_op write; + struct layout_op getdevinfo; + struct layout_op layout_get; + struct layout_op layout_commit; + struct layout_op layout_return; + struct layout_op recall; +}; + +struct transport_stats { + uint64_t rx_bytes; + uint64_t rx_pkt; + uint64_t rx_err; + uint64_t tx_bytes; + uint64_t tx_pkt; + uint64_t tx_err; +}; + +#ifdef _USE_9P +struct _9p_stats { + struct proto_op cmds; /* non-I/O ops */ + struct xfer_op read; + struct xfer_op write; + struct transport_stats trans; + struct proto_op *opcodes[_9P_RWSTAT+1]; +}; +#endif + +struct global_stats { + struct nfsv3_stats nfsv3; + struct mnt_stats mnt; + struct nlmv4_stats nlm4; + struct rquota_stats rquota; + struct nfsv40_stats nfsv40; + struct nfsv41_stats nfsv41; + struct nfsv41_stats nfsv42; /* Uses v41 stats */ + struct nfsv3_ops v3; + struct nfsv4_ops v4; + struct nlm_ops lm; + struct mnt_ops mn; + struct qta_ops qt; +}; + +struct deleg_stats { + uint32_t curr_deleg_grants; /* current num of delegations owned by + this client */ + uint32_t tot_recalls; /* total num of times client was asked to + recall */ + uint32_t failed_recalls; /* times client failed to process recall */ + uint32_t num_revokes; /* Num revokes for the client */ +}; + +extern int global_stats_shmid; +extern struct global_stats *global_st; + +#endif + void server_stats_nfs_done(request_data_t *reqdata, int rc, bool dup); #ifdef _USE_9P @@ -64,5 +238,8 @@ void inc_revokes(struct gsh_client *client); void inc_recalls(struct gsh_client *client); void inc_failed_recalls(struct gsh_client *client); +int global_stats_init(void); +void global_stats_free(void); + #endif /* !SERVER_STATS_H */ /** @} */ diff --git a/src/support/CMakeLists.txt b/src/support/CMakeLists.txt index 2c9ee6f562..b4171eafd2 100644 --- a/src/support/CMakeLists.txt +++ b/src/support/CMakeLists.txt @@ -50,6 +50,19 @@ SET(support_STAT_SRCS export_mgr.c ) +SET(support_DISPLAY_STATS + display_stats.c +) + +add_executable(display_stats + ${support_DISPLAY_STATS} + ${support_STATS_SRCS} +) + +target_link_libraries(display_stats + ${DBUS_LIBRARIES} +) + if(ERROR_INJECTION) set(support_STAT_SRCS ${support_STAT_SRCS} diff --git a/src/support/display_stats.c b/src/support/display_stats.c new file mode 100644 index 0000000000..18e2c9347a --- /dev/null +++ b/src/support/display_stats.c @@ -0,0 +1,235 @@ +/* + * vim:noexpandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) Panasas Inc., 2013 + * Author: Sriram Patil (spsrirampatil@gmail.com) + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * ------------- + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "gsh_types.h" +#include "gsh_list.h" +#include "gsh_dbus.h" +#include "nfs_core.h" +#include "server_stats.h" + +typedef struct global_stats global_stats; + +const struct op_name optabv4[] = { + [0] = {.name = NULL,}, /* Illegal */ + [1] = {.name = NULL,}, /* Illegal */ + [2] = {.name = NULL,}, /* Illegal */ + [NFS4_OP_ACCESS] = {.name = "ACCESS",}, + [NFS4_OP_CLOSE] = {.name = NULL,}, + [NFS4_OP_COMMIT] = {.name = "COMMIT",}, + [NFS4_OP_CREATE] = {.name = "CREATE",}, + [NFS4_OP_DELEGPURGE] = {.name = NULL,}, + [NFS4_OP_DELEGRETURN] = {.name = NULL,}, + [NFS4_OP_GETATTR] = {.name = "GETATTR",}, + [NFS4_OP_GETFH] = {.name = NULL,}, + [NFS4_OP_LINK] = {.name = "LINK",}, + [NFS4_OP_LOCK] = {.name = "LOCK",}, + [NFS4_OP_LOCKT] = {.name = NULL,}, + [NFS4_OP_LOCKU] = {.name = NULL,}, + [NFS4_OP_LOOKUP] = {.name = "LOOKUP",}, + [NFS4_OP_LOOKUPP] = {.name = "LOOKUPP",}, + [NFS4_OP_NVERIFY] = {.name = NULL,}, + [NFS4_OP_OPEN] = {.name = "OPEN",}, + [NFS4_OP_OPENATTR] = {.name = NULL,}, + [NFS4_OP_OPEN_CONFIRM] = {.name = NULL,}, + [NFS4_OP_OPEN_DOWNGRADE] = {.name = NULL,}, + [NFS4_OP_PUTFH] = {.name = NULL,}, + [NFS4_OP_PUTPUBFH] = {.name = NULL,}, + [NFS4_OP_PUTROOTFH] = {.name = NULL,}, + [NFS4_OP_READ] = {.name = "READ",}, + [NFS4_OP_READDIR] = {.name = "READDIR",}, + [NFS4_OP_READLINK] = {.name = "READLINK",}, + [NFS4_OP_REMOVE] = {.name = "REMOVE",}, + [NFS4_OP_RENAME] = {.name = "RENAME",}, + [NFS4_OP_RENEW] = {.name = NULL,}, + [NFS4_OP_RESTOREFH] = {.name = NULL,}, + [NFS4_OP_SAVEFH] = {.name = NULL,}, + [NFS4_OP_SECINFO] = {.name = NULL,}, + [NFS4_OP_SETATTR] = {.name = "SETATTR",}, + [NFS4_OP_SETCLIENTID] = {.name = NULL,}, + [NFS4_OP_SETCLIENTID_CONFIRM] = {.name = NULL,}, + [NFS4_OP_VERIFY] = {.name = NULL,}, + [NFS4_OP_WRITE] = {.name = "WRITE",}, +}; +/* + [NFS4_OP_RELEASE_LOCKOWNER] = {.name = NULL,}, + [NFS4_OP_BACKCHANNEL_CTL] = {.name = NULL,}, + [NFS4_OP_BIND_CONN_TO_SESSION] = {.name = NULL,}, + [NFS4_OP_EXCHANGE_ID] = {.name = NULL,}, + [NFS4_OP_CREATE_SESSION] = {.name = NULL,}, + [NFS4_OP_DESTROY_SESSION] = {.name = "DESTROY_SESSION",}, + [NFS4_OP_FREE_STATEID] = {.name = "FREE_STATEID",}, + [NFS4_OP_GET_DIR_DELEGATION] = {.name = "GET_DIR_DELEGATION",}, + [NFS4_OP_GETDEVICEINFO] = {.name = "GETDEVICEINFO",}, + [NFS4_OP_GETDEVICELIST] = {.name = "GETDEVICELIST",}, + [NFS4_OP_LAYOUTCOMMIT] = {.name = "LAYOUTCOMMIT",}, + [NFS4_OP_LAYOUTGET] = {.name = "LAYOUTGET",}, + [NFS4_OP_LAYOUTRETURN] = {.name = "LAYOUTRETURN",}, + [NFS4_OP_SECINFO_NO_NAME] = {.name = "SECINFO_NO_NAME",}, + [NFS4_OP_SEQUENCE] = {.name = "SEQUENCE",}, + [NFS4_OP_SET_SSV] = {.name = "SET_SSV",}, + [NFS4_OP_TEST_STATEID] = {.name = "TEST_STATEID",}, + [NFS4_OP_WANT_DELEGATION] = {.name = "WANT_DELEGATION",}, + [NFS4_OP_DESTROY_CLIENTID] = {.name = "DESTROY_CLIENTID",}, + [NFS4_OP_RECLAIM_COMPLETE] = {.name = "RECLAIM_COMPLETE",}, +//NFSv4.2 +[NFS4_OP_ALLOCATE] = {.name = "ALLOCATE",}, +[NFS4_OP_COPY] = {.name = "COPY",}, +[NFS4_OP_COPY_NOTIFY] = {.name = "COPY_NOTIFY",}, +[NFS4_OP_DEALLOCATE] = {.name = "DEALLOCATE",}, +[NFS4_OP_IO_ADVISE] = {.name = "IO_ADVISE",}, +[NFS4_OP_LAYOUTERROR] = {.name = "LAYOUTERROR",}, +[NFS4_OP_OFFLOAD_CANCEL] = {.name = "OFFLOAD_CANCEL",}, +[NFS4_OP_OFFLOAD_STATUS] = {.name = "OFFLOAD_STATUS",}, +[NFS4_OP_READ_PLUS] = {.name = "READ_PLUS",}, +[NFS4_OP_SEEK] = {.name = "SEEK",}, +[NFS4_OP_WRITE_SAME] = {.name = "WRITE_SAME",}, +}; + */ + +static void print_header(int count) +{ + int i; + + for (i = 0; i < count; ++i) { + if (optabv4[i].name != NULL + && (i != NFS4_OP_READ && i != NFS4_OP_WRITE)) { + fprintf(stdout, "%-10s", optabv4[i].name); + } + } + + fprintf(stdout, "%-10s%-10s\n", optabv4[NFS4_OP_READ].name, + optabv4[NFS4_OP_WRITE].name); +} + +static inline void copy_stats(global_stats *src, global_stats *dest) +{ + memcpy(dest, src, sizeof(global_stats)); +} + +void do_diffs(global_stats *curr, global_stats *prev, global_stats *diff, + int opcount) +{ + int i; + + for (i = 0; i < opcount; i++) { + if (optabv4[i].name != NULL) + diff->v4.op[i] = curr->v4.op[i] - prev->v4.op[i]; + } + + diff->nfsv40.read.requested = curr->nfsv40.read.requested + - prev->nfsv40.read.requested; + diff->nfsv40.read.transferred = curr->nfsv40.read.transferred + - prev->nfsv40.read.transferred; + diff->nfsv40.write.requested = curr->nfsv40.write.requested + - prev->nfsv40.write.requested; + diff->nfsv40.write.transferred = curr->nfsv40.write.transferred + - prev->nfsv40.write.transferred; +} + +static void print_stats(global_stats *st, int opcount) +{ + int i; + + for (i = 0; i < opcount; i++) { + if (optabv4[i].name != NULL + && (i != NFS4_OP_READ && i != NFS4_OP_WRITE)) { + fprintf(stdout, "%-10lu", st->v4.op[i]); + } + } + + fprintf(stdout, "%-4lu %-5lu", st->v4.op[NFS4_OP_READ], + (st->nfsv40.read.transferred >> 20)); + fprintf(stdout, "%-4lu %-5lu\n", st->v4.op[NFS4_OP_WRITE], + (st->nfsv40.write.transferred >> 20)); +} + +static void dump_stats(global_stats *shm_stats, int opcount) +{ + global_stats prev, curr, diff; + int j = 0; + + memset(&prev, 0, sizeof(global_stats)); + memset(&curr, 0, sizeof(global_stats)); + memset(&diff, 0, sizeof(global_stats)); + + copy_stats(shm_stats, &curr); + + while (1) { + if (j % 10 == 0) { + fprintf(stdout, "\n"); + print_header(opcount); + } + + sleep(1); + + copy_stats(&curr, &prev); + + /* The stats will be updated by ganesha in the shm */ + copy_stats(shm_stats, &curr); + do_diffs(&curr, &prev, &diff, opcount); + print_stats(&diff, opcount); + + j++; + } +} + +int main(int argc, char *argv[]) +{ + int key = 2049, err, count; + void *addr = NULL; + size_t size = sizeof(global_stats); + global_stats *st = NULL; + int shmid = shmget(key, size, 0); + + if (shmid < 0) { + err = errno; + fprintf(stderr, "***shmget failed, key %d, errno %d\n", key, + err); + return err; + } + + /* attach it now. */ + addr = shmat(shmid, 0, 0); + if (addr == (void *) -1) { + err = errno; + fprintf(stderr, "shmat: could not attach, errno %d\n", errno); + return err; + } + + count = sizeof(optabv4) / sizeof(struct op_name); + st = (global_stats *)addr; + + dump_stats(st, count); + shmdt(addr); + return 0; +} diff --git a/src/support/server_stats.c b/src/support/server_stats.c index bb883c6b52..7a7b69c09c 100644 --- a/src/support/server_stats.c +++ b/src/support/server_stats.c @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include "fsal.h" #include "nfs_core.h" #include "log.h" @@ -74,10 +76,6 @@ #ifdef USE_DBUS -struct op_name { - char *name; -}; - static const struct op_name optqta[] = { [RQUOTAPROC_GETQUOTA] = {.name = "GETQUOTA", }, [RQUOTAPROC_GETACTIVEQUOTA] = {.name = "GETACTIVEQUOTA", }, @@ -143,7 +141,7 @@ static const struct op_name optabv3[] = { [NFSPROC3_COMMIT] = {.name = "COMMIT", }, }; -static const struct op_name optabv4[] = { +const struct op_name optabv4[] = { [0] = {.name = "ILLEGAL", }, [1] = {.name = "ILLEGAL",}, [2] = {.name = "ILLEGAL",}, @@ -261,170 +259,8 @@ static const uint32_t nfsv42_optype[NFS_V42_NB_OPERATION] = { [NFS4_OP_READ_PLUS] = READ_OP, }; -/* latency stats - */ -struct op_latency { - uint64_t latency; - uint64_t min; - uint64_t max; -}; - -/* v3 ops - */ -struct nfsv3_ops { - uint64_t op[NFSPROC3_COMMIT+1]; -}; - -/* quota ops - */ -struct qta_ops { - uint64_t op[RQUOTAPROC_SETACTIVEQUOTA+1]; -}; - -/* nlm ops - */ -struct nlm_ops { - uint64_t op[NLMPROC4_FREE_ALL+1]; -}; - -/* mount ops - */ -struct mnt_ops { - uint64_t op[MOUNTPROC3_EXPORT+1]; -}; - -/* v4 ops - */ -struct nfsv4_ops { - uint64_t op[NFS4_OP_LAST_ONE]; -}; - -/* basic op counter - */ - -struct proto_op { - uint64_t total; /* total of any kind */ - uint64_t errors; /* ! NFS_OK */ - uint64_t dups; /* detected dup requests */ - struct op_latency latency; /* either executed ops latency */ - struct op_latency dup_latency; /* or latency (runtime) to replay */ - struct op_latency queue_latency; /* queue wait time */ -}; - -/* basic I/O transfer counter - */ -struct xfer_op { - struct proto_op cmd; - uint64_t requested; - uint64_t transferred; -}; - -/* pNFS Layout counters - */ - -struct layout_op { - uint64_t total; /* total ops */ - uint64_t errors; /* ! NFS4_OK && !NFS4ERR_DELAY */ - uint64_t delays; /* NFS4ERR_DELAY */ -}; - -/* NFSv3 statistics counters - */ - -struct nfsv3_stats { - struct proto_op cmds; /* non-I/O ops = cmds - (read+write) */ - struct xfer_op read; - struct xfer_op write; -}; - -/* Mount statistics counters - */ -struct mnt_stats { - struct proto_op v1_ops; - struct proto_op v3_ops; -}; - -/* lock manager counters - */ - -struct nlmv4_stats { - struct proto_op ops; -}; - -/* Quota counters - */ - -struct rquota_stats { - struct proto_op ops; - struct proto_op ext_ops; -}; - -/* NFSv4 statistics counters - */ - -struct nfsv40_stats { - struct proto_op compounds; - uint64_t ops_per_compound; /* avg = total / ops_per */ - struct xfer_op read; - struct xfer_op write; -}; - -struct nfsv41_stats { - struct proto_op compounds; - uint64_t ops_per_compound; /* for size averaging */ - struct xfer_op read; - struct xfer_op write; - struct layout_op getdevinfo; - struct layout_op layout_get; - struct layout_op layout_commit; - struct layout_op layout_return; - struct layout_op recall; -}; - -struct transport_stats { - uint64_t rx_bytes; - uint64_t rx_pkt; - uint64_t rx_err; - uint64_t tx_bytes; - uint64_t tx_pkt; - uint64_t tx_err; -}; - -#ifdef _USE_9P -struct _9p_stats { - struct proto_op cmds; /* non-I/O ops */ - struct xfer_op read; - struct xfer_op write; - struct transport_stats trans; - struct proto_op *opcodes[_9P_RWSTAT+1]; -}; -#endif - -struct global_stats { - struct nfsv3_stats nfsv3; - struct mnt_stats mnt; - struct nlmv4_stats nlm4; - struct rquota_stats rquota; - struct nfsv40_stats nfsv40; - struct nfsv41_stats nfsv41; - struct nfsv41_stats nfsv42; /* Uses v41 stats */ - struct nfsv3_ops v3; - struct nfsv4_ops v4; - struct nlm_ops lm; - struct mnt_ops mn; - struct qta_ops qt; -}; - -struct deleg_stats { - uint32_t curr_deleg_grants; /* current num of delegations owned by - this client */ - uint32_t tot_recalls; /* total num of times client was asked to - recall */ - uint32_t failed_recalls; /* times client failed to process recall */ - uint32_t num_revokes; /* Num revokes for the client */ -}; - -static struct global_stats global_st; +int global_stats_shmid = 0; +struct global_stats *global_st = NULL; struct cache_stats cache_st; struct cache_stats *cache_stp = &cache_st; @@ -621,6 +457,48 @@ static void record_io(struct xfer_op *iop, size_t requested, size_t transferred, * @brief record i/o stats by protocol */ +static void record_global_io_stats(size_t requested, size_t transferred, + bool success, bool is_write) +{ + struct xfer_op *iop = NULL; + + if (op_ctx->req_type == NFS_REQUEST) { + if (op_ctx->nfs_vers == NFS_V3) { + struct nfsv3_stats *sp = &global_st->nfsv3; + + if (sp == NULL) + return; + iop = is_write ? &sp->write : &sp->read; + } else if (op_ctx->nfs_vers == NFS_V4) { + if (op_ctx->nfs_minorvers == 0) { + struct nfsv40_stats *sp = &global_st->nfsv40; + + if (sp == NULL) + return; + iop = is_write ? &sp->write : &sp->read; + } else if (op_ctx->nfs_minorvers == 1) { + struct nfsv41_stats *sp = &global_st->nfsv41; + + if (sp == NULL) + return; + iop = is_write ? &sp->write : &sp->read; + } else if (op_ctx->nfs_minorvers == 2) { + struct nfsv41_stats *sp = &global_st->nfsv42; + + if (sp == NULL) + return; + iop = is_write ? &sp->write : &sp->read; + } + /* the frightening thought is someday minor == 3 */ + } else { + return; + } + } else { + return; + } + record_io(iop, requested, transferred, success); +} + static void record_io_stats(struct gsh_stats *gsh_st, pthread_rwlock_t *lock, size_t requested, size_t transferred, bool success, bool is_write) @@ -880,7 +758,7 @@ static void record_stats(struct gsh_stats *gsh_st, pthread_rwlock_t *lock, return; /* record stuff */ if (global) - record_op(&global_st.nfsv3.cmds, request_time, + record_op(&global_st->nfsv3.cmds, request_time, qwait_time, success, dup); switch (nfsv3_optype[proto_op]) { case READ_OP: @@ -903,10 +781,10 @@ static void record_stats(struct gsh_stats *gsh_st, pthread_rwlock_t *lock, struct mnt_stats *sp = get_mnt(gsh_st, lock); if (global && req->rq_vers == MOUNT_V1) - record_op(&global_st.mnt.v1_ops, request_time, + record_op(&global_st->mnt.v1_ops, request_time, qwait_time, success, dup); else if (global) - record_op(&global_st.mnt.v3_ops, request_time, + record_op(&global_st->mnt.v3_ops, request_time, qwait_time, success, dup); if (sp == NULL) @@ -922,7 +800,7 @@ static void record_stats(struct gsh_stats *gsh_st, pthread_rwlock_t *lock, struct nlmv4_stats *sp = get_nlm4(gsh_st, lock); if (global) - record_op(&global_st.nlm4.ops, request_time, + record_op(&global_st->nlm4.ops, request_time, qwait_time, success, dup); if (sp == NULL) return; @@ -932,7 +810,7 @@ static void record_stats(struct gsh_stats *gsh_st, pthread_rwlock_t *lock, struct rquota_stats *sp = get_rquota(gsh_st, lock); if (global) - record_op(&global_st.rquota.ops, request_time, + record_op(&global_st->rquota.ops, request_time, qwait_time, success, dup); if (sp == NULL) return; @@ -1048,13 +926,13 @@ void server_stats_nfs_done(request_data_t *reqdata, int rc, bool dup) uint32_t proto_op = req->rq_proc; if (req->rq_prog == NFS_PROGRAM && op_ctx->nfs_vers == NFS_V3) - global_st.v3.op[proto_op]++; + global_st->v3.op[proto_op]++; else if (req->rq_prog == nfs_param.core_param.program[P_NLM]) - global_st.lm.op[proto_op]++; + global_st->lm.op[proto_op]++; else if (req->rq_prog == nfs_param.core_param.program[P_MNT]) - global_st.mn.op[proto_op]++; + global_st->mn.op[proto_op]++; else if (req->rq_prog == nfs_param.core_param.program[P_RQUOTA]) - global_st.qt.op[proto_op]++; + global_st->qt.op[proto_op]++; if (nfs_param.core_param.enable_FASTSTATS) return; @@ -1098,7 +976,7 @@ void server_stats_nfsv4_op_done(int proto_op, nsecs_elapsed_t stop_time; if (op_ctx->nfs_vers == NFS_V4) - global_st.v4.op[proto_op]++; + global_st->v4.op[proto_op]++; if (nfs_param.core_param.enable_FASTSTATS) return; @@ -1117,13 +995,13 @@ void server_stats_nfsv4_op_done(int proto_op, } if (op_ctx->nfs_minorvers == 0) - record_op(&global_st.nfsv40.compounds, stop_time - start_time, + record_op(&global_st->nfsv40.compounds, stop_time - start_time, op_ctx->queue_wait, status == NFS4_OK, false); else if (op_ctx->nfs_minorvers == 1) - record_op(&global_st.nfsv41.compounds, stop_time - start_time, + record_op(&global_st->nfsv41.compounds, stop_time - start_time, op_ctx->queue_wait, status == NFS4_OK, false); else if (op_ctx->nfs_minorvers == 2) - record_op(&global_st.nfsv42.compounds, stop_time - start_time, + record_op(&global_st->nfsv42.compounds, stop_time - start_time, op_ctx->queue_wait, status == NFS4_OK, false); if (op_ctx->export != NULL) { @@ -1187,6 +1065,8 @@ void server_stats_compound_done(int num_ops, int status) void server_stats_io_done(size_t requested, size_t transferred, bool success, bool is_write) { + record_global_io_stats(requested, transferred, success, is_write); + if (op_ctx->client != NULL) { struct server_stats *server_st; @@ -1473,42 +1353,42 @@ void global_dbus_total(DBusMessageIter *iter) dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.nfsv3.cmds.total); + &global_st->nfsv3.cmds.total); version = "NFSv40"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.nfsv40.compounds.total); + &global_st->nfsv40.compounds.total); version = "NFSv41"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.nfsv41.compounds.total); + &global_st->nfsv41.compounds.total); version = "NFSv42"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.nfsv42.compounds.total); + &global_st->nfsv42.compounds.total); version = "NLM4"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.nlm4.ops.total); + &global_st->nlm4.ops.total); version = "MNTv1"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.mnt.v1_ops.total); + &global_st->mnt.v1_ops.total); version = "MNTv3"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.mnt.v3_ops.total); + &global_st->mnt.v3_ops.total); version = "RQUOTA"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, - &global_st.rquota.ops.total); + &global_st->rquota.ops.total); dbus_message_iter_close_container(iter, &struct_iter); } @@ -1526,60 +1406,60 @@ void global_dbus_fast(DBusMessageIter *iter) dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); for (i = 0; i < NFSPROC3_COMMIT; i++) { - if (global_st.v3.op[i] > 0) { + if (global_st->v3.op[i] > 0) { op = optabv3[i].name; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &op); dbus_message_iter_append_basic(&struct_iter, - DBUS_TYPE_UINT64, &global_st.v3.op[i]); + DBUS_TYPE_UINT64, &global_st->v3.op[i]); } } version = "\nNFSv4:"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); for (i = 0; i < NFS4_OP_LAST_ONE; i++) { - if (global_st.v4.op[i] > 0) { + if (global_st->v4.op[i] > 0) { op = optabv4[i].name; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &op); dbus_message_iter_append_basic(&struct_iter, - DBUS_TYPE_UINT64, &global_st.v4.op[i]); + DBUS_TYPE_UINT64, &global_st->v4.op[i]); } } version = "\nNLM:"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); for (i = 0; i < NLM4_FAILED; i++) { - if (global_st.lm.op[i] > 0) { + if (global_st->lm.op[i] > 0) { op = optnlm[i].name; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &op); dbus_message_iter_append_basic(&struct_iter, - DBUS_TYPE_UINT64, &global_st.lm.op[i]); + DBUS_TYPE_UINT64, &global_st->lm.op[i]); } } version = "\nMNT:"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); for (i = 0; i < MOUNTPROC3_EXPORT; i++) { - if (global_st.mn.op[i] > 0) { + if (global_st->mn.op[i] > 0) { op = optmnt[i].name; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &op); dbus_message_iter_append_basic(&struct_iter, - DBUS_TYPE_UINT64, &global_st.mn.op[i]); + DBUS_TYPE_UINT64, &global_st->mn.op[i]); } } version = "\nQUOTA:"; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &version); for (i = 0; i < RQUOTAPROC_SETACTIVEQUOTA; i++) { - if (global_st.qt.op[i] > 0) { + if (global_st->qt.op[i] > 0) { op = optqta[i].name; dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &op); dbus_message_iter_append_basic(&struct_iter, - DBUS_TYPE_UINT64, &global_st.qt.op[i]); + DBUS_TYPE_UINT64, &global_st->qt.op[i]); } } dbus_message_iter_close_container(iter, &struct_iter); @@ -1933,4 +1813,46 @@ void server_stats_free(struct gsh_stats *statsp) #endif } +int global_stats_init(void) +{ + int err = 0; + const int key = 2049; + void *addr = NULL; + size_t size = sizeof(struct global_stats); + + global_stats_shmid = shmget(key, size, IPC_CREAT | 0644); + if (global_stats_shmid < 0) { + /* already present, remove and reattach */ + global_stats_shmid = shmget(key, size, IPC_CREAT); + if (global_stats_shmid < 0) { + err = errno; + global_st = (struct global_stats *) + gsh_calloc(sizeof(struct global_stats), 1); + return err; + } + } + + /* attach it now. */ + addr = shmat(global_stats_shmid, 0, 0); + if (addr == (void *) -1) { + err = errno; + shmctl(global_stats_shmid, IPC_RMID, 0); + return err; + } + + global_st = (struct global_stats *)addr; + memset(global_st, 0, sizeof(struct global_stats)); + return global_stats_shmid; +} + +void global_stats_free(void) +{ + if (global_stats_shmid < 0) { + gsh_free(global_st); + } else { + shmdt(global_st); + shmctl(global_stats_shmid, IPC_RMID, 0); + } +} + /** @} */