static int configfs_release_bin_file(struct inode *inode, struct file *filp) { struct configfs_buffer *buffer = filp->private_data; struct dentry *dentry = filp->f_path.dentry; struct config_item *item = to_item(dentry->d_parent); struct configfs_item_operations *ops = buffer->ops; struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ssize_t len = 0; int ret; buffer->read_in_progress = 0; if (buffer->write_in_progress) { buffer->write_in_progress = 0; len = ops->write_bin_attribute(item, bin_attr, buffer->bin_buffer, buffer->bin_buffer_size); /* vfree on NULL is safe */ vfree(buffer->bin_buffer); buffer->bin_buffer = NULL; buffer->bin_buffer_size = 0; buffer->needs_read_fill = 1; } ret = do_release(inode, filp, to_item(filp->f_path.dentry->d_parent), to_attr(filp->f_path.dentry), CONFIGFS_ITEM_BIN_ATTR); if (len < 0) return len; return ret; }
static ssize_t configfs_read_bin_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct configfs_buffer *buffer = file->private_data; struct dentry *dentry = file->f_path.dentry; struct config_item *item = to_item(dentry->d_parent); struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ssize_t retval = 0; ssize_t len = min_t(size_t, count, PAGE_SIZE); mutex_lock(&buffer->mutex); /* we don't support switching read/write modes */ if (buffer->write_in_progress) { retval = -ETXTBSY; goto out; } buffer->read_in_progress = 1; if (buffer->needs_read_fill) { /* perform first read with buf == NULL to get extent */ len = bin_attr->read(item, NULL, 0); if (len <= 0) { retval = len; goto out; } /* do not exceed the maximum value */ if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) { retval = -EFBIG; goto out; } buffer->bin_buffer = vmalloc(len); if (buffer->bin_buffer == NULL) { retval = -ENOMEM; goto out; } buffer->bin_buffer_size = len; /* perform second read to fill buffer */ len = bin_attr->read(item, buffer->bin_buffer, len); if (len < 0) { retval = len; vfree(buffer->bin_buffer); buffer->bin_buffer_size = 0; buffer->bin_buffer = NULL; goto out; } buffer->needs_read_fill = 0; } retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer, buffer->bin_buffer_size); out: mutex_unlock(&buffer->mutex); return retval; }
static int flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count) { struct configfs_attribute * attr = to_attr(dentry); struct config_item * item = to_item(dentry->d_parent); return attr->store(item, buffer->page, count); }
static int flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count) { struct configfs_attribute * attr = to_attr(dentry); struct config_item * item = to_item(dentry->d_parent); struct configfs_item_operations * ops = buffer->ops; return ops->store_attribute(item,attr,buffer->page,count); }
static int configfs_release(struct inode * inode, struct file * filp) { struct config_item * item = to_item(filp->f_dentry->d_parent); struct configfs_attribute * attr = to_attr(filp->f_dentry); struct module * owner = attr->ca_owner; struct configfs_buffer * buffer = filp->private_data; if (item) config_item_put(item); /* 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 item. * @dentry: dentry pointer. * @buffer: data buffer for file. * * Allocate @buffer->page, if it hasn't been already, then call the * config_item'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 configfs_buffer * buffer) { struct configfs_attribute * attr = to_attr(dentry); struct config_item * item = to_item(dentry->d_parent); struct configfs_item_operations * 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_attribute(item,attr,buffer->page); buffer->needs_read_fill = 0; BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE); if (count >= 0) buffer->count = count; else ret = count; return ret; }
static int configfs_release_file(struct inode *inode, struct file *filp) { return do_release(inode, filp, to_item(filp->f_path.dentry->d_parent), to_attr(filp->f_path.dentry), CONFIGFS_ITEM_ATTR); }