LCOV - code coverage report
Current view: top level - lkbce/fs/configfs - file.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 123 123 100.0 %
Date: 2017-01-25 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /* -*- mode: c; c-basic-offset: 8; -*-
       2             :  * vim: noexpandtab sw=8 ts=8 sts=0:
       3             :  *
       4             :  * file.c - operations for regular (text) files.
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2 of the License, or (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public
      17             :  * License along with this program; if not, write to the
      18             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      19             :  * Boston, MA 021110-1307, USA.
      20             :  *
      21             :  * Based on sysfs:
      22             :  *      sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
      23             :  *
      24             :  * configfs Copyright (C) 2005 Oracle.  All rights reserved.
      25             :  */
      26             : 
      27             : #include <linux/fs.h>
      28             : #include <linux/module.h>
      29             : #include <linux/slab.h>
      30             : #include <linux/mutex.h>
      31             : #include <asm/uaccess.h>
      32             : 
      33             : #include <linux/configfs.h>
      34             : #include "configfs_internal.h"
      35             : 
      36             : /*
      37             :  * A simple attribute can only be 4096 characters.  Why 4k?  Because the
      38             :  * original code limited it to PAGE_SIZE.  That's a bad idea, though,
      39             :  * because an attribute of 16k on ia64 won't work on x86.  So we limit to
      40             :  * 4k, our minimum common page size.
      41             :  */
      42             : #define SIMPLE_ATTR_SIZE 4096
      43             : 
      44             : struct configfs_buffer {
      45             :         size_t                  count;
      46             :         loff_t                  pos;
      47             :         char                    * page;
      48             :         struct configfs_item_operations * ops;
      49             :         struct mutex            mutex;
      50             :         int                     needs_read_fill;
      51             : };
      52             : 
      53             : 
      54             : /**
      55             :  *      fill_read_buffer - allocate and fill buffer from item.
      56             :  *      @dentry:        dentry pointer.
      57             :  *      @buffer:        data buffer for file.
      58             :  *
      59             :  *      Allocate @buffer->page, if it hasn't been already, then call the
      60             :  *      config_item's show() method to fill the buffer with this attribute's
      61             :  *      data.
      62             :  *      This is called only once, on the file's first read.
      63             :  */
      64             : static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buffer)
      65             : {
      66           4 :         struct configfs_attribute * attr = to_attr(dentry);
      67           4 :         struct config_item * item = to_item(dentry->d_parent);
      68           2 :         struct configfs_item_operations * ops = buffer->ops;
      69           2 :         int ret = 0;
      70           1 :         ssize_t count;
      71           1 : 
      72           4 :         if (!buffer->page)
      73           3 :                 buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
      74           4 :         if (!buffer->page)
      75           1 :                 return -ENOMEM;
      76             : 
      77           1 :         count = ops->show_attribute(item,attr,buffer->page);
      78           1 :         buffer->needs_read_fill = 0;
      79           6 :         BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
      80           2 :         if (count >= 0)
      81           1 :                 buffer->count = count;
      82             :         else
      83           1 :                 ret = count;
      84           1 :         return ret;
      85             : }
      86             : 
      87             : /**
      88             :  *      configfs_read_file - read an attribute.
      89             :  *      @file:  file pointer.
      90             :  *      @buf:   buffer to fill.
      91             :  *      @count: number of bytes to read.
      92             :  *      @ppos:  starting offset in file.
      93             :  *
      94             :  *      Userspace wants to read an attribute file. The attribute descriptor
      95             :  *      is in the file's ->d_fsdata. The target item is in the directory's
      96             :  *      ->d_fsdata.
      97             :  *
      98             :  *      We call fill_read_buffer() to allocate and fill the buffer from the
      99             :  *      item's show() method exactly once (if the read is happening from
     100             :  *      the beginning of the file). That should fill the entire buffer with
     101             :  *      all the data the item has to offer for that attribute.
     102             :  *      We then call flush_read_buffer() to copy the buffer to userspace
     103             :  *      in the increments specified.
     104             :  */
     105             : 
     106             : static ssize_t
     107             : configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
     108             : {
     109           3 :         struct configfs_buffer * buffer = file->private_data;
     110           2 :         ssize_t retval = 0;
     111           1 : 
     112           1 :         mutex_lock(&buffer->mutex);
     113           2 :         if (buffer->needs_read_fill) {
     114           6 :                 if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
     115           1 :                         goto out;
     116             :         }
     117             :         pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
     118             :                  __func__, count, *ppos, buffer->page);
     119           4 :         retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
     120             :                                          buffer->count);
     121             : out:
     122           4 :         mutex_unlock(&buffer->mutex);
     123           2 :         return retval;
     124             : }
     125             : 
     126             : 
     127             : /**
     128             :  *      fill_write_buffer - copy buffer from userspace.
     129             :  *      @buffer:        data buffer for file.
     130             :  *      @buf:           data from user.
     131             :  *      @count:         number of bytes in @userbuf.
     132             :  *
     133             :  *      Allocate @buffer->page if it hasn't been already, then
     134             :  *      copy the user-supplied buffer into it.
     135             :  */
     136             : 
     137             : static int
     138             : fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size_t count)
     139             : {
     140             :         int error;
     141           1 : 
     142           4 :         if (!buffer->page)
     143           3 :                 buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0);
     144           3 :         if (!buffer->page)
     145           1 :                 return -ENOMEM;
     146             : 
     147           2 :         if (count >= SIMPLE_ATTR_SIZE)
     148           1 :                 count = SIMPLE_ATTR_SIZE - 1;
     149           5 :         error = copy_from_user(buffer->page,buf,count);
     150           1 :         buffer->needs_read_fill = 1;
     151             :         /* if buf is assumed to contain a string, terminate it by \0,
     152             :          * so e.g. sscanf() can scan the string easily */
     153           1 :         buffer->page[count] = 0;
     154           6 :         return error ? -EFAULT : count;
     155             : }
     156             : 
     157             : 
     158             : /**
     159             :  *      flush_write_buffer - push buffer to config_item.
     160             :  *      @dentry:        dentry to the attribute
     161             :  *      @buffer:        data buffer for file.
     162             :  *      @count:         number of bytes
     163             :  *
     164             :  *      Get the correct pointers for the config_item and the attribute we're
     165             :  *      dealing with, then call the store() method for the attribute,
     166             :  *      passing the buffer that we acquired in fill_write_buffer().
     167             :  */
     168             : 
     169             : static int
     170             : flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count)
     171             : {
     172           3 :         struct configfs_attribute * attr = to_attr(dentry);
     173           4 :         struct config_item * item = to_item(dentry->d_parent);
     174           2 :         struct configfs_item_operations * ops = buffer->ops;
     175           1 : 
     176           4 :         return ops->store_attribute(item,attr,buffer->page,count);
     177           1 : }
     178           1 : 
     179             : 
     180             : /**
     181             :  *      configfs_write_file - write an attribute.
     182             :  *      @file:  file pointer
     183             :  *      @buf:   data to write
     184             :  *      @count: number of bytes
     185             :  *      @ppos:  starting offset
     186             :  *
     187             :  *      Similar to configfs_read_file(), though working in the opposite direction.
     188             :  *      We allocate and fill the data from the user in fill_write_buffer(),
     189             :  *      then push it to the config_item in flush_write_buffer().
     190             :  *      There is no easy way for us to know if userspace is only doing a partial
     191             :  *      write, so we don't support them. We expect the entire buffer to come
     192             :  *      on the first write.
     193             :  *      Hint: if you're writing a value, first read the file, modify only the
     194             :  *      the value you're changing, then write entire buffer back.
     195             :  */
     196             : 
     197             : static ssize_t
     198             : configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
     199             : {
     200           2 :         struct configfs_buffer * buffer = file->private_data;
     201           1 :         ssize_t len;
     202           1 : 
     203           2 :         mutex_lock(&buffer->mutex);
     204           5 :         len = fill_write_buffer(buffer, buf, count);
     205           2 :         if (len > 0)
     206           3 :                 len = flush_write_buffer(file->f_path.dentry, buffer, count);
     207           4 :         if (len > 0)
     208           2 :                 *ppos += len;
     209           2 :         mutex_unlock(&buffer->mutex);
     210           2 :         return len;
     211             : }
     212             : 
     213             : static int check_perm(struct inode * inode, struct file * file)
     214             : {
     215           4 :         struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
     216           4 :         struct configfs_attribute * attr = to_attr(file->f_path.dentry);
     217           1 :         struct configfs_buffer * buffer;
     218           2 :         struct configfs_item_operations * ops = NULL;
     219           2 :         int error = 0;
     220           1 : 
     221           5 :         if (!item || !attr)
     222           2 :                 goto Einval;
     223           1 : 
     224           1 :         /* Grab the module reference for this attribute if we have one */
     225           4 :         if (!try_module_get(attr->ca_owner)) {
     226           1 :                 error = -ENODEV;
     227           1 :                 goto Done;
     228             :         }
     229             : 
     230           3 :         if (item->ci_type)
     231           1 :                 ops = item->ci_type->ct_item_ops;
     232             :         else
     233           1 :                 goto Eaccess;
     234             : 
     235             :         /* File needs write support.
     236             :          * The inode's perms must say it's ok,
     237             :          * and we must have a store method.
     238             :          */
     239           2 :         if (file->f_mode & FMODE_WRITE) {
     240             : 
     241           6 :                 if (!(inode->i_mode & S_IWUGO) || !ops->store_attribute)
     242           1 :                         goto Eaccess;
     243             : 
     244             :         }
     245             : 
     246             :         /* File needs read support.
     247             :          * The inode's perms must say it's ok, and we there
     248             :          * must be a show method for it.
     249             :          */
     250           3 :         if (file->f_mode & FMODE_READ) {
     251           6 :                 if (!(inode->i_mode & S_IRUGO) || !ops->show_attribute)
     252           1 :                         goto Eaccess;
     253             :         }
     254             : 
     255             :         /* No error? Great, allocate a buffer for the file, and store it
     256             :          * it in file->private_data for easy access.
     257             :          */
     258           3 :         buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
     259           2 :         if (!buffer) {
     260           1 :                 error = -ENOMEM;
     261           1 :                 goto Enomem;
     262             :         }
     263           1 :         mutex_init(&buffer->mutex);
     264           1 :         buffer->needs_read_fill = 1;
     265           1 :         buffer->ops = ops;
     266           1 :         file->private_data = buffer;
     267           1 :         goto Done;
     268           1 : 
     269             :  Einval:
     270           1 :         error = -EINVAL;
     271           1 :         goto Done;
     272           1 :  Eaccess:
     273           1 :         error = -EACCES;
     274           1 :  Enomem:
     275           4 :         module_put(attr->ca_owner);
     276             :  Done:
     277          17 :         if (error && item)
     278           8 :                 config_item_put(item);
     279           5 :         return error;
     280             : }
     281             : 
     282             : static int configfs_open_file(struct inode * inode, struct file * filp)
     283             : {
     284           8 :         return check_perm(inode,filp);
     285             : }
     286             : 
     287             : static int configfs_release(struct inode * inode, struct file * filp)
     288             : {
     289           4 :         struct config_item * item = to_item(filp->f_path.dentry->d_parent);
     290           4 :         struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
     291           2 :         struct module * owner = attr->ca_owner;
     292           3 :         struct configfs_buffer * buffer = filp->private_data;
     293           1 : 
     294           3 :         if (item)
     295           2 :                 config_item_put(item);
     296             :         /* After this point, attr should not be accessed. */
     297           4 :         module_put(owner);
     298             : 
     299           2 :         if (buffer) {
     300           3 :                 if (buffer->page)
     301           2 :                         free_page((unsigned long)buffer->page);
     302             :                 mutex_destroy(&buffer->mutex);
     303           1 :                 kfree(buffer);
     304             :         }
     305           1 :         return 0;
     306             : }
     307             : 
     308           1 : const struct file_operations configfs_file_operations = {
     309             :         .read           = configfs_read_file,
     310             :         .write          = configfs_write_file,
     311             :         .llseek         = generic_file_llseek,
     312             :         .open           = configfs_open_file,
     313             :         .release        = configfs_release,
     314             : };
     315             : 
     316             : 
     317             : int configfs_add_file(struct dentry * dir, const struct configfs_attribute * attr, int type)
     318             : {
     319           8 :         struct configfs_dirent * parent_sd = dir->d_fsdata;
     320          12 :         umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
     321           8 :         int error = 0;
     322           4 : 
     323           4 :         mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL);
     324          16 :         error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
     325           4 :         mutex_unlock(&dir->d_inode->i_mutex);
     326             : 
     327           4 :         return error;
     328             : }
     329             : 
     330             : 
     331             : /**
     332             :  *      configfs_create_file - create an attribute file for an item.
     333             :  *      @item:  item we're creating for.
     334             :  *      @attr:  atrribute descriptor.
     335             :  */
     336             : 
     337             : int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr)
     338             : {
     339          38 :         BUG_ON(!item || !item->ci_dentry || !attr);
     340           2 : 
     341          12 :         return configfs_add_file(item->ci_dentry, attr,
     342             :                                  CONFIGFS_ITEM_ATTR);
     343             : }
     344             : 

Generated by: LCOV version 1.10