0

A few years ago, Linux 3.8 was ported to the TI-nSpire graphing calculator (https://github.com/tangrs/linux). While some of the changes were upstreamed, most of them were not. I've been rewriting the patches for the latest kernel sources, but I'm stuck on a deprecated function:

create_proc_entry()

I got two GCC error messages relating to this. The first one I fixed by changing create_proc_entry(BOOT1_PROCFS_NAME, 0644, NULL); to proc_create_data(BOOT1_PROCFS_NAME, 0644, NULL, NULL, NULL); (If there is something better, please let me know.)

The second error,

arch/arm/mach-nspire/boot1.c:37:18: error: dereferencing pointer to incomplete type ‘struct proc_dir_entry’
boot1_proc_entry->read_proc = boot1_read;

I have been unable to fix. I looked at the git history where read_proc_t *read_proc; (part of struct proc_dir_entry; then located in include/linux/proc_fs.h, now located in fs/proc/internal.h) was removed (https://github.com/torvalds/linux/commit/3cb5bf1bf947d325fcf6e9458952b51cfd7e6677#diff-a2f17c99c50d86d5160c8f7f0261fbbd), expecting to see something else put in it's place, but that is not the case. Instead, it was deprecated along with create_proc_entry().

So how should I rewrite the line boot1_proc_entry->read_proc = boot1_read; (full file here: https://github.com/tangrs/linux/blob/nspire/arch/arm/mach-nspire/boot1.c) so that it will compile with current kernel sources?

Billy
  • 1,177
  • 2
  • 15
  • 35

1 Answers1

2

Function proc_create_data has prototype

struct proc_dir_entry *proc_create_data(const char *, umode_t,
                       struct proc_dir_entry *,
                       const struct file_operations *,
                       void *);

and its 4th parameter is a structure of file operations.

For specify, how data should be read from the file, you need to setup .read field of that structure: this is a replacement for (old) assigning read_proc field in the proc_dir_entry object.

While signature for .read function (callback) is very generic:

ssize_t (*read) (struct file * file, char __user * buf, size_t size, loff_t * ppos);

Linux kernel has several helpers for implement this function for simple cases.

E.g., if you want to "map" some buffer as file's content, you may use simple_read_from_buffer helper:

ssize_t my_read (struct file * file, char __user * buf, size_t size, loff_t * ppos)
{
    return simple_read_from_buffer(
        buf, size, ppos, // first 3 arguments are just ones for .read function
        NSPIRE_BOOT1_VIRT_BASE, // address of the buffer's start
        NSPIRE_BOOT1_SIZE // size of the buffer
    )
}

The rest of code:

// Define file operations for given file.
static const struct file_operations my_fops = {
    .owner = THIS_MODULE, // This is useful almost in any case
    .read = my_read, // Setup .read function
};

// And create the file itself
entry = proc_create_data(BOOT1_PROCFS_NAME, 0644, NULL, &my_fops, NULL);
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153