Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754898AbbGCKvt (ORCPT ); Fri, 3 Jul 2015 06:51:49 -0400 Received: from mailout1.w1.samsung.com ([210.118.77.11]:62411 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755040AbbGCKug (ORCPT ); Fri, 3 Jul 2015 06:50:36 -0400 X-AuditID: cbfec7f4-f79c56d0000012ee-50-559668e9cb11 From: Marcin Niesluchowski To: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org Cc: Jonathan Corbet , Greg Kroah-Hartman , Petr Mladek , Tejun Heo , Kay Sievers , Andrew Morton , Joe Perches , Karol Lewandowski , Bartlomiej Zolnierkiewicz , Marcin Niesluchowski Subject: [RFC 7/8] kmsg: add ioctl for adding and deleting kmsg* devices Date: Fri, 03 Jul 2015 12:49:54 +0200 Message-id: <1435920595-30879-8-git-send-email-m.niesluchow@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1435920595-30879-1-git-send-email-m.niesluchow@samsung.com> References: <1435920595-30879-1-git-send-email-m.niesluchow@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrGLMWRmVeSWpSXmKPExsVy+t/xK7ovM6aFGnz/q2MxZ/0aNouNM9az Wjw50M5o0bx4PZvF7PuPWSwaP81ltri16jm7xebvHWwWC9uWsFhc3jWHzeLQ2R8sFgv/b2ay +LX8KKMDr8emVZ1sHidm/Gbx2D93DbvH4r7JrB5fVl1j9ujbsorR48yCI+wenzfJeXxc7xnA GcVlk5Kak1mWWqRvl8CV8XxSH0vBW/OK3tPdzA2MS3S7GDk5JARMJM6+aWCDsMUkLtxbD2Rz cQgJLGWUuPOpgxHCaWaSmLj1IztIFZuAqUTbsj1gtohAhMTCi00sIEXMAtOYJc4272UGSQgL eEh0tGxnBLFZBFQl/h66CbaCFyi+404/C8Q6OYmTxyazgticAp4Sn/qWgfUKAdVsODafaQIj 7wJGhlWMoqmlyQXFSem5hnrFibnFpXnpesn5uZsYIaH7ZQfj4mNWhxgFOBiVeHgvnJ4aKsSa WFZcmXuIUYKDWUmE93nwtFAh3pTEyqrUovz4otKc1OJDjNIcLErivHN3vQ8REkhPLEnNTk0t SC2CyTJxcEo1MEadZDCQ1zqjYiY4n8lHX+uU/M6Jryau7mtM/J1h8vDV4/odxz1ivqWlpCUk Sl2XLHc8Z5n7u2LNPp4f038vE94SkvXJrPbRr7bLGXPrxJaI7zunPrnkVE6CrCNXzK+3LU2r O6fZ/3dhXp3yc9+m3FTvohKmuFU/r07ZHbk5PXLRjv3RuX2PHyqxFGckGmoxFxUnAgCZlNua WQIAAA== Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7137 Lines: 262 There is no possibility to add/delete kmsg* buffers from userspace. Adds following ioctl for main kmsg device adding and deleting additional kmsg devices: * KMSG_CMD_BUFFER_ADD * KMSG_CMD_BUFFER_DEL Signed-off-by: Marcin Niesluchowski --- Documentation/ioctl/ioctl-number.txt | 1 + drivers/char/mem.c | 134 +++++++++++++++++++++++++++++++++-- include/uapi/linux/Kbuild | 1 + include/uapi/linux/kmsg_ioctl.h | 30 ++++++++ 4 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 include/uapi/linux/kmsg_ioctl.h diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 611c522..26c0e53 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -312,6 +312,7 @@ Code Seq#(hex) Include File Comments 0xB1 00-1F PPPoX 0xB3 00 linux/mmc/ioctl.h +0xBB 00-02 uapi/linux/kmsg_ioctl.h 0xC0 00-0F linux/usb/iowarrior.h 0xCA 00-0F uapi/misc/cxl.h 0xCB 00-1F CBM serial IEC bus in development: diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 8d5ba0d..2893d8e 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -34,8 +34,14 @@ # include #endif +#ifdef CONFIG_PRINTK +#include +#endif + #define DEVPORT_MINOR 4 +static struct class *mem_class; + static inline unsigned long size_inside_page(unsigned long start, unsigned long size) { @@ -715,6 +721,113 @@ static int open_port(struct inode *inode, struct file *filp) return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } +#ifdef CONFIG_PRINTK +#define KMSG_MINOR 11 + +#define MAX_MINOR_LEN 20 + +static int kmsg_open_ext(struct inode *inode, struct file *file) +{ + return kmsg_fops.open(inode, file); +} + +static ssize_t kmsg_write_iter_ext(struct kiocb *iocb, struct iov_iter *from) +{ + return kmsg_fops.write_iter(iocb, from); +} + +static ssize_t kmsg_read_ext(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + return kmsg_fops.read(file, buf, count, ppos); +} + +static loff_t kmsg_llseek_ext(struct file *file, loff_t offset, int whence) +{ + return kmsg_fops.llseek(file, offset, whence); +} + +static unsigned int kmsg_poll_ext(struct file *file, + struct poll_table_struct *wait) +{ + return kmsg_fops.poll(file, wait); +} + +static long kmsg_ioctl_buffers(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + size_t size; + umode_t mode; + char name[4 + MAX_MINOR_LEN + 1]; + struct device *dev; + int minor; + + if (iminor(file->f_inode) != KMSG_MINOR) + return -ENOTTY; + + switch (cmd) { + case KMSG_CMD_BUFFER_ADD: + if (copy_from_user(&size, argp, sizeof(size))) + return -EFAULT; + argp += sizeof(size); + if (copy_from_user(&mode, argp, sizeof(mode))) + return -EFAULT; + argp += sizeof(mode); + minor = kmsg_sys_buffer_add(size, mode); + if (minor < 0) + return minor; + sprintf(name, "kmsg%d", minor); + dev = device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor), + NULL, name); + if (IS_ERR(dev)) { + kmsg_sys_buffer_del(minor); + return PTR_ERR(dev); + } + if (copy_to_user(argp, &minor, sizeof(minor))) { + device_destroy(mem_class, MKDEV(MEM_MAJOR, minor)); + kmsg_sys_buffer_del(minor); + return -EFAULT; + } + return 0; + case KMSG_CMD_BUFFER_DEL: + if (copy_from_user(&minor, argp, sizeof(minor))) + return -EFAULT; + if (minor <= KMSG_MINOR) + return -EINVAL; + device_destroy(mem_class, MKDEV(MEM_MAJOR, minor)); + kmsg_sys_buffer_del(minor); + return 0; + } + return -ENOTTY; +} + +static long kmsg_unlocked_ioctl_ext(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long ret = kmsg_ioctl_buffers(file, cmd, arg); + + if (ret == -ENOTTY) + return kmsg_fops.unlocked_ioctl(file, cmd, arg); + return ret; +} + +static long kmsg_compat_ioctl_ext(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long ret = kmsg_ioctl_buffers(file, cmd, arg); + + if (ret == -ENOTTY) + return kmsg_fops.compat_ioctl(file, cmd, arg); + return ret; +} + +static int kmsg_release_ext(struct inode *inode, struct file *file) +{ + return kmsg_fops.release(inode, file); +} +#endif + #define zero_lseek null_lseek #define full_lseek null_lseek #define write_zero write_null @@ -779,6 +892,19 @@ static const struct file_operations full_fops = { .write = write_full, }; +#ifdef CONFIG_PRINTK +static const struct file_operations kmsg_fops_ext = { + .open = kmsg_open_ext, + .read = kmsg_read_ext, + .write_iter = kmsg_write_iter_ext, + .llseek = kmsg_llseek_ext, + .poll = kmsg_poll_ext, + .unlocked_ioctl = kmsg_unlocked_ioctl_ext, + .compat_ioctl = kmsg_compat_ioctl_ext, + .release = kmsg_release_ext, +}; +#endif + static const struct memdev { const char *name; umode_t mode; @@ -800,14 +926,10 @@ static const struct memdev { [8] = { "random", 0666, &random_fops, 0 }, [9] = { "urandom", 0666, &urandom_fops, 0 }, #ifdef CONFIG_PRINTK - [11] = { "kmsg", 0644, &kmsg_fops, 0 }, + [11] = { "kmsg", 0644, &kmsg_fops_ext, 0 }, #endif }; -#ifdef CONFIG_PRINTK -#define KMSG_MINOR 11 -#endif - static int memory_open(struct inode *inode, struct file *filp) { int minor; @@ -858,8 +980,6 @@ static char *mem_devnode(struct device *dev, umode_t *mode) return NULL; } -static struct class *mem_class; - static int __init chr_dev_init(void) { int minor; diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 1ff9942..faf13a8 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -224,6 +224,7 @@ header-y += kernel-page-flags.h header-y += kexec.h header-y += keyboard.h header-y += keyctl.h +header-y += kmsg_ioctl.h ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h \ $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h),) diff --git a/include/uapi/linux/kmsg_ioctl.h b/include/uapi/linux/kmsg_ioctl.h new file mode 100644 index 0000000..89c0c61 --- /dev/null +++ b/include/uapi/linux/kmsg_ioctl.h @@ -0,0 +1,30 @@ +/* + * This is ioctl include for kmsg* devices + */ + +#ifndef _KMSG_IOCTL_H_ +#define _KMSG_IOCTL_H_ + +#include +#include + +struct kmsg_cmd_buffer_add { + size_t size; + unsigned short mode; + int minor; +} __attribute__((packed)); + +#define KMSG_IOCTL_MAGIC 0xBB + +/* + * A ioctl interface for kmsg device. + * + * KMSG_CMD_BUFFER_ADD: Creates additional kmsg device based on its size + * and mode. Minor of created device is put. + * KMSG_CMD_BUFFER_DEL: Removes additional kmsg device based on its minor + */ +#define KMSG_CMD_BUFFER_ADD _IOWR(KMSG_IOCTL_MAGIC, 0x00, \ + struct kmsg_cmd_buffer_add) +#define KMSG_CMD_BUFFER_DEL _IOW(KMSG_IOCTL_MAGIC, 0x01, int) + +#endif -- 1.9.1 -- 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/