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