Google Groups Home
Help | Sign in
relayfs redux, part 4
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  7 messages - Collapse all
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
Tom Zanussi  
View profile
 More options Feb 9 2005, 10:00 pm
Newsgroups: linux.kernel
From: Tom Zanussi <zanu...@us.ibm.com>
Date: Thu, 10 Feb 2005 04:00:13 +0100
Local: Wed, Feb 9 2005 10:00 pm
Subject: [PATCH] relayfs redux, part 4
Hi,

Here's the latest relayfs patch, incorporating the previous round of
suggestions.  Thanks to everyone who sent comments.  Here's a list of
the major changes:

- replaced remap_page_range() and reserved bits with a nopage()
  handler.
- buffers are now allocated/freed as part of inode alloc/destroy.
- got rid of the automatic creation/teardown of directory hierarchies,
  and exported create/remove dir functions instead.
- replaced the fileop callback with explicit map/unmap callbacks - these
  were the only fileops currently being used by anything, so I got rid
  of the other cases.
- relay_write() and __relay_write() no longer return a value - it
  doesn't really make sense for clients to check a return value in the
  fast path anyway.
- added a buf_full() callback to notify users that a buffer has become
  full and therefore events might be lost.
- got rid of the 'helper' macros, which weren't helping much.
- various other bits of code and comment cleanup.

Also, there was some question as to whether or not the memcpy in
relay_write() was being inlined properly - I looked at the generated
assembly code, and it seems to be, but I'll be taking a closer look
later.

This is what the API now looks like:

  API functions:

    rchan *relay_open(base_filename, parent, subbuf_size, n_subbufs,
                      flags, callbacks);
    void relay_close(chan);
    dentry *relayfs_create_dir(name, parent);
    int relayfs_remove_dir(dentry);
    void relay_reset(chan);

    void relay_write(chan, data, length);
    void __relay_write(chan, data, length);
    void *relay_reserve(chan, length);

    void relay_subbufs_consumed(chan, subbufs_consumed, cpu);
    void relay_commit(buf, subbuf_idx, count);

  callbacks:

    int subbuf_start(buf, subbuf, prev_subbuf_idx);
    int deliver(buffer, subbuf, subbuf_idx);
    void buf_mapped(buf, filp);
    void buf_unmapped(buf, filp);
    void buf_full(buf);

As before, I've tested this code on a single proc machine using a
hacked version of the kprobes network packet tracing module, which can
be found here:

http://prdownloads.sourceforge.net/dprobes/plog.tar.gz?download

If people are more or less happy with the current version, I'll do
some SMP testing and write some Documentation.

Thanks,

Tom

Signed-off-by: Tom Zanussi <zanu...@us.ibm.com>

 fs/Kconfig                 |   12
 fs/Makefile                |    1
 fs/relayfs/Makefile        |    4
 fs/relayfs/buffers.c       |  119 ++++++++
 fs/relayfs/buffers.h       |   14 +
 fs/relayfs/inode.c         |  447 ++++++++++++++++++++++++++++++++
 fs/relayfs/relay.c         |  616 +++++++++++++++++++++++++++++++++++++++++++++
 fs/relayfs/relay.h         |   31 ++
 include/linux/relayfs_fs.h |  253 ++++++++++++++++++
 9 files changed, 1497 insertions(+)

diff -urpN -X dontdiff linux-2.6.10/fs/Kconfig linux-2.6.10-cur/fs/Kconfig
--- linux-2.6.10/fs/Kconfig     2004-12-24 15:34:58.000000000 -0600
+++ linux-2.6.10-cur/fs/Kconfig 2005-01-31 21:49:27.000000000 -0600
@@ -972,6 +972,18 @@ config RAMFS
          To compile this as a module, choose M here: the module will be called
          ramfs.

+config RELAYFS_FS
+       tristate "Relayfs file system support"
+       ---help---
+         Relayfs is a high-speed data relay filesystem designed to provide
+         an efficient mechanism for tools and facilities to relay large
+         amounts of data from kernel space to user space.
+
+         To compile this code as a module, choose M here: the module will be
+         called relayfs.
+
+         If unsure, say N.
+
 endmenu

 menu "Miscellaneous filesystems"
diff -urpN -X dontdiff linux-2.6.10/fs/Makefile linux-2.6.10-cur/fs/Makefile
--- linux-2.6.10/fs/Makefile    2004-12-24 15:34:58.000000000 -0600
+++ linux-2.6.10-cur/fs/Makefile        2005-01-31 21:49:27.000000000 -0600
@@ -94,3 +94,4 @@ obj-$(CONFIG_AFS_FS)          += afs/
 obj-$(CONFIG_BEFS_FS)          += befs/
 obj-$(CONFIG_HOSTFS)           += hostfs/
 obj-$(CONFIG_HPPFS)            += hppfs/
+obj-$(CONFIG_RELAYFS_FS)       += relayfs/
diff -urpN -X dontdiff linux-2.6.10/fs/relayfs/Makefile linux-2.6.10-cur/fs/relayfs/Makefile
--- linux-2.6.10/fs/relayfs/Makefile    1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.10-cur/fs/relayfs/Makefile        2005-02-03 06:34:11.000000000 -0600
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RELAYFS_FS) += relayfs.o
+
+relayfs-y := relay.o buffers.o inode.o
+
diff -urpN -X dontdiff linux-2.6.10/fs/relayfs/buffers.c linux-2.6.10-cur/fs/relayfs/buffers.c
--- linux-2.6.10/fs/relayfs/buffers.c   1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.10-cur/fs/relayfs/buffers.c       2005-02-03 08:16:39.000000000 -0600
@@ -0,0 +1,119 @@
+/*
+ * RelayFS buffer management code.
+ *
+ * Copyright (C) 2002, 2003 - Tom Zanussi (zanu...@us.ibm.com), IBM Corp
+ * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (ka...@opersys.com)
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include "buffers.h"
+
+/**
+ *     alloc_page_array - alloc array to hold pages, but not pages
+ *     @size: the total size of the memory represented by the page array
+ *     @page_count: the number of pages the array can hold
+ *
+ *     Returns a pointer to the page array if successful, NULL otherwise.
+ */
+static inline struct page **alloc_page_array(int size, int *page_count)
+{
+       int n_pages;
+       struct page **page_array;
+
+       size = PAGE_ALIGN(size);
+       n_pages = size >> PAGE_SHIFT;
+
+       page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
+       if (!page_array)
+               return NULL;
+       *page_count = n_pages;
+
+       return page_array;
+}
+
+/**
+ *     depopulate_page_array - free and unreserve all pages in the array
+ *     @page_array: pointer to the page array
+ *     @page_count: number of pages to free
+ */
+static void depopulate_page_array(struct page **page_array, int page_count)
+{
+       int i;
+
+       for (i = 0; i < page_count; i++)
+               __free_page(page_array[i]);
+}
+
+/**
+ *     populate_page_array - allocate and reserve pages
+ *     @page_array: pointer to the page array
+ *     @page_count: number of pages to allocate
+ *
+ *     Returns 0 if successful, negative otherwise.
+ */
+static int populate_page_array(struct page **page_array, int page_count)
+{
+       int i;
+
+       for (i = 0; i < page_count; i++) {
+               page_array[i] = alloc_page(GFP_KERNEL);
+               if (unlikely(!page_array[i])) {
+                       depopulate_page_array(page_array, i);
+                       return -ENOMEM;
+               }
+       }
+       return 0;
+}
+
+/**
+ *     relay_alloc_rchan_buf - allocate a channel buffer
+ *     @size: total size of the buffer
+ *     @page_array: receives a pointer to the buffer's page array
+ *     @page_count: receives the number of pages allocated
+ *
+ *     Returns a pointer to the resulting buffer, NULL if unsuccessful
+ */
+void *relay_alloc_rchan_buf(unsigned long size, struct page ***page_array,
+                           int *page_count)
+{
+       void *mem;
+
+       *page_array = alloc_page_array(size, page_count);
+       if (!*page_array)
+               return NULL;
+
+       if (populate_page_array(*page_array, *page_count)) {
+               kfree(*page_array);
+               *page_array = NULL;
+               return NULL;
+       }
+
+       mem = vmap(*page_array, *page_count, GFP_KERNEL, PAGE_KERNEL);
+       if (!mem) {
+               depopulate_page_array(*page_array, *page_count);
+               kfree(*page_array);
+               *page_array = NULL;
+               return NULL;
+       }
+       memset(mem, 0, size);
+
+       return mem;
+}
+
+/**
+ *     relay_free_rchan_buf - free a channel buffer
+ *     @buf: pointer to the buffer to free
+ *     @page_array: pointer to the buffer's page array
+ *     @page_count: number of pages in page array
+ */
+void relay_free_rchan_buf(void *buf, struct page **page_array,
+                         int page_count)
+{
+       vunmap(buf);
+       depopulate_page_array(page_array, page_count);
+       kfree(page_array);
+}
diff -urpN -X dontdiff linux-2.6.10/fs/relayfs/buffers.h linux-2.6.10-cur/fs/relayfs/buffers.h
--- linux-2.6.10/fs/relayfs/buffers.h   1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.10-cur/fs/relayfs/buffers.h       2005-01-31 21:49:27.000000000 -0600
@@ -0,0 +1,14 @@
+#ifndef _BUFFERS_H
+#define _BUFFERS_H
+
+/* This inspired by rtai/shmem */
+#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE
+
+extern void *relay_alloc_rchan_buf(unsigned long size,
+                                  struct page ***page_array,
+                                  int *page_count);
+extern void relay_free_rchan_buf(void *buf,
+                                struct page **page_array,
+                                int page_count);
+
+#endif/* _BUFFERS_H */
diff -urpN -X dontdiff linux-2.6.10/fs/relayfs/inode.c linux-2.6.10-cur/fs/relayfs/inode.c
--- linux-2.6.10/fs/relayfs/inode.c     1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.10-cur/fs/relayfs/inode.c 2005-02-06 00:22:18.000000000 -0600
@@ -0,0 +1,447 @@
+/*
+ * VFS-related code for RelayFS, a high-speed data relay filesystem.
+ *
+ * Copyright (C) 2003 - Tom Zanussi <zanu...@us.ibm.com>, IBM Corp
+ * Copyright (C) 2003 - Karim Yaghmour <ka...@opersys.com>
+ *
+ * Based on ramfs, Copyright (C) 2002 - Linus Torvalds
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/backing-dev.h>
+#include <linux/namei.h>
+#include <linux/poll.h>
+#include <linux/relayfs_fs.h>
+#include "relay.h"
+
+#define RELAYFS_MAGIC                  0x26F82121
+
+static struct vfsmount *               relayfs_mount;
+static int                             relayfs_mount_count;
+static kmem_cache_t *                  relayfs_inode_cachep;
+
+static struct backing_dev_info         relayfs_backing_dev_info = {
+       .ra_pages       = 0,    /* No readahead */
+       .memory_backed  = 1,    /* Does not contribute to dirty memory */
+};
+
+static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
+                                      struct rchan *chan)
+{
+       struct rchan_buf *buf = NULL;
+       struct inode *inode;
+
+       if (S_ISREG(mode)) {
+               BUG_ON(!chan);
+               buf = rchan_create_buf(chan);
+               if (!buf)
+                       return NULL;
+       }
+      
+       inode = new_inode(sb);
+       if (!inode) {
+               rchan_destroy_buf(buf);
+               return NULL;
+       }
+      
+       inode->i_mode = mode;
+       inode->i_uid = 0;
+       inode->i_gid = 0;
+       inode->i_blksize = PAGE_CACHE_SIZE;
+       inode->i_blocks = 0;
+       inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info;
+ ...

read more »


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Maneesh Soni  
View profile
 More options Feb 10 2005, 1:40 am
Newsgroups: linux.kernel
From: Maneesh Soni <mane...@in.ibm.com>
Date: Thu, 10 Feb 2005 07:40:08 +0100
Local: Thurs, Feb 10 2005 1:40 am
Subject: Re: [PATCH] relayfs redux, part 4
On Wed, Feb 09, 2005 at 08:49:36PM -0600, Tom Zanussi wrote:

[..]

> + */
> +struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
> +                             int mode, struct rchan *chan)
> +{
> +  struct dentry *dentry;
> +  int error;
> +  
> +  if (!mode)
> +          mode = S_IRUSR;
> +  mode = (mode & S_IALLUGO) | S_IFREG;
> +
> +  error = relayfs_create_entry(name, parent, mode, chan, &dentry);

^^^^
I think you missed GregKH's suggesstion to have relayfs_create_entry()
return pointer to struct dentry, and reduce one parameter.

                ^^^^^^^^
                Typo? statement after return !

Thanks
Maneesh

--
Maneesh Soni
Linux Technology Center,
IBM India Software Labs,
Bangalore, India
email: mane...@in.ibm.com
Phone: 91-80-25044990
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tom Zanussi  
View profile
 More options Feb 10 2005, 2:00 am
Newsgroups: linux.kernel
From: Tom Zanussi <zanu...@us.ibm.com>
Date: Thu, 10 Feb 2005 08:00:15 +0100
Local: Thurs, Feb 10 2005 2:00 am
Subject: Re: [PATCH] relayfs redux, part 4
Maneesh Soni writes:

 > On Wed, Feb 09, 2005 at 08:49:36PM -0600, Tom Zanussi wrote:
 > [..]
 > > + */
 > > +struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
 > > +                               int mode, struct rchan *chan)
 > > +{
 > > +    struct dentry *dentry;
 > > +    int error;
 > > +    
 > > +    if (!mode)
 > > +            mode = S_IRUSR;
 > > +    mode = (mode & S_IALLUGO) | S_IFREG;
 > > +
 > > +    error = relayfs_create_entry(name, parent, mode, chan, &dentry);
 >
 > ^^^^
 > I think you missed GregKH's suggesstion to have relayfs_create_entry()
 > return pointer to struct dentry, and reduce one parameter.

Yes, you're right - somehow I missed that one.

 > > +
 > > +    if (unlikely(relay_buf_full(buf))) {
 > > +            return 0;
 > > +            buf->chan->cb->buf_full(buf);
 >
 >           ^^^^^^^^
 >           Typo? statement after return !

Yikes!  Obviously I haven't tested the buffer full condition yet ;-)

Thanks for pointing these out.

Tom

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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pekka Enberg  
View profile
 More options Feb 10 2005, 2:40 am
Newsgroups: linux.kernel
From: Pekka Enberg <penb...@gmail.com>
Date: Thu, 10 Feb 2005 08:40:09 +0100
Local: Thurs, Feb 10 2005 2:40 am
Subject: Re: [PATCH] relayfs redux, part 4
Hi Tom,

[snip]

[snip]

Please consider inlining alloc_page_array() and populate_page_array()
into relay_alloc_rchan_buf() as they're only used once. You'd get rid
of passing page_count as a pointer this way. If inlining is
unacceptable, please at least move the n_pages calculation to
relay_alloc_rchan_buf() to make the API more sane.

I think relay_alloc_rchan_buf also would benefit from goto-styled
error handling.

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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pekka Enberg  
View profile
 More options Feb 10 2005, 3:00 am
Newsgroups: linux.kernel
From: Pekka Enberg <penb...@gmail.com>
Date: Thu, 10 Feb 2005 09:00:20 +0100
Local: Thurs, Feb 10 2005 3:00 am
Subject: Re: [PATCH] relayfs redux, part 4

Please move the nested if statement to the parent expression. The
!parent part is always evaluated first.

> +static struct inode *relayfs_alloc_inode(struct super_block *sb)
> +{
> +       struct relayfs_inode_info *p;
> +       p = (struct relayfs_inode_info *)kmem_cache_alloc(relayfs_inode_cachep,
> +                                                         SLAB_KERNEL);

Please drop the spurious cast from void *.

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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pekka J Enberg  
View profile
 More options Feb 10 2005, 4:20 am
Newsgroups: linux.kernel
From: "Pekka J Enberg" <penb...@cs.helsinki.fi>
Date: Thu, 10 Feb 2005 10:20:23 +0100
Local: Thurs, Feb 10 2005 4:20 am
Subject: Re: relayfs redux, part 4

I wrote:
>> Please consider inlining alloc_page_array() and populate_page_array()
>> into relay_alloc_rchan_buf() as they're only used once. You'd get rid
>> of passing page_count as a pointer this way. If inlining is
>> unacceptable, please at least move the n_pages calculation to
>> relay_alloc_rchan_buf() to make the API more sane.
Andi Kleen writes:
> Modern gcc (3.3-hammer with unit-at-a-time or 3.4) will do that anyways on
> its own.

I know that but I am commenting on readability. The pointer passing is due
to silly interface (alloc_page_array() calculating number of pages on its
own).

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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andi Kleen  
View profile
 More options Feb 10 2005, 4:20 am
Newsgroups: linux.kernel
From: Andi Kleen <a...@muc.de>
Date: Thu, 10 Feb 2005 10:20:27 +0100
Local: Thurs, Feb 10 2005 4:20 am
Subject: Re: [PATCH] relayfs redux, part 4

> Please consider inlining alloc_page_array() and populate_page_array()
> into relay_alloc_rchan_buf() as they're only used once. You'd get rid
> of passing page_count as a pointer this way. If inlining is
> unacceptable, please at least move the n_pages calculation to
> relay_alloc_rchan_buf() to make the API more sane.

Modern gcc (3.3-hammer with unit-at-a-time or 3.4) will do that anyways on
its own.

-Andi

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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google