^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* -*- mode: c; c-basic-offset: 8; -*-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * vim: noexpandtab sw=8 ts=8 sts=0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * file.c - operations for regular (text) files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on sysfs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * configfs Copyright (C) 2005 Oracle. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/configfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "configfs_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * A simple attribute can only be 4096 characters. Why 4k? Because the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * original code limited it to PAGE_SIZE. That's a bad idea, though,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * because an attribute of 16k on ia64 won't work on x86. So we limit to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 4k, our minimum common page size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SIMPLE_ATTR_SIZE 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct configfs_buffer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) size_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) loff_t pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) char * page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct configfs_item_operations * ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int needs_read_fill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) bool read_in_progress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) bool write_in_progress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) char *bin_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int bin_buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int cb_max_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct config_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct module *owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct configfs_attribute *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct configfs_bin_attribute *bin_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static inline struct configfs_fragment *to_frag(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct configfs_dirent *sd = file->f_path.dentry->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return sd->s_frag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int fill_read_buffer(struct file *file, struct configfs_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct configfs_fragment *frag = to_frag(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ssize_t count = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (!buffer->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!buffer->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) down_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!frag->frag_dead)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) count = buffer->attr->show(buffer->item, buffer->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) up_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (count < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (WARN_ON_ONCE(count > (ssize_t)SIMPLE_ATTR_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) buffer->needs_read_fill = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) buffer->count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * configfs_read_file - read an attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @file: file pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @buf: buffer to fill.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @count: number of bytes to read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @ppos: starting offset in file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Userspace wants to read an attribute file. The attribute descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * is in the file's ->d_fsdata. The target item is in the directory's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * ->d_fsdata.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * We call fill_read_buffer() to allocate and fill the buffer from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * item's show() method exactly once (if the read is happening from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * the beginning of the file). That should fill the entire buffer with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * all the data the item has to offer for that attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * We then call flush_read_buffer() to copy the buffer to userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * in the increments specified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct configfs_buffer *buffer = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ssize_t retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) mutex_lock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (buffer->needs_read_fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) retval = fill_read_buffer(file, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) __func__, count, *ppos, buffer->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) buffer->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) mutex_unlock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * configfs_read_bin_file - read a binary attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @file: file pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @buf: buffer to fill.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @count: number of bytes to read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @ppos: starting offset in file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Userspace wants to read a binary attribute file. The attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * descriptor is in the file's ->d_fsdata. The target item is in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * directory's ->d_fsdata.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * We check whether we need to refill the buffer. If so we will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * call the attributes' attr->read() twice. The first time we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * will pass a NULL as a buffer pointer, which the attributes' method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * will use to return the size of the buffer required. If no error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * occurs we will allocate the buffer using vmalloc and call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * attr->read() again passing that buffer as an argument.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Then we just copy to user-space using simple_read_from_buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) configfs_read_bin_file(struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct configfs_fragment *frag = to_frag(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct configfs_buffer *buffer = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ssize_t retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ssize_t len = min_t(size_t, count, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) mutex_lock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* we don't support switching read/write modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (buffer->write_in_progress) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) retval = -ETXTBSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) buffer->read_in_progress = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (buffer->needs_read_fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* perform first read with buf == NULL to get extent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) down_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (!frag->frag_dead)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) len = buffer->bin_attr->read(buffer->item, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) len = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) up_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (len <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) retval = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* do not exceed the maximum value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (buffer->cb_max_size && len > buffer->cb_max_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) retval = -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) buffer->bin_buffer = vmalloc(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (buffer->bin_buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) buffer->bin_buffer_size = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* perform second read to fill buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) down_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (!frag->frag_dead)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) len = buffer->bin_attr->read(buffer->item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) buffer->bin_buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) len = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) up_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) retval = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) vfree(buffer->bin_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) buffer->bin_buffer_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) buffer->bin_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) buffer->needs_read_fill = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) buffer->bin_buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) mutex_unlock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * fill_write_buffer - copy buffer from userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * @buffer: data buffer for file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * @buf: data from user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * @count: number of bytes in @userbuf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * Allocate @buffer->page if it hasn't been already, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * copy the user-supplied buffer into it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!buffer->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!buffer->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (count >= SIMPLE_ATTR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) count = SIMPLE_ATTR_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) error = copy_from_user(buffer->page,buf,count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) buffer->needs_read_fill = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* if buf is assumed to contain a string, terminate it by \0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * so e.g. sscanf() can scan the string easily */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) buffer->page[count] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return error ? -EFAULT : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) flush_write_buffer(struct file *file, struct configfs_buffer *buffer, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct configfs_fragment *frag = to_frag(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) int res = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) down_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (!frag->frag_dead)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) res = buffer->attr->store(buffer->item, buffer->page, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) up_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * configfs_write_file - write an attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * @file: file pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * @buf: data to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * @count: number of bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * @ppos: starting offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * Similar to configfs_read_file(), though working in the opposite direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * We allocate and fill the data from the user in fill_write_buffer(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * then push it to the config_item in flush_write_buffer().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * There is no easy way for us to know if userspace is only doing a partial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * write, so we don't support them. We expect the entire buffer to come
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * on the first write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * Hint: if you're writing a value, first read the file, modify only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * the value you're changing, then write entire buffer back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct configfs_buffer *buffer = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mutex_lock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) len = fill_write_buffer(buffer, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) len = flush_write_buffer(file, buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) *ppos += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) mutex_unlock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * configfs_write_bin_file - write a binary attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @file: file pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @buf: data to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * @count: number of bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * @ppos: starting offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * Writing to a binary attribute file is similar to a normal read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * We buffer the consecutive writes (binary attribute files do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * support lseek) in a continuously growing buffer, but we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * commit until the close of the file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) configfs_write_bin_file(struct file *file, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct configfs_buffer *buffer = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) void *tbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) mutex_lock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* we don't support switching read/write modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (buffer->read_in_progress) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) len = -ETXTBSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) buffer->write_in_progress = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* buffer grows? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (*ppos + count > buffer->bin_buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (buffer->cb_max_size &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *ppos + count > buffer->cb_max_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) len = -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) tbuf = vmalloc(*ppos + count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (tbuf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) len = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* copy old contents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (buffer->bin_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) memcpy(tbuf, buffer->bin_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) buffer->bin_buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) vfree(buffer->bin_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* clear the new area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) memset(tbuf + buffer->bin_buffer_size, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) *ppos + count - buffer->bin_buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) buffer->bin_buffer = tbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) buffer->bin_buffer_size = *ppos + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) len = simple_write_to_buffer(buffer->bin_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) buffer->bin_buffer_size, ppos, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) mutex_unlock(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int __configfs_open_file(struct inode *inode, struct file *file, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct dentry *dentry = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct configfs_fragment *frag = to_frag(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct configfs_attribute *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct configfs_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) buffer = kzalloc(sizeof(struct configfs_buffer), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) down_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (unlikely(frag->frag_dead))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto out_free_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) buffer->item = to_item(dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!buffer->item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) goto out_free_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) attr = to_attr(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) goto out_free_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (type & CONFIGFS_ITEM_BIN_ATTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) buffer->bin_attr = to_bin_attr(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) buffer->cb_max_size = buffer->bin_attr->cb_max_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) buffer->attr = attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) buffer->owner = attr->ca_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* Grab the module reference for this attribute if we have one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!try_module_get(buffer->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) goto out_free_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (!buffer->item->ci_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) goto out_put_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) buffer->ops = buffer->item->ci_type->ct_item_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* File needs write support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * The inode's perms must say it's ok,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * and we must have a store method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (file->f_mode & FMODE_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (!(inode->i_mode & S_IWUGO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) goto out_put_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) goto out_put_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) goto out_put_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* File needs read support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * The inode's perms must say it's ok, and we there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * must be a show method for it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (file->f_mode & FMODE_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!(inode->i_mode & S_IRUGO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto out_put_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) goto out_put_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) goto out_put_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) mutex_init(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) buffer->needs_read_fill = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) buffer->read_in_progress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) buffer->write_in_progress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) file->private_data = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) up_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) out_put_module:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) module_put(buffer->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) out_free_buffer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) up_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static int configfs_release(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct configfs_buffer *buffer = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) module_put(buffer->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (buffer->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) free_page((unsigned long)buffer->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) mutex_destroy(&buffer->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static int configfs_open_file(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return __configfs_open_file(inode, filp, CONFIGFS_ITEM_ATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static int configfs_open_bin_file(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return __configfs_open_file(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static int configfs_release_bin_file(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct configfs_buffer *buffer = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) buffer->read_in_progress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (buffer->write_in_progress) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct configfs_fragment *frag = to_frag(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) buffer->write_in_progress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) down_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!frag->frag_dead) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* result of ->release() is ignored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) buffer->bin_attr->write(buffer->item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) buffer->bin_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) buffer->bin_buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) up_read(&frag->frag_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) vfree(buffer->bin_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) buffer->bin_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) buffer->bin_buffer_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) buffer->needs_read_fill = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) configfs_release(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) const struct file_operations configfs_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) .read = configfs_read_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) .write = configfs_write_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .open = configfs_open_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .release = configfs_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) const struct file_operations configfs_bin_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .read = configfs_read_bin_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .write = configfs_write_bin_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .llseek = NULL, /* bin file is not seekable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .open = configfs_open_bin_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .release = configfs_release_bin_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * configfs_create_file - create an attribute file for an item.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * @item: item we're creating for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * @attr: atrribute descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct dentry *dir = item->ci_dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct configfs_dirent *parent_sd = dir->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) CONFIGFS_ITEM_ATTR, parent_sd->s_frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) inode_unlock(d_inode(dir));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * configfs_create_bin_file - create a binary attribute file for an item.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * @item: item we're creating for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * @attr: atrribute descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int configfs_create_bin_file(struct config_item *item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) const struct configfs_bin_attribute *bin_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct dentry *dir = item->ci_dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct configfs_dirent *parent_sd = dir->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) inode_unlock(dir->d_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }