LCOV - code coverage report
Current view: top level - fs/configfs - file.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 0 179 0.0 %
Date: 2020-09-30 20:25:01 Functions: 0 14 0.0 %
Branches: 0 106 0.0 %

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

Generated by: LCOV version 1.14