Messages in this thread Patch in this message | | | Subject | [RFC][PATCH 3/3] Process events biarch bug: New process events connector value | From | Matt Helsley <> | Date | Tue, 27 Jun 2006 04:49:35 -0700 |
| |
"Deprecate" existing Process Events connector interface and add a new one that works cleanly on biarch platforms.
Any expansion of the previous event structure would break userspace's ability to workaround the biarch incompatibility problem. Hence this patch creates a new interface and generates events (for both when necessary).
Signed-off-by: Matt Helsley <matthltc@us.ibm.com> --- drivers/connector/cn_proc.c | 65 +++++++++++++++++++++++++++++--------------- include/linux/cn_proc.h | 23 ++++++++++----- include/linux/connector.h | 3 +- 3 files changed, 61 insertions(+), 30 deletions(-)
Index: linux-2.6.17-mm3-biarch/include/linux/connector.h =================================================================== --- linux-2.6.17-mm3-biarch.orig/include/linux/connector.h +++ linux-2.6.17-mm3-biarch/include/linux/connector.h @@ -29,11 +29,12 @@ /* * Process Events connector unique ids -- used for message routing */ #define CN_IDX_PROC 0x1 -#define CN_VAL_PROC 0x1 +#define CN_VAL_PROC_DEPRECATED 0x1 /* deprecated */ +#define CN_VAL_PROC 0x2 #define CN_IDX_CIFS 0x2 #define CN_VAL_CIFS 0x1 #define CN_W1_IDX 0x3 /* w1 communication */ #define CN_W1_VAL 0x1 Index: linux-2.6.17-mm3-biarch/drivers/connector/cn_proc.c =================================================================== --- linux-2.6.17-mm3-biarch.orig/drivers/connector/cn_proc.c +++ linux-2.6.17-mm3-biarch/drivers/connector/cn_proc.c @@ -30,13 +30,19 @@ #include <linux/notifier.h> #include <asm/atomic.h> #include <linux/cn_proc.h> -#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) - -static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); +#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + \ + max(sizeof(struct proc_event), \ + sizeof(struct proc_event_deprecated))) + +static atomic_t proc_event_num_old_listeners = ATOMIC_INIT(0); +static struct cb_id cn_proc_event_deprecated_id = { + CN_IDX_PROC, + CN_VAL_PROC_DEPRECATED +}; static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; /* proc_event_counts is used as the sequence number of the netlink message */ static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; @@ -100,18 +106,18 @@ static inline void proc_exit_connector(s * mechanisms. */ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) { struct cn_msg *msg; - struct proc_event *ev; + struct proc_event_deprecated *ev; __u8 buffer[CN_PROC_MSG_SIZE]; - if (atomic_read(&proc_event_num_listeners) < 1) + if (atomic_read(&proc_event_num_old_listeners) < 1) return; msg = (struct cn_msg*)buffer; - ev = (struct proc_event*)msg->data; + ev = (struct proc_event_deprecated*)msg->data; msg->seq = rcvd_seq; ktime_get_ts(&ev->timestamp); ev->cpu = -1; ev->what = PROC_EVENT_NONE; ev->event_data.ack.err = err; @@ -123,11 +129,11 @@ static void cn_proc_ack(int err, int rcv /** * cn_proc_mcast_ctl * @data: message sent from userspace via the connector */ -static void cn_proc_mcast_ctl(void *data) +static void cn_proc_mcast_old_ctl(void *data) { struct cn_msg *msg = data; enum proc_cn_mcast_op *mc_op = NULL; int err = 0; @@ -135,14 +141,14 @@ static void cn_proc_mcast_ctl(void *data return; mc_op = (enum proc_cn_mcast_op*)msg->data; switch (*mc_op) { case PROC_CN_MCAST_LISTEN: - atomic_inc(&proc_event_num_listeners); + atomic_inc(&proc_event_num_old_listeners); break; case PROC_CN_MCAST_IGNORE: - atomic_dec(&proc_event_num_listeners); + atomic_dec(&proc_event_num_old_listeners); break; default: err = EINVAL; break; } @@ -158,16 +164,15 @@ static int cn_proc_watch_task(struct not void *t) { struct task_struct *task = t; struct cn_msg *msg; struct proc_event *ev; + struct proc_event_deprecated *ev_old; + struct timespec timestamp; __u8 buffer[CN_PROC_MSG_SIZE]; int rc = NOTIFY_OK; - if (atomic_read(&proc_event_num_listeners) < 1) - return rc; - msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; switch (get_watch_event(val)) { case WATCH_TASK_CLONE: proc_fork_connector(task, ev); @@ -189,16 +194,26 @@ static int cn_proc_watch_task(struct not break; } if (rc != NOTIFY_OK) return rc; get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */ + ktime_get_ts(×tamp); /* get high res monotonic timestamp */ + ev->timestamp_ns = ((__u64)timestamp.tv_sec*(__u64)NSEC_PER_SEC) + (__u64)timestamp.tv_nsec; memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); /* If cn_netlink_send() fails, drop data */ + + if (atomic_read(&proc_event_num_old_listeners) < 1) + return rc; + ev_old = (struct proc_event_deprecated*)msg->data; + msg->len = sizeof(*ev_old); + memmove(&ev_old->event_data, &ev->event_data, sizeof(ev->event_data)); + memcpy(&ev_old->timestamp, ×tamp, sizeof(timestamp)); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); + /* If cn_netlink_send() fails, drop data */ return rc; } static struct notifier_block __read_mostly cn_proc_nb = { .notifier_call = cn_proc_watch_task, @@ -211,20 +226,27 @@ static struct notifier_block __read_most */ static int __init cn_proc_init(void) { int err; - if ((err = cn_add_callback(&cn_proc_event_id, "cn_proc", - &cn_proc_mcast_ctl))) { - printk(KERN_WARNING "cn_proc failed to register\n"); - goto out; - } + err = cn_add_callback(&cn_proc_event_deprecated_id, "cn_proc_old", + &cn_proc_mcast_old_ctl); + if (err) + goto error_old; + err = cn_add_callback(&cn_proc_event_id, "cn_proc", NULL); + if (err) + goto error; err = register_task_watcher(&cn_proc_nb); - if (err != 0) - cn_del_callback(&cn_proc_event_id); -out: + if (err) + goto error; + return err; +error: + cn_del_callback(&cn_proc_event_id); +error_old: + cn_del_callback(&cn_proc_event_deprecated_id); + printk(KERN_WARNING "cn_proc failed to register\n"); return err; } static void cn_proc_fini(void) { @@ -234,10 +256,11 @@ static void cn_proc_fini(void) if (err != 0) printk(KERN_WARNING "cn_proc failed to unregister its task notify block\n"); cn_del_callback(&cn_proc_event_id); + cn_del_callback(&cn_proc_event_deprecated_id); } module_init(cn_proc_init); module_exit(cn_proc_fini); Index: linux-2.6.17-mm3-biarch/include/linux/cn_proc.h =================================================================== --- linux-2.6.17-mm3-biarch.orig/include/linux/cn_proc.h +++ linux-2.6.17-mm3-biarch/include/linux/cn_proc.h @@ -55,18 +55,11 @@ struct proc_event { /* "next" should be 0x00000400 */ /* "last" is the last process event: exit */ PROC_EVENT_EXIT = 0x80000000 } what; __u32 cpu; - - /* - * UGH! timespec is biarch incompatible. See - * Documentation/connector/process_events.txt if you're going to listen - * for process events in userspace. - */ - struct timespec timestamp; - + __u64 timestamp_ns; union process_event_data { /* must be last field of proc_event struct */ struct { __u32 err; } ack; @@ -100,6 +93,20 @@ struct proc_event { pid_t process_tgid; __u32 exit_code, exit_signal; } exit; } event_data; }; + +struct proc_event_deprecated { + enum what what; + __u32 cpu; + + /* + * UGH! timespec is biarch incompatible. See + * Documentation/connector/process_events.txt if you're going to listen + * for process events in userspace. + */ + struct timespec timestamp; + union process_event_data event_data; +}; + #endif /* CN_PROC_H */ --
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |