lkml.org 
[lkml]   [2007]   [Oct]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] compat_ioctl: introduce generic_compat_ioctl helper
    Date
    Many drivers use only compatible ioctl numbers. In order to
    avoid having to write a special compat_ioctl handler for each
    of them or listing every ioctl number in fs/compat_ioctl.c,
    let's introduce a generic handler that simply calls the
    driver specific f_op->unlocked_ioctl() or f_op->ioctl() handler.

    Signed-off-by: Arnd Bergman <arnd@arndb.de>
    ---
    On Saturday 13 October 2007, Al Viro wrote:
    > Just how many instances of that sucker do we need? It's nothing but
    >
    > struct inode *inode = file->f_path.dentry->d_inode;
    > return file->f_op->ioctl(inode, file, cmd, compat_ptr(arg));

    Is this what you had in mind? I've been meaning to do something like
    it for some time, but had forgotten about it.

    I guess we can kill a significant amount of COMPATIBLE_IOCTL
    lines in fs/compat_ioctl.c with this.

    Index: linux-2.6/fs/compat_ioctl.c
    ===================================================================
    --- linux-2.6.orig/fs/compat_ioctl.c
    +++ linux-2.6/fs/compat_ioctl.c
    @@ -1877,6 +1877,30 @@ lp_timeout_trans(unsigned int fd, unsign
    return sys_ioctl(fd, cmd, (unsigned long)tn);
    }

    +/*
    + * Helper function for device drivers that only have COMPATIBLE_IOCTL
    + * numbers. This can be used as f_op->compat_ioctl without any #ifdef
    + * and will simply call the native ioctl handler with the argument
    + * pointer.
    + * Don't use for drivers that interpret arg as an unsigned long instead
    + * of a pointer.
    + */
    +long generic_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    +{
    + int ret = -ENOTTY;
    + arg = (unsigned long)compat_ptr(arg);
    +
    + if (file->f_op->unlocked_ioctl)
    + ret = file->f_op->unlocked_ioctl(file, cmd, arg);
    + else if (file->f_op->ioctl) {
    + lock_kernel();
    + ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
    + unlock_kernel();
    + }
    +
    + return ret;
    +}
    +EXPORT_SYMBOL_GPL(generic_compat_ioctl);

    typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
    unsigned long, struct file *);
    Index: linux-2.6/include/linux/fs.h
    ===================================================================
    --- linux-2.6.orig/include/linux/fs.h
    +++ linux-2.6/include/linux/fs.h
    @@ -1807,6 +1807,12 @@ extern void do_generic_mapping_read(stru
    extern int generic_segment_checks(const struct iovec *iov,
    unsigned long *nr_segs, size_t *count, int access_flags);

    +#ifdef CONFIG_COMPAT
    +extern long generic_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
    +#else
    +#define generic_compat_ioctl (long (*)(struct file *, unsigned int, unsigned long))NULL
    +#endif
    +
    /* fs/splice.c */
    extern ssize_t generic_file_splice_read(struct file *, loff_t *,
    struct pipe_inode_info *, size_t, unsigned int);
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2007-10-20 17:55    [W:0.047 / U:30.868 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site