[RFC PATCH 21/21] Re-add late setup/early tracing.

From: Tom Zanussi
Date: Thu Oct 16 2008 - 02:19:27 EST


---
include/linux/relay_pagewriter.h | 5 +++
kernel/relay_pagewriter.c | 66 +++++++++++++++++++++++++++++++-------
2 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/include/linux/relay_pagewriter.h b/include/linux/relay_pagewriter.h
index 91ad16b..8fb4038 100644
--- a/include/linux/relay_pagewriter.h
+++ b/include/linux/relay_pagewriter.h
@@ -26,6 +26,7 @@
*/
#define PAGEWRITER_PAD_WRITES 0x00010000 /* don't cross pages */
#define PAGEWRITER_FLIGHT_MODE 0x00020000 /* n_pages page ring */
+#define PAGEWRITER_LATE_SETUP 0x00040000 /* delay chan create */

/*
* Per-cpu pagewriter buffer
@@ -49,12 +50,14 @@ struct pagewriter {
struct rchan *rchan; /* associated relay channel */
struct pagewriter_callbacks *cb; /* client callbacks */
size_t n_pages; /* number of pages per buffer */
+ size_t n_pages_wakeup; /* save for LATE */
struct kref kref; /* channel refcount */
void *private_data; /* for user-defined data */
size_t last_toobig; /* tried to log event > page size */
struct pagewriter_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
struct list_head list; /* for channel list */
atomic_t dropped; /* dropped events due to buffer-full */
+ char base_filename[NAME_MAX]; /* saved base filename, for LATE */
unsigned long flags; /* pagewriter flags for this channel */
};

@@ -286,5 +289,7 @@ extern void pagewriter_flush(struct pagewriter *pagewriter);
extern void pagewriter_close(struct pagewriter *pagewriter);
extern void pagewriter_reset(struct pagewriter *pagewriter);
extern void pagewriter_save_flight_data(struct pagewriter *pagewriter);
+extern int pagewriter_late_setup(struct pagewriter *pagewriter,
+ struct dentry *parent);

#endif /* _LINUX_RELAY_PAGEWRITER_H */
diff --git a/kernel/relay_pagewriter.c b/kernel/relay_pagewriter.c
index c3369f5..369abbe 100644
--- a/kernel/relay_pagewriter.c
+++ b/kernel/relay_pagewriter.c
@@ -72,23 +72,27 @@ struct pagewriter *pagewriter_open(const char *base_filename,
{
unsigned int i;
struct pagewriter *pagewriter;
- struct rchan *rchan;

if (!n_pages)
return NULL;

- rchan = relay_open(base_filename, parent, n_pages_wakeup, NULL,
- private_data, flags);
- if (!rchan)
- return NULL;
-
pagewriter = kzalloc(sizeof(struct pagewriter), GFP_KERNEL);
- if (!pagewriter) {
- relay_close(rchan);
+ if (!pagewriter)
return NULL;
+
+ if (flags & PAGEWRITER_LATE_SETUP) {
+ strlcpy(pagewriter->base_filename, base_filename, NAME_MAX);
+ pagewriter->n_pages_wakeup = n_pages_wakeup;
+ } else {
+ pagewriter->rchan = relay_open(base_filename, parent,
+ n_pages_wakeup, NULL,
+ private_data, flags);
+ if (!pagewriter->rchan) {
+ kfree(pagewriter);
+ return NULL;
+ }
}

- pagewriter->rchan = rchan;
pagewriter->flags = flags;
pagewriter->n_pages = n_pages;
atomic_set(&pagewriter->dropped, 0);
@@ -115,9 +119,9 @@ free_bufs:
pagewriter_close_buf(pagewriter->buf[i]);
}

- kfree(pagewriter);
- relay_close(rchan);
+ relay_close(pagewriter->rchan);
kref_put(&pagewriter->kref, pagewriter_destroy);
+ kfree(pagewriter);
mutex_unlock(&pagewriters_mutex);
return NULL;
}
@@ -240,6 +244,43 @@ void pagewriter_save_flight_data(struct pagewriter *pagewriter)
}
EXPORT_SYMBOL_GPL(pagewriter_save_flight_data);

+/**
+ * pagewriter_late_setup - create relay channel and log early pages
+ * @pagewriter: pagewriter
+ * @parent: dentry of parent directory, %NULL for root directory
+ *
+ * If the pagewriter was initially created in early mode
+ * (PAGEWRITER_LATE_SETUP), this creates the relay channel and
+ * sends all the early pages in the page pools to relay and
+ * therefore onto their final destination e.g. disk or network.
+ *
+ * Returns 0 if successful, non-zero otherwise.
+ *
+ * Use to setup files for a previously buffer-only channel.
+ * Useful to do early tracing in kernel, before VFS is up, for example.
+ */
+int pagewriter_late_setup(struct pagewriter *pagewriter,
+ struct dentry *parent)
+{
+ if (!pagewriter)
+ return -EINVAL;
+
+ pagewriter->rchan = relay_open(pagewriter->base_filename,
+ parent,
+ pagewriter->n_pages_wakeup,
+ NULL,
+ pagewriter->private_data,
+ pagewriter->flags);
+ if (!pagewriter->rchan)
+ return -ENOMEM;
+
+ pagewriter->flags &= ~PAGEWRITER_LATE_SETUP;
+ pagewriter_save_flight_data(pagewriter);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pagewriter_late_setup);
+
/*
* end relay kernel API
*/
@@ -573,7 +614,8 @@ size_t pagewriter_switch_page_default_callback(struct pagewriter_buf *buf,
if (!(buf->pagewriter->flags & PAGEWRITER_PAD_WRITES))
remainder = length - (PAGE_SIZE - buf->offset);

- if (buf->pagewriter->flags & PAGEWRITER_FLIGHT_MODE) {
+ if (buf->pagewriter->flags & PAGEWRITER_FLIGHT_MODE ||
+ buf->pagewriter->flags & PAGEWRITER_LATE_SETUP) {
list_add_tail(&buf->page->list, &buf->pool);
buf->n_pages_flight++;
} else {
--
1.5.3.5



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/