File getdelays-compat.diff of Package delayacct-utils
--- delayacct-utils-0.3/getdelays.c.orig 2007-08-22 15:07:18.000000000 +0200
+++ delayacct-utils-0.3/getdelays.c 2007-10-22 17:04:39.195544000 +0200
@@ -8,7 +8,7 @@
* Copyright (c) Jay Lan, SGI. 2006
*
* Compile with
- * gcc -I/usr/src/linux/include getdelays.c -o getdelays
+ * gcc -I/usr/src/linux/include -Os -Wall getdelays.c -o getdelays
*
* This program is derived from getdelays.c in the Linux kernel source
* and so the kernel license applies.
@@ -182,7 +182,7 @@ int get_family_id(int sd)
char buf[256];
} ans;
- int id, rc;
+ int id = -1, rc;
struct nlattr *na;
int rep_len;
@@ -206,6 +206,51 @@ int get_family_id(int sd)
void print_delayacct(struct taskstats *t)
{
+ struct taskstats *oldt = t;
+ PRINTF("taskstats version %i (compiled for %i)\n",
+ t->version, TASKSTATS_VERSION);
+ /* Someone extended struct taskstat in an incompatible way from
+ * version 1 to 2. Version 1 had
+ * __u16 version;
+ * __u16 padding[3];
+ * __u64 cpu_count;
+ * which puts cpu_count at offset 8. Version 2 had
+ * __u16 version;
+ * __u32 ac_exitcode;
+ * __u8 ac_flag;
+ * __u8 ac_nice;
+ * __u64 cpu_count;
+ * and the author surely assumed that this put cpu_count also at
+ * offset 8. Wrong; it's at offset 16 (on 64bit architectures),
+ * as the ac_exitcode is naturally aligned at offset 4, not 2, without
+ * using the __attribute__((packed)). Version 4 has
+ * ...
+ * __u64 cpu_count __attribute__((aligned(8)));
+ * to enforce the alignment to offset 16 even on 32bit archs, so
+ * we're at least consistent, but the interface changed yet another
+ * time on 32bit archs ...
+ * Oh well, a lesson in basic C programming would have avoided this
+ * whole mess. garloff@suse.de, 2007-10-22
+ */
+#if TASKSTATS_VERSION == 1 /* gcc assumes offset 8 */
+ if (t->version >= 4) /* real offset is 16 */
+ t = (struct taskstats*) ((char*)t + 8);
+ else if (t->version > 1) /* real offset is 12/16 */
+ t = (struct taskstats*) ((char*)t + sizeof(void*));
+#elif TASKSTATS_VERSION < 4 /* gcc assumes offset 12/16 */
+ if (t->version >= 4 && sizeof(void*) < 8) /* real 16/16 */
+ t = (struct taskstats*) ((char*)t + 4);
+ else if (t->version <= 1) /* real 8 */
+ t = (struct taskstats*) ((char*)t - sizeof(void*));
+#else /* gcc assumes offset 16 */
+ if (t->version <= 1) /* real 8 */
+ t = (struct taskstats*) ((char*)t - 8);
+ else if (t->version < 4 && sizeof(void*) < 8) /* real 12/16 */
+ t = (struct taskstats*) ((char*)t - 4);
+#endif
+ if (t != oldt)
+ PRINTF("Fixup: taskstat %p -> %p\n", oldt, t);
+
printf("\n\nCPU %15s%15s%15s%15s\n"
" %15llu%15llu%15llu%15llu\n"
"IO %15s%15s\n"
@@ -222,16 +267,37 @@ void print_delayacct(struct taskstats *t
void print_ioacct(struct taskstats *t)
{
+ /* TODO: The offsets of these fields have also changed
+ * on 32bit architectures due to the alignment fixes in
+ * version 4.
+ */
+ int samever = 0;
+ if ( (sizeof(void*) == 8) ||
+ ( (TASKSTATS_VERSION < 4) == (t->version < 4) ) )
+ samever = 1;
+#ifdef TASKSTATS_HAS_IO_ACCOUNTING
+ if (t->version >= 3 && samever)
printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
t->ac_comm,
(unsigned long long)t->read_bytes,
(unsigned long long)t->write_bytes,
(unsigned long long)t->cancelled_write_bytes);
+ else
+#endif
+#if TASKSTATS_VERSION >= 2
+ if (t->version >= 2 && samever)
+ printf("%s: readchar=%llu, writechar=%llu\n",
+ t->ac_comm,
+ (unsigned long long)t->read_char,
+ (unsigned long long)t->write_char);
+ else
+#endif
+ printf("no io stats available\n");
}
int main(int argc, char *argv[])
{
- int c, rc, rep_len, aggr_len, len2, cmd_type;
+ int c, rc, rep_len, aggr_len, len2, cmd_type = -1;
__u16 id;
__u32 mypid;
@@ -367,7 +433,7 @@ int main(int argc, char *argv[])
goto done;
}
- PRINTF("nlmsghdr size=%d, nlmsg_len=%d, rep_len=%d\n",
+ PRINTF("nlmsghdr size=%zd, nlmsg_len=%d, rep_len=%d\n",
sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len);