From 892b1cd26f52a28a96ee71dac1a194d4a4512ea8 Mon Sep 17 00:00:00 2001 From: Sebastien Godard Date: Sun, 10 Oct 2010 16:39:28 +0200 Subject: [PATCH] Added a new magical value for each activity in file. A format change can now hit only one activity instead of the whole file. Sadf has also been updated to be able to display activities with unknown format (sadf -H). --- CHANGES | 3 +++ activity.c | 34 ++++++++++++++++++++++++++++++++++ sa.h | 20 ++++++++++++++++++++ sa_common.c | 46 +++++++++++++++++++++++++++++++++++----------- sadc.c | 40 +++++++++++++++++++++++----------------- sadf.c | 13 ++++++++----- sar.c | 9 +++++++-- 7 files changed, 130 insertions(+), 35 deletions(-) diff --git a/CHANGES b/CHANGES index a918eb7..84280f4 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,9 @@ Changes: xxxx/xx/xx: Version 9.1.6 - Sebastien Godard (sysstat orange.fr) WARNING: Daily data files format has changed, and is *not* compatible with the previous one! [0x2171] + * Added a new magical value for each activity in file. + A format change can now hit only one activity instead of + the whole file. * Added hugepages utilization statistics to sar. * [Ivana Varekova]: Moved manual pages to $prefix/share/man instead of $prefix/man. diff --git a/activity.c b/activity.c index 81ff0a1..23293da 100644 --- a/activity.c +++ b/activity.c @@ -66,6 +66,7 @@ struct act_bitmap irq_bitmap = { struct activity cpu_act = { .id = A_CPU, .options = AO_COLLECTED + AO_REMANENT + AO_GLOBAL_ITV + AO_MULTIPLE_OUTPUTS, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_cpu_nr, .f_count2 = NULL, @@ -95,6 +96,7 @@ struct activity cpu_act = { struct activity pcsw_act = { .id = A_PCSW, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -123,6 +125,7 @@ struct activity pcsw_act = { struct activity irq_act = { .id = A_IRQ, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_irq_nr, .f_count2 = NULL, @@ -151,6 +154,7 @@ struct activity irq_act = { struct activity swap_act = { .id = A_SWAP, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -179,6 +183,7 @@ struct activity swap_act = { struct activity paging_act = { .id = A_PAGE, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -208,6 +213,7 @@ struct activity paging_act = { struct activity io_act = { .id = A_IO, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -236,6 +242,7 @@ struct activity io_act = { struct activity memory_act = { .id = A_MEMORY, .options = AO_COLLECTED + AO_MULTIPLE_OUTPUTS, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -266,6 +273,7 @@ struct activity memory_act = { struct activity ktables_act = { .id = A_KTABLES, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -294,6 +302,7 @@ struct activity ktables_act = { struct activity queue_act = { .id = A_QUEUE, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -322,6 +331,7 @@ struct activity queue_act = { struct activity serial_act = { .id = A_SERIAL, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_serial_nr, .f_count2 = NULL, @@ -350,6 +360,7 @@ struct activity serial_act = { struct activity disk_act = { .id = A_DISK, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_disk_nr, .f_count2 = NULL, @@ -378,6 +389,7 @@ struct activity disk_act = { struct activity net_dev_act = { .id = A_NET_DEV, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_iface_nr, .f_count2 = NULL, @@ -406,6 +418,7 @@ struct activity net_dev_act = { struct activity net_edev_act = { .id = A_NET_EDEV, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_iface_nr, .f_count2 = NULL, @@ -435,6 +448,7 @@ struct activity net_edev_act = { struct activity net_nfs_act = { .id = A_NET_NFS, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -463,6 +477,7 @@ struct activity net_nfs_act = { struct activity net_nfsd_act = { .id = A_NET_NFSD, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -492,6 +507,7 @@ struct activity net_nfsd_act = { struct activity net_sock_act = { .id = A_NET_SOCK, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -520,6 +536,7 @@ struct activity net_sock_act = { struct activity net_ip_act = { .id = A_NET_IP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -548,6 +565,7 @@ struct activity net_ip_act = { struct activity net_eip_act = { .id = A_NET_EIP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -576,6 +594,7 @@ struct activity net_eip_act = { struct activity net_icmp_act = { .id = A_NET_ICMP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -605,6 +624,7 @@ struct activity net_icmp_act = { struct activity net_eicmp_act = { .id = A_NET_EICMP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -634,6 +654,7 @@ struct activity net_eicmp_act = { struct activity net_tcp_act = { .id = A_NET_TCP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -662,6 +683,7 @@ struct activity net_tcp_act = { struct activity net_etcp_act = { .id = A_NET_ETCP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -690,6 +712,7 @@ struct activity net_etcp_act = { struct activity net_udp_act = { .id = A_NET_UDP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -718,6 +741,7 @@ struct activity net_udp_act = { struct activity net_sock6_act = { .id = A_NET_SOCK6, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -746,6 +770,7 @@ struct activity net_sock6_act = { struct activity net_ip6_act = { .id = A_NET_IP6, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -775,6 +800,7 @@ struct activity net_ip6_act = { struct activity net_eip6_act = { .id = A_NET_EIP6, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -804,6 +830,7 @@ struct activity net_eip6_act = { struct activity net_icmp6_act = { .id = A_NET_ICMP6, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -834,6 +861,7 @@ struct activity net_icmp6_act = { struct activity net_eicmp6_act = { .id = A_NET_EICMP6, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -863,6 +891,7 @@ struct activity net_eicmp6_act = { struct activity net_udp6_act = { .id = A_NET_UDP6, .options = AO_CLOSE_MARKUP, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, @@ -891,6 +920,7 @@ struct activity net_udp6_act = { struct activity pwr_cpufreq_act = { .id = A_PWR_CPUFREQ, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_cpu_nr, .f_count2 = NULL, @@ -919,6 +949,7 @@ struct activity pwr_cpufreq_act = { struct activity pwr_fan_act = { .id = A_PWR_FAN, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_fan_nr, .f_count2 = NULL, @@ -947,6 +978,7 @@ struct activity pwr_fan_act = { struct activity pwr_temp_act = { .id = A_PWR_TEMP, .options = AO_NULL, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_temp_nr, .f_count2 = NULL, @@ -975,6 +1007,7 @@ struct activity pwr_temp_act = { struct activity pwr_in_act = { .id = A_PWR_IN, .options = AO_CLOSE_MARKUP, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = wrap_get_in_nr, .f_count2 = NULL, @@ -1003,6 +1036,7 @@ struct activity pwr_in_act = { struct activity huge_act = { .id = A_HUGE, .options = AO_COLLECTED, + .magic = ACTIVITY_MAGIC_BASE, #ifdef SOURCE_SADC .f_count = NULL, .f_count2 = NULL, diff --git a/sa.h b/sa.h index 33eadd0..ec51d9e 100644 --- a/sa.h +++ b/sa.h @@ -284,6 +284,12 @@ struct activity { * Activity options (AO_SELECTED, ...) */ unsigned int options; + /* + * Activity magical number. This number changes when activity format in file + * is no longer compatible with the format of that same activity from + * previous versions. + */ + unsigned int magic; /* * The f_count() function is used to count the number of * items (serial lines, network interfaces, etc.) -> @nr @@ -507,12 +513,26 @@ struct file_header { #define FILE_HEADER_SIZE (sizeof(struct file_header)) +/* + * Base magical number for activities. + */ +#define ACTIVITY_MAGIC_BASE 0x8a +/* + * Magical value used for activities with + * unknown format (used for sadf -H only). + */ +#define ACTIVITY_MAGIC_UNKNOWN 0x89 + /* List of activities saved in file */ struct file_activity { /* * Identification value of activity. */ unsigned int id __attribute__ ((aligned (4))); + /* + * Activity magical number. + */ + unsigned int magic __attribute__ ((packed)); /* * Number of items for this activity. */ diff --git a/sa_common.c b/sa_common.c index e0ec855..72eff3c 100644 --- a/sa_common.c +++ b/sa_common.c @@ -990,10 +990,11 @@ void read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr, for (i = 0; i < act_nr; i++, fal++) { - if ((p = get_activity_position(act, fal->id)) < 0) { + if (((p = get_activity_position(act, fal->id)) < 0) || + (act[p]->magic != fal->magic)) { /* * Ignore current activity in file, which is unknown to - * current sysstat version. + * current sysstat version or has an unknown format. */ if (lseek(ifd, fal->size * fal->nr * fal->nr2, SEEK_CUR) < (fal->size * fal->nr * fal->nr2)) { close(ifd); @@ -1095,23 +1096,46 @@ void check_file_actlst(int *ifd, char *dfile, struct activity *act[], handle_invalid_sa_file(ifd, file_magic, dfile, 0); } + if ((p = get_activity_position(act, fal->id)) < 0) + /* Unknown activity */ + continue; + + if (act[p]->magic != fal->magic) { + /* Bad magical number */ + if (ignore) { + /* + * This is how sadf -H knows that this + * activity has an unknown format. + */ + act[p]->magic = ACTIVITY_MAGIC_UNKNOWN; + } + else + continue; + } + if (fal->id == A_CPU) { a_cpu = TRUE; } - if ((p = get_activity_position(act, fal->id)) >= 0) { - if (fal->size > act[p]->msize) { - act[p]->msize = fal->size; - } - act[p]->fsize = fal->size; - act[p]->nr = fal->nr; - act[p]->nr2 = fal->nr2; - id_seq[j++] = fal->id; + if (fal->size > act[p]->msize) { + act[p]->msize = fal->size; } + act[p]->fsize = fal->size; + act[p]->nr = fal->nr; + act[p]->nr2 = fal->nr2; + /* + * This is a known activity with a known format + * (magical number). Only such activities will be displayed. + * (Well, this may also be an unknown format if we have entered sadf -H.) + */ + id_seq[j++] = fal->id; } if (!a_cpu) { - /* CPU activity should always be in file */ + /* + * CPU activity should always be in file + * and have a known format (expected magical number). + */ handle_invalid_sa_file(ifd, file_magic, dfile, 0); } diff --git a/sadc.c b/sadc.c index a3a6b57..0489e12 100644 --- a/sadc.c +++ b/sadc.c @@ -249,6 +249,7 @@ void sa_sys_init(void) act[i]->nr2 = (*act[i]->f_count2)(act[i]); } /* else act[i]->nr2 is a constant and doesn't need to be calculated */ + if (!act[i]->nr2) { act[i]->nr = 0; } @@ -415,7 +416,7 @@ void fill_magic_header(struct file_magic *file_magic) * Fill system activity file header, then write it (or print it if stdout). * * IN: - * @fd Output file descriptor. May be stdout. + * @fd Output file descriptor. May be stdout. *************************************************************************** */ void setup_file_hdr(int fd) @@ -473,10 +474,11 @@ void setup_file_hdr(int fd) continue; if (IS_COLLECTED(act[p]->options)) { - file_act.id = act[p]->id; - file_act.nr = act[p]->nr; - file_act.nr2 = act[p]->nr2; - file_act.size = act[p]->fsize; + file_act.id = act[p]->id; + file_act.magic = act[p]->magic; + file_act.nr = act[p]->nr; + file_act.nr2 = act[p]->nr2; + file_act.size = act[p]->fsize; if ((n = write_all(fd, &file_act, FILE_ACTIVITY_SIZE)) != FILE_ACTIVITY_SIZE) @@ -502,8 +504,8 @@ write_error: * before the cron daemon is started to avoid conflict with sa1/sa2 scripts. * * IN: - * @ofd Output file descriptor. - * @rtype Record type to write (dummy or comment). + * @ofd Output file descriptor. + * @rtype Record type to write (dummy or comment). *************************************************************************** */ void write_special_record(int ofd, int rtype) @@ -547,7 +549,7 @@ void write_special_record(int ofd, int rtype) * Write stats (or print them if stdout). * * IN: - * @ofd Output file descriptor. May be stdout. + * @ofd Output file descriptor. May be stdout. *************************************************************************** */ void write_stats(int ofd) @@ -591,10 +593,10 @@ void write_stats(int ofd) * Create a system activity daily data file. * * IN: - * @ofile Name of output file. + * @ofile Name of output file. * * OUT: - * @ofd Output file descriptor. + * @ofd Output file descriptor. *************************************************************************** */ void create_sa_file(int *ofd, char *ofile) @@ -623,11 +625,11 @@ void create_sa_file(int *ofd, char *ofile) * Get descriptor for stdout. * * IN: - * @stdfd A value >= 0 indicates that stats data should also - * be written to stdout. + * @stdfd A value >= 0 indicates that stats data should also + * be written to stdout. * * OUT: - * @stdfd Stdout file descriptor. + * @stdfd Stdout file descriptor. *************************************************************************** */ void open_stdout(int *stdfd) @@ -648,10 +650,10 @@ void open_stdout(int *stdfd) * We may enter this function several times (when we rotate a file). * * IN: - * @ofile Name of output file. + * @ofile Name of output file. * * OUT: - * @ofd Output file descriptor. + * @ofd Output file descriptor. *************************************************************************** */ void open_ofile(int *ofd, char ofile[]) @@ -727,8 +729,12 @@ void open_ofile(int *ofd, char ofile[]) p = get_activity_position(act, file_act.id); - if ((p < 0) || (act[p]->fsize != file_act.size)) - /* Unknown activity in list or item size has changed */ + if ((p < 0) || (act[p]->fsize != file_act.size) || + (act[p]->magic != file_act.magic)) + /* + * Unknown activity in list or item size has changed or + * unknown activity format. + */ goto append_error; if ((act[p]->nr != file_act.nr) || (act[p]->nr2 != file_act.nr2)) { diff --git a/sadf.c b/sadf.c index 45006ca..b746442 100644 --- a/sadf.c +++ b/sadf.c @@ -591,9 +591,9 @@ void sadf_print_special(int curr, int use_tm_start, int use_tm_end, int rtype, i * Display data file header. * * IN: - * @dfile Name of system activity data file - * @file_magic System activity file magic header - * @file_hdr System activity file standard header + * @dfile Name of system activity data file. + * @file_magic System activity file magic header. + * @file_hdr System activity file standard header. *************************************************************************** */ void display_file_header(char *dfile, struct file_magic *file_magic, @@ -601,7 +601,7 @@ void display_file_header(char *dfile, struct file_magic *file_magic, { int i, p; static __nr_t cpu_nr = -1; - + if (cpu_nr < 0) { cpu_nr = act[get_activity_position(act, A_CPU)]->nr; } @@ -632,7 +632,10 @@ void display_file_header(char *dfile, struct file_magic *file_magic, } printf("%02d: %s\t(x%d)", act[p]->id, act[p]->name, act[p]->nr); if (act[p]->f_count2 || (act[p]->nr2 > 1)) { - printf(" (x%d)", act[p]->nr2); + printf("\t(x%d)", act[p]->nr2); + } + if (act[p]->magic == ACTIVITY_MAGIC_UNKNOWN) { + printf(_("\t[Unknown activity format]")); } printf("\n"); } diff --git a/sar.c b/sar.c index 8612914..84cc562 100644 --- a/sar.c +++ b/sar.c @@ -804,7 +804,9 @@ void read_header_data(void) if ((p < 0) || (act[p]->fsize != file_act.size) || !file_act.nr - || !file_act.nr2) { + || !file_act.nr2 + || (act[p]->magic != file_act.magic)) { + /* Remember that we are reading data from sadc and not from a file... */ fprintf(stderr, _("Inconsistent input data\n")); exit(3); } @@ -894,7 +896,10 @@ void read_stats_from_file(char from_file[]) exit(2); } - /* Read and write stats located between two possible Linux restarts */ + /* + * Read and write stats located between two possible Linux restarts. + * Activities that should be displayed are saved in id_seq[] array. + */ for (i = 0; i < NR_ACT; i++) { if (!id_seq[i]) -- 2.40.0