static int flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) { struct attribute * attr = to_attr(dentry); struct kobject * kobj = to_kobj(dentry->d_parent); struct sysfs_ops * ops = buffer->ops; return ops->store(kobj,attr,buffer->page,count); }
static int flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) { struct bin_attribute *attr = to_bin_attr(dentry); struct kobject *kobj = to_kobj(dentry->d_parent); if (!attr->write) return -EIO; return attr->write(kobj, buffer, offset, count); }
static int fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) { struct bin_attribute * attr = to_bin_attr(dentry); struct kobject * kobj = to_kobj(dentry->d_parent); if (!attr->read) return -EIO; return attr->read(kobj, buffer, off, count); }
static int mmap(struct file *file, struct vm_area_struct *vma) { struct dentry *dentry = file->f_dentry; struct bin_attribute *attr = to_bin_attr(dentry); struct kobject *kobj = to_kobj(dentry->d_parent); if (!attr->mmap) return -EINVAL; return attr->mmap(kobj, attr, vma); }
static int release(struct inode * inode, struct file * file) { struct kobject * kobj = to_kobj(file->f_dentry->d_parent); struct bin_attribute * attr = to_bin_attr(file->f_dentry); u8 * buffer = file->private_data; if (kobj) kobject_put(kobj); module_put(attr->attr.owner); kfree(buffer); return 0; }
/* Sysfs attribute files are pollable. The idea is that you read * the content and then you use 'poll' or 'select' to wait for * the content to change. When the content changes (assuming the * manager for the kobject supports notification), poll will * return POLLERR|POLLPRI, and select will return the fd whether * it is waiting for read, write, or exceptions. * Once poll/select indicates that the value has changed, you * need to close and re-open the file, as simply seeking and reading * again will not get new data, or reset the state of 'poll'. * Reminder: this only works for attributes which actively support * it, and it is not possible to test an attribute from userspace * to see if it supports poll (Nether 'poll' or 'select' return * an appropriate error code). When in doubt, set a suitable timeout value. */ static unsigned int sysfs_poll(struct file *filp, poll_table *wait) { struct sysfs_buffer * buffer = filp->private_data; struct kobject * kobj = to_kobj(filp->f_dentry->d_parent); struct sysfs_dirent * sd = filp->f_dentry->d_fsdata; int res = 0; poll_wait(filp, &kobj->poll, wait); if (buffer->event != atomic_read(&sd->s_event)) { res = POLLERR|POLLPRI; buffer->needs_read_fill = 1; } return res; }
static int sysfs_release(struct inode * inode, struct file * filp) { struct kobject * kobj = to_kobj(filp->f_dentry->d_parent); struct attribute * attr = to_attr(filp->f_dentry); struct module * owner = attr->owner; struct sysfs_buffer * buffer = filp->private_data; if (kobj) kobject_put(kobj); /* After this point, attr should not be accessed. */ module_put(owner); if (buffer) { if (buffer->page) free_page((unsigned long)buffer->page); kfree(buffer); } return 0; }
/** * fill_read_buffer - allocate and fill buffer from object. * @dentry: dentry pointer. * @buffer: data buffer for file. * * Allocate @buffer->page, if it hasn't been already, then call the * kobject's show() method to fill the buffer with this attribute's * data. * This is called only once, on the file's first read. */ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) { struct attribute * attr = to_attr(dentry); struct kobject * kobj = to_kobj(dentry->d_parent); struct sysfs_ops * ops = buffer->ops; int ret = 0; ssize_t count; if (!buffer->page) buffer->page = (char *) get_zeroed_page(GFP_KERNEL); if (!buffer->page) return -ENOMEM; count = ops->show(kobj,attr,buffer->page); buffer->needs_read_fill = 0; BUG_ON(count > (ssize_t)PAGE_SIZE); if (count >= 0) buffer->count = count; else ret = count; return ret; }