📄 debugfs_compat.c
字号:
#include <linux/module.h>#include <linux/pagemap.h>#include <linux/mount.h>#include <linux/vfs.h>#include <asm/uaccess.h>#include "debugfs_compat.h"/* * "nonseekable_open is so trivial, it's not worth putting in the kapi * compat stuff just for the one use in this file. * This code ripped from fs/open.c in the 2.6.14 kernel *//* And of course, these FMODE_* may not be defined in older * kernels. */#ifndef FMODE_LSEEK#define FMODE_LSEEK 4#endif#ifndef FMODE_PREAD#define FMODE_PREAD 8#endif#ifndef FMODE_PWRITE#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */#endif/* * This is used by subsystems that don't want seekable * file descriptors */static int compat_nonseekable_open(struct inode *inode, struct file *filp){ filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); return 0;}/* * Ripped from fs/libfs.c in the 2.6.14 kernel. */ssize_t compat_simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos, const void *from, size_t available){ loff_t pos = *ppos; if (pos < 0) return -EINVAL; if (pos >= available) return 0; if (count > available - pos) count = available - pos; if (copy_to_user(to, from + pos, count)) return -EFAULT; *ppos = pos + count; return count;}/* Simple attribute files */struct simple_attr { u64 (*get)(void *); void (*set)(void *, u64); char get_buf[24]; /* enough to store a u64 and "\n\0" */ char set_buf[24]; void *data; const char *fmt; /* format for read operation */ struct semaphore sem; /* protects access to these buffers */};/* simple_attr_open is called by an actual attribute open file operation * to set the attribute specific access operations. */int simple_attr_open(struct inode *inode, struct file *file, u64 (*get)(void *), void (*set)(void *, u64), const char *fmt){ struct simple_attr *attr; attr = kmalloc(sizeof(*attr), GFP_KERNEL); if (!attr) return -ENOMEM; attr->get = get; attr->set = set; attr->data = inode->u.generic_ip; attr->fmt = fmt; init_MUTEX(&attr->sem); file->private_data = attr; return compat_nonseekable_open(inode, file);}int simple_attr_close(struct inode *inode, struct file *file){ kfree(file->private_data); return 0;}/* read from the buffer that is filled with the get function */ssize_t simple_attr_read(struct file *file, char __user *buf, size_t len, loff_t *ppos){ struct simple_attr *attr; size_t size; ssize_t ret; attr = file->private_data; if (!attr->get) return -EACCES; down(&attr->sem); if (*ppos) /* continued read */ size = strlen(attr->get_buf); else /* first read */ size = scnprintf(attr->get_buf, sizeof(attr->get_buf), attr->fmt, (unsigned long long)attr->get(attr->data)); ret = compat_simple_read_from_buffer(buf, len, ppos, attr->get_buf, size); up(&attr->sem); return ret;}/* interpret the buffer as a number to call the set function with */ssize_t simple_attr_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos){ struct simple_attr *attr; u64 val; size_t size; ssize_t ret; attr = file->private_data; if (!attr->set) return -EACCES; down(&attr->sem); ret = -EFAULT; size = min(sizeof(attr->set_buf) - 1, len); if (copy_from_user(attr->set_buf, buf, size)) goto out; ret = len; /* claim we got the whole input */ attr->set_buf[size] = '\0'; val = simple_strtol(attr->set_buf, NULL, 0); attr->set(attr->data, val);out: up(&attr->sem); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -