Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755555AbYJPGMd (ORCPT ); Thu, 16 Oct 2008 02:12:33 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755160AbYJPGL6 (ORCPT ); Thu, 16 Oct 2008 02:11:58 -0400 Received: from qmta10.emeryville.ca.mail.comcast.net ([76.96.30.17]:43139 "EHLO QMTA10.emeryville.ca.mail.comcast.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754982AbYJPGLx (ORCPT ); Thu, 16 Oct 2008 02:11:53 -0400 X-Authority-Analysis: v=1.0 c=1 a=1_itVgU-qY8A:10 a=IX0hwOJc-j8A:10 a=WJfgWLpVyee67jL_EXUA:9 a=hPz76RWG6cs6rnRzYOgA:7 a=WBlnbm85NGCNFkDfE5_0g9VJHbYA:4 a=T81ihCft0O8A:10 Subject: [RFC PATCH 1/21] relay - Clean up relay_switch_subbuf() and make waking up consumers optional. From: Tom Zanussi To: Linux Kernel Mailing List Cc: Martin Bligh , Peter Zijlstra , prasad@linux.vnet.ibm.com, Linus Torvalds , Thomas Gleixner , Mathieu Desnoyers , Steven Rostedt , od@suse.com, "Frank Ch. Eigler" , Andrew Morton , hch@lst.de, David Wilder , Jens Axboe , Pekka Enberg , Eduard - Gabriel Munteanu Content-Type: text/plain Date: Thu, 16 Oct 2008 01:05:26 -0500 Message-Id: <1224137126.16328.220.camel@charm-linux> Mime-Version: 1.0 X-Mailer: Evolution 2.12.0 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5685 Lines: 180 Over time, relay_switch_subbuf() has accumulated some cruft - this patch cleans it up and at the same time makes available some of it available as common functions that any subbuf-switch implementor would need (this is partially in preparation for the next patch, which makes the subbuf-switch function completely replaceable). It also removes the hard-coded reader wakeup and moves it into a replaceable callback called notify_consumers(); this allows any given tracer to implement consumer notification as it sees fit. --- include/linux/relay.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ kernel/relay.c | 43 +++++++++++++++++++++++------------------ 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/include/linux/relay.h b/include/linux/relay.h index 953fc05..17f0515 100644 --- a/include/linux/relay.h +++ b/include/linux/relay.h @@ -159,6 +159,15 @@ struct rchan_callbacks * The callback should return 0 if successful, negative if not. */ int (*remove_buf_file)(struct dentry *dentry); + + /* + * notify_consumers - new sub-buffer available, let consumers know + * @buf: the channel buffer + * + * Called during sub-buffer switch. Applications which don't + * want to notify anyone should implement an empty version. + */ + void (*notify_consumers)(struct rchan_buf *buf); }; /* @@ -186,6 +195,48 @@ extern size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length); /** + * relay_event_toobig - is event too big to fit in a sub-buffer? + * @buf: relay channel buffer + * @length: length of event + * + * Returns 1 if too big, 0 otherwise. + * + * switch_subbuf() helper function. + */ +static inline int relay_event_toobig(struct rchan_buf *buf, size_t length) +{ + return length > buf->chan->subbuf_size; +} + +/** + * relay_update_filesize - increase relay file i_size by length + * @buf: relay channel buffer + * @length: length to add + * + * switch_subbuf() helper function. + */ +static inline void relay_update_filesize(struct rchan_buf *buf, size_t length) +{ + if (buf->dentry) + buf->dentry->d_inode->i_size += length; + else + buf->early_bytes += length; + + smp_mb(); +} + +/** + * relay_inc_produced - increase number of sub-buffers produced by 1 + * @buf: relay channel buffer + * + * switch_subbuf() helper function. + */ +static inline void relay_inc_produced(struct rchan_buf *buf) +{ + buf->subbufs_produced++; +} + +/** * relay_write - write data into the channel * @chan: relay channel * @data: data to be written diff --git a/kernel/relay.c b/kernel/relay.c index 8d13a78..53652f1 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -324,6 +324,21 @@ static int remove_buf_file_default_callback(struct dentry *dentry) return -EINVAL; } +/* + * notify_consumers() default callback. + */ +static void notify_consumers_default_callback(struct rchan_buf *buf) +{ + if (waitqueue_active(&buf->read_wait)) + /* + * Calling wake_up_interruptible() from here + * will deadlock if we happen to be logging + * from the scheduler (trying to re-grab + * rq->lock), so defer it. + */ + __mod_timer(&buf->timer, jiffies + 1); +} + /* relay channel default callbacks */ static struct rchan_callbacks default_channel_callbacks = { .subbuf_start = subbuf_start_default_callback, @@ -331,6 +346,7 @@ static struct rchan_callbacks default_channel_callbacks = { .buf_unmapped = buf_unmapped_default_callback, .create_buf_file = create_buf_file_default_callback, .remove_buf_file = remove_buf_file_default_callback, + .notify_consumers = notify_consumers_default_callback, }; /** @@ -508,6 +524,8 @@ static void setup_callbacks(struct rchan *chan, cb->create_buf_file = create_buf_file_default_callback; if (!cb->remove_buf_file) cb->remove_buf_file = remove_buf_file_default_callback; + if (!cb->notify_consumers) + cb->notify_consumers = notify_consumers_default_callback; chan->cb = cb; } @@ -726,30 +744,17 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) void *old, *new; size_t old_subbuf, new_subbuf; - if (unlikely(length > buf->chan->subbuf_size)) + if (unlikely(relay_event_toobig(buf, length))) goto toobig; if (buf->offset != buf->chan->subbuf_size + 1) { buf->prev_padding = buf->chan->subbuf_size - buf->offset; old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; buf->padding[old_subbuf] = buf->prev_padding; - buf->subbufs_produced++; - if (buf->dentry) - buf->dentry->d_inode->i_size += - buf->chan->subbuf_size - - buf->padding[old_subbuf]; - else - buf->early_bytes += buf->chan->subbuf_size - - buf->padding[old_subbuf]; - smp_mb(); - if (waitqueue_active(&buf->read_wait)) - /* - * Calling wake_up_interruptible() from here - * will deadlock if we happen to be logging - * from the scheduler (trying to re-grab - * rq->lock), so defer it. - */ - __mod_timer(&buf->timer, jiffies + 1); + relay_inc_produced(buf); + relay_update_filesize(buf, buf->chan->subbuf_size - + buf->padding[old_subbuf]); + buf->chan->cb->notify_consumers(buf); } old = buf->data; @@ -763,7 +768,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) buf->data = new; buf->padding[new_subbuf] = 0; - if (unlikely(length + buf->offset > buf->chan->subbuf_size)) + if (unlikely(relay_event_toobig(buf, length + buf->offset))) goto toobig; return length; -- 1.5.3.5 -- 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/