From: Joel Becker <jlbec@evilplan.org>
To: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Cc: Grant Likely <grant.likely@secretlab.ca>,
Rob Herring <robherring2@gmail.com>,
Stephen Warren <swarren@wwwdotorg.org>,
Matt Porter <matt.porter@linaro.org>,
Koen Kooi <koen@dominion.thruhere.net>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Alison Chaiken <Alison_Chaiken@mentor.com>,
Dinh Nguyen <dinh.linux@gmail.com>, Jan Lubbe <jluebbe@lasnet.de>,
Alexander Sverdlin <alexander.sverdlin@nsn.com>,
Michael Stickel <ms@mycable.de>,
Guenter Roeck <linux@roeck-us.net>,
Dirk Behme <dirk.behme@gmail.com>,
Alan Tull <delicious.quinoa@gmail.com>,
Sascha Hauer <s.hauer@pengutronix.de>,
Michael Bohan <mbohan@codeaurora.org>,
Ionut Nicu <ioan.nicu.ext@nsn.com>,
Michal Simek <monstr@monstr.eu>,
Matt Ranostay <mranostay@gmail.com>,
devicetree@vger.kernel.org, Wolfram Sang <wsa@the-dreams.de>,
linux-i2c@vger.kernel.org, Mark Brown <broonie@kernel.org>,
linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org,
Pete Popov <pete.popov@konsulko.com>,
Dan Malek <dan.malek@konsulko.com>,
Georgi Vlaev <georgi.vlaev@konsulko.com>,
Pantelis Antoniou <panto@antoniou-consulting.com>
Subject: Re: [PATCH] configfs: Implement binary attributes
Date: Wed, 25 Jun 2014 13:52:52 +0100 [thread overview]
Message-ID: <20140625125252.GU30852@ZenIV.linux.org.uk> (raw)
In-Reply-To: <1403429862-15022-1-git-send-email-pantelis.antoniou@konsulko.com>
On Sun, Jun 22, 2014 at 12:37:42PM +0300, Pantelis Antoniou wrote:
> ConfigFS lacked binary attributes up until now. This patch
> introduces support for binary attributes in a somewhat similar
> manner of sysfs binary attributes albeit with changes that
> fit the configfs usage model.
>
> Problems that configfs binary attributes fix are everything that
> requires a binary blob as part of the configuration of a resource,
> such as bitstream loading for FPGAs, DTBs for dynamically created
> devices etc.
I wanted to object on principle, but I actually think I like the way you
did this. More comments inline.
>
> Look at Documentation/filesystems/configfs/configfs.txt for internals
> and howto use them.
>
> This patch generates a bunch of checkpatch warnings, but this stems from
> following the formatting of the configfs code, so please ignore.
I thought someone had looked into cleaning up that cut-n-paste legacy.
I'm fine with new code following sanity..
> @@ -431,7 +438,9 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
> spin_unlock(&configfs_dirent_lock);
>
> error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
> - configfs_init_file);
> + (sd->s_type & CONFIGFS_ITEM_ATTR) ?
> + configfs_init_file :
> + configfs_init_bin_file);
> if (error) {
> configfs_put(sd);
> return error;
> @@ -591,6 +600,7 @@ static int populate_attrs(struct config_item *item)
> {
> struct config_item_type *t = item->ci_type;
> struct configfs_attribute *attr;
> + struct configfs_bin_attribute *bin_attr;
> int error = 0;
> int i;
>
> @@ -603,6 +613,13 @@ static int populate_attrs(struct config_item *item)
> }
> }
>
No need for this blank line.
> + if (t->ct_bin_attrs) {
> + for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) {
> + if ((error = configfs_create_bin_file(item, bin_attr)))
> + break;
> + }
> + }
> +
> if (error)
> detach_attrs(item);
>
> diff --git a/fs/configfs/file.c b/fs/configfs/file.c
> index 1d1c41f..aec051b 100644
> --- a/fs/configfs/file.c
> +++ b/fs/configfs/file.c
> @@ -48,6 +48,10 @@ struct configfs_buffer {
> struct configfs_item_operations * ops;
> struct mutex mutex;
> int needs_read_fill;
> + int read_in_progress;
> + int write_in_progress;
> + char *bin_buffer;
> + int bin_buffer_size;
> };
>
>
> @@ -107,8 +111,15 @@ static ssize_t
> configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
> {
> struct configfs_buffer * buffer = file->private_data;
> + struct configfs_dirent * sd = file->f_path.dentry->d_fsdata;
> ssize_t retval = 0;
>
> + if (WARN_ON(sd == NULL))
> + return -EINVAL;
> +
> + if (WARN_ON(!(sd->s_type & CONFIGFS_ITEM_ATTR)))
> + return -EINVAL;
> +
> mutex_lock(&buffer->mutex);
> if (buffer->needs_read_fill) {
> if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
> @@ -123,6 +134,93 @@ out:
> return retval;
> }
>
> +/**
> + * configfs_read_bin_file - read a binary attribute.
> + * @file: file pointer.
> + * @buf: buffer to fill.
> + * @count: number of bytes to read.
> + * @ppos: starting offset in file.
> + *
> + * Userspace wants to read a binary attribute file. The attribute descriptor
> + * is in the file's ->d_fsdata. The target item is in the directory's
> + * ->d_fsdata.
> + *
> + * We check whether we need to refill the buffer. If so we will
> + * call the attributes' ops->read_bin_attribute() twice. The first time we
> + * will pass a NULL as a buffer pointer, which the attributes' method
> + * will use to return the size of the buffer required. If no error
> + * occurs we will allocate the buffer using kmalloc and call
> + * ops->read_bin_atribute() again passing that buffer as an argument.
> + * Then we just copy to user-space using simple_read_from_buffer.
> + */
> +
> +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 configfs_dirent * sd = dentry->d_fsdata;
> + struct config_item * item = to_item(dentry->d_parent);
> + struct configfs_item_operations * ops = buffer->ops;
> + struct configfs_attribute * attr = to_attr(dentry);
> + struct configfs_bin_attribute *bin_attr =
> + container_of(attr, struct configfs_bin_attribute, attr);
You defined to_bin_attr(). Use it here and in write_bin_file() rather
than open-coding the container_of() calls.
> + ssize_t retval = 0;
> + ssize_t len = min_t(size_t, count, PAGE_SIZE);
> +
> + if (WARN_ON(sd == NULL))
> + return -EINVAL;
> +
> + if (WARN_ON(!(sd->s_type & CONFIGFS_ITEM_BIN_ATTR)))
> + return -EINVAL;
> +
> + mutex_lock(&buffer->mutex);
> +
> + /* we don't support switching read/write modes */
> + if (buffer->write_in_progress) {
> + retval = -EINVAL;
> + goto out;
> + }
> + if (!buffer->read_in_progress)
> + buffer->read_in_progress = 1;
You can always set read_in_progress, even if the read has already
started.
> +
> + if (buffer->needs_read_fill) {
> +
> + /* perform first read with buf == NULL to get extent */
> + len = ops->read_bin_attribute(item, bin_attr, NULL, 0);
> + if (len < 0) {
> + retval = len;
> + goto out;
> + }
> +
> + buffer->bin_buffer = kmalloc(len, GFP_KERNEL);
> + if (buffer->bin_buffer == NULL) {
> + retval = -ENOMEM;
> + goto out;
> + }
> + buffer->bin_buffer_size = len;
> +
> + /* perform second read to fill buffer */
> + len = ops->read_bin_attribute(item, bin_attr,
> + buffer->bin_buffer, len);
> + if (len < 0) {
> + retval = len;
> + kfree(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;
> +}
> +
>
> /**
> * fill_write_buffer - copy buffer from userspace.
> @@ -198,8 +296,15 @@ static ssize_t
> configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
> {
> struct configfs_buffer * buffer = file->private_data;
> + struct configfs_dirent * sd = file->f_path.dentry->d_fsdata;
> ssize_t len;
>
> + if (WARN_ON(sd == NULL))
> + return -EINVAL;
> +
> + if (WARN_ON(!(sd->s_type & CONFIGFS_ITEM_ATTR)))
> + return -EINVAL;
> +
> mutex_lock(&buffer->mutex);
> len = fill_write_buffer(buffer, buf, count);
> if (len > 0)
> @@ -210,10 +315,80 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
> return len;
> }
>
> -static int check_perm(struct inode * inode, struct file * file)
> +/**
> + * configfs_write_bin_file - write a binary attribute.
> + * @file: file pointer
> + * @buf: data to write
> + * @count: number of bytes
> + * @ppos: starting offset
> + *
> + * Writting to a binary attribute file is similar to a normal read.
> + * We buffer the consecutive writes (binary attribute files do not
> + * support lseek) in a continuously growing buffer, but we don't
> + * commit until the close of the file.
> + */
> +
> +static ssize_t
> +configfs_write_bin_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
> +{
> + struct configfs_buffer * buffer = file->private_data;
> + struct dentry *dentry = file->f_path.dentry;
> + struct configfs_dirent * sd = dentry->d_fsdata;
> + void *tbuf = NULL;
> + ssize_t len;
> +
> + if (WARN_ON(sd == NULL))
> + return -EINVAL;
> +
> + if (WARN_ON(!(sd->s_type & CONFIGFS_ITEM_BIN_ATTR)))
> + return -EINVAL;
> +
> + mutex_lock(&buffer->mutex);
> +
> + /* we don't support switching read/write modes */
> + if (buffer->read_in_progress) {
> + len = -EINVAL;
> + goto out;
> + }
> + if (!buffer->write_in_progress)
> + buffer->write_in_progress = 1;
> +
> + /* buffer grows? */
> + if (*ppos + count > buffer->bin_buffer_size) {
> +
> + tbuf = kmalloc(*ppos + count, GFP_KERNEL);
> + if (tbuf == NULL) {
> + len = -ENOMEM;
> + goto out;
> + }
> +
> + /* copy old contents */
> + if (buffer->bin_buffer) {
> + memcpy(tbuf, buffer->bin_buffer,
> + buffer->bin_buffer_size);
Fix the argument alignment. Do this elsewhere in your patch, too.
> + kfree(buffer->bin_buffer);
> + }
> +
> + /* clear the new area */
> + memset(tbuf + buffer->bin_buffer_size, 0,
> + *ppos + count - buffer->bin_buffer_size);
> + buffer->bin_buffer = tbuf;
> + buffer->bin_buffer_size = *ppos + count;
> + }
> +
> + len = simple_write_to_buffer(buffer->bin_buffer, buffer->bin_buffer_size,
> + ppos, buf, count);
> + if (len > 0)
> + *ppos += len;
> +out:
> + mutex_unlock(&buffer->mutex);
> + return len;
> +}
> +
<snip>
> diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
> index 5946ad9..dd9c24b 100644
> --- a/fs/configfs/inode.c
> +++ b/fs/configfs/inode.c
> @@ -231,7 +231,7 @@ const unsigned char * configfs_get_name(struct configfs_dirent *sd)
> if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK))
> return sd->s_dentry->d_name.name;
>
> - if (sd->s_type & CONFIGFS_ITEM_ATTR) {
> + if (sd->s_type & (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR)) {
> attr = sd->s_element;
> return attr->ca_name;
> }
> diff --git a/include/linux/configfs.h b/include/linux/configfs.h
> index 34025df..15f1079 100644
> --- a/include/linux/configfs.h
> +++ b/include/linux/configfs.h
<snip>
> @@ -207,6 +209,89 @@ static ssize_t _item##_attr_store(struct config_item *item, \
> return ret; \
> }
>
> +struct file;
> +struct vm_area_struct;
> +
> +struct configfs_bin_attribute {
> + struct configfs_attribute attr;
> + void *private;
> +};
cb_attr and cb_private or similar prefixes, please.
Joel
next prev parent reply other threads:[~2014-06-25 12:52 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-22 9:37 [PATCH] configfs: Implement binary attributes Pantelis Antoniou
2014-06-25 12:52 ` Joel Becker [this message]
2014-06-25 12:58 ` Pantelis Antoniou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140625125252.GU30852@ZenIV.linux.org.uk \
--to=jlbec@evilplan.org \
--cc=Alison_Chaiken@mentor.com \
--cc=alexander.sverdlin@nsn.com \
--cc=broonie@kernel.org \
--cc=dan.malek@konsulko.com \
--cc=delicious.quinoa@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=dinh.linux@gmail.com \
--cc=dirk.behme@gmail.com \
--cc=georgi.vlaev@konsulko.com \
--cc=grant.likely@secretlab.ca \
--cc=gregkh@linuxfoundation.org \
--cc=ioan.nicu.ext@nsn.com \
--cc=jluebbe@lasnet.de \
--cc=koen@dominion.thruhere.net \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=matt.porter@linaro.org \
--cc=mbohan@codeaurora.org \
--cc=monstr@monstr.eu \
--cc=mranostay@gmail.com \
--cc=ms@mycable.de \
--cc=pantelis.antoniou@konsulko.com \
--cc=panto@antoniou-consulting.com \
--cc=pete.popov@konsulko.com \
--cc=robherring2@gmail.com \
--cc=s.hauer@pengutronix.de \
--cc=swarren@wwwdotorg.org \
--cc=wsa@the-dreams.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox