I am trying to use relayFS from an interrupt context. I read the
documentation and downloaded and ran successfully the examples from
http://relayfs.sourceforge.net.

I am running on Fedora 6 machine with 2.6.18-1.2798.fc6 kernel (no patches).
I have two years of experience in linux kernel programming.

I am mounting successfully debugfs on /debug.

According to relay.txt from the Linux documentation,
relay_write() should be used if you might be logging from interrupt context.

My module needs to write from interrupt context (in fact, it is a soft
interrupt) so I tried using relay_write.

My user space application try to read the relayFS files using read, not mmap,
following the read-mod kernel module from the examples (which I tried
successfully).

What happens that when I try reading the relayFS files (by cat, which
eventually uses read) which I generated
from interrupt context in my module, I get nothing;
while when trying files which are generated
from a kernel thread with relay_write, I do succeed with reading these
files using cat.
I am attaching the code for the test module I wrote and I hope you can
take a look at it; I simplified it and removed away everything which is
not connected directly to my question.
What happens is, in fact: when calling start_test_thread_new() we DO succeed to
read the file with cat /debug/testTree/cpu0, whereas when
using the second alternative, meaning calling directly test_thread_new()
from the main_hook() (which runs in software interrupt context) we
do not read anything (cat /debug/testTree/cpu0 shows nothing; there is,however,
no segfault when running "cat /debug/testTree/cpu0" in that case).

here below is test.c, a short module which I wrote demonstarting this
problem.


Any ideas?

Regards,
Rami Rosen



// test.c

#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/compiler.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/byteorder/generic.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/spinlock.h>
#include <net/ip.h>
#include <linux/vmalloc.h>
#include <linux/debugfs.h>
#include <linux/relay.h>
#include <linux/kthread.h>


#define MAX_EVENT_SIZE 256


struct dentry *dir;
struct rchan *channel;
static struct completion done;
static int hooksRegistered = 0;
static struct task_struct *kthread_thread;

static int test_thread_new(void *unused)
{
        int i,count;
        char buf[MAX_EVENT_SIZE + 1];

        for (i = 0; i < 10; i++) {
                        count = snprintf(buf, MAX_EVENT_SIZE,
                                "[%08i]test event\n", i);
        
                        relay_write(channel, buf, count);
        }
        return 0;
}


static void start_test_thread_new(void)
{
        int cpu = 0;
        struct task_struct *p;
        printk("in start_test_thread_new\n");
        init_completion(&done);
        
        p = kthread_create(test_thread_new, NULL, "%s/%d", "test", cpu);
        if (IS_ERR(p))
                return;
        if (p) {
                kthread_bind(p, cpu);
                wake_up_process(p);
                kthread_thread = p;
        }

}



static int test_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
                                     void *prev_subbuf, size_t prev_padding)
{
        if (relay_buf_full(buf))
                {
                printk("buffer full\n");      
                return 0;
                }

        return 1;
                
}

static int test_remove_buf_file_callback(struct dentry *dentry)
{
         debugfs_remove(dentry);
         return 0;
}


static struct dentry *test_create_buf_file_callback(const char *filename,
                                                   struct dentry *parent,
                                                   int mode,
                                                   struct rchan_buf *buf,
                                                   int *is_global)
{
         return debugfs_create_file(filename, mode, parent, buf,
                                   &relay_file_operations);
}

static struct nf_hook_ops netfilter_ops_in;
        
static int inithook(void);

//////////////////////////////////////////////////////////////////////////////  


unsigned int main_hook(unsigned int hooknum,
                                                                                
         struct sk_buff** skb,
                                                                                
         const struct net_device* in,
                                                                                
         const struct net_device* out,
                                                                                
         int (*okfn)(struct sk_buff*))
 {
        static int counter=0;
        void *unused=NULL;
        counter++;      
        printk("in main_hook counter=%d\n",counter);
        test_thread_new(unused);
        return NF_ACCEPT;
        }
        
//////////////////////////////////////////////////////////////////////////////

static int inithook()
{
        int i;
        printk("starting inithook\n");

        netfilter_ops_in.hook     = main_hook;
        netfilter_ops_in.pf       = PF_INET;    
        netfilter_ops_in.hooknum  = NF_IP_PRE_ROUTING;
        netfilter_ops_in.priority = NF_IP_PRI_FIRST;
        nf_register_hook(&netfilter_ops_in);

        hooksRegistered = 1;
        printk(KERN_INFO "ioctl_init finished OK \n");
        
        return 0;
        }


//////////////////////////////////////////////////////////////////////////////
        
        
        
static int __init test_init(void)
        {
        int ret;
        int j;
        int res;
        
        printk("starting test_init \n");
                {
                static struct rchan_callbacks blk_relay_callbacks = {
        .subbuf_start           = test_subbuf_start_callback,
        .create_buf_file        = test_create_buf_file_callback,
        .remove_buf_file        = test_remove_buf_file_callback,
                };
                
                dir = debugfs_create_dir("testTree",0);
                if (!dir)
                        {
                        printk("debugfs_create_dir failed!\n");
                        }
                else
                        printk("debugfs_create_dir succeeded!\n");

                channel=relay_open("cpu",
                                                                                
          dir,
                                                                                
                262144,
                                                                                
                4,
                                                                                    
            &blk_relay_callbacks);
                if (!(channel))
                        {
                        printk("relay_open() failed!\n");
                        return -1;
                        }

                }
        res = inithook();
        // start_test_thread_new();
        if (res==-1)
                        return -1;
        return 0;
        }

//////////////////////////////////////////////////////////////////////////////

static void __exit test_exit(void)
        {
        if (hooksRegistered)
                nf_unregister_hook(&netfilter_ops_in);
        if (channel)
                relay_close(channel);   
        if (dir)
                        debugfs_remove(dir);
        printk("test_exit finished \n");
        }
        
//////////////////////////////////////////////////////////////////////////////

module_init(test_init)
module_exit(test_exit)

MODULE_AUTHOR("test");
MODULE_DESCRIPTION("test");
MODULE_LICENSE("GPL");
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to