Re: Writing inode_operations->create() function.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi All,

The program code

lwfs ==> superblock operations, registering the file system and unregistering the file system code.
file.c ==> file_operations implementation.
inode.c ==> inode_operations implementation.

Problem which I am facing with this code ==>
After mounting the file system. When I do echo "test" > mnt_pt/some_file_name.    It is giving oops. When file is getting closed.

Here, are some of the messages displayed in the dmesg

[ 4950.360171] Got good INODE.
[ 4950.360191] Got good INODE.
[ 4950.360205] Got good INODE.
[ 4950.360217] Got good INODE.
[ 4960.322256] Got good INODE.
[ 4960.322267] Inode Created : 17190 = test<1>BUG: unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 4960.322328]  printing eip:
[ 4960.322332] c01f3ffe
[ 4960.322335] *pde = 00000000
[ 4960.322341] Oops: 0000 [#2]
[ 4960.322344] SMP
[ 4960.322350] Modules linked in: fs cpufreq_stats cpufreq_ondemand freq_table ac evdev thermal processor fan
[ 4960.322370] CPU:    1
[ 4960.322372] EIP:    0060:[<c01f3ffe>]    Not tainted VLI
[ 4960.322376] EFLAGS: 00010282   (2.6.20 #8)
[ 4960.322386] EIP is at list_del+0xa/0x61
[ 4960.322391] eax: f8868080   ebx: f8868044   ecx: 00000000   edx: e75ef5cc
[ 4960.322398] esi: f8868080   edi: 00000000   ebp: e9464f30   esp: e9464f20
[ 4960.322403] ds: 007b   es: 007b   ss: 0068
[ 4960.322409] Process bash (pid: 6062, ti=e9464000 task=f751b4f0 task.ti=e9464000)
[ 4960.322415] Stack: e75ef5cc e9464f30 c0344186 f8868044 e9464f48 c0179342 e75ef5cc 00000008
[ 4960.322430]        f599e03c e75ef5cc e9464f70 c0155b0a 00000000 00000000 e826b1cc dfff0988
[ 4960.322445]        f599e03c e75ef5cc f7baaca8 00000000 e9464f78 c0155bd8 e9464f90 c0153610
[ 4960.322459] Call Trace:
[ 4960.322462]  [<c01048a2>] show_trace_log_lvl+0x1a/0x2f
[ 4960.322472]  [<c0104954>] show_stack_log_lvl+0x9d/0xa5
[ 4960.322481]  [<c0104af1>] show_registers+0x195/0x26b
[ 4960.322489]  [<c0104ce0>] die+0x119/0x21a
[ 4960.322496]  [<c034713d>] do_page_fault+0x443/0x514
[ 4960.322504]  [<c034597c>] error_code+0x7c/0x84
[ 4960.322511]  [<c0179342>] eventpoll_release_file+0x25/0x69
[ 4960.322519]  [<c0155b0a>] __fput+0xa3/0x15a
[ 4960.322526]  [<c0155bd8>] fput+0x17/0x19
[ 4960.322532]  [<c0153610>] filp_close+0x54/0x5c
[ 4960.322539]  [<c015e6e9>] sys_dup2+0xd0/0xfc
[ 4960.322547]  [<c0103854>] sysenter_past_esp+0x5d/0x99
[ 4960.322555]  =======================
[ 4960.322558] Code: 00 00 8d 4b 0c 8b 51 04 8d 46 0c e8 72 00 00 00 89 f8 e8 87 fe ff ff 83 c4 10 5b 5e 5f 5d c3 90 90 55 89 e5 53 83 ec 0c 8b 48 04 <8b> 11 39 c2 74 18 89 54 24 08 89 44 24 04 c7 04 24 92 37 3e c0
[ 4960.322635] EIP: [<c01f3ffe>] list_del+0xa/0x61 SS:ESP 0068:e9464f20


Please help........
Thanks and Regards,
Prasad.

Code is as follows.

root@prasad-desktop:/home/prasad/programs/ldd/lwfs# cat lwfs.c
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pagemap.h>      /* PAGE_CACHE_SIZE */
#include <linux/fs.h>           /* This is where libfs stuff is declared */
#include <asm/atomic.h>
#include <asm/uaccess.h>        /* copy_to_user */

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jonathan Corbet");

#define LFS_MAGIC 0x19980122


#include "file.h"
#include "inode.h"

static struct dentry *lfs_create_dir (struct super_block *sb, struct dentry *parent, const char *name)
{
        struct dentry *dentry;
        struct inode *inode;
        struct qstr qname;

        qname.name = name;
        qname.len = strlen (name);
        qname.hash = full_name_hash(name, qname.len);
        dentry = d_alloc(parent, &qname);
        if (! dentry)
                goto out;

        inode = lfs_make_inode(sb, S_IFDIR | 0777);
        if (! inode)
                goto out_dput;
        inode->i_op = &lwfs_i_ops;
        inode->i_fop = &simple_dir_operations;

        d_add(dentry, inode);
        return dentry;

  out_dput:
        dput(dentry);
  out:
        return 0;
}

static void lfs_create_files (struct super_block *sb, struct dentry *root)
{
        struct dentry *subdir;

        atomic_set(&counter, 0);
        lfs_create_file(sb, root, "counter", &counter);

        atomic_set(&subcounter, 0);
        subdir = lfs_create_dir(sb, root, "subdir");
        if (subdir)
                lfs_create_file(sb, subdir, "subcounter", &subcounter);
}

static struct super_operations lfs_s_ops =
{
        .statfs         = simple_statfs,
        .drop_inode     = generic_delete_inode,
};

static int lfs_fill_super (struct super_block *sb, void *data, int silent)
{
        struct inode *root;
        struct dentry *root_dentry;

        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
        sb->s_magic = LFS_MAGIC;
        sb->s_op = &lfs_s_ops;

        root = lfs_make_inode (sb, S_IFDIR | 0777);
        if (! root)
                goto out;
        root->i_op = &lwfs_i_ops;
        root->i_fop = &simple_dir_operations;

        root_dentry = d_alloc_root(root);
        if (! root_dentry)
                goto out_iput;
        sb->s_root = root_dentry;

        lfs_create_files (sb, root_dentry);
        return 0;

  out_iput:
        iput(root);
  out:
        return -ENOMEM;
}

static int lfs_get_super(struct file_system_type *fst, int flags, const char *devname, void *data, struct vfsmount *mnt )
{
        return get_sb_single(fst, flags, data, lfs_fill_super, mnt);
}

static struct file_system_type lfs_type = {
        .owner          = THIS_MODULE,
        .name           = "lwnfs",
        .get_sb         = lfs_get_super,
        .kill_sb        = kill_litter_super,
};

static int __init lfs_init(void)
{
        return register_filesystem(&lfs_type);
}

static void __exit lfs_exit(void)
{
        unregister_filesystem(&lfs_type);
}

module_init(lfs_init);
module_exit(lfs_exit);

root@prasad-desktop:/home/prasad/programs/ldd/lwfs# cat file.c
#include <linux/fs.h>
#include <asm/uaccess.h>

#include "file.h"
#include "inode.h"

#define TMPSIZE 20


struct file_operations lfs_file_ops =
{
        .open   = lfs_open,
        .read   = lfs_read_file,
        .write  = lfs_write_file,
};

int lfs_open(struct inode *inode, struct file *filp)
{
        filp->private_data = inode->i_private;
        return 0;
}

ssize_t lfs_read_file(struct file *filp, char *buf, size_t count, loff_t *offset)
{
        atomic_t *counter = (atomic_t *) filp->private_data;
        int v, len;
        char tmp[TMPSIZE];

        v = atomic_read(counter);
        if (*offset > 0)
                v -= 1;  /* the value returned when offset was zero */
        else
                atomic_inc(counter);
        len = snprintf(tmp, TMPSIZE, "%d\n", v);
        if (*offset > len)
                return 0;
        if (count > len - *offset)
                count = len - *offset;

        if (copy_to_user(buf, tmp + *offset, count))
                return -EFAULT;
        *offset += count;
        return count;
}

ssize_t lfs_write_file(struct file *filp, const char *buf, size_t count, loff_t *offset)
{
        atomic_t *counter = (atomic_t *) filp->private_data;
        char tmp[TMPSIZE];

        if (*offset != 0)
                return -EINVAL;

        if (count >= TMPSIZE)
                return -EINVAL;
        memset(tmp, 0, TMPSIZE);
        if (copy_from_user(tmp, buf, count))
                return -EFAULT;

        atomic_set(counter, simple_strtol(tmp, NULL, 10));
        return count;
}


struct dentry *lfs_create_file (struct super_block *sb, struct dentry *dir, const char *name, atomic_t *counter)
{
        struct dentry *dentry;
        struct inode *inode;
        struct qstr qname;

        qname.name = name;
        qname.len = strlen (name);
        qname.hash = full_name_hash(name, qname.len);

        dentry = d_alloc(dir, &qname);
        if (! dentry)
                goto out;
        inode = lfs_make_inode(sb, S_IFREG | 777);
        if (! inode)
                goto out_dput;
        inode->i_fop = &lfs_file_ops;
        inode->i_private = counter;

        d_add(dentry, inode);
        return dentry;

  out_dput:
        dput(dentry);
  out:
        return 0;
}

root@prasad-desktop:/home/prasad/programs/ldd/lwfs# cat inode.c
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/namei.h>
#include <asm/atomic.h>


#include "inode.h"
#include "file.h"

atomic_t counter, subcounter ;

struct inode_operations lwfs_i_ops =
{
        .lookup     = simple_lookup,
        .create = create_inode,
        .unlink = unlink_inode
} ;

int unlink_inode (struct inode *dir,struct dentry *dentry)
{
        struct inode *inode = dentry->d_inode;
        inode_dec_link_count(inode);
        return 0 ;
}


int create_inode (struct inode * dir, struct dentry *dentry, int mode, struct nameidata *nd )
{
        struct inode *inode  = lfs_make_inode ( dir->i_sb, mode) ;
        if ( !inode )
                goto out;

        inode->i_fop = &lfs_file_ops ;

        inode->i_fop = &lfs_file_ops;
        inode->i_private = &counter;

        d_add ( dentry, inode) ;
        printk ( KERN_INFO "Inode Created : %ld = %s", inode->i_ino, dentry->d_name.name) ;
        return 0 ;

        out:
                printk ( KERN_INFO "Got BAD INODE.\n" ) ;
                return -1 ;
}

struct inode *lfs_make_inode(struct super_block *sb, int mode)
{
        struct inode *ret = new_inode(sb);


        if (ret)
        {
                printk  (KERN_INFO "Got good INODE.\n" ) ;

                ret->i_mode = mode;
                ret->i_uid = ret->i_gid = 0;
                ret->i_blkbits = PAGE_CACHE_SIZE;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
        }
        return ret;
}


On 3/12/07, Avishay Traeger <atraeger@xxxxxxxxxxxxx> wrote:
On Mon, 2007-03-12 at 20:10 +0530, Prasad Joshi wrote:
>
> Please someone help or at least point me to some more such links.
>
> Thanks and regards,
> Prasad.

Post all of your code and I (and hopefully others) will take a look.

Avishay




[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux