aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandra Seetharaman <sekharan@us.ibm.com>2006-07-30 06:03:04 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-31 16:28:36 -0400
commit822cfbff2ef49a08d1b9618d50f81b475d4f936c (patch)
tree9b8bd37b3940410a13d0c439cc585d5aea1147ac
parent2ccb48ebb4de139eef4fcefd5f2bb823cb0d81b9 (diff)
[PATCH] Process Events: Fix biarch compatibility issue. use __u64 timestamp
Events sent by Process Events Connector from a 64-bit kernel are not binary compatible with a 32-bit userspace program because the "timestamp" field (struct timespec) is not arch independent. This affects the fields that follow "timestamp" as they will be be off by 8 bytes. This is a problem for 32-bit userspace programs running with 64-bit kernels on ppc64, s390, x86-64.. any "biarch" system. Matt had submitted a different solution to lkml as an RFC earlier. We have since switched to a solution recommended by Evgeniy Polyakov. This patch fixes the problem by changing the timestamp to be a __u64, which stores the number of nanoseconds. Tested on a x86_64 system with both 32 bit application and 64 bit application and on a i386 system. Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Signed-off-by: Matt Helsley <matthltc@us.ibm.com> Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Cc: Guillaume Thouvenin <guillaume.thouvenin@bull.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/connector/cn_proc.c20
-rw-r--r--include/linux/cn_proc.h3
2 files changed, 17 insertions, 6 deletions
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 498aa37bca22..3ece69231343 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -51,6 +51,7 @@ void proc_fork_connector(struct task_struct *task)
51 struct cn_msg *msg; 51 struct cn_msg *msg;
52 struct proc_event *ev; 52 struct proc_event *ev;
53 __u8 buffer[CN_PROC_MSG_SIZE]; 53 __u8 buffer[CN_PROC_MSG_SIZE];
54 struct timespec ts;
54 55
55 if (atomic_read(&proc_event_num_listeners) < 1) 56 if (atomic_read(&proc_event_num_listeners) < 1)
56 return; 57 return;
@@ -58,7 +59,8 @@ void proc_fork_connector(struct task_struct *task)
58 msg = (struct cn_msg*)buffer; 59 msg = (struct cn_msg*)buffer;
59 ev = (struct proc_event*)msg->data; 60 ev = (struct proc_event*)msg->data;
60 get_seq(&msg->seq, &ev->cpu); 61 get_seq(&msg->seq, &ev->cpu);
61 ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */ 62 ktime_get_ts(&ts); /* get high res monotonic timestamp */
63 ev->timestamp_ns = timespec_to_ns(&ts);
62 ev->what = PROC_EVENT_FORK; 64 ev->what = PROC_EVENT_FORK;
63 ev->event_data.fork.parent_pid = task->real_parent->pid; 65 ev->event_data.fork.parent_pid = task->real_parent->pid;
64 ev->event_data.fork.parent_tgid = task->real_parent->tgid; 66 ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -76,6 +78,7 @@ void proc_exec_connector(struct task_struct *task)
76{ 78{
77 struct cn_msg *msg; 79 struct cn_msg *msg;
78 struct proc_event *ev; 80 struct proc_event *ev;
81 struct timespec ts;
79 __u8 buffer[CN_PROC_MSG_SIZE]; 82 __u8 buffer[CN_PROC_MSG_SIZE];
80 83
81 if (atomic_read(&proc_event_num_listeners) < 1) 84 if (atomic_read(&proc_event_num_listeners) < 1)
@@ -84,7 +87,8 @@ void proc_exec_connector(struct task_struct *task)
84 msg = (struct cn_msg*)buffer; 87 msg = (struct cn_msg*)buffer;
85 ev = (struct proc_event*)msg->data; 88 ev = (struct proc_event*)msg->data;
86 get_seq(&msg->seq, &ev->cpu); 89 get_seq(&msg->seq, &ev->cpu);
87 ktime_get_ts(&ev->timestamp); 90 ktime_get_ts(&ts); /* get high res monotonic timestamp */
91 ev->timestamp_ns = timespec_to_ns(&ts);
88 ev->what = PROC_EVENT_EXEC; 92 ev->what = PROC_EVENT_EXEC;
89 ev->event_data.exec.process_pid = task->pid; 93 ev->event_data.exec.process_pid = task->pid;
90 ev->event_data.exec.process_tgid = task->tgid; 94 ev->event_data.exec.process_tgid = task->tgid;
@@ -100,6 +104,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
100 struct cn_msg *msg; 104 struct cn_msg *msg;
101 struct proc_event *ev; 105 struct proc_event *ev;
102 __u8 buffer[CN_PROC_MSG_SIZE]; 106 __u8 buffer[CN_PROC_MSG_SIZE];
107 struct timespec ts;
103 108
104 if (atomic_read(&proc_event_num_listeners) < 1) 109 if (atomic_read(&proc_event_num_listeners) < 1)
105 return; 110 return;
@@ -118,7 +123,8 @@ void proc_id_connector(struct task_struct *task, int which_id)
118 } else 123 } else
119 return; 124 return;
120 get_seq(&msg->seq, &ev->cpu); 125 get_seq(&msg->seq, &ev->cpu);
121 ktime_get_ts(&ev->timestamp); 126 ktime_get_ts(&ts); /* get high res monotonic timestamp */
127 ev->timestamp_ns = timespec_to_ns(&ts);
122 128
123 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 129 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
124 msg->ack = 0; /* not used */ 130 msg->ack = 0; /* not used */
@@ -131,6 +137,7 @@ void proc_exit_connector(struct task_struct *task)
131 struct cn_msg *msg; 137 struct cn_msg *msg;
132 struct proc_event *ev; 138 struct proc_event *ev;
133 __u8 buffer[CN_PROC_MSG_SIZE]; 139 __u8 buffer[CN_PROC_MSG_SIZE];
140 struct timespec ts;
134 141
135 if (atomic_read(&proc_event_num_listeners) < 1) 142 if (atomic_read(&proc_event_num_listeners) < 1)
136 return; 143 return;
@@ -138,7 +145,8 @@ void proc_exit_connector(struct task_struct *task)
138 msg = (struct cn_msg*)buffer; 145 msg = (struct cn_msg*)buffer;
139 ev = (struct proc_event*)msg->data; 146 ev = (struct proc_event*)msg->data;
140 get_seq(&msg->seq, &ev->cpu); 147 get_seq(&msg->seq, &ev->cpu);
141 ktime_get_ts(&ev->timestamp); 148 ktime_get_ts(&ts); /* get high res monotonic timestamp */
149 ev->timestamp_ns = timespec_to_ns(&ts);
142 ev->what = PROC_EVENT_EXIT; 150 ev->what = PROC_EVENT_EXIT;
143 ev->event_data.exit.process_pid = task->pid; 151 ev->event_data.exit.process_pid = task->pid;
144 ev->event_data.exit.process_tgid = task->tgid; 152 ev->event_data.exit.process_tgid = task->tgid;
@@ -164,6 +172,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
164 struct cn_msg *msg; 172 struct cn_msg *msg;
165 struct proc_event *ev; 173 struct proc_event *ev;
166 __u8 buffer[CN_PROC_MSG_SIZE]; 174 __u8 buffer[CN_PROC_MSG_SIZE];
175 struct timespec ts;
167 176
168 if (atomic_read(&proc_event_num_listeners) < 1) 177 if (atomic_read(&proc_event_num_listeners) < 1)
169 return; 178 return;
@@ -171,7 +180,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
171 msg = (struct cn_msg*)buffer; 180 msg = (struct cn_msg*)buffer;
172 ev = (struct proc_event*)msg->data; 181 ev = (struct proc_event*)msg->data;
173 msg->seq = rcvd_seq; 182 msg->seq = rcvd_seq;
174 ktime_get_ts(&ev->timestamp); 183 ktime_get_ts(&ts); /* get high res monotonic timestamp */
184 ev->timestamp_ns = timespec_to_ns(&ts);
175 ev->cpu = -1; 185 ev->cpu = -1;
176 ev->what = PROC_EVENT_NONE; 186 ev->what = PROC_EVENT_NONE;
177 ev->event_data.ack.err = err; 187 ev->event_data.ack.err = err;
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
index dbb7769009be..1c86d65bc4b9 100644
--- a/include/linux/cn_proc.h
+++ b/include/linux/cn_proc.h
@@ -57,7 +57,8 @@ struct proc_event {
57 PROC_EVENT_EXIT = 0x80000000 57 PROC_EVENT_EXIT = 0x80000000
58 } what; 58 } what;
59 __u32 cpu; 59 __u32 cpu;
60 struct timespec timestamp; 60 __u64 __attribute__((aligned(8))) timestamp_ns;
61 /* Number of nano seconds since system boot */
61 union { /* must be last field of proc_event struct */ 62 union { /* must be last field of proc_event struct */
62 struct { 63 struct {
63 __u32 err; 64 __u32 err;