* [PATCH] user-cr: Extract headers from kernel source tree.
@ 2009-10-03 7:20 Matt Helsley
[not found] ` <1254554424-2979-2-git-send-email-matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Matt Helsley @ 2009-10-03 7:20 UTC (permalink / raw)
To: Oren Laadan; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Using kernel headers directly from userspace is strongly discouraged.
Sanitize kernel headers for userspace by extracting non-__KERNEL__
portions of the various checkpoint headers and placing them in a
similar organization of userspace headers.
The script is run from the top level of the user-cr source tree like:
./scripts/extract-headers.sh -s <path-to-kern-source> -o ./include
The patch includes a copy of the auto-generated headers and adjusts
the user-cr programs to use them.
Programs should only include linux/checkpoint.h and
linux/checkpoint_hdr.h. asm/checkpoint_hdr.h is included from
linux/checkpoint_hdr.h
Signed-off-by: Matt Helsley <matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Changelog:
v3:
Inverted headers/$(CKPT_HEADERS) rule dependency. This causes it
to extract headers only when one or more are missing.
Moved all of the include definition hacks into a kernel header
patch instead.
v2:
Re-added KERNELSRC ?= ../linux
Merged checkpoint_syscalls.h with checkpoint.h and added a
comment about the unistd code eventually going away.
Thanks to Oren for pointing out the latter.
Added special-case code for stripping linux/un.h from the
checkpoint_hdr.h; (s/linux/sys/ did not work)
Cleaned up do_cpp to make the "include" regex tricks more
obvious to the casual reader.
Modified Makefile to re-extract headers for every build.
Removed the find command that filled CKPT_HEADERS.
This was the easiest solution. Otherwise the Makefiles
might become considerably more obfuscated.
Tested on and made changes for s390x:
Always include sys/types.h before linux/types.h to avoid
conflicting definitions.
Define NUM_CR_WORDS if it's not already defined in
asm/ptrace.h (seems some s390x installs don't
define NUM_CR_WORDS anywhere outside the kernel
source).
---
Makefile | 40 +-
ckptinfo.c | 1 +
clone_ppc.c | 1 +
clone_s390x.c | 1 +
clone_x86_32.c | 1 +
include/asm-powerpc/checkpoint_hdr.h | 21 +
include/asm-s390/checkpoint_hdr.h | 89 ++++
include/asm-x86/checkpoint_hdr.h | 126 ++++++
include/asm/checkpoint_hdr.h | 15 +
include/linux/checkpoint.h | 73 ++++
include/linux/checkpoint_hdr.h | 749 ++++++++++++++++++++++++++++++++++
| 250 +++++++++++
12 files changed, 1344 insertions(+), 23 deletions(-)
create mode 100644 include/asm-powerpc/checkpoint_hdr.h
create mode 100644 include/asm-s390/checkpoint_hdr.h
create mode 100644 include/asm-x86/checkpoint_hdr.h
create mode 100644 include/asm/checkpoint_hdr.h
create mode 100644 include/linux/checkpoint.h
create mode 100644 include/linux/checkpoint_hdr.h
create mode 100755 scripts/extract-headers.sh
diff --git a/Makefile b/Makefile
index 7f5cb27..181cc1c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,24 +1,9 @@
-
KERNELSRC ?= ../linux
-KERNELBUILD ?= ../linux
-
-# default with 'make headers_install'
-KERNELHDR ?= $(KERNELSRC)/usr/include
-
-ifneq "$(realpath $(KERNELHDR)/linux/checkpoint.h)" ""
-# if .../usr/include contains our headers
-CKPT_INCLUDE = -I$(KERNELHDR)
-CKPT_HEADERS = $(KERNELHDR)/linux/checkpoint_hdr.h \
- $(KERNELHDR)/asm/checkpoint_hdr.h
-else
-# else, usr the kernel source itself
-# but first, find linux architecure
-KERN_ARCH = $(shell readlink $(KERNELBUILD)/include/asm | sed 's/^asm-//')
-CKPT_INCLUDE = -I$(KERNELSRC)/include \
- -I$(KERNELSRC)/arch/$(KERN_ARCH)/include
-CKPT_HEADERS = $(KERNELSRC)/include/linux/checkpoint_hdr.h \
- $(KERNELSRC)/arch/$(KERN_ARCH)/include/asm/checkpoint_hdr.h
-endif
+
+CKPT_INCLUDE = -I./include
+CKPT_HEADERS = include/linux/checkpoint.h \
+ include/linux/checkpoint_hdr.h \
+ include/asm/checkpoint_hdr.h
# detect architecture (for clone_with_pids)
SUBARCH = $(patsubst i%86,x86_32,$(shell uname -m))
@@ -42,6 +27,8 @@ OTHER = ckptinfo_types.c
LDLIBS = -lm
+.PHONY: all distclean clean headers install
+
all: $(PROGS)
@make -C test
@@ -63,13 +50,20 @@ endif
ckptinfo: ckptinfo_types.o
ckptinfo_types.c: $(CKPT_HEADERS) ckptinfo.py
- @echo cat $(CKPT_HEADERS) | ./ckptinfo.py > ckptinfo_types.c
- @cat $(CKPT_HEADERS) | ./ckptinfo.py > ckptinfo_types.c
+ cat $(CKPT_HEADERS) | ./ckptinfo.py > ckptinfo_types.c
install:
@echo /usr/bin/install -m 755 checkpoint restart ckptinfo $(INSTALL_DIR)
@/usr/bin/install -m 755 checkpoint restart ckptinfo $(INSTALL_DIR)
+$(CKPT_HEADERS): %:
+ ./scripts/extract-headers.sh -s $(KERNELSRC) -o ./include
+
+headers: $(CKPT_HEADERS)
+
+distclean: clean
+ @rm -f $(CKPT_HEADERS)
+
clean:
- @rm -f $(PROGS) $(OTHER) *~ *.o
+ @rm -f $(PROGS) $(OTHER) *~ *.o headers.h
@make -C test clean
diff --git a/ckptinfo.c b/ckptinfo.c
index 6859742..9eea791 100644
--- a/ckptinfo.c
+++ b/ckptinfo.c
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include <linux/checkpoint.h>
#include <linux/checkpoint_hdr.h>
#include <asm/checkpoint_hdr.h>
diff --git a/clone_ppc.c b/clone_ppc.c
index 09b51b5..49797fd 100644
--- a/clone_ppc.c
+++ b/clone_ppc.c
@@ -31,6 +31,7 @@ extern int __clone_with_pids(int (*fn)(void *arg),
* libc doesn't support clone_with_pid() yet...
* below is arch-dependent code to use the syscall
*/
+#include <linux/checkpoint.h>
#if defined(__NR_clone_with_pids)
/* (see: http://lkml.indiana.edu/hypermail/linux/kernel/9604.3/0204.html) */
diff --git a/clone_s390x.c b/clone_s390x.c
index 661a5c4..dada822 100644
--- a/clone_s390x.c
+++ b/clone_s390x.c
@@ -22,6 +22,7 @@
* libc doesn't support clone_with_pid() yet...
* below is arch-dependent code to use the syscall
*/
+#include <linux/checkpoint.h>
#if defined(__NR_clone_with_pids)
/* this really belongs to some kernel header ! */
diff --git a/clone_x86_32.c b/clone_x86_32.c
index 05a689e..8ab3c3e 100644
--- a/clone_x86_32.c
+++ b/clone_x86_32.c
@@ -20,6 +20,7 @@
* libc doesn't support clone_with_pid() yet...
* below is arch-dependent code to use the syscall
*/
+#include <linux/checkpoint.h>
#if defined(__NR_clone_with_pids)
/* this really belongs to some kernel header ! */
diff --git a/include/asm-powerpc/checkpoint_hdr.h b/include/asm-powerpc/checkpoint_hdr.h
new file mode 100644
index 0000000..105a184
--- /dev/null
+++ b/include/asm-powerpc/checkpoint_hdr.h
@@ -0,0 +1,21 @@
+/*
+ * Generated by extract-headers.sh.
+ */
+#ifndef __ASM_POWERPC_CHECKPOINT_HDR_H_
+#define __ASM_POWERPC_CHECKPOINT_HDR_H_
+
+
+#include <linux/types.h>
+
+/* arch dependent constants */
+#define CKPT_ARCH_NSIG 64
+#define CKPT_TTY_NCC 10
+
+struct ckpt_hdr_header_arch {
+ struct ckpt_hdr h;
+ __u32 what;
+} __attribute__((aligned(8)));
+
+
+
+#endif /* __ASM_POWERPC_CHECKPOINT_HDR_H_ */
diff --git a/include/asm-s390/checkpoint_hdr.h b/include/asm-s390/checkpoint_hdr.h
new file mode 100644
index 0000000..ad1a2e2
--- /dev/null
+++ b/include/asm-s390/checkpoint_hdr.h
@@ -0,0 +1,89 @@
+/*
+ * Generated by extract-headers.sh.
+ */
+#ifndef __ASM_S390_CHECKPOINT_HDR_H_
+#define __ASM_S390_CHECKPOINT_HDR_H_
+
+/*
+ * Checkpoint/restart - architecture specific headers s/390
+ *
+ * Copyright IBM Corp. 2009
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ */
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+
+/*
+ * Notes
+ * NUM_GPRS defined in <asm/ptrace.h> to be 16
+ * NUM_FPRS defined in <asm/ptrace.h> to be 16
+ * NUM_APRS defined in <asm/ptrace.h> to be 16
+ * NUM_CR_WORDS defined in <asm/ptrace.h> to be 3
+ * but is not yet in glibc headers.
+ */
+
+#define NUM_CR_WORDS 3
+
+struct ckpt_hdr_cpu {
+ struct ckpt_hdr h;
+ __u64 args[1];
+ __u64 gprs[NUM_GPRS];
+ __u64 orig_gpr2;
+ __u16 svcnr;
+ __u16 ilc;
+ __u32 acrs[NUM_ACRS];
+ __u64 ieee_instruction_pointer;
+
+ /* psw_t */
+ __u64 psw_t_mask;
+ __u64 psw_t_addr;
+
+ /* s390_fp_regs_t */
+ __u32 fpc;
+ union {
+ float f;
+ double d;
+ __u64 ui;
+ struct {
+ __u32 fp_hi;
+ __u32 fp_lo;
+ } fp;
+ } fprs[NUM_FPRS];
+
+ /* per_struct */
+ __u64 per_control_regs[NUM_CR_WORDS];
+ __u64 starting_addr;
+ __u64 ending_addr;
+ __u64 address;
+ __u16 perc_atmid;
+ __u8 access_id;
+ __u8 single_step;
+ __u8 instruction_fetch;
+};
+
+struct ckpt_hdr_mm_context {
+ struct ckpt_hdr h;
+ unsigned long vdso_base;
+ int noexec;
+ int has_pgste;
+ int alloc_pgste;
+ unsigned long asce_bits;
+ unsigned long asce_limit;
+};
+
+#define CKPT_ARCH_NSIG 64
+#define CKPT_TTY_NCC 8
+
+/* arch dependent constants */
+
+struct ckpt_hdr_header_arch {
+ struct ckpt_hdr h;
+};
+
+
+
+#endif /* __ASM_S390_CHECKPOINT_HDR_H_ */
diff --git a/include/asm-x86/checkpoint_hdr.h b/include/asm-x86/checkpoint_hdr.h
new file mode 100644
index 0000000..4bf3b8a
--- /dev/null
+++ b/include/asm-x86/checkpoint_hdr.h
@@ -0,0 +1,126 @@
+/*
+ * Generated by extract-headers.sh.
+ */
+#ifndef __ASM_X86_CHECKPOINT_HDR_H_
+#define __ASM_X86_CHECKPOINT_HDR_H_
+
+/*
+ * Checkpoint/restart - architecture specific headers x86
+ *
+ * Copyright (C) 2008-2009 Oren Laadan
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ */
+
+#include <linux/types.h>
+
+/*
+ * To maintain compatibility between 32-bit and 64-bit architecture flavors,
+ * keep data 64-bit aligned: use padding for structure members, and use
+ * __attribute__((aligned (8))) for the entire structure.
+ *
+ * Quoting Arnd Bergmann:
+ * "This structure has an odd multiple of 32-bit members, which means
+ * that if you put it into a larger structure that also contains 64-bit
+ * members, the larger structure may get different alignment on x86-32
+ * and x86-64, which you might want to avoid. I can't tell if this is
+ * an actual problem here. ... In this case, I'm pretty sure that
+ * sizeof(ckpt_hdr_task) on x86-32 is different from x86-64, since it
+ * will be 32-bit aligned on x86-32."
+ */
+
+/* i387 structure seen from kernel/userspace */
+
+/* arch dependent header types */
+enum {
+ CKPT_HDR_CPU_FPU = 201,
+ CKPT_HDR_MM_CONTEXT_LDT,
+};
+
+/* arch dependent constants */
+#define CKPT_ARCH_NSIG 64
+#define CKPT_TTY_NCC 8
+
+struct ckpt_hdr_header_arch {
+ struct ckpt_hdr h;
+ /* FIXME: add HAVE_HWFP */
+ __u16 has_fxsr;
+ __u16 has_xsave;
+ __u16 xstate_size;
+ __u16 _pading;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_thread {
+ struct ckpt_hdr h;
+ __u32 thread_info_flags;
+ __u16 gdt_entry_tls_entries;
+ __u16 sizeof_tls_array;
+} __attribute__((aligned(8)));
+
+/* designed to work for both x86_32 and x86_64 */
+struct ckpt_hdr_cpu {
+ struct ckpt_hdr h;
+ /* see struct pt_regs (x86_64) */
+ __u64 r15;
+ __u64 r14;
+ __u64 r13;
+ __u64 r12;
+ __u64 bp;
+ __u64 bx;
+ __u64 r11;
+ __u64 r10;
+ __u64 r9;
+ __u64 r8;
+ __u64 ax;
+ __u64 cx;
+ __u64 dx;
+ __u64 si;
+ __u64 di;
+ __u64 orig_ax;
+ __u64 ip;
+ __u64 sp;
+
+ __u64 flags;
+
+ /* segment registers */
+ __u64 fs;
+ __u64 gs;
+
+ __u16 fsindex;
+ __u16 gsindex;
+ __u16 cs;
+ __u16 ss;
+ __u16 ds;
+ __u16 es;
+
+ __u32 used_math;
+
+ /* debug registers */
+ __u64 debugreg0;
+ __u64 debugreg1;
+ __u64 debugreg2;
+ __u64 debugreg3;
+ __u64 debugreg6;
+ __u64 debugreg7;
+
+ /* thread_xstate contents follow (if used_math) */
+} __attribute__((aligned(8)));
+
+#define CKPT_X86_SEG_NULL 0
+#define CKPT_X86_SEG_USER32_CS 1
+#define CKPT_X86_SEG_USER32_DS 2
+#define CKPT_X86_SEG_TLS 0x4000 /* 0100 0000 0000 00xx */
+#define CKPT_X86_SEG_LDT 0x8000 /* 100x xxxx xxxx xxxx */
+
+struct ckpt_hdr_mm_context {
+ struct ckpt_hdr h;
+ __u64 vdso;
+ __u32 ldt_entry_size;
+ __u32 nldt;
+} __attribute__((aligned(8)));
+
+
+
+#endif /* __ASM_X86_CHECKPOINT_HDR_H_ */
diff --git a/include/asm/checkpoint_hdr.h b/include/asm/checkpoint_hdr.h
new file mode 100644
index 0000000..859f58e
--- /dev/null
+++ b/include/asm/checkpoint_hdr.h
@@ -0,0 +1,15 @@
+/*
+ * Generated by extract-headers.sh.
+ */
+#ifndef __ASM_CHECKPOINT_HDR_H_
+#define __ASM_CHECKPOINT_HDR_H_
+#if __powerpc__
+#include <asm-powerpc/checkpoint_hdr.h>
+#elif __s390x__
+#include <asm-s390/checkpoint_hdr.h>
+#elif __i386__ || __x86_64__
+#include <asm-x86/checkpoint_hdr.h>
+#else
+#error "Architecture does not have definitons needed for checkpoint images."
+#endif
+#endif /* __ASM_CHECKPOINT_HDR_H_ */
diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
new file mode 100644
index 0000000..75fdb0a
--- /dev/null
+++ b/include/linux/checkpoint.h
@@ -0,0 +1,73 @@
+/*
+ * Generated by extract-headers.sh.
+ */
+#ifndef _LINUX_CHECKPOINT_H_
+#define _LINUX_CHECKPOINT_H_
+
+/*
+ * Generic checkpoint-restart
+ *
+ * Copyright (C) 2008-2009 Oren Laadan
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ */
+
+#define CHECKPOINT_VERSION 2
+
+/* checkpoint user flags */
+#define CHECKPOINT_SUBTREE 0x1
+
+/* restart user flags */
+#define RESTART_TASKSELF 0x1
+#define RESTART_FROZEN 0x2
+#define RESTART_GHOST 0x4
+
+
+#if __powerpc__
+
+# ifndef __NR_checkpoint
+# define __NR_checkpoint 323
+# endif
+
+# ifndef __NR_restart
+# define __NR_restart 324
+# endif
+
+# ifndef __NR_clone_with_pids
+# define __NR_clone_with_pids 325
+# endif
+
+#elif __s390x__
+
+# ifndef __NR_checkpoint
+# define __NR_checkpoint 332
+# endif
+
+# ifndef __NR_restart
+# define __NR_restart 333
+# endif
+
+# ifndef __NR_clone_with_pids
+# define __NR_clone_with_pids 334
+# endif
+
+#elif __i386__
+
+# ifndef __NR_clone_with_pids
+# define __NR_clone_with_pids 337
+# endif
+
+# ifndef __NR_checkpoint
+# define __NR_checkpoint 338
+# endif
+
+# ifndef __NR_restart
+# define __NR_restart 339
+# endif
+
+#else
+#error "Architecture does not have definitons for __NR_(checkpoint|restart)"
+#endif
+#endif /* _LINUX_CHECKPOINT_H_ */
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
new file mode 100644
index 0000000..01f9957
--- /dev/null
+++ b/include/linux/checkpoint_hdr.h
@@ -0,0 +1,749 @@
+/*
+ * Generated by extract-headers.sh.
+ */
+#ifndef _CHECKPOINT_CKPT_HDR_H_
+#define _CHECKPOINT_CKPT_HDR_H_
+
+/*
+ * Generic container checkpoint-restart
+ *
+ * Copyright (C) 2008-2009 Oren Laadan
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ */
+
+/* In userspace sys/types.h must be included before linux/types.h */
+#include <sys/types.h>
+
+#include <linux/types.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+/*
+ * To maintain compatibility between 32-bit and 64-bit architecture flavors,
+ * keep data 64-bit aligned: use padding for structure members, and use
+ * __attribute__((aligned (8))) for the entire structure.
+ *
+ * Quoting Arnd Bergmann:
+ * "This structure has an odd multiple of 32-bit members, which means
+ * that if you put it into a larger structure that also contains 64-bit
+ * members, the larger structure may get different alignment on x86-32
+ * and x86-64, which you might want to avoid. I can't tell if this is
+ * an actual problem here. ... In this case, I'm pretty sure that
+ * sizeof(ckpt_hdr_task) on x86-32 is different from x86-64, since it
+ * will be 32-bit aligned on x86-32."
+ */
+
+/*
+ * header format: 'struct ckpt_hdr' must prefix all other headers. Therfore
+ * when a header is passed around, the information about it (type, size)
+ * is readily available. Structs that include a struct ckpt_hdr are named
+ * struct ckpt_hdr_* by convention (usualy the struct ckpt_hdr is the first
+ * member).
+ */
+struct ckpt_hdr {
+ __u32 type;
+ __u32 len;
+} __attribute__((aligned(8)));
+
+#include <asm/checkpoint_hdr.h>
+
+/* header types */
+enum {
+ CKPT_HDR_HEADER = 1,
+ CKPT_HDR_HEADER_ARCH,
+ CKPT_HDR_BUFFER,
+ CKPT_HDR_STRING,
+ CKPT_HDR_OBJREF,
+
+ CKPT_HDR_TREE = 101,
+ CKPT_HDR_TASK,
+ CKPT_HDR_TASK_NS,
+ CKPT_HDR_TASK_OBJS,
+ CKPT_HDR_RESTART_BLOCK,
+ CKPT_HDR_THREAD,
+ CKPT_HDR_CPU,
+ CKPT_HDR_NS,
+ CKPT_HDR_UTS_NS,
+ CKPT_HDR_IPC_NS,
+ CKPT_HDR_CAPABILITIES,
+ CKPT_HDR_USER_NS,
+ CKPT_HDR_CRED,
+ CKPT_HDR_USER,
+ CKPT_HDR_GROUPINFO,
+ CKPT_HDR_TASK_CREDS,
+
+ /* 201-299: reserved for arch-dependent */
+
+ CKPT_HDR_FILE_TABLE = 301,
+ CKPT_HDR_FILE_DESC,
+ CKPT_HDR_FILE_NAME,
+ CKPT_HDR_FILE,
+ CKPT_HDR_PIPE_BUF,
+ CKPT_HDR_TTY,
+ CKPT_HDR_TTY_LDISC,
+
+ CKPT_HDR_MM = 401,
+ CKPT_HDR_VMA,
+ CKPT_HDR_PGARR,
+ CKPT_HDR_MM_CONTEXT,
+
+ CKPT_HDR_IPC = 501,
+ CKPT_HDR_IPC_SHM,
+ CKPT_HDR_IPC_MSG,
+ CKPT_HDR_IPC_MSG_MSG,
+ CKPT_HDR_IPC_SEM,
+
+ CKPT_HDR_SIGHAND = 601,
+ CKPT_HDR_SIGNAL,
+ CKPT_HDR_SIGNAL_TASK,
+ CKPT_HDR_SIGPENDING,
+
+ CKPT_HDR_SOCKET = 701,
+ CKPT_HDR_SOCKET_QUEUE,
+ CKPT_HDR_SOCKET_BUFFER,
+ CKPT_HDR_SOCKET_UNIX,
+ CKPT_HDR_SOCKET_INET,
+
+ CKPT_HDR_TAIL = 9001,
+
+ CKPT_HDR_ERROR = 9999,
+ CKPT_HDR_KERNEL_STACK = 10000,
+};
+
+/* architecture */
+enum {
+ /* do not change order (will break ABI) */
+ CKPT_ARCH_X86_32 = 1,
+ CKPT_ARCH_S390X,
+ CKPT_ARCH_PPC32,
+ CKPT_ARCH_PPC64,
+};
+
+/* shared objrects (objref) */
+struct ckpt_hdr_objref {
+ struct ckpt_hdr h;
+ __u32 objtype;
+ __s32 objref;
+} __attribute__((aligned(8)));
+
+/* shared objects types */
+enum obj_type {
+ CKPT_OBJ_IGNORE = 0,
+ CKPT_OBJ_INODE,
+ CKPT_OBJ_FILE_TABLE,
+ CKPT_OBJ_FILE,
+ CKPT_OBJ_MM,
+ CKPT_OBJ_SIGHAND,
+ CKPT_OBJ_SIGNAL,
+ CKPT_OBJ_NS,
+ CKPT_OBJ_UTS_NS,
+ CKPT_OBJ_IPC_NS,
+ CKPT_OBJ_USER_NS,
+ CKPT_OBJ_CRED,
+ CKPT_OBJ_USER,
+ CKPT_OBJ_GROUPINFO,
+ CKPT_OBJ_SOCK,
+ CKPT_OBJ_TTY,
+ CKPT_OBJ_MAX
+};
+
+/* kernel constants */
+struct ckpt_const {
+ /* task */
+ __u16 task_comm_len;
+ /* mm */
+ __u16 mm_saved_auxv_len;
+ /* signal */
+ __u16 signal_nsig;
+ /* uts */
+ __u16 uts_sysname_len;
+ __u16 uts_nodename_len;
+ __u16 uts_release_len;
+ __u16 uts_version_len;
+ __u16 uts_machine_len;
+ __u16 uts_domainname_len;
+ /* rlimit */
+ __u16 rlimit_nlimits;
+ /* tty */
+ __u16 n_tty_buf_size;
+ __u16 tty_termios_ncc;
+} __attribute__((aligned(8)));
+
+/* checkpoint image header */
+struct ckpt_hdr_header {
+ struct ckpt_hdr h;
+ __u64 magic;
+
+ __u16 arch_id;
+
+ __u16 major;
+ __u16 minor;
+ __u16 patch;
+ __u16 rev;
+
+ struct ckpt_const constants;
+
+ __u64 time; /* when checkpoint taken */
+ __u64 uflags; /* uflags from checkpoint */
+
+ /*
+ * the header is followed by three strings:
+ * char release[const.uts_release_len];
+ * char version[const.uts_version_len];
+ * char machine[const.uts_machine_len];
+ */
+} __attribute__((aligned(8)));
+
+/* checkpoint image trailer */
+struct ckpt_hdr_tail {
+ struct ckpt_hdr h;
+ __u64 magic;
+} __attribute__((aligned(8)));
+
+/* task tree */
+struct ckpt_hdr_tree {
+ struct ckpt_hdr h;
+ __s32 nr_tasks;
+} __attribute__((aligned(8)));
+
+struct ckpt_pids {
+ __s32 vpid;
+ __s32 vppid;
+ __s32 vtgid;
+ __s32 vpgid;
+ __s32 vsid;
+} __attribute__((aligned(8)));
+
+/* pids */
+#define CKPT_PID_NULL -1
+
+/* task data */
+struct ckpt_hdr_task {
+ struct ckpt_hdr h;
+ __u32 state;
+ __u32 exit_state;
+ __u32 exit_code;
+ __u32 exit_signal;
+ __u32 pdeath_signal;
+
+ __u64 set_child_tid;
+ __u64 clear_child_tid;
+
+ __u32 compat_robust_futex_head_len;
+ __u32 compat_robust_futex_list; /* a compat __user ptr */
+ __u32 robust_futex_head_len;
+ __u64 robust_futex_list; /* a __user ptr */
+} __attribute__((aligned(8)));
+
+/* Posix capabilities */
+struct ckpt_capabilities {
+ __u32 cap_i_0, cap_i_1; /* inheritable set */
+ __u32 cap_p_0, cap_p_1; /* permitted set */
+ __u32 cap_e_0, cap_e_1; /* effective set */
+ __u32 cap_b_0, cap_b_1; /* bounding set */
+ __u32 securebits;
+ __u32 padding;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_task_creds {
+ struct ckpt_hdr h;
+ __s32 cred_ref;
+ __s32 ecred_ref;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_cred {
+ struct ckpt_hdr h;
+ __u32 uid, suid, euid, fsuid;
+ __u32 gid, sgid, egid, fsgid;
+ __s32 user_ref;
+ __s32 groupinfo_ref;
+ struct ckpt_capabilities cap_s;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_groupinfo {
+ struct ckpt_hdr h;
+ __u32 ngroups;
+ /*
+ * This is followed by ngroups __u32s
+ */
+ __u32 groups[0];
+} __attribute__((aligned(8)));
+
+/*
+ * todo - keyrings and LSM
+ * These may be better done with userspace help though
+ */
+struct ckpt_hdr_user_struct {
+ struct ckpt_hdr h;
+ __u32 uid;
+ __s32 userns_ref;
+} __attribute__((aligned(8)));
+
+/*
+ * The user-struct mostly tracks system resource usage.
+ * Most of it's contents therefore will simply be set
+ * correctly as restart opens resources
+ */
+struct ckpt_hdr_user_ns {
+ struct ckpt_hdr h;
+ __s32 creator_ref;
+} __attribute__((aligned(8)));
+
+/* namespaces */
+struct ckpt_hdr_task_ns {
+ struct ckpt_hdr h;
+ __s32 ns_objref;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_ns {
+ struct ckpt_hdr h;
+ __s32 uts_objref;
+ __u32 ipc_objref;
+} __attribute__((aligned(8)));
+
+/* cannot include <linux/tty.h> from userspace, so define: */
+#define CKPT_NEW_UTS_LEN 64
+
+struct ckpt_hdr_utsns {
+ struct ckpt_hdr h;
+ char sysname[CKPT_NEW_UTS_LEN + 1];
+ char nodename[CKPT_NEW_UTS_LEN + 1];
+ char release[CKPT_NEW_UTS_LEN + 1];
+ char version[CKPT_NEW_UTS_LEN + 1];
+ char machine[CKPT_NEW_UTS_LEN + 1];
+ char domainname[CKPT_NEW_UTS_LEN + 1];
+} __attribute__((aligned(8)));
+
+/* task's shared resources */
+struct ckpt_hdr_task_objs {
+ struct ckpt_hdr h;
+
+ __s32 files_objref;
+ __s32 mm_objref;
+ __s32 sighand_objref;
+ __s32 signal_objref;
+} __attribute__((aligned(8)));
+
+/* restart blocks */
+struct ckpt_hdr_restart_block {
+ struct ckpt_hdr h;
+ __u64 function_type;
+ __u64 arg_0;
+ __u64 arg_1;
+ __u64 arg_2;
+ __u64 arg_3;
+ __u64 arg_4;
+} __attribute__((aligned(8)));
+
+enum restart_block_type {
+ CKPT_RESTART_BLOCK_NONE = 1,
+ CKPT_RESTART_BLOCK_HRTIMER_NANOSLEEP,
+ CKPT_RESTART_BLOCK_POSIX_CPU_NANOSLEEP,
+ CKPT_RESTART_BLOCK_COMPAT_NANOSLEEP,
+ CKPT_RESTART_BLOCK_COMPAT_CLOCK_NANOSLEEP,
+ CKPT_RESTART_BLOCK_POLL,
+ CKPT_RESTART_BLOCK_FUTEX
+};
+
+/* file system */
+struct ckpt_hdr_file_table {
+ struct ckpt_hdr h;
+ __s32 fdt_nfds;
+} __attribute__((aligned(8)));
+
+/* file descriptors */
+struct ckpt_hdr_file_desc {
+ struct ckpt_hdr h;
+ __s32 fd_objref;
+ __s32 fd_descriptor;
+ __u32 fd_close_on_exec;
+} __attribute__((aligned(8)));
+
+enum file_type {
+ CKPT_FILE_IGNORE = 0,
+ CKPT_FILE_GENERIC,
+ CKPT_FILE_PIPE,
+ CKPT_FILE_FIFO,
+ CKPT_FILE_SOCKET,
+ CKPT_FILE_TTY,
+ CKPT_FILE_MAX
+};
+
+/* file objects */
+struct ckpt_hdr_file {
+ struct ckpt_hdr h;
+ __u32 f_type;
+ __u32 f_mode;
+ __u32 f_flags;
+ __s32 f_credref;
+ __u64 f_pos;
+ __u64 f_version;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_file_generic {
+ struct ckpt_hdr_file common;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_file_pipe {
+ struct ckpt_hdr_file common;
+ __s32 pipe_objref;
+} __attribute__((aligned(8)));
+
+/* socket */
+struct ckpt_hdr_socket {
+ struct ckpt_hdr h;
+
+ struct { /* struct socket */
+ __u64 flags;
+ __u8 state;
+ } socket __attribute__ ((aligned(8)));
+
+ struct { /* struct sock_common */
+ __u32 bound_dev_if;
+ __u32 reuse;
+ __u16 family;
+ __u8 state;
+ } sock_common __attribute__ ((aligned(8)));
+
+ struct { /* struct sock */
+ __s64 rcvlowat;
+ __u64 flags;
+
+ __s64 rcvtimeo;
+ __s64 sndtimeo;
+
+ __u32 err;
+ __u32 err_soft;
+ __u32 priority;
+ __s32 rcvbuf;
+ __s32 sndbuf;
+ __u16 type;
+ __s16 backlog;
+
+ __u8 protocol;
+ __u8 state;
+ __u8 shutdown;
+ __u8 userlocks;
+ __u8 no_check;
+
+ struct linger linger;
+ } sock __attribute__ ((aligned(8)));
+} __attribute__ ((aligned(8)));
+
+struct ckpt_hdr_socket_queue {
+ struct ckpt_hdr h;
+ __u32 skb_count;
+ __u32 total_bytes;
+} __attribute__ ((aligned(8)));
+
+struct ckpt_hdr_socket_buffer {
+ struct ckpt_hdr h;
+ __s32 sk_objref;
+ __s32 pr_objref;
+};
+
+#define CKPT_UNIX_LINKED 1
+struct ckpt_hdr_socket_unix {
+ struct ckpt_hdr h;
+ __s32 this;
+ __s32 peer;
+ __u32 peercred_uid;
+ __u32 peercred_gid;
+ __u32 flags;
+ __u32 laddr_len;
+ __u32 raddr_len;
+ struct sockaddr_un laddr;
+ struct sockaddr_un raddr;
+} __attribute__ ((aligned(8)));
+
+struct ckpt_hdr_socket_inet {
+ struct ckpt_hdr h;
+ __u32 laddr_len;
+ __u32 raddr_len;
+ struct sockaddr_in laddr;
+ struct sockaddr_in raddr;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_file_socket {
+ struct ckpt_hdr_file common;
+ __s32 sock_objref;
+} __attribute__((aligned(8)));
+
+/* memory layout */
+struct ckpt_hdr_mm {
+ struct ckpt_hdr h;
+ __u32 map_count;
+ __s32 exe_objref;
+
+ __u64 def_flags;
+ __u64 flags;
+
+ __u64 start_code, end_code, start_data, end_data;
+ __u64 start_brk, brk, start_stack;
+ __u64 arg_start, arg_end, env_start, env_end;
+} __attribute__((aligned(8)));
+
+/* vma subtypes - index into restore_vma_dispatch[] */
+enum vma_type {
+ CKPT_VMA_IGNORE = 0,
+ CKPT_VMA_VDSO, /* special vdso vma */
+ CKPT_VMA_ANON, /* private anonymous */
+ CKPT_VMA_FILE, /* private mapped file */
+ CKPT_VMA_SHM_ANON, /* shared anonymous */
+ CKPT_VMA_SHM_ANON_SKIP, /* shared anonymous (skip contents) */
+ CKPT_VMA_SHM_FILE, /* shared mapped file, only msync */
+ CKPT_VMA_SHM_IPC, /* shared sysvipc */
+ CKPT_VMA_SHM_IPC_SKIP, /* shared sysvipc (skip contents) */
+ CKPT_VMA_MAX,
+};
+
+/* vma descriptor */
+struct ckpt_hdr_vma {
+ struct ckpt_hdr h;
+ __u32 vma_type;
+ __s32 vma_objref; /* objref of backing file */
+ __s32 ino_objref; /* objref of shared segment */
+ __u32 _padding;
+ __u64 ino_size; /* size of shared segment */
+
+ __u64 vm_start;
+ __u64 vm_end;
+ __u64 vm_page_prot;
+ __u64 vm_flags;
+ __u64 vm_pgoff;
+} __attribute__((aligned(8)));
+
+/* page array */
+struct ckpt_hdr_pgarr {
+ struct ckpt_hdr h;
+ __u64 nr_pages; /* number of pages to saved */
+} __attribute__((aligned(8)));
+
+/* signals */
+struct ckpt_sigset {
+ __u8 sigset[CKPT_ARCH_NSIG / 8];
+} __attribute__((aligned(8)));
+
+struct ckpt_sigaction {
+ __u64 _sa_handler;
+ __u64 sa_flags;
+ __u64 sa_restorer;
+ struct ckpt_sigset sa_mask;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_sighand {
+ struct ckpt_hdr h;
+ struct ckpt_sigaction action[0];
+} __attribute__((aligned(8)));
+
+struct ckpt_siginfo {
+ __u32 signo;
+ __u32 _errno;
+ __u32 code;
+
+ __u32 pid;
+ __s32 uid;
+ __u32 sigval_int;
+ __u64 sigval_ptr;
+ __u64 utime;
+ __u64 stime;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_sigpending {
+ struct ckpt_hdr h;
+ __u32 nr_pending;
+ struct ckpt_sigset signal;
+ struct ckpt_siginfo siginfo[0];
+} __attribute__((aligned(8)));
+
+struct ckpt_rlimit {
+ __u64 rlim_cur;
+ __u64 rlim_max;
+} __attribute__((aligned(8)));
+
+/* cannot include <linux/resource.h> from userspace, so define: */
+#define CKPT_RLIM_NLIMITS 16
+
+struct ckpt_hdr_signal {
+ struct ckpt_hdr h;
+ /* rlimit */
+ struct ckpt_rlimit rlim[CKPT_RLIM_NLIMITS];
+ /* itimer */
+ __u64 it_real_value;
+ __u64 it_real_incr;
+ __u64 it_virt_value;
+ __u64 it_virt_incr;
+ __u64 it_prof_value;
+ __u64 it_prof_incr;
+ /* tty */
+ __s32 tty_objref;
+ __s32 tty_pgrp;
+ __s32 tty_old_pgrp;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_signal_task {
+ struct ckpt_hdr h;
+ struct ckpt_sigset blocked;
+} __attribute__((aligned(8)));
+
+/* ipc commons */
+struct ckpt_hdr_ipcns {
+ struct ckpt_hdr h;
+ __u64 shm_ctlmax;
+ __u64 shm_ctlall;
+ __s32 shm_ctlmni;
+
+ __s32 msg_ctlmax;
+ __s32 msg_ctlmnb;
+ __s32 msg_ctlmni;
+
+ __s32 sem_ctl_msl;
+ __s32 sem_ctl_mns;
+ __s32 sem_ctl_opm;
+ __s32 sem_ctl_mni;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_ipc {
+ struct ckpt_hdr h;
+ __u32 ipc_type;
+ __u32 ipc_count;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_ipc_perms {
+ struct ckpt_hdr h;
+ __s32 id;
+ __u32 key;
+ __u32 uid;
+ __u32 gid;
+ __u32 cuid;
+ __u32 cgid;
+ __u32 mode;
+ __u32 _padding;
+ __u64 seq;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_ipc_shm {
+ struct ckpt_hdr h;
+ struct ckpt_hdr_ipc_perms perms;
+ __u64 shm_segsz;
+ __u64 shm_atim;
+ __u64 shm_dtim;
+ __u64 shm_ctim;
+ __s32 shm_cprid;
+ __s32 shm_lprid;
+ __u32 mlock_uid;
+ __u32 flags;
+ __u32 objref;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_ipc_msg {
+ struct ckpt_hdr h;
+ struct ckpt_hdr_ipc_perms perms;
+ __u64 q_stime;
+ __u64 q_rtime;
+ __u64 q_ctime;
+ __u64 q_cbytes;
+ __u64 q_qnum;
+ __u64 q_qbytes;
+ __s32 q_lspid;
+ __s32 q_lrpid;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_ipc_msg_msg {
+ struct ckpt_hdr h;
+ __s32 m_type;
+ __u32 m_ts;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_ipc_sem {
+ struct ckpt_hdr h;
+ struct ckpt_hdr_ipc_perms perms;
+ __u64 sem_otime;
+ __u64 sem_ctime;
+ __u32 sem_nsems;
+} __attribute__((aligned(8)));
+
+/* devices */
+struct ckpt_hdr_file_tty {
+ struct ckpt_hdr_file common;
+ __s32 tty_objref;
+};
+
+struct ckpt_hdr_tty {
+ struct ckpt_hdr h;
+
+ __u16 driver_type;
+ __u16 driver_subtype;
+
+ __s32 link_objref;
+ __s32 file_objref;
+ __u32 _padding;
+
+ __u32 index;
+ __u32 ldisc;
+ __u64 flags;
+
+ /* termios */
+ struct {
+ __u16 c_iflag;
+ __u16 c_oflag;
+ __u16 c_cflag;
+ __u16 c_lflag;
+ __u8 c_line;
+ __u8 c_cc[CKPT_TTY_NCC];
+ } __attribute__((aligned(8))) termios;
+
+ /* winsize */
+ struct {
+ __u16 ws_row;
+ __u16 ws_col;
+ __u16 ws_xpixel;
+ __u16 ws_ypixel;
+ } __attribute__((aligned(8))) winsize;
+} __attribute__((aligned(8)));
+
+/* cannot include <linux/tty.h> from userspace, so define: */
+#define CKPT_N_TTY_BUF_SIZE 4096
+
+struct ckpt_hdr_ldisc_n_tty {
+ struct ckpt_hdr h;
+
+ __u32 column;
+ __u32 datalen;
+ __u32 canon_column;
+ __u32 canon_datalen;
+ __u32 canon_data;
+
+ __u16 minimum_to_wake;
+
+ __u8 stopped;
+ __u8 hw_stopped;
+ __u8 flow_stopped;
+ __u8 packet;
+ __u8 ctrl_status;
+ __u8 lnext;
+ __u8 erasing;
+ __u8 raw;
+ __u8 real_raw;
+ __u8 icanon;
+ __u8 closing;
+ __u8 padding[3];
+
+ __u8 read_flags[CKPT_N_TTY_BUF_SIZE / 8];
+
+ /* if @datalen > 0, buffer contents follow (next object) */
+} __attribute__((aligned(8)));
+
+#define CKPT_TST_OVERFLOW_16(a,b) ((sizeof(a) > sizeof(b)) && ((a) > SHORT_MAX))
+
+#define CKPT_TST_OVERFLOW_32(a,b) ((sizeof(a) > sizeof(b)) && ((a) > INT_MAX))
+
+#define CKPT_TST_OVERFLOW_64(a,b) ((sizeof(a) > sizeof(b)) && ((a) > LONG_MAX))
+
+
+#endif /* _CHECKPOINT_CKPT_HDR_H_ */
--git a/scripts/extract-headers.sh b/scripts/extract-headers.sh
new file mode 100755
index 0000000..360a889
--- /dev/null
+++ b/scripts/extract-headers.sh
@@ -0,0 +1,250 @@
+#!/bin/bash
+#
+# Copyright (C) 2009 IBM Corp.
+# Author: Matt Helsley <matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file COPYING in the main directory of the Linux
+# distribution for more details.
+#
+
+#
+# Sanitize checkpoint/restart kernel headers for userspace.
+#
+
+function usage()
+{
+ echo "Usage: $0 [-h|--help] -s|--kernel-src=DIR"
+}
+
+OUTPUT_INCLUDES="include"
+OPTIONS=`getopt -o s:o:h --long kernel-src:,output:,help -- "$@"`
+eval set -- "${OPTIONS}"
+while true ; do
+ case "$1" in
+ -s|--kernel-src)
+ KERNELSRC="$2"
+ shift 2 ;;
+ -o|--output)
+ OUTPUT_INCLUDES="$2"
+ shift 2 ;;
+ -h|--help)
+ usage
+ exit 0 ;;
+ --)
+ shift
+ break ;;
+ *)
+ echo "Unknown option: $1"
+ shift
+ echo "Unparsed options: $@"
+ usage 1>&2
+ exit 2 ;;
+ esac
+done
+
+if [ -z "${KERNELSRC}" -o '!' -d "${KERNELSRC}" ]; then
+ usage 1>&2
+ exit 2
+fi
+
+# Match cpp includes
+INCLUDE_PRE_REGEX='#[[:space:]]*include[[:space:]]*\([<"]'
+INCLUDE_FILE_REGEX='[^">]*'
+INCLUDE_POST_REGEX='[">]\)'
+
+# Match cpp includes with \1 being the included file
+INCLUDE_REGEX="${INCLUDE_PRE_REGEX}${INCLUDE_FILE_REGEX}${INCLUDE_POST_REGEX}"
+
+# Match includes of linux/types.h (\1 == linux/types.h)
+INCLUDE_LINUX_TYPES_REGEX="${INCLUDE_PRE_REGEX}linux\/types\.h${INCLUDE_POST_REGEX}"
+
+# Match includes of linux/* with \1 being everything preceding "linux/" and \2
+# being everything following "linux/"
+INCLUDE_LINUX_REGEX="${INCLUDE_PRE_REGEX}"'\)'"linux\/"'\('"${INCLUDE_FILE_REGEX}${INCLUDE_POST_REGEX}"
+
+#
+# Run the kernel header through cpp to strip out __KERNEL__ sections but try
+# to leave the rest untouched.
+#
+function do_cpp ()
+{
+ local CPP_FILE="$1"
+ local START_DEFINE="$2"
+ shift 2
+
+ #
+ # Hide #include directives then run cpp. Make cpp keep comments, not
+ # insert line numbers, avoid system/gcc/std defines, and only expand
+ # directives. Strip cpp output until we get to #define START_DEFINE,
+ # and collapse the excessive number of blank lines that cpp outputs
+ # in place of directives. Finally, replace linux/ with sys/ prefixes
+ # of include paths, except for linux/types.h (needed for __uXX types).
+ #
+ sed -e 's|'"${INCLUDE_REGEX}"'|/*#include \1*/|g' "${CPP_FILE}" | \
+ cpp -CC -P -U__KERNEL__ -undef -nostdinc -fdirectives-only -dDI "$@" | \
+ awk 'BEGIN { do_print = 0; }
+ /#[[:space:]]*define '"${START_DEFINE}"'/ { do_print = 1; next; }
+ (do_print == 1) { print }' | \
+ cat -s | \
+ sed -e 's|/\*'"${INCLUDE_REGEX}"'\*/|#include \1|g' | \
+ sed -e "/${INCLUDE_LINUX_TYPES_REGEX}/n" \
+ -e "s|${INCLUDE_LINUX_REGEX}|#include \1sys/\2|"
+ echo ''
+}
+
+# Map KARCH to something suitable for CPP e.g. __i386__
+function karch_to_cpparch ()
+{
+ local KARCH="$1"
+ local WORDBITS="$2"
+ shift 2;
+
+ case "${KARCH}" in
+ x86) [ "${WORDBITS}" == "32" ] && echo -n "i386"
+ [ "${WORDBITS}" == "64" ] && echo -n "x86_64"
+ [ -z "${WORDBITS}" ] && echo -n 'i386__ || __x86_64' # HACK
+ ;;
+ s390*) echo -n "s390x" ;;
+ *) echo -n "${KARCH}" ;;
+ esac
+ return 0
+}
+
+set -e
+
+mkdir -p "${OUTPUT_INCLUDES}/linux"
+mkdir -p "${OUTPUT_INCLUDES}/asm"
+
+#
+# Process include/linux/checkpoint_hdr.h -> include/linux/checkpoint_hdr.h
+#
+cat - > "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h" <<-EOFOO
+/*
+ * Generated by $(basename "$0").
+ */
+#ifndef _CHECKPOINT_CKPT_HDR_H_
+#define _CHECKPOINT_CKPT_HDR_H_
+
+EOFOO
+
+do_cpp "${KERNELSRC}/include/linux/checkpoint_hdr.h" "_CHECKPOINT_CKPT_HDR_H_" \
+>> "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h"
+echo '#endif /* _CHECKPOINT_CKPT_HDR_H_ */' >> "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h"
+
+#
+# Process include/linux/checkpoint.h -> include/linux/checkpoint.h
+# and arch/*/include/asm/unistd.h -> include/linux/checkpoint.h.
+# Eventually the unistd.h portion will get into the glibc headers and
+# we can drop that part of this script.
+#
+
+(
+#
+# We use ARCH_COND to break up architecture-specific sections of the header.
+#
+ARCH_COND='#if'
+REGEX='[[:space:]]*#[[:space:]]*define[[:space:]]+__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+[[:digit:]]+'
+
+cat - <<-EOFOE
+/*
+ * Generated by $(basename "$0").
+ */
+#ifndef _LINUX_CHECKPOINT_H_
+#define _LINUX_CHECKPOINT_H_
+
+EOFOE
+
+do_cpp "${KERNELSRC}/include/linux/checkpoint.h" "_LINUX_CHECKPOINT_H_"
+
+find "${KERNELSRC}/arch" -name 'unistd*.h' -print | sort | \
+while read UNISTDH ; do
+ [ -n "${UNISTDH}" ] || continue
+ grep -q -E "${REGEX}" "${UNISTDH}" || continue
+
+ KARCH=$(echo "${UNISTDH}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|')
+ WORDBITS=$(basename "${UNISTDH}" | sed -e 's/unistd_*\([[:digit:]]\+\)\.h/\1/')
+ CPPARCH="$(karch_to_cpparch "${KARCH}" "${WORDBITS}")"
+ echo -e "${ARCH_COND} __${CPPARCH}__\\n"
+ grep -E "${REGEX}" "${UNISTDH}" | \
+ sed -e 's/^[[:space:]]*#[[:space:]]*define[[:space:]]\+__NR_\([^[:space:]]\+\)[[:space:]]\+\([^[:space:]]\+\).*$/#\tifndef __NR_\1\n#\t\tdefine __NR_\1 \2\n#\tendif\n/'
+ ARCH_COND='#elif'
+done
+
+cat - <<-EOFOFOE
+#else
+#error "Architecture does not have definitons for __NR_(checkpoint|restart)"
+#endif
+#endif /* _LINUX_CHECKPOINT_H_ */
+EOFOFOE
+
+) > "${OUTPUT_INCLUDES}/linux/checkpoint.h"
+
+#
+# Process arch/*/include/asm/checkpoint_hdr.h -> include/asm/checkpoint_hdr.h
+# Use #if __arch1__ ... #elif __arch2___ ... #endif to wrap each portion.
+#
+ARCH_COND='#if'
+
+find "${KERNELSRC}/arch" -name 'checkpoint_hdr.h' -print | sort | \
+while read ARCH_CHECKPOINT_HDR_H ; do
+ [ -n "${ARCH_CHECKPOINT_HDR_H}" ] || continue
+
+ KARCH=$(echo "${ARCH_CHECKPOINT_HDR_H}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|')
+ UPCASE_KARCH=$(echo "${KARCH}" | tr 'a-z' 'A-Z')
+ mkdir -p "${OUTPUT_INCLUDES}/asm-${KARCH}"
+ cat - > "${OUTPUT_INCLUDES}/asm-${KARCH}/checkpoint_hdr.h" <<-EOFOEOF
+ /*
+ * Generated by $(basename "$0").
+ */
+ #ifndef __ASM_${UPCASE_KARCH}_CHECKPOINT_HDR_H_
+ #define __ASM_${UPCASE_KARCH}_CHECKPOINT_HDR_H_
+
+ EOFOEOF
+
+ do_cpp "${KERNELSRC}/arch/${KARCH}/include/asm/checkpoint_hdr.h" '__ASM.*_CKPT_HDR_H' -D_CHECKPOINT_CKPT_HDR_H_ >> "${OUTPUT_INCLUDES}/asm-${KARCH}/checkpoint_hdr.h"
+
+ cat - >> "${OUTPUT_INCLUDES}/asm-${KARCH}/checkpoint_hdr.h" <<-FOEOEOF
+
+ #endif /* __ASM_${UPCASE_KARCH}_CHECKPOINT_HDR_H_ */
+ FOEOEOF
+
+ ARCH_COND='#elif'
+done
+
+#
+# Process arch/*/include/asm/checkpoint_hdr.h -> include/asm/checkpoint_hdr.h
+# Use #if __arch1__ ... #elif __arch2___ ... #endif to wrap each portion.
+#
+(
+ARCH_COND='#if'
+
+cat - <<-EOFOEOF
+/*
+ * Generated by $(basename "$0").
+ */
+#ifndef __ASM_CHECKPOINT_HDR_H_
+#define __ASM_CHECKPOINT_HDR_H_
+EOFOEOF
+
+find "${KERNELSRC}/arch" -name 'checkpoint_hdr.h' -print | sort | \
+while read ARCH_CHECKPOINT_HDR_H ; do
+ [ -n "${ARCH_CHECKPOINT_HDR_H}" ] || continue
+
+ KARCH=$(echo "${ARCH_CHECKPOINT_HDR_H}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|')
+ CPPARCH="$(karch_to_cpparch "${KARCH}" "")"
+ cat - <<-EOFOEOF
+ ${ARCH_COND} __${CPPARCH}__
+ #include <asm-${KARCH}/checkpoint_hdr.h>
+ EOFOEOF
+ ARCH_COND='#elif'
+done
+
+cat - <<-FOEOEOF
+#else
+#error "Architecture does not have definitons needed for checkpoint images."
+#endif
+#endif /* __ASM_CHECKPOINT_HDR_H_ */
+FOEOEOF
+
+) > "${OUTPUT_INCLUDES}/asm/checkpoint_hdr.h"
--
1.5.6.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] user-cr: Extract headers from kernel source tree.
[not found] ` <1254554424-2979-2-git-send-email-matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2009-10-03 7:26 ` Matt Helsley
2009-10-03 21:40 ` Nathan Lynch
2009-10-23 18:38 ` Oren Laadan
2 siblings, 0 replies; 6+ messages in thread
From: Matt Helsley @ 2009-10-03 7:26 UTC (permalink / raw)
To: Oren Laadan; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
On Sat, Oct 03, 2009 at 12:20:25AM -0700, Matt Helsley wrote:
> Using kernel headers directly from userspace is strongly discouraged.
>
>
> Sanitize kernel headers for userspace by extracting non-__KERNEL__
> portions of the various checkpoint headers and placing them in a
> similar organization of userspace headers.
>
> The script is run from the top level of the user-cr source tree like:
>
> ./scripts/extract-headers.sh -s <path-to-kern-source> -o ./include
>
> The patch includes a copy of the auto-generated headers and adjusts
> the user-cr programs to use them.
>
> Programs should only include linux/checkpoint.h and
> linux/checkpoint_hdr.h. asm/checkpoint_hdr.h is included from
> linux/checkpoint_hdr.h
>
> Signed-off-by: Matt Helsley <matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Note that:
"[PATCH] Fix up headers so we can munge them for use by userspace."
must be applied to the kernel tree before the script in this patch will
reproduce the headers properly. Since this patch includes the necessary
headers synchronizing the transition shouldn't be a problem.
Cheers,
-Matt
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] user-cr: Extract headers from kernel source tree.
[not found] ` <1254554424-2979-2-git-send-email-matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-03 7:26 ` Matt Helsley
@ 2009-10-03 21:40 ` Nathan Lynch
[not found] ` <1254606041.2928.3.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2009-10-23 18:38 ` Oren Laadan
2 siblings, 1 reply; 6+ messages in thread
From: Nathan Lynch @ 2009-10-03 21:40 UTC (permalink / raw)
To: Matt Helsley; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
On Sat, 2009-10-03 at 00:20 -0700, Matt Helsley wrote:
> Sanitize kernel headers for userspace by extracting non-__KERNEL__
> portions of the various checkpoint headers and placing them in a
> similar organization of userspace headers.
>
> The script is run from the top level of the user-cr source tree like:
>
> ./scripts/extract-headers.sh -s <path-to-kern-source> -o ./include
>
> The patch includes a copy of the auto-generated headers and adjusts
> the user-cr programs to use them.
I appreciate the effort put into this, but why isn't the
"headers_install" target of the kernel Makefile sufficient to produce
headers that are usable by userspace? So far as I know, other projects
with complex kernel/user interfaces (e.g. kvm) haven't had to resort to
special-purpose programs like this.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] user-cr: Extract headers from kernel source tree.
[not found] ` <1254606041.2928.3.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2009-10-05 18:00 ` Matt Helsley
[not found] ` <20091005180000.GD18101-52DBMbEzqgQ/wnmkkaCWp/UQ3DHhIser@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Matt Helsley @ 2009-10-05 18:00 UTC (permalink / raw)
To: Nathan Lynch; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
On Sat, Oct 03, 2009 at 04:40:41PM -0500, Nathan Lynch wrote:
> On Sat, 2009-10-03 at 00:20 -0700, Matt Helsley wrote:
> > Sanitize kernel headers for userspace by extracting non-__KERNEL__
> > portions of the various checkpoint headers and placing them in a
> > similar organization of userspace headers.
> >
> > The script is run from the top level of the user-cr source tree like:
> >
> > ./scripts/extract-headers.sh -s <path-to-kern-source> -o ./include
> >
> > The patch includes a copy of the auto-generated headers and adjusts
> > the user-cr programs to use them.
>
> I appreciate the effort put into this, but why isn't the
> "headers_install" target of the kernel Makefile sufficient to produce
> headers that are usable by userspace? So far as I know, other projects
> with complex kernel/user interfaces (e.g. kvm) haven't had to resort to
> special-purpose programs like this.
This script trims down the kernel headers from 4MB to 62k and places them
in the user-cr source tree. That means it's reasonable to just copy user-cr
anywhere and rebuild -- no need to copy your kernel headers seperately
and then fuss with KERNELSRC etc.
At one point this patch also moved all arch-detection out of the Makefile
and left it to cpp. That's no longer true now that we have the bits
necessary for clone_with_pids. A seperate patch could finish that though.
Removing arch-detection in the Makefile might make cross-compiling easier.
That said, it's not meant to replace /usr/include headers. When the
syscall numbers make it into /usr/include, for instance, the part of this
script that gathers them will be obsolete.
Lastly, it may be useful for anyone who wants to compare c/r headers to
build checkpoint image translation tools. It should be alot easier to
see the relevant changes...
So it's useful for me. Perhaps I should make it optional and toss it into
contrib/ instead.
Cheers,
-Matt Helsley
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] user-cr: Extract headers from kernel source tree.
[not found] ` <20091005180000.GD18101-52DBMbEzqgQ/wnmkkaCWp/UQ3DHhIser@public.gmane.org>
@ 2009-10-06 2:25 ` Serge E. Hallyn
0 siblings, 0 replies; 6+ messages in thread
From: Serge E. Hallyn @ 2009-10-06 2:25 UTC (permalink / raw)
To: Matt Helsley
Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
Nathan Lynch
Quoting Matt Helsley (matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org):
> On Sat, Oct 03, 2009 at 04:40:41PM -0500, Nathan Lynch wrote:
> > On Sat, 2009-10-03 at 00:20 -0700, Matt Helsley wrote:
> > > Sanitize kernel headers for userspace by extracting non-__KERNEL__
> > > portions of the various checkpoint headers and placing them in a
> > > similar organization of userspace headers.
> > >
> > > The script is run from the top level of the user-cr source tree like:
> > >
> > > ./scripts/extract-headers.sh -s <path-to-kern-source> -o ./include
> > >
> > > The patch includes a copy of the auto-generated headers and adjusts
> > > the user-cr programs to use them.
> >
> > I appreciate the effort put into this, but why isn't the
> > "headers_install" target of the kernel Makefile sufficient to produce
> > headers that are usable by userspace? So far as I know, other projects
> > with complex kernel/user interfaces (e.g. kvm) haven't had to resort to
> > special-purpose programs like this.
>
> This script trims down the kernel headers from 4MB to 62k and places them
> in the user-cr source tree. That means it's reasonable to just copy user-cr
> anywhere and rebuild -- no need to copy your kernel headers seperately
> and then fuss with KERNELSRC etc.
>
> At one point this patch also moved all arch-detection out of the Makefile
> and left it to cpp. That's no longer true now that we have the bits
> necessary for clone_with_pids. A seperate patch could finish that though.
> Removing arch-detection in the Makefile might make cross-compiling easier.
>
> That said, it's not meant to replace /usr/include headers. When the
> syscall numbers make it into /usr/include, for instance, the part of this
> script that gathers them will be obsolete.
>
> Lastly, it may be useful for anyone who wants to compare c/r headers to
> build checkpoint image translation tools. It should be alot easier to
> see the relevant changes...
>
> So it's useful for me. Perhaps I should make it optional and toss it into
> contrib/ instead.
Perhaps we need more discussion on how we all compile this stuff...
On my one system, I don't have kernel sources on my target machine at
all. Every time there is a meaningful change of headers I do
scp include/linux/checkpoint* root@target:/usr/include/linux
scp arch/s390/include/asm/checkpoint_hdr.h root@target:/usr/include/asm/
On my kvm partition, I can't recall whether make headers_install worked,
or whether I manually copied the checkpoint headers in. I basically never
compile ckptinfo precisely because it requires finagling with KERNELSRC
and then doesn't compile anyway...
-serge
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] user-cr: Extract headers from kernel source tree.
[not found] ` <1254554424-2979-2-git-send-email-matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-03 7:26 ` Matt Helsley
2009-10-03 21:40 ` Nathan Lynch
@ 2009-10-23 18:38 ` Oren Laadan
2 siblings, 0 replies; 6+ messages in thread
From: Oren Laadan @ 2009-10-23 18:38 UTC (permalink / raw)
To: Matt Helsley; +Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Pulled, thanks.
Matt Helsley wrote:
> Using kernel headers directly from userspace is strongly discouraged.
>
> Sanitize kernel headers for userspace by extracting non-__KERNEL__
> portions of the various checkpoint headers and placing them in a
> similar organization of userspace headers.
>
> The script is run from the top level of the user-cr source tree like:
>
> ./scripts/extract-headers.sh -s <path-to-kern-source> -o ./include
>
> The patch includes a copy of the auto-generated headers and adjusts
> the user-cr programs to use them.
>
> Programs should only include linux/checkpoint.h and
> linux/checkpoint_hdr.h. asm/checkpoint_hdr.h is included from
> linux/checkpoint_hdr.h
>
> Signed-off-by: Matt Helsley <matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
>
> Changelog:
> v3:
> Inverted headers/$(CKPT_HEADERS) rule dependency. This causes it
> to extract headers only when one or more are missing.
>
> Moved all of the include definition hacks into a kernel header
> patch instead.
>
> v2:
> Re-added KERNELSRC ?= ../linux
>
> Merged checkpoint_syscalls.h with checkpoint.h and added a
> comment about the unistd code eventually going away.
> Thanks to Oren for pointing out the latter.
>
> Added special-case code for stripping linux/un.h from the
> checkpoint_hdr.h; (s/linux/sys/ did not work)
>
> Cleaned up do_cpp to make the "include" regex tricks more
> obvious to the casual reader.
>
> Modified Makefile to re-extract headers for every build.
>
> Removed the find command that filled CKPT_HEADERS.
> This was the easiest solution. Otherwise the Makefiles
> might become considerably more obfuscated.
>
> Tested on and made changes for s390x:
>
> Always include sys/types.h before linux/types.h to avoid
> conflicting definitions.
>
> Define NUM_CR_WORDS if it's not already defined in
> asm/ptrace.h (seems some s390x installs don't
> define NUM_CR_WORDS anywhere outside the kernel
> source).
> ---
> Makefile | 40 +-
> ckptinfo.c | 1 +
> clone_ppc.c | 1 +
> clone_s390x.c | 1 +
> clone_x86_32.c | 1 +
> include/asm-powerpc/checkpoint_hdr.h | 21 +
> include/asm-s390/checkpoint_hdr.h | 89 ++++
> include/asm-x86/checkpoint_hdr.h | 126 ++++++
> include/asm/checkpoint_hdr.h | 15 +
> include/linux/checkpoint.h | 73 ++++
> include/linux/checkpoint_hdr.h | 749 ++++++++++++++++++++++++++++++++++
> scripts/extract-headers.sh | 250 +++++++++++
> 12 files changed, 1344 insertions(+), 23 deletions(-)
> create mode 100644 include/asm-powerpc/checkpoint_hdr.h
> create mode 100644 include/asm-s390/checkpoint_hdr.h
> create mode 100644 include/asm-x86/checkpoint_hdr.h
> create mode 100644 include/asm/checkpoint_hdr.h
> create mode 100644 include/linux/checkpoint.h
> create mode 100644 include/linux/checkpoint_hdr.h
> create mode 100755 scripts/extract-headers.sh
>
> diff --git a/Makefile b/Makefile
> index 7f5cb27..181cc1c 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1,24 +1,9 @@
> -
> KERNELSRC ?= ../linux
> -KERNELBUILD ?= ../linux
> -
> -# default with 'make headers_install'
> -KERNELHDR ?= $(KERNELSRC)/usr/include
> -
> -ifneq "$(realpath $(KERNELHDR)/linux/checkpoint.h)" ""
> -# if .../usr/include contains our headers
> -CKPT_INCLUDE = -I$(KERNELHDR)
> -CKPT_HEADERS = $(KERNELHDR)/linux/checkpoint_hdr.h \
> - $(KERNELHDR)/asm/checkpoint_hdr.h
> -else
> -# else, usr the kernel source itself
> -# but first, find linux architecure
> -KERN_ARCH = $(shell readlink $(KERNELBUILD)/include/asm | sed 's/^asm-//')
> -CKPT_INCLUDE = -I$(KERNELSRC)/include \
> - -I$(KERNELSRC)/arch/$(KERN_ARCH)/include
> -CKPT_HEADERS = $(KERNELSRC)/include/linux/checkpoint_hdr.h \
> - $(KERNELSRC)/arch/$(KERN_ARCH)/include/asm/checkpoint_hdr.h
> -endif
> +
> +CKPT_INCLUDE = -I./include
> +CKPT_HEADERS = include/linux/checkpoint.h \
> + include/linux/checkpoint_hdr.h \
> + include/asm/checkpoint_hdr.h
>
> # detect architecture (for clone_with_pids)
> SUBARCH = $(patsubst i%86,x86_32,$(shell uname -m))
> @@ -42,6 +27,8 @@ OTHER = ckptinfo_types.c
>
> LDLIBS = -lm
>
> +.PHONY: all distclean clean headers install
> +
> all: $(PROGS)
> @make -C test
>
> @@ -63,13 +50,20 @@ endif
> ckptinfo: ckptinfo_types.o
>
> ckptinfo_types.c: $(CKPT_HEADERS) ckptinfo.py
> - @echo cat $(CKPT_HEADERS) | ./ckptinfo.py > ckptinfo_types.c
> - @cat $(CKPT_HEADERS) | ./ckptinfo.py > ckptinfo_types.c
> + cat $(CKPT_HEADERS) | ./ckptinfo.py > ckptinfo_types.c
>
> install:
> @echo /usr/bin/install -m 755 checkpoint restart ckptinfo $(INSTALL_DIR)
> @/usr/bin/install -m 755 checkpoint restart ckptinfo $(INSTALL_DIR)
>
> +$(CKPT_HEADERS): %:
> + ./scripts/extract-headers.sh -s $(KERNELSRC) -o ./include
> +
> +headers: $(CKPT_HEADERS)
> +
> +distclean: clean
> + @rm -f $(CKPT_HEADERS)
> +
> clean:
> - @rm -f $(PROGS) $(OTHER) *~ *.o
> + @rm -f $(PROGS) $(OTHER) *~ *.o headers.h
> @make -C test clean
> diff --git a/ckptinfo.c b/ckptinfo.c
> index 6859742..9eea791 100644
> --- a/ckptinfo.c
> +++ b/ckptinfo.c
> @@ -18,6 +18,7 @@
> #include <sys/stat.h>
> #include <fcntl.h>
>
> +#include <linux/checkpoint.h>
> #include <linux/checkpoint_hdr.h>
> #include <asm/checkpoint_hdr.h>
>
> diff --git a/clone_ppc.c b/clone_ppc.c
> index 09b51b5..49797fd 100644
> --- a/clone_ppc.c
> +++ b/clone_ppc.c
> @@ -31,6 +31,7 @@ extern int __clone_with_pids(int (*fn)(void *arg),
> * libc doesn't support clone_with_pid() yet...
> * below is arch-dependent code to use the syscall
> */
> +#include <linux/checkpoint.h>
> #if defined(__NR_clone_with_pids)
>
> /* (see: http://lkml.indiana.edu/hypermail/linux/kernel/9604.3/0204.html) */
> diff --git a/clone_s390x.c b/clone_s390x.c
> index 661a5c4..dada822 100644
> --- a/clone_s390x.c
> +++ b/clone_s390x.c
> @@ -22,6 +22,7 @@
> * libc doesn't support clone_with_pid() yet...
> * below is arch-dependent code to use the syscall
> */
> +#include <linux/checkpoint.h>
> #if defined(__NR_clone_with_pids)
>
> /* this really belongs to some kernel header ! */
> diff --git a/clone_x86_32.c b/clone_x86_32.c
> index 05a689e..8ab3c3e 100644
> --- a/clone_x86_32.c
> +++ b/clone_x86_32.c
> @@ -20,6 +20,7 @@
> * libc doesn't support clone_with_pid() yet...
> * below is arch-dependent code to use the syscall
> */
> +#include <linux/checkpoint.h>
> #if defined(__NR_clone_with_pids)
>
> /* this really belongs to some kernel header ! */
> diff --git a/include/asm-powerpc/checkpoint_hdr.h b/include/asm-powerpc/checkpoint_hdr.h
> new file mode 100644
> index 0000000..105a184
> --- /dev/null
> +++ b/include/asm-powerpc/checkpoint_hdr.h
> @@ -0,0 +1,21 @@
> +/*
> + * Generated by extract-headers.sh.
> + */
> +#ifndef __ASM_POWERPC_CHECKPOINT_HDR_H_
> +#define __ASM_POWERPC_CHECKPOINT_HDR_H_
> +
> +
> +#include <linux/types.h>
> +
> +/* arch dependent constants */
> +#define CKPT_ARCH_NSIG 64
> +#define CKPT_TTY_NCC 10
> +
> +struct ckpt_hdr_header_arch {
> + struct ckpt_hdr h;
> + __u32 what;
> +} __attribute__((aligned(8)));
> +
> +
> +
> +#endif /* __ASM_POWERPC_CHECKPOINT_HDR_H_ */
> diff --git a/include/asm-s390/checkpoint_hdr.h b/include/asm-s390/checkpoint_hdr.h
> new file mode 100644
> index 0000000..ad1a2e2
> --- /dev/null
> +++ b/include/asm-s390/checkpoint_hdr.h
> @@ -0,0 +1,89 @@
> +/*
> + * Generated by extract-headers.sh.
> + */
> +#ifndef __ASM_S390_CHECKPOINT_HDR_H_
> +#define __ASM_S390_CHECKPOINT_HDR_H_
> +
> +/*
> + * Checkpoint/restart - architecture specific headers s/390
> + *
> + * Copyright IBM Corp. 2009
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file COPYING in the main directory of the Linux
> + * distribution for more details.
> + */
> +
> +#include <linux/types.h>
> +#include <asm/ptrace.h>
> +
> +/*
> + * Notes
> + * NUM_GPRS defined in <asm/ptrace.h> to be 16
> + * NUM_FPRS defined in <asm/ptrace.h> to be 16
> + * NUM_APRS defined in <asm/ptrace.h> to be 16
> + * NUM_CR_WORDS defined in <asm/ptrace.h> to be 3
> + * but is not yet in glibc headers.
> + */
> +
> +#define NUM_CR_WORDS 3
> +
> +struct ckpt_hdr_cpu {
> + struct ckpt_hdr h;
> + __u64 args[1];
> + __u64 gprs[NUM_GPRS];
> + __u64 orig_gpr2;
> + __u16 svcnr;
> + __u16 ilc;
> + __u32 acrs[NUM_ACRS];
> + __u64 ieee_instruction_pointer;
> +
> + /* psw_t */
> + __u64 psw_t_mask;
> + __u64 psw_t_addr;
> +
> + /* s390_fp_regs_t */
> + __u32 fpc;
> + union {
> + float f;
> + double d;
> + __u64 ui;
> + struct {
> + __u32 fp_hi;
> + __u32 fp_lo;
> + } fp;
> + } fprs[NUM_FPRS];
> +
> + /* per_struct */
> + __u64 per_control_regs[NUM_CR_WORDS];
> + __u64 starting_addr;
> + __u64 ending_addr;
> + __u64 address;
> + __u16 perc_atmid;
> + __u8 access_id;
> + __u8 single_step;
> + __u8 instruction_fetch;
> +};
> +
> +struct ckpt_hdr_mm_context {
> + struct ckpt_hdr h;
> + unsigned long vdso_base;
> + int noexec;
> + int has_pgste;
> + int alloc_pgste;
> + unsigned long asce_bits;
> + unsigned long asce_limit;
> +};
> +
> +#define CKPT_ARCH_NSIG 64
> +#define CKPT_TTY_NCC 8
> +
> +/* arch dependent constants */
> +
> +struct ckpt_hdr_header_arch {
> + struct ckpt_hdr h;
> +};
> +
> +
> +
> +#endif /* __ASM_S390_CHECKPOINT_HDR_H_ */
> diff --git a/include/asm-x86/checkpoint_hdr.h b/include/asm-x86/checkpoint_hdr.h
> new file mode 100644
> index 0000000..4bf3b8a
> --- /dev/null
> +++ b/include/asm-x86/checkpoint_hdr.h
> @@ -0,0 +1,126 @@
> +/*
> + * Generated by extract-headers.sh.
> + */
> +#ifndef __ASM_X86_CHECKPOINT_HDR_H_
> +#define __ASM_X86_CHECKPOINT_HDR_H_
> +
> +/*
> + * Checkpoint/restart - architecture specific headers x86
> + *
> + * Copyright (C) 2008-2009 Oren Laadan
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file COPYING in the main directory of the Linux
> + * distribution for more details.
> + */
> +
> +#include <linux/types.h>
> +
> +/*
> + * To maintain compatibility between 32-bit and 64-bit architecture flavors,
> + * keep data 64-bit aligned: use padding for structure members, and use
> + * __attribute__((aligned (8))) for the entire structure.
> + *
> + * Quoting Arnd Bergmann:
> + * "This structure has an odd multiple of 32-bit members, which means
> + * that if you put it into a larger structure that also contains 64-bit
> + * members, the larger structure may get different alignment on x86-32
> + * and x86-64, which you might want to avoid. I can't tell if this is
> + * an actual problem here. ... In this case, I'm pretty sure that
> + * sizeof(ckpt_hdr_task) on x86-32 is different from x86-64, since it
> + * will be 32-bit aligned on x86-32."
> + */
> +
> +/* i387 structure seen from kernel/userspace */
> +
> +/* arch dependent header types */
> +enum {
> + CKPT_HDR_CPU_FPU = 201,
> + CKPT_HDR_MM_CONTEXT_LDT,
> +};
> +
> +/* arch dependent constants */
> +#define CKPT_ARCH_NSIG 64
> +#define CKPT_TTY_NCC 8
> +
> +struct ckpt_hdr_header_arch {
> + struct ckpt_hdr h;
> + /* FIXME: add HAVE_HWFP */
> + __u16 has_fxsr;
> + __u16 has_xsave;
> + __u16 xstate_size;
> + __u16 _pading;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_thread {
> + struct ckpt_hdr h;
> + __u32 thread_info_flags;
> + __u16 gdt_entry_tls_entries;
> + __u16 sizeof_tls_array;
> +} __attribute__((aligned(8)));
> +
> +/* designed to work for both x86_32 and x86_64 */
> +struct ckpt_hdr_cpu {
> + struct ckpt_hdr h;
> + /* see struct pt_regs (x86_64) */
> + __u64 r15;
> + __u64 r14;
> + __u64 r13;
> + __u64 r12;
> + __u64 bp;
> + __u64 bx;
> + __u64 r11;
> + __u64 r10;
> + __u64 r9;
> + __u64 r8;
> + __u64 ax;
> + __u64 cx;
> + __u64 dx;
> + __u64 si;
> + __u64 di;
> + __u64 orig_ax;
> + __u64 ip;
> + __u64 sp;
> +
> + __u64 flags;
> +
> + /* segment registers */
> + __u64 fs;
> + __u64 gs;
> +
> + __u16 fsindex;
> + __u16 gsindex;
> + __u16 cs;
> + __u16 ss;
> + __u16 ds;
> + __u16 es;
> +
> + __u32 used_math;
> +
> + /* debug registers */
> + __u64 debugreg0;
> + __u64 debugreg1;
> + __u64 debugreg2;
> + __u64 debugreg3;
> + __u64 debugreg6;
> + __u64 debugreg7;
> +
> + /* thread_xstate contents follow (if used_math) */
> +} __attribute__((aligned(8)));
> +
> +#define CKPT_X86_SEG_NULL 0
> +#define CKPT_X86_SEG_USER32_CS 1
> +#define CKPT_X86_SEG_USER32_DS 2
> +#define CKPT_X86_SEG_TLS 0x4000 /* 0100 0000 0000 00xx */
> +#define CKPT_X86_SEG_LDT 0x8000 /* 100x xxxx xxxx xxxx */
> +
> +struct ckpt_hdr_mm_context {
> + struct ckpt_hdr h;
> + __u64 vdso;
> + __u32 ldt_entry_size;
> + __u32 nldt;
> +} __attribute__((aligned(8)));
> +
> +
> +
> +#endif /* __ASM_X86_CHECKPOINT_HDR_H_ */
> diff --git a/include/asm/checkpoint_hdr.h b/include/asm/checkpoint_hdr.h
> new file mode 100644
> index 0000000..859f58e
> --- /dev/null
> +++ b/include/asm/checkpoint_hdr.h
> @@ -0,0 +1,15 @@
> +/*
> + * Generated by extract-headers.sh.
> + */
> +#ifndef __ASM_CHECKPOINT_HDR_H_
> +#define __ASM_CHECKPOINT_HDR_H_
> +#if __powerpc__
> +#include <asm-powerpc/checkpoint_hdr.h>
> +#elif __s390x__
> +#include <asm-s390/checkpoint_hdr.h>
> +#elif __i386__ || __x86_64__
> +#include <asm-x86/checkpoint_hdr.h>
> +#else
> +#error "Architecture does not have definitons needed for checkpoint images."
> +#endif
> +#endif /* __ASM_CHECKPOINT_HDR_H_ */
> diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
> new file mode 100644
> index 0000000..75fdb0a
> --- /dev/null
> +++ b/include/linux/checkpoint.h
> @@ -0,0 +1,73 @@
> +/*
> + * Generated by extract-headers.sh.
> + */
> +#ifndef _LINUX_CHECKPOINT_H_
> +#define _LINUX_CHECKPOINT_H_
> +
> +/*
> + * Generic checkpoint-restart
> + *
> + * Copyright (C) 2008-2009 Oren Laadan
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file COPYING in the main directory of the Linux
> + * distribution for more details.
> + */
> +
> +#define CHECKPOINT_VERSION 2
> +
> +/* checkpoint user flags */
> +#define CHECKPOINT_SUBTREE 0x1
> +
> +/* restart user flags */
> +#define RESTART_TASKSELF 0x1
> +#define RESTART_FROZEN 0x2
> +#define RESTART_GHOST 0x4
> +
> +
> +#if __powerpc__
> +
> +# ifndef __NR_checkpoint
> +# define __NR_checkpoint 323
> +# endif
> +
> +# ifndef __NR_restart
> +# define __NR_restart 324
> +# endif
> +
> +# ifndef __NR_clone_with_pids
> +# define __NR_clone_with_pids 325
> +# endif
> +
> +#elif __s390x__
> +
> +# ifndef __NR_checkpoint
> +# define __NR_checkpoint 332
> +# endif
> +
> +# ifndef __NR_restart
> +# define __NR_restart 333
> +# endif
> +
> +# ifndef __NR_clone_with_pids
> +# define __NR_clone_with_pids 334
> +# endif
> +
> +#elif __i386__
> +
> +# ifndef __NR_clone_with_pids
> +# define __NR_clone_with_pids 337
> +# endif
> +
> +# ifndef __NR_checkpoint
> +# define __NR_checkpoint 338
> +# endif
> +
> +# ifndef __NR_restart
> +# define __NR_restart 339
> +# endif
> +
> +#else
> +#error "Architecture does not have definitons for __NR_(checkpoint|restart)"
> +#endif
> +#endif /* _LINUX_CHECKPOINT_H_ */
> diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
> new file mode 100644
> index 0000000..01f9957
> --- /dev/null
> +++ b/include/linux/checkpoint_hdr.h
> @@ -0,0 +1,749 @@
> +/*
> + * Generated by extract-headers.sh.
> + */
> +#ifndef _CHECKPOINT_CKPT_HDR_H_
> +#define _CHECKPOINT_CKPT_HDR_H_
> +
> +/*
> + * Generic container checkpoint-restart
> + *
> + * Copyright (C) 2008-2009 Oren Laadan
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file COPYING in the main directory of the Linux
> + * distribution for more details.
> + */
> +
> +/* In userspace sys/types.h must be included before linux/types.h */
> +#include <sys/types.h>
> +
> +#include <linux/types.h>
> +
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <netinet/in.h>
> +
> +/*
> + * To maintain compatibility between 32-bit and 64-bit architecture flavors,
> + * keep data 64-bit aligned: use padding for structure members, and use
> + * __attribute__((aligned (8))) for the entire structure.
> + *
> + * Quoting Arnd Bergmann:
> + * "This structure has an odd multiple of 32-bit members, which means
> + * that if you put it into a larger structure that also contains 64-bit
> + * members, the larger structure may get different alignment on x86-32
> + * and x86-64, which you might want to avoid. I can't tell if this is
> + * an actual problem here. ... In this case, I'm pretty sure that
> + * sizeof(ckpt_hdr_task) on x86-32 is different from x86-64, since it
> + * will be 32-bit aligned on x86-32."
> + */
> +
> +/*
> + * header format: 'struct ckpt_hdr' must prefix all other headers. Therfore
> + * when a header is passed around, the information about it (type, size)
> + * is readily available. Structs that include a struct ckpt_hdr are named
> + * struct ckpt_hdr_* by convention (usualy the struct ckpt_hdr is the first
> + * member).
> + */
> +struct ckpt_hdr {
> + __u32 type;
> + __u32 len;
> +} __attribute__((aligned(8)));
> +
> +#include <asm/checkpoint_hdr.h>
> +
> +/* header types */
> +enum {
> + CKPT_HDR_HEADER = 1,
> + CKPT_HDR_HEADER_ARCH,
> + CKPT_HDR_BUFFER,
> + CKPT_HDR_STRING,
> + CKPT_HDR_OBJREF,
> +
> + CKPT_HDR_TREE = 101,
> + CKPT_HDR_TASK,
> + CKPT_HDR_TASK_NS,
> + CKPT_HDR_TASK_OBJS,
> + CKPT_HDR_RESTART_BLOCK,
> + CKPT_HDR_THREAD,
> + CKPT_HDR_CPU,
> + CKPT_HDR_NS,
> + CKPT_HDR_UTS_NS,
> + CKPT_HDR_IPC_NS,
> + CKPT_HDR_CAPABILITIES,
> + CKPT_HDR_USER_NS,
> + CKPT_HDR_CRED,
> + CKPT_HDR_USER,
> + CKPT_HDR_GROUPINFO,
> + CKPT_HDR_TASK_CREDS,
> +
> + /* 201-299: reserved for arch-dependent */
> +
> + CKPT_HDR_FILE_TABLE = 301,
> + CKPT_HDR_FILE_DESC,
> + CKPT_HDR_FILE_NAME,
> + CKPT_HDR_FILE,
> + CKPT_HDR_PIPE_BUF,
> + CKPT_HDR_TTY,
> + CKPT_HDR_TTY_LDISC,
> +
> + CKPT_HDR_MM = 401,
> + CKPT_HDR_VMA,
> + CKPT_HDR_PGARR,
> + CKPT_HDR_MM_CONTEXT,
> +
> + CKPT_HDR_IPC = 501,
> + CKPT_HDR_IPC_SHM,
> + CKPT_HDR_IPC_MSG,
> + CKPT_HDR_IPC_MSG_MSG,
> + CKPT_HDR_IPC_SEM,
> +
> + CKPT_HDR_SIGHAND = 601,
> + CKPT_HDR_SIGNAL,
> + CKPT_HDR_SIGNAL_TASK,
> + CKPT_HDR_SIGPENDING,
> +
> + CKPT_HDR_SOCKET = 701,
> + CKPT_HDR_SOCKET_QUEUE,
> + CKPT_HDR_SOCKET_BUFFER,
> + CKPT_HDR_SOCKET_UNIX,
> + CKPT_HDR_SOCKET_INET,
> +
> + CKPT_HDR_TAIL = 9001,
> +
> + CKPT_HDR_ERROR = 9999,
> + CKPT_HDR_KERNEL_STACK = 10000,
> +};
> +
> +/* architecture */
> +enum {
> + /* do not change order (will break ABI) */
> + CKPT_ARCH_X86_32 = 1,
> + CKPT_ARCH_S390X,
> + CKPT_ARCH_PPC32,
> + CKPT_ARCH_PPC64,
> +};
> +
> +/* shared objrects (objref) */
> +struct ckpt_hdr_objref {
> + struct ckpt_hdr h;
> + __u32 objtype;
> + __s32 objref;
> +} __attribute__((aligned(8)));
> +
> +/* shared objects types */
> +enum obj_type {
> + CKPT_OBJ_IGNORE = 0,
> + CKPT_OBJ_INODE,
> + CKPT_OBJ_FILE_TABLE,
> + CKPT_OBJ_FILE,
> + CKPT_OBJ_MM,
> + CKPT_OBJ_SIGHAND,
> + CKPT_OBJ_SIGNAL,
> + CKPT_OBJ_NS,
> + CKPT_OBJ_UTS_NS,
> + CKPT_OBJ_IPC_NS,
> + CKPT_OBJ_USER_NS,
> + CKPT_OBJ_CRED,
> + CKPT_OBJ_USER,
> + CKPT_OBJ_GROUPINFO,
> + CKPT_OBJ_SOCK,
> + CKPT_OBJ_TTY,
> + CKPT_OBJ_MAX
> +};
> +
> +/* kernel constants */
> +struct ckpt_const {
> + /* task */
> + __u16 task_comm_len;
> + /* mm */
> + __u16 mm_saved_auxv_len;
> + /* signal */
> + __u16 signal_nsig;
> + /* uts */
> + __u16 uts_sysname_len;
> + __u16 uts_nodename_len;
> + __u16 uts_release_len;
> + __u16 uts_version_len;
> + __u16 uts_machine_len;
> + __u16 uts_domainname_len;
> + /* rlimit */
> + __u16 rlimit_nlimits;
> + /* tty */
> + __u16 n_tty_buf_size;
> + __u16 tty_termios_ncc;
> +} __attribute__((aligned(8)));
> +
> +/* checkpoint image header */
> +struct ckpt_hdr_header {
> + struct ckpt_hdr h;
> + __u64 magic;
> +
> + __u16 arch_id;
> +
> + __u16 major;
> + __u16 minor;
> + __u16 patch;
> + __u16 rev;
> +
> + struct ckpt_const constants;
> +
> + __u64 time; /* when checkpoint taken */
> + __u64 uflags; /* uflags from checkpoint */
> +
> + /*
> + * the header is followed by three strings:
> + * char release[const.uts_release_len];
> + * char version[const.uts_version_len];
> + * char machine[const.uts_machine_len];
> + */
> +} __attribute__((aligned(8)));
> +
> +/* checkpoint image trailer */
> +struct ckpt_hdr_tail {
> + struct ckpt_hdr h;
> + __u64 magic;
> +} __attribute__((aligned(8)));
> +
> +/* task tree */
> +struct ckpt_hdr_tree {
> + struct ckpt_hdr h;
> + __s32 nr_tasks;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_pids {
> + __s32 vpid;
> + __s32 vppid;
> + __s32 vtgid;
> + __s32 vpgid;
> + __s32 vsid;
> +} __attribute__((aligned(8)));
> +
> +/* pids */
> +#define CKPT_PID_NULL -1
> +
> +/* task data */
> +struct ckpt_hdr_task {
> + struct ckpt_hdr h;
> + __u32 state;
> + __u32 exit_state;
> + __u32 exit_code;
> + __u32 exit_signal;
> + __u32 pdeath_signal;
> +
> + __u64 set_child_tid;
> + __u64 clear_child_tid;
> +
> + __u32 compat_robust_futex_head_len;
> + __u32 compat_robust_futex_list; /* a compat __user ptr */
> + __u32 robust_futex_head_len;
> + __u64 robust_futex_list; /* a __user ptr */
> +} __attribute__((aligned(8)));
> +
> +/* Posix capabilities */
> +struct ckpt_capabilities {
> + __u32 cap_i_0, cap_i_1; /* inheritable set */
> + __u32 cap_p_0, cap_p_1; /* permitted set */
> + __u32 cap_e_0, cap_e_1; /* effective set */
> + __u32 cap_b_0, cap_b_1; /* bounding set */
> + __u32 securebits;
> + __u32 padding;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_task_creds {
> + struct ckpt_hdr h;
> + __s32 cred_ref;
> + __s32 ecred_ref;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_cred {
> + struct ckpt_hdr h;
> + __u32 uid, suid, euid, fsuid;
> + __u32 gid, sgid, egid, fsgid;
> + __s32 user_ref;
> + __s32 groupinfo_ref;
> + struct ckpt_capabilities cap_s;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_groupinfo {
> + struct ckpt_hdr h;
> + __u32 ngroups;
> + /*
> + * This is followed by ngroups __u32s
> + */
> + __u32 groups[0];
> +} __attribute__((aligned(8)));
> +
> +/*
> + * todo - keyrings and LSM
> + * These may be better done with userspace help though
> + */
> +struct ckpt_hdr_user_struct {
> + struct ckpt_hdr h;
> + __u32 uid;
> + __s32 userns_ref;
> +} __attribute__((aligned(8)));
> +
> +/*
> + * The user-struct mostly tracks system resource usage.
> + * Most of it's contents therefore will simply be set
> + * correctly as restart opens resources
> + */
> +struct ckpt_hdr_user_ns {
> + struct ckpt_hdr h;
> + __s32 creator_ref;
> +} __attribute__((aligned(8)));
> +
> +/* namespaces */
> +struct ckpt_hdr_task_ns {
> + struct ckpt_hdr h;
> + __s32 ns_objref;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_ns {
> + struct ckpt_hdr h;
> + __s32 uts_objref;
> + __u32 ipc_objref;
> +} __attribute__((aligned(8)));
> +
> +/* cannot include <linux/tty.h> from userspace, so define: */
> +#define CKPT_NEW_UTS_LEN 64
> +
> +struct ckpt_hdr_utsns {
> + struct ckpt_hdr h;
> + char sysname[CKPT_NEW_UTS_LEN + 1];
> + char nodename[CKPT_NEW_UTS_LEN + 1];
> + char release[CKPT_NEW_UTS_LEN + 1];
> + char version[CKPT_NEW_UTS_LEN + 1];
> + char machine[CKPT_NEW_UTS_LEN + 1];
> + char domainname[CKPT_NEW_UTS_LEN + 1];
> +} __attribute__((aligned(8)));
> +
> +/* task's shared resources */
> +struct ckpt_hdr_task_objs {
> + struct ckpt_hdr h;
> +
> + __s32 files_objref;
> + __s32 mm_objref;
> + __s32 sighand_objref;
> + __s32 signal_objref;
> +} __attribute__((aligned(8)));
> +
> +/* restart blocks */
> +struct ckpt_hdr_restart_block {
> + struct ckpt_hdr h;
> + __u64 function_type;
> + __u64 arg_0;
> + __u64 arg_1;
> + __u64 arg_2;
> + __u64 arg_3;
> + __u64 arg_4;
> +} __attribute__((aligned(8)));
> +
> +enum restart_block_type {
> + CKPT_RESTART_BLOCK_NONE = 1,
> + CKPT_RESTART_BLOCK_HRTIMER_NANOSLEEP,
> + CKPT_RESTART_BLOCK_POSIX_CPU_NANOSLEEP,
> + CKPT_RESTART_BLOCK_COMPAT_NANOSLEEP,
> + CKPT_RESTART_BLOCK_COMPAT_CLOCK_NANOSLEEP,
> + CKPT_RESTART_BLOCK_POLL,
> + CKPT_RESTART_BLOCK_FUTEX
> +};
> +
> +/* file system */
> +struct ckpt_hdr_file_table {
> + struct ckpt_hdr h;
> + __s32 fdt_nfds;
> +} __attribute__((aligned(8)));
> +
> +/* file descriptors */
> +struct ckpt_hdr_file_desc {
> + struct ckpt_hdr h;
> + __s32 fd_objref;
> + __s32 fd_descriptor;
> + __u32 fd_close_on_exec;
> +} __attribute__((aligned(8)));
> +
> +enum file_type {
> + CKPT_FILE_IGNORE = 0,
> + CKPT_FILE_GENERIC,
> + CKPT_FILE_PIPE,
> + CKPT_FILE_FIFO,
> + CKPT_FILE_SOCKET,
> + CKPT_FILE_TTY,
> + CKPT_FILE_MAX
> +};
> +
> +/* file objects */
> +struct ckpt_hdr_file {
> + struct ckpt_hdr h;
> + __u32 f_type;
> + __u32 f_mode;
> + __u32 f_flags;
> + __s32 f_credref;
> + __u64 f_pos;
> + __u64 f_version;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_file_generic {
> + struct ckpt_hdr_file common;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_file_pipe {
> + struct ckpt_hdr_file common;
> + __s32 pipe_objref;
> +} __attribute__((aligned(8)));
> +
> +/* socket */
> +struct ckpt_hdr_socket {
> + struct ckpt_hdr h;
> +
> + struct { /* struct socket */
> + __u64 flags;
> + __u8 state;
> + } socket __attribute__ ((aligned(8)));
> +
> + struct { /* struct sock_common */
> + __u32 bound_dev_if;
> + __u32 reuse;
> + __u16 family;
> + __u8 state;
> + } sock_common __attribute__ ((aligned(8)));
> +
> + struct { /* struct sock */
> + __s64 rcvlowat;
> + __u64 flags;
> +
> + __s64 rcvtimeo;
> + __s64 sndtimeo;
> +
> + __u32 err;
> + __u32 err_soft;
> + __u32 priority;
> + __s32 rcvbuf;
> + __s32 sndbuf;
> + __u16 type;
> + __s16 backlog;
> +
> + __u8 protocol;
> + __u8 state;
> + __u8 shutdown;
> + __u8 userlocks;
> + __u8 no_check;
> +
> + struct linger linger;
> + } sock __attribute__ ((aligned(8)));
> +} __attribute__ ((aligned(8)));
> +
> +struct ckpt_hdr_socket_queue {
> + struct ckpt_hdr h;
> + __u32 skb_count;
> + __u32 total_bytes;
> +} __attribute__ ((aligned(8)));
> +
> +struct ckpt_hdr_socket_buffer {
> + struct ckpt_hdr h;
> + __s32 sk_objref;
> + __s32 pr_objref;
> +};
> +
> +#define CKPT_UNIX_LINKED 1
> +struct ckpt_hdr_socket_unix {
> + struct ckpt_hdr h;
> + __s32 this;
> + __s32 peer;
> + __u32 peercred_uid;
> + __u32 peercred_gid;
> + __u32 flags;
> + __u32 laddr_len;
> + __u32 raddr_len;
> + struct sockaddr_un laddr;
> + struct sockaddr_un raddr;
> +} __attribute__ ((aligned(8)));
> +
> +struct ckpt_hdr_socket_inet {
> + struct ckpt_hdr h;
> + __u32 laddr_len;
> + __u32 raddr_len;
> + struct sockaddr_in laddr;
> + struct sockaddr_in raddr;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_file_socket {
> + struct ckpt_hdr_file common;
> + __s32 sock_objref;
> +} __attribute__((aligned(8)));
> +
> +/* memory layout */
> +struct ckpt_hdr_mm {
> + struct ckpt_hdr h;
> + __u32 map_count;
> + __s32 exe_objref;
> +
> + __u64 def_flags;
> + __u64 flags;
> +
> + __u64 start_code, end_code, start_data, end_data;
> + __u64 start_brk, brk, start_stack;
> + __u64 arg_start, arg_end, env_start, env_end;
> +} __attribute__((aligned(8)));
> +
> +/* vma subtypes - index into restore_vma_dispatch[] */
> +enum vma_type {
> + CKPT_VMA_IGNORE = 0,
> + CKPT_VMA_VDSO, /* special vdso vma */
> + CKPT_VMA_ANON, /* private anonymous */
> + CKPT_VMA_FILE, /* private mapped file */
> + CKPT_VMA_SHM_ANON, /* shared anonymous */
> + CKPT_VMA_SHM_ANON_SKIP, /* shared anonymous (skip contents) */
> + CKPT_VMA_SHM_FILE, /* shared mapped file, only msync */
> + CKPT_VMA_SHM_IPC, /* shared sysvipc */
> + CKPT_VMA_SHM_IPC_SKIP, /* shared sysvipc (skip contents) */
> + CKPT_VMA_MAX,
> +};
> +
> +/* vma descriptor */
> +struct ckpt_hdr_vma {
> + struct ckpt_hdr h;
> + __u32 vma_type;
> + __s32 vma_objref; /* objref of backing file */
> + __s32 ino_objref; /* objref of shared segment */
> + __u32 _padding;
> + __u64 ino_size; /* size of shared segment */
> +
> + __u64 vm_start;
> + __u64 vm_end;
> + __u64 vm_page_prot;
> + __u64 vm_flags;
> + __u64 vm_pgoff;
> +} __attribute__((aligned(8)));
> +
> +/* page array */
> +struct ckpt_hdr_pgarr {
> + struct ckpt_hdr h;
> + __u64 nr_pages; /* number of pages to saved */
> +} __attribute__((aligned(8)));
> +
> +/* signals */
> +struct ckpt_sigset {
> + __u8 sigset[CKPT_ARCH_NSIG / 8];
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_sigaction {
> + __u64 _sa_handler;
> + __u64 sa_flags;
> + __u64 sa_restorer;
> + struct ckpt_sigset sa_mask;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_sighand {
> + struct ckpt_hdr h;
> + struct ckpt_sigaction action[0];
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_siginfo {
> + __u32 signo;
> + __u32 _errno;
> + __u32 code;
> +
> + __u32 pid;
> + __s32 uid;
> + __u32 sigval_int;
> + __u64 sigval_ptr;
> + __u64 utime;
> + __u64 stime;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_sigpending {
> + struct ckpt_hdr h;
> + __u32 nr_pending;
> + struct ckpt_sigset signal;
> + struct ckpt_siginfo siginfo[0];
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_rlimit {
> + __u64 rlim_cur;
> + __u64 rlim_max;
> +} __attribute__((aligned(8)));
> +
> +/* cannot include <linux/resource.h> from userspace, so define: */
> +#define CKPT_RLIM_NLIMITS 16
> +
> +struct ckpt_hdr_signal {
> + struct ckpt_hdr h;
> + /* rlimit */
> + struct ckpt_rlimit rlim[CKPT_RLIM_NLIMITS];
> + /* itimer */
> + __u64 it_real_value;
> + __u64 it_real_incr;
> + __u64 it_virt_value;
> + __u64 it_virt_incr;
> + __u64 it_prof_value;
> + __u64 it_prof_incr;
> + /* tty */
> + __s32 tty_objref;
> + __s32 tty_pgrp;
> + __s32 tty_old_pgrp;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_signal_task {
> + struct ckpt_hdr h;
> + struct ckpt_sigset blocked;
> +} __attribute__((aligned(8)));
> +
> +/* ipc commons */
> +struct ckpt_hdr_ipcns {
> + struct ckpt_hdr h;
> + __u64 shm_ctlmax;
> + __u64 shm_ctlall;
> + __s32 shm_ctlmni;
> +
> + __s32 msg_ctlmax;
> + __s32 msg_ctlmnb;
> + __s32 msg_ctlmni;
> +
> + __s32 sem_ctl_msl;
> + __s32 sem_ctl_mns;
> + __s32 sem_ctl_opm;
> + __s32 sem_ctl_mni;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_ipc {
> + struct ckpt_hdr h;
> + __u32 ipc_type;
> + __u32 ipc_count;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_ipc_perms {
> + struct ckpt_hdr h;
> + __s32 id;
> + __u32 key;
> + __u32 uid;
> + __u32 gid;
> + __u32 cuid;
> + __u32 cgid;
> + __u32 mode;
> + __u32 _padding;
> + __u64 seq;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_ipc_shm {
> + struct ckpt_hdr h;
> + struct ckpt_hdr_ipc_perms perms;
> + __u64 shm_segsz;
> + __u64 shm_atim;
> + __u64 shm_dtim;
> + __u64 shm_ctim;
> + __s32 shm_cprid;
> + __s32 shm_lprid;
> + __u32 mlock_uid;
> + __u32 flags;
> + __u32 objref;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_ipc_msg {
> + struct ckpt_hdr h;
> + struct ckpt_hdr_ipc_perms perms;
> + __u64 q_stime;
> + __u64 q_rtime;
> + __u64 q_ctime;
> + __u64 q_cbytes;
> + __u64 q_qnum;
> + __u64 q_qbytes;
> + __s32 q_lspid;
> + __s32 q_lrpid;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_ipc_msg_msg {
> + struct ckpt_hdr h;
> + __s32 m_type;
> + __u32 m_ts;
> +} __attribute__((aligned(8)));
> +
> +struct ckpt_hdr_ipc_sem {
> + struct ckpt_hdr h;
> + struct ckpt_hdr_ipc_perms perms;
> + __u64 sem_otime;
> + __u64 sem_ctime;
> + __u32 sem_nsems;
> +} __attribute__((aligned(8)));
> +
> +/* devices */
> +struct ckpt_hdr_file_tty {
> + struct ckpt_hdr_file common;
> + __s32 tty_objref;
> +};
> +
> +struct ckpt_hdr_tty {
> + struct ckpt_hdr h;
> +
> + __u16 driver_type;
> + __u16 driver_subtype;
> +
> + __s32 link_objref;
> + __s32 file_objref;
> + __u32 _padding;
> +
> + __u32 index;
> + __u32 ldisc;
> + __u64 flags;
> +
> + /* termios */
> + struct {
> + __u16 c_iflag;
> + __u16 c_oflag;
> + __u16 c_cflag;
> + __u16 c_lflag;
> + __u8 c_line;
> + __u8 c_cc[CKPT_TTY_NCC];
> + } __attribute__((aligned(8))) termios;
> +
> + /* winsize */
> + struct {
> + __u16 ws_row;
> + __u16 ws_col;
> + __u16 ws_xpixel;
> + __u16 ws_ypixel;
> + } __attribute__((aligned(8))) winsize;
> +} __attribute__((aligned(8)));
> +
> +/* cannot include <linux/tty.h> from userspace, so define: */
> +#define CKPT_N_TTY_BUF_SIZE 4096
> +
> +struct ckpt_hdr_ldisc_n_tty {
> + struct ckpt_hdr h;
> +
> + __u32 column;
> + __u32 datalen;
> + __u32 canon_column;
> + __u32 canon_datalen;
> + __u32 canon_data;
> +
> + __u16 minimum_to_wake;
> +
> + __u8 stopped;
> + __u8 hw_stopped;
> + __u8 flow_stopped;
> + __u8 packet;
> + __u8 ctrl_status;
> + __u8 lnext;
> + __u8 erasing;
> + __u8 raw;
> + __u8 real_raw;
> + __u8 icanon;
> + __u8 closing;
> + __u8 padding[3];
> +
> + __u8 read_flags[CKPT_N_TTY_BUF_SIZE / 8];
> +
> + /* if @datalen > 0, buffer contents follow (next object) */
> +} __attribute__((aligned(8)));
> +
> +#define CKPT_TST_OVERFLOW_16(a,b) ((sizeof(a) > sizeof(b)) && ((a) > SHORT_MAX))
> +
> +#define CKPT_TST_OVERFLOW_32(a,b) ((sizeof(a) > sizeof(b)) && ((a) > INT_MAX))
> +
> +#define CKPT_TST_OVERFLOW_64(a,b) ((sizeof(a) > sizeof(b)) && ((a) > LONG_MAX))
> +
> +
> +#endif /* _CHECKPOINT_CKPT_HDR_H_ */
> diff --git a/scripts/extract-headers.sh b/scripts/extract-headers.sh
> new file mode 100755
> index 0000000..360a889
> --- /dev/null
> +++ b/scripts/extract-headers.sh
> @@ -0,0 +1,250 @@
> +#!/bin/bash
> +#
> +# Copyright (C) 2009 IBM Corp.
> +# Author: Matt Helsley <matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> +#
> +# This file is subject to the terms and conditions of the GNU General Public
> +# License. See the file COPYING in the main directory of the Linux
> +# distribution for more details.
> +#
> +
> +#
> +# Sanitize checkpoint/restart kernel headers for userspace.
> +#
> +
> +function usage()
> +{
> + echo "Usage: $0 [-h|--help] -s|--kernel-src=DIR"
> +}
> +
> +OUTPUT_INCLUDES="include"
> +OPTIONS=`getopt -o s:o:h --long kernel-src:,output:,help -- "$@"`
> +eval set -- "${OPTIONS}"
> +while true ; do
> + case "$1" in
> + -s|--kernel-src)
> + KERNELSRC="$2"
> + shift 2 ;;
> + -o|--output)
> + OUTPUT_INCLUDES="$2"
> + shift 2 ;;
> + -h|--help)
> + usage
> + exit 0 ;;
> + --)
> + shift
> + break ;;
> + *)
> + echo "Unknown option: $1"
> + shift
> + echo "Unparsed options: $@"
> + usage 1>&2
> + exit 2 ;;
> + esac
> +done
> +
> +if [ -z "${KERNELSRC}" -o '!' -d "${KERNELSRC}" ]; then
> + usage 1>&2
> + exit 2
> +fi
> +
> +# Match cpp includes
> +INCLUDE_PRE_REGEX='#[[:space:]]*include[[:space:]]*\([<"]'
> +INCLUDE_FILE_REGEX='[^">]*'
> +INCLUDE_POST_REGEX='[">]\)'
> +
> +# Match cpp includes with \1 being the included file
> +INCLUDE_REGEX="${INCLUDE_PRE_REGEX}${INCLUDE_FILE_REGEX}${INCLUDE_POST_REGEX}"
> +
> +# Match includes of linux/types.h (\1 == linux/types.h)
> +INCLUDE_LINUX_TYPES_REGEX="${INCLUDE_PRE_REGEX}linux\/types\.h${INCLUDE_POST_REGEX}"
> +
> +# Match includes of linux/* with \1 being everything preceding "linux/" and \2
> +# being everything following "linux/"
> +INCLUDE_LINUX_REGEX="${INCLUDE_PRE_REGEX}"'\)'"linux\/"'\('"${INCLUDE_FILE_REGEX}${INCLUDE_POST_REGEX}"
> +
> +#
> +# Run the kernel header through cpp to strip out __KERNEL__ sections but try
> +# to leave the rest untouched.
> +#
> +function do_cpp ()
> +{
> + local CPP_FILE="$1"
> + local START_DEFINE="$2"
> + shift 2
> +
> + #
> + # Hide #include directives then run cpp. Make cpp keep comments, not
> + # insert line numbers, avoid system/gcc/std defines, and only expand
> + # directives. Strip cpp output until we get to #define START_DEFINE,
> + # and collapse the excessive number of blank lines that cpp outputs
> + # in place of directives. Finally, replace linux/ with sys/ prefixes
> + # of include paths, except for linux/types.h (needed for __uXX types).
> + #
> + sed -e 's|'"${INCLUDE_REGEX}"'|/*#include \1*/|g' "${CPP_FILE}" | \
> + cpp -CC -P -U__KERNEL__ -undef -nostdinc -fdirectives-only -dDI "$@" | \
> + awk 'BEGIN { do_print = 0; }
> + /#[[:space:]]*define '"${START_DEFINE}"'/ { do_print = 1; next; }
> + (do_print == 1) { print }' | \
> + cat -s | \
> + sed -e 's|/\*'"${INCLUDE_REGEX}"'\*/|#include \1|g' | \
> + sed -e "/${INCLUDE_LINUX_TYPES_REGEX}/n" \
> + -e "s|${INCLUDE_LINUX_REGEX}|#include \1sys/\2|"
> + echo ''
> +}
> +
> +# Map KARCH to something suitable for CPP e.g. __i386__
> +function karch_to_cpparch ()
> +{
> + local KARCH="$1"
> + local WORDBITS="$2"
> + shift 2;
> +
> + case "${KARCH}" in
> + x86) [ "${WORDBITS}" == "32" ] && echo -n "i386"
> + [ "${WORDBITS}" == "64" ] && echo -n "x86_64"
> + [ -z "${WORDBITS}" ] && echo -n 'i386__ || __x86_64' # HACK
> + ;;
> + s390*) echo -n "s390x" ;;
> + *) echo -n "${KARCH}" ;;
> + esac
> + return 0
> +}
> +
> +set -e
> +
> +mkdir -p "${OUTPUT_INCLUDES}/linux"
> +mkdir -p "${OUTPUT_INCLUDES}/asm"
> +
> +#
> +# Process include/linux/checkpoint_hdr.h -> include/linux/checkpoint_hdr.h
> +#
> +cat - > "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h" <<-EOFOO
> +/*
> + * Generated by $(basename "$0").
> + */
> +#ifndef _CHECKPOINT_CKPT_HDR_H_
> +#define _CHECKPOINT_CKPT_HDR_H_
> +
> +EOFOO
> +
> +do_cpp "${KERNELSRC}/include/linux/checkpoint_hdr.h" "_CHECKPOINT_CKPT_HDR_H_" \
> +>> "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h"
> +echo '#endif /* _CHECKPOINT_CKPT_HDR_H_ */' >> "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h"
> +
> +#
> +# Process include/linux/checkpoint.h -> include/linux/checkpoint.h
> +# and arch/*/include/asm/unistd.h -> include/linux/checkpoint.h.
> +# Eventually the unistd.h portion will get into the glibc headers and
> +# we can drop that part of this script.
> +#
> +
> +(
> +#
> +# We use ARCH_COND to break up architecture-specific sections of the header.
> +#
> +ARCH_COND='#if'
> +REGEX='[[:space:]]*#[[:space:]]*define[[:space:]]+__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+[[:digit:]]+'
> +
> +cat - <<-EOFOE
> +/*
> + * Generated by $(basename "$0").
> + */
> +#ifndef _LINUX_CHECKPOINT_H_
> +#define _LINUX_CHECKPOINT_H_
> +
> +EOFOE
> +
> +do_cpp "${KERNELSRC}/include/linux/checkpoint.h" "_LINUX_CHECKPOINT_H_"
> +
> +find "${KERNELSRC}/arch" -name 'unistd*.h' -print | sort | \
> +while read UNISTDH ; do
> + [ -n "${UNISTDH}" ] || continue
> + grep -q -E "${REGEX}" "${UNISTDH}" || continue
> +
> + KARCH=$(echo "${UNISTDH}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|')
> + WORDBITS=$(basename "${UNISTDH}" | sed -e 's/unistd_*\([[:digit:]]\+\)\.h/\1/')
> + CPPARCH="$(karch_to_cpparch "${KARCH}" "${WORDBITS}")"
> + echo -e "${ARCH_COND} __${CPPARCH}__\\n"
> + grep -E "${REGEX}" "${UNISTDH}" | \
> + sed -e 's/^[[:space:]]*#[[:space:]]*define[[:space:]]\+__NR_\([^[:space:]]\+\)[[:space:]]\+\([^[:space:]]\+\).*$/#\tifndef __NR_\1\n#\t\tdefine __NR_\1 \2\n#\tendif\n/'
> + ARCH_COND='#elif'
> +done
> +
> +cat - <<-EOFOFOE
> +#else
> +#error "Architecture does not have definitons for __NR_(checkpoint|restart)"
> +#endif
> +#endif /* _LINUX_CHECKPOINT_H_ */
> +EOFOFOE
> +
> +) > "${OUTPUT_INCLUDES}/linux/checkpoint.h"
> +
> +#
> +# Process arch/*/include/asm/checkpoint_hdr.h -> include/asm/checkpoint_hdr.h
> +# Use #if __arch1__ ... #elif __arch2___ ... #endif to wrap each portion.
> +#
> +ARCH_COND='#if'
> +
> +find "${KERNELSRC}/arch" -name 'checkpoint_hdr.h' -print | sort | \
> +while read ARCH_CHECKPOINT_HDR_H ; do
> + [ -n "${ARCH_CHECKPOINT_HDR_H}" ] || continue
> +
> + KARCH=$(echo "${ARCH_CHECKPOINT_HDR_H}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|')
> + UPCASE_KARCH=$(echo "${KARCH}" | tr 'a-z' 'A-Z')
> + mkdir -p "${OUTPUT_INCLUDES}/asm-${KARCH}"
> + cat - > "${OUTPUT_INCLUDES}/asm-${KARCH}/checkpoint_hdr.h" <<-EOFOEOF
> + /*
> + * Generated by $(basename "$0").
> + */
> + #ifndef __ASM_${UPCASE_KARCH}_CHECKPOINT_HDR_H_
> + #define __ASM_${UPCASE_KARCH}_CHECKPOINT_HDR_H_
> +
> + EOFOEOF
> +
> + do_cpp "${KERNELSRC}/arch/${KARCH}/include/asm/checkpoint_hdr.h" '__ASM.*_CKPT_HDR_H' -D_CHECKPOINT_CKPT_HDR_H_ >> "${OUTPUT_INCLUDES}/asm-${KARCH}/checkpoint_hdr.h"
> +
> + cat - >> "${OUTPUT_INCLUDES}/asm-${KARCH}/checkpoint_hdr.h" <<-FOEOEOF
> +
> + #endif /* __ASM_${UPCASE_KARCH}_CHECKPOINT_HDR_H_ */
> + FOEOEOF
> +
> + ARCH_COND='#elif'
> +done
> +
> +#
> +# Process arch/*/include/asm/checkpoint_hdr.h -> include/asm/checkpoint_hdr.h
> +# Use #if __arch1__ ... #elif __arch2___ ... #endif to wrap each portion.
> +#
> +(
> +ARCH_COND='#if'
> +
> +cat - <<-EOFOEOF
> +/*
> + * Generated by $(basename "$0").
> + */
> +#ifndef __ASM_CHECKPOINT_HDR_H_
> +#define __ASM_CHECKPOINT_HDR_H_
> +EOFOEOF
> +
> +find "${KERNELSRC}/arch" -name 'checkpoint_hdr.h' -print | sort | \
> +while read ARCH_CHECKPOINT_HDR_H ; do
> + [ -n "${ARCH_CHECKPOINT_HDR_H}" ] || continue
> +
> + KARCH=$(echo "${ARCH_CHECKPOINT_HDR_H}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|')
> + CPPARCH="$(karch_to_cpparch "${KARCH}" "")"
> + cat - <<-EOFOEOF
> + ${ARCH_COND} __${CPPARCH}__
> + #include <asm-${KARCH}/checkpoint_hdr.h>
> + EOFOEOF
> + ARCH_COND='#elif'
> +done
> +
> +cat - <<-FOEOEOF
> +#else
> +#error "Architecture does not have definitons needed for checkpoint images."
> +#endif
> +#endif /* __ASM_CHECKPOINT_HDR_H_ */
> +FOEOEOF
> +
> +) > "${OUTPUT_INCLUDES}/asm/checkpoint_hdr.h"
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-10-23 18:38 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-03 7:20 [PATCH] user-cr: Extract headers from kernel source tree Matt Helsley
[not found] ` <1254554424-2979-2-git-send-email-matthltc-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-03 7:26 ` Matt Helsley
2009-10-03 21:40 ` Nathan Lynch
[not found] ` <1254606041.2928.3.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2009-10-05 18:00 ` Matt Helsley
[not found] ` <20091005180000.GD18101-52DBMbEzqgQ/wnmkkaCWp/UQ3DHhIser@public.gmane.org>
2009-10-06 2:25 ` Serge E. Hallyn
2009-10-23 18:38 ` Oren Laadan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.