diff options
Diffstat (limited to 'src/pmdas/gfs2/ftrace.c')
-rw-r--r-- | src/pmdas/gfs2/ftrace.c | 586 |
1 files changed, 586 insertions, 0 deletions
diff --git a/src/pmdas/gfs2/ftrace.c b/src/pmdas/gfs2/ftrace.c new file mode 100644 index 0000000..6485c00 --- /dev/null +++ b/src/pmdas/gfs2/ftrace.c @@ -0,0 +1,586 @@ +/* + * GFS2 ftrace based trace-point metrics. + * + * Copyright (c) 2013 - 2014 Red Hat. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 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 General Public License + * for more details. + */ + +#include "pmapi.h" +#include "impl.h" +#include "pmda.h" + +#include "pmdagfs2.h" +#include "ftrace.h" +#include "worst_glock.h" +#include "latency.h" + +#include <fcntl.h> +#include <string.h> +#include <inttypes.h> +#include <sys/sysmacros.h> +#include <sys/types.h> + + +static char *TRACE_PIPE = "/sys/kernel/debug/tracing/trace_pipe"; +static int max_glock_throughput = INITIAL_GLOBAL_MAX_GLOCK_THROUGHPUT; + +static struct ftrace_data ftrace_data; +static int num_accepted_entries; + +/* + * Fetches the value for the given metric item and then assigns to pmAtomValue. + * We check to see if item is in valid range for the metric. + */ +int +gfs2_ftrace_fetch(int item, struct ftrace *ftrace, pmAtomValue *atom) +{ + /* Ensure that metric value wanted is valid */ + if ((item < 0 || item >= NUM_TRACEPOINT_STATS)) + return PM_ERR_PMID; + + atom->ull = ftrace->values[item]; + return 1; +} + +/* + * External function to allow the increment of the num_accepted_locks + * variable from pmStore. + */ +void +ftrace_increase_num_accepted_entries(){ + num_accepted_entries++; +} + +/* + * Sets the value of max_glock_throughput using pmstore, value should + * must be positive. + */ +int +ftrace_set_threshold(pmValueSet *vsp) +{ + int value = vsp->vlist[0].value.lval; + + if (value < 0) /* Ensure positive value */ + return PM_ERR_SIGN; + + max_glock_throughput = value; + + return 0; +} + +/* + * Returns the max number of glocks we allow per run through the trace_pipe, + * Used by the fetch for the control metrics. + */ +int +ftrace_get_threshold() +{ + return max_glock_throughput; +} + +/* + * We open the ftrace trace file in write mode and straight after + * close it. This acts as a way to completely clear the trace ring- + * buffer when needed. + */ +static int +ftrace_clear_buffer() +{ + char *TRACE = "/sys/kernel/debug/tracing/trace"; + FILE *fp; + + /* Open in write mode and then straight close will purge buffer contents */ + if (( fp = fopen(TRACE, "w")) == NULL ) + return -oserror(); + + fclose(fp); + + return 0; +} + +/* + * We take tracedata from the trace pipe and store only the data which is + * from GFS2 metrics. We collect all the data in one array to be worked + * through later, this is because all trace data comes through the + * trace pipe mixed. + */ +static int +gfs2_extract_trace_values(char *buffer, pmInDom gfs_fs_indom) +{ + struct ftrace_data temp; + + unsigned int major, minor; + char *data; + + /* Interpret data, we work out what tracepoint it belongs to first */ + if ((data = strstr(buffer, "gfs2_glock_state_change: "))) { + temp.tracepoint = GLOCK_STATE_CHANGE; + sscanf(data, "gfs2_glock_state_change: %"SCNu32",%"SCNu32"", &major, &minor); + + /* + * Pass tracepoint data over for latency metrics for processing, + * only if the metrics are enabled. + */ + if (latency_get_state() == 1) + gfs2_extract_latency(major, minor, temp.tracepoint, buffer, gfs_fs_indom); + + } else if ((data = strstr(buffer, "gfs2_glock_put: "))) { + temp.tracepoint = GLOCK_PUT; + sscanf(data, "gfs2_glock_put: %"SCNu32",%"SCNu32"", &major, &minor); + + } else if ((data = strstr(buffer, "gfs2_demote_rq: "))) { + temp.tracepoint = DEMOTE_RQ; + sscanf(data, "gfs2_demote_rq: %"SCNu32",%"SCNu32"", &major, &minor); + + /* + * Pass tracepoint data over for latency metrics for processing, + * only if the metrics are enabled. + */ + if (latency_get_state() == 1) + gfs2_extract_latency(major, minor, temp.tracepoint, buffer, gfs_fs_indom); + + } else if ((data = strstr(buffer, "gfs2_promote: "))) { + temp.tracepoint = PROMOTE; + sscanf(data, "gfs2_promote: %"SCNu32",%"SCNu32"", &major, &minor); + + } else if ((data = strstr(buffer, "gfs2_glock_queue: "))) { + temp.tracepoint = GLOCK_QUEUE; + sscanf(data, "gfs2_glock_queue: %"SCNu32",%"SCNu32"", &major, &minor); + + /* + * Pass tracepoint data over for latency metrics for processing, + * only if the metrics are enabled. + */ + if (latency_get_state() == 1) + gfs2_extract_latency(major, minor, temp.tracepoint, buffer, gfs_fs_indom); + + } else if ((data = strstr(buffer, "gfs2_glock_lock_time: "))) { + temp.tracepoint = GLOCK_LOCK_TIME; + sscanf(data, "gfs2_glock_lock_time: %"SCNu32",%"SCNu32"", &major, &minor); + + /* + * Pass tracepoint data over for worst_glock metrics for processing, + * only if the metrics are enabled. + */ + if (worst_glock_get_state() == 1) + gfs2_extract_worst_glock(&data, gfs_fs_indom); + + } else if ((data = strstr(buffer, "gfs2_pin: "))) { + temp.tracepoint = PIN; + sscanf(data, "gfs2_pin: %"SCNu32",%"SCNu32"", &major, &minor); + + } else if ((data = strstr(buffer, "gfs2_log_flush: "))) { + temp.tracepoint = LOG_FLUSH; + sscanf(data, "gfs2_log_flush: %"SCNu32",%"SCNu32"", &major, &minor); + + } else if ((data = strstr(buffer, "gfs2_log_blocks: "))) { + temp.tracepoint = LOG_BLOCKS; + sscanf(data, "gfs2_log_blocks: %"SCNu32",%"SCNu32"", &major, &minor); + + } else if ((data = strstr(buffer, "gfs2_ail_flush: "))) { + temp.tracepoint = AIL_FLUSH; + sscanf(data, "gfs2_ail_flush: %"SCNu32",%"SCNu32"", &major, &minor); + + } else if ((data = strstr(buffer, "gfs2_block_alloc: "))) { + temp.tracepoint = BLOCK_ALLOC; + sscanf(data, "gfs2_block_alloc: %"SCNu32",%"SCNu32" %s", &major, &minor, data); + + } else if ((data = strstr(buffer, "gfs2_bmap: "))) { + temp.tracepoint = BMAP; + sscanf(data, "gfs2_bmap: %"SCNu32",%"SCNu32"", &major, &minor); + + } else if ((data = strstr(buffer, "gfs2_rs: "))) { + temp.tracepoint = RS; + sscanf(data, "gfs2_rs: %"SCNu32",%"SCNu32" %s", &major, &minor, data); + } else { + return 0; /* If we do not have matching data, return and continue */ + } + + temp.dev_id = makedev(major, minor); + strncpy(temp.data, data, sizeof(temp.data)-1); + + /* Assign data in the array and update counters */ + ftrace_data = temp; + num_accepted_entries++; + + return 0; +} + +/* + * We work though each mounted filesystem and update the metric data based + * off what tracepoint information we have collected from the trace pipe. + */ +static void +gfs2_assign_ftrace(pmInDom gfs2_fs_indom, int reset_flag) +{ + int i, j, sts; + struct gfs2_fs *fs; + + /* We walk through for each filesystem */ + for (pmdaCacheOp(gfs2_fs_indom, PMDA_CACHE_WALK_REWIND);;) { + if ((i = pmdaCacheOp(gfs2_fs_indom, PMDA_CACHE_WALK_NEXT)) < 0) + break; + sts = pmdaCacheLookup(gfs2_fs_indom, i, NULL, (void **)&fs); + if (sts != PMDA_CACHE_ACTIVE) + continue; + + if(reset_flag == 1){ + for (j = 0; j < NUM_TRACEPOINT_STATS; j++) { + /* Reset old metric data for all tracepoints */ + fs->ftrace.values[j] = 0; + reset_flag = 0; + } + } + + if (fs->dev_id == ftrace_data.dev_id) { + + /* Work through the data, increasing metric counters */ + if (ftrace_data.tracepoint == GLOCK_STATE_CHANGE) { + char state[3], target[3]; + + sscanf(ftrace_data.data, + "gfs2_glock_state_change: %*d,%*d glock %*d:%*d state %*s to %s tgt:%s dmt:%*s flags:%*s", + state, target + ); + + if (strncmp(state, "NL", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKSTATE_NULLLOCK]++; + } else if (strncmp(state, "CR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKSTATE_CONCURRENTREAD]++; + } else if (strncmp(state, "CW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKSTATE_CONCURRENTWRITE]++; + } else if (strncmp(state, "PR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKSTATE_PROTECTEDREAD]++; + } else if (strncmp(state, "PW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKSTATE_PROTECTEDWRITE]++; + } else if (strncmp(state, "EX", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKSTATE_EXCLUSIVE]++; + } + fs->ftrace.values[FTRACE_GLOCKSTATE_TOTAL]++; + + if (strncmp(state, target, 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKSTATE_GLOCK_CHANGEDTARGET]++; + } else { + fs->ftrace.values[FTRACE_GLOCKSTATE_GLOCK_MISSEDTARGET]++; + } + + } else if (ftrace_data.tracepoint == GLOCK_PUT) { + char state[3]; + + sscanf(ftrace_data.data, + "gfs2_glock_put: %*d,%*d glock %*d:%*d state %*s => %s flags:%*s", + state + ); + + if (strncmp(state, "NL", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKPUT_NULLLOCK]++; + } else if (strncmp(state, "CR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKPUT_CONCURRENTREAD]++; + } else if (strncmp(state, "CW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKPUT_CONCURRENTWRITE]++; + } else if (strncmp(state, "PR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKPUT_PROTECTEDREAD]++; + } else if (strncmp(state, "PW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKPUT_PROTECTEDWRITE]++; + } else if (strncmp(state, "EX", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKPUT_EXCLUSIVE]++; + } + fs->ftrace.values[FTRACE_GLOCKPUT_TOTAL]++; + + } else if (ftrace_data.tracepoint == DEMOTE_RQ) { + char state[3], remote[7]; + + sscanf(ftrace_data.data, + "gfs2_demote_rq: %*d,%*d glock %*d:%*d demote %*s to %s flags:%*s %s", + state, remote + ); + + if (strncmp(state, "NL", 2) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_NULLLOCK]++; + } else if (strncmp(state, "CR", 2) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_CONCURRENTREAD]++; + } else if (strncmp(state, "CW", 2) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_CONCURRENTWRITE]++; + } else if (strncmp(state, "PR", 2) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_PROTECTEDREAD]++; + } else if (strncmp(state, "PW", 2) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_PROTECTEDWRITE]++; + } else if (strncmp(state, "EX", 2) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_EXCLUSIVE]++; + } + fs->ftrace.values[FTRACE_DEMOTERQ_TOTAL]++; + + if (strncmp(remote, "remote", 6) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_REQUESTED_REMOTE]++; + } else if (strncmp(remote, "local", 6) == 0) { + fs->ftrace.values[FTRACE_DEMOTERQ_REQUESTED_LOCAL]++; + } + + } else if (ftrace_data.tracepoint == PROMOTE) { + char state[3], first[6]; + + sscanf(ftrace_data.data, + "gfs2_promote: %*d,%*d glock %*d:%*d promote %s %s", + first, state + ); + + if (strncmp(first, "first", 5) == 0) { + if (strncmp(state, "NL", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_FIRST_NULLLOCK]++; + } else if (strncmp(state, "CR", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_FIRST_CONCURRENTREAD]++; + } else if (strncmp(state, "CW", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_FIRST_CONCURRENTWRITE]++; + } else if (strncmp(state, "PR", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_FIRST_PROTECTEDREAD]++; + } else if (strncmp(state, "PW", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_FIRST_PROTECTEDWRITE]++; + } else if (strncmp(state, "EX", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_FIRST_EXCLUSIVE]++; + } + } else if (strncmp(first, "other", 5) == 0) { + if (strncmp(state, "NL", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_OTHER_NULLLOCK]++; + } else if (strncmp(state, "CR", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_OTHER_CONCURRENTREAD]++; + } else if (strncmp(state, "CW", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_OTHER_CONCURRENTWRITE]++; + } else if (strncmp(state, "PR", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_OTHER_PROTECTEDREAD]++; + } else if (strncmp(state, "PW", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_OTHER_PROTECTEDWRITE]++; + } else if (strncmp(state, "EX", 2) == 0) { + fs->ftrace.values[FTRACE_PROMOTE_OTHER_EXCLUSIVE]++; + } + } + fs->ftrace.values[FTRACE_PROMOTE_TOTAL]++; + + } else if (ftrace_data.tracepoint == GLOCK_QUEUE) { + char state[3], queue[8]; + + sscanf(ftrace_data.data, + "gfs2_glock_queue: %*d,%*d glock %*d:%*d %s %s", + queue, state + ); + + if (strncmp(queue, "queue", 6) == 0) { + if (strncmp(state, "NL", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_QUEUE_NULLLOCK]++; + } else if (strncmp(state, "CR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_QUEUE_CONCURRENTREAD]++; + } else if (strncmp(state, "CW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_QUEUE_CONCURRENTWRITE]++; + } else if (strncmp(state, "PR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_QUEUE_PROTECTEDREAD]++; + } else if (strncmp(state, "PW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_QUEUE_PROTECTEDWRITE]++; + } else if (strncmp(state, "EX", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_QUEUE_EXCLUSIVE]++; + } + fs->ftrace.values[FTRACE_GLOCKQUEUE_QUEUE_TOTAL]++; + + } else if (strncmp(queue, "dequeue", 8) == 0) { + if (strncmp(state, "NL", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_DEQUEUE_NULLLOCK]++; + } else if (strncmp(state, "CR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_DEQUEUE_CONCURRENTREAD]++; + } else if (strncmp(state, "CW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_DEQUEUE_CONCURRENTWRITE]++; + } else if (strncmp(state, "PR", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_DEQUEUE_PROTECTEDREAD]++; + } else if (strncmp(state, "PW", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_DEQUEUE_PROTECTEDWRITE]++; + } else if (strncmp(state, "EX", 2) == 0) { + fs->ftrace.values[FTRACE_GLOCKQUEUE_DEQUEUE_EXCLUSIVE]++; + } + fs->ftrace.values[FTRACE_GLOCKQUEUE_DEQUEUE_TOTAL]++; + } + fs->ftrace.values[FTRACE_GLOCKQUEUE_TOTAL]++; + + } else if (ftrace_data.tracepoint == GLOCK_LOCK_TIME) { + uint32_t lock_type; + + sscanf(ftrace_data.data, + "gfs2_glock_lock_time: %*d,%*d glock %"SCNu32":%*d status:%*d flags:%*x tdiff:%*d srtt:%*d/%*d srttb:%*d/%*d sirt:%*d/%*d dcnt:%*d qcnt:%*d", + &lock_type + ); + + if (lock_type == 1) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_TRANS]++; + } else if (lock_type == 2) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_INDOE]++; + } else if (lock_type == 3) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_RGRP]++; + } else if (lock_type == 4) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_META]++; + } else if (lock_type == 5) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_IOPEN]++; + } else if (lock_type == 6) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_FLOCK]++; + } else if (lock_type == 8) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_QUOTA]++; + } else if (lock_type == 9) { + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_JOURNAL]++; + } + fs->ftrace.values[FTRACE_GLOCKLOCKTIME_TOTAL]++; + + } else if (ftrace_data.tracepoint == PIN) { + char pinned[6]; + uint32_t length; + + sscanf(ftrace_data.data, + "gfs2_pin: %*d,%*d log %s %*d/%"SCNu32" inode: %*d", + pinned, &length + ); + + if (strncmp(pinned, "pin", 5) == 0) { + fs->ftrace.values[FTRACE_PIN_PINTOTAL]++; + } else if (strncmp(pinned, "unpin", 5) == 0) { + fs->ftrace.values[FTRACE_PIN_UNPINTOTAL]++; + } + fs->ftrace.values[FTRACE_PIN_TOTAL]++; + + if(fs->ftrace.values[FTRACE_PIN_LONGESTPINNED] < length) + fs->ftrace.values[FTRACE_PIN_LONGESTPINNED] = length; + + } else if (ftrace_data.tracepoint == LOG_FLUSH) { + char end[6]; + + sscanf(ftrace_data.data, + "gfs2_log_flush: %*d,%*d log flush %s %*u", + end + ); + + if (strncmp(end, "end", 6) == 0) + fs->ftrace.values[FTRACE_LOGFLUSH_TOTAL]++; + + } else if (ftrace_data.tracepoint == LOG_BLOCKS) { + + fs->ftrace.values[FTRACE_LOGBLOCKS_TOTAL]++; + + } else if (ftrace_data.tracepoint == AIL_FLUSH) { + char end[6]; + + sscanf(ftrace_data.data, + "gfs2_ail_flush: %*d,%*d ail flush %s %*s %*u", + end + ); + + if (strncmp(end, "end", 6) == 0) + fs->ftrace.values[FTRACE_AILFLUSH_TOTAL]++; + + } else if (ftrace_data.tracepoint == BLOCK_ALLOC) { + char type[8]; + + sscanf(ftrace_data.data, + "gfs2_block_alloc: %*d,%*d bmap %*u alloc %*u/%*u %s rg:%*u rf:%*u rr:%*u", + type + ); + + if (strncmp(type, "free", 8) == 0) { + fs->ftrace.values[FTRACE_BLOCKALLOC_FREE]++; + } else if (strncmp(type, "used", 8) == 0) { + fs->ftrace.values[FTRACE_BLOCKALLOC_USED]++; + } else if (strncmp(type, "dinode", 8) == 0) { + fs->ftrace.values[FTRACE_BLOCKALLOC_DINODE]++; + } else if (strncmp(type, "unlinked", 8) == 0) { + fs->ftrace.values[FTRACE_BLOCKALLOC_UNLINKED]++; + } + fs->ftrace.values[FTRACE_BLOCKALLOC_TOTAL]++; + + } else if (ftrace_data.tracepoint == BMAP) { + char type[8]; + + sscanf(ftrace_data.data, + "gfs2_bmap: %*d,%*d bmap %*u map %*u/%*u to %*u flags:%*x %s %*d", + type + ); + + if (strncmp(type, "create", 8) == 0) { + fs->ftrace.values[FTRACE_BMAP_CREATE]++; + } else if (strncmp(type, "nocreate", 8) == 0) { + fs->ftrace.values[FTRACE_BMAP_NOCREATE]++; + } + fs->ftrace.values[FTRACE_BMAP_TOTAL]++; + + } else if (ftrace_data.tracepoint == RS) { + char type[8]; + + sscanf(ftrace_data.data, + "gfs2_rs: %*d,%*d bmap %*u resrv %*u rg:%*u rf:%*u rr:%*u %s f:%*u", + type + ); + + if (strncmp(type, "del", 4) == 0) { + fs->ftrace.values[FTRACE_RS_DEL]++; + } else if (strncmp(type, "tdel", 4) == 0) { + fs->ftrace.values[FTRACE_RS_TDEL]++; + } else if (strncmp(type, "ins", 4) == 0) { + fs->ftrace.values[FTRACE_RS_INS]++; + } else if (strncmp(type, "clm", 4) == 0) { + fs->ftrace.values[FTRACE_RS_CLM]++; + } + fs->ftrace.values[FTRACE_RS_TOTAL]++; + + } + } + } +} + +/* + * We take all required data from the trace_pipe. Whilst keeping track of + * the number of locks we have seen so far. After locks have been collected + * we assign values and return. + */ +int +gfs2_refresh_ftrace_stats(pmInDom gfs_fs_indom) +{ + FILE *fp; + int fd, flags, reset_flag; + char buffer[8196]; + + /* Reset the metric types we have found */ + num_accepted_entries = 0; + reset_flag = 1; + + /* We open the pipe in both read-only and non-blocking mode */ + if ((fp = fopen(TRACE_PIPE, "r")) == NULL) + return -oserror(); + + /* Set flags of fp as non-blocking */ + fd = fileno(fp); + flags = fcntl(fd, F_GETFL); + if (fcntl(fd, F_SETFL, flags | O_RDONLY | O_NONBLOCK) < 0) { + fclose(fp); + return -oserror(); + } + + /* Extract data from the trace_pipe */ + while (fgets(buffer, sizeof(buffer), fp) != NULL) { + if (num_accepted_entries >= max_glock_throughput) + break; + + /* In the event of an allocation error */ + if (gfs2_extract_trace_values(buffer, gfs_fs_indom) != 0) + break; + + /* Processing here */ + gfs2_assign_ftrace(gfs_fs_indom, reset_flag); + } + + fclose(fp); + + /* Clear the rest of the ring buffer after passing max_glock_throughput */ + ftrace_clear_buffer(); + + return 0; +} |