eager2learn
eager2learn

Reputation: 1488

proc_dir_entry warning: initialization from incompatible pointer type [enabled by default]

I'm trying to build a kernel module, but while compiling it in a make file I got some errors which I can't solve. This is the code for the module:

#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>

#include "sar_main.h"

#define PROCFS_NAME "sarlkm"

char procfs_buffer[PROCFS_MAX_SIZE];

static unsigned long procfs_buffer_size = 0;

struct proc_dir_entry *proc_file_entry;


int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data){
    int ret;

    printk(KERN_INFO "procfile_read (/proc/%s) called \n",  PROCFS_NAME);

    if (offset > 0){
        ret = 0;
    }
    else{
        copy_to_user(procfs_buffer, buffer, procfs_buffer_size);
        ret = procfs_buffer_size;
    }
    return ret;
}

int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data){

    procfs_buffer_size = count;
    if (procfs_buffer_size > PROCFS_MAX_SIZE){
        procfs_buffer_size = PROCFS_MAX_SIZE;
    }
    if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size)){
        return -EFAULT;
    }
    return procfs_buffer_size;
}

static const struct file_operations proc_file_ops = {
    .read = procfile_read,
    .write = procfile_write,
};


static int __init sar_init(void)
{
    proc_file_entry = proc_create(PROCFS_NAME, 0644, NULL, &proc_file_ops);

    if (proc_file_entry == NULL){
        remove_proc_entry(PROCFS_NAME, NULL);
        printk(KERN_ALERT "Error: Unable to create proc file");
        return -ENOMEM;
    }


    printk(KERN_INFO "proc/%s successfully created", PROCFS_NAME);
    return 0;
}

static void __exit sar_cleanup(void)
{
    remove_proc_entry(PROCFS_NAME, NULL);
    printk(KERN_INFO "proc/%s deleted", PROCFS_NAME);
}

module_init(sar_init);
module_exit(sar_cleanup);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

So I get the error while defining the struct proc_file_ops. I haven't been able to find a definition for the read and write functions of proc_dir_entry, but I have found some examples on the web that have used the exact same statements that I've used. Can anybody explain why I get this warning and what to do about it please?

Upvotes: 1

Views: 1673

Answers (1)

Sam Protsenko
Sam Protsenko

Reputation: 14743

Root cause

Probably examples you found are intended for some different kernel version (other than you use). Internal kernel API varies from version to version. See Documentation/stable_api_nonsense.txt for details. The general advice is to look into exactly your kernel sources for code examples. For example see how proc API implemented in kernel/time/timer_stats.c (in your kernel code, of course).

Why warnings

Your signatures of procfile_read() and procfile_write() functions must be the same as in struct file_operations:

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

But you have next signatures instead:

int procfile_read(char *buffer, char **buffer_location, off_t offset,
                  int buffer_length, int *eof, void *data)
int procfile_write(struct file *file, const char *buffer,
                   unsigned long count, void *data)

You probably need to double check the actual signatures in struct file_operations for your kernel version.

Example code insights

Also you may notice that .read callback need to be set like that (in new kernel versions):

.read = seq_read,

And actual reading should be done via .open callback:

.open = tstats_open,

In open function you need to call your actual show function, like this:

static int tstats_open(struct inode *inode, struct file *filp)
{
    return single_open(filp, tstats_show, NULL);
}

And show function should have signature like this:

static int tstats_show(struct seq_file *m, void *v)

For complete example see kernel/time/timer_stats.c in your kernel.

Upvotes: 3

Related Questions