linux-bk/fs/sysfs/file.c
<<
>>
Prefs
   1/*
   2 * file.c - operations for regular (text) files.
   3 */
   4
   5#include <linux/module.h>
   6#include <linux/dnotify.h>
   7#include <linux/kobject.h>
   8#include <asm/uaccess.h>
   9#include <asm/semaphore.h>
  10
  11#include "sysfs.h"
  12
  13#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
  14#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
  15
  16/**
  17 * Subsystem file operations.
  18 * These operations allow subsystems to have files that can be 
  19 * read/written. 
  20 */
  21static ssize_t 
  22subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
  23{
  24        struct subsystem * s = to_subsys(kobj);
  25        struct subsys_attribute * sattr = to_sattr(attr);
  26        ssize_t ret = 0;
  27
  28        if (sattr->show)
  29                ret = sattr->show(s,page);
  30        return ret;
  31}
  32
  33static ssize_t 
  34subsys_attr_store(struct kobject * kobj, struct attribute * attr, 
  35                  const char * page, size_t count)
  36{
  37        struct subsystem * s = to_subsys(kobj);
  38        struct subsys_attribute * sattr = to_sattr(attr);
  39        ssize_t ret = 0;
  40
  41        if (sattr->store)
  42                ret = sattr->store(s,page,count);
  43        return ret;
  44}
  45
  46static struct sysfs_ops subsys_sysfs_ops = {
  47        .show   = subsys_attr_show,
  48        .store  = subsys_attr_store,
  49};
  50
  51
  52struct sysfs_buffer {
  53        size_t                  count;
  54        loff_t                  pos;
  55        char                    * page;
  56        struct sysfs_ops        * ops;
  57        struct semaphore        sem;
  58        int                     needs_read_fill;
  59};
  60
  61
  62/**
  63 *      fill_read_buffer - allocate and fill buffer from object.
  64 *      @dentry:        dentry pointer.
  65 *      @buffer:        data buffer for file.
  66 *
  67 *      Allocate @buffer->page, if it hasn't been already, then call the
  68 *      kobject's show() method to fill the buffer with this attribute's 
  69 *      data. 
  70 *      This is called only once, on the file's first read. 
  71 */
  72static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
  73{
  74        struct attribute * attr = to_attr(dentry);
  75        struct kobject * kobj = to_kobj(dentry->d_parent);
  76        struct sysfs_ops * ops = buffer->ops;
  77        int ret = 0;
  78        ssize_t count;
  79
  80        if (!buffer->page)
  81                buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
  82        if (!buffer->page)
  83                return -ENOMEM;
  84
  85        count = ops->show(kobj,attr,buffer->page);
  86        buffer->needs_read_fill = 0;
  87        BUG_ON(count > (ssize_t)PAGE_SIZE);
  88        if (count >= 0)
  89                buffer->count = count;
  90        else
  91                ret = count;
  92        return ret;
  93}
  94
  95
  96/**
  97 *      flush_read_buffer - push buffer to userspace.
  98 *      @buffer:        data buffer for file.
  99 *      @userbuf:       user-passed buffer.
 100 *      @count:         number of bytes requested.
 101 *      @ppos:          file position.
 102 *
 103 *      Copy the buffer we filled in fill_read_buffer() to userspace.
 104 *      This is done at the reader's leisure, copying and advancing 
 105 *      the amount they specify each time.
 106 *      This may be called continuously until the buffer is empty.
 107 */
 108static int flush_read_buffer(struct sysfs_buffer * buffer, char __user * buf,
 109                             size_t count, loff_t * ppos)
 110{
 111        int error;
 112
 113        if (*ppos > buffer->count)
 114                return 0;
 115
 116        if (count > (buffer->count - *ppos))
 117                count = buffer->count - *ppos;
 118
 119        error = copy_to_user(buf,buffer->page + *ppos,count);
 120        if (!error)
 121                *ppos += count;
 122        return error ? -EFAULT : count;
 123}
 124
 125/**
 126 *      sysfs_read_file - read an attribute. 
 127 *      @file:  file pointer.
 128 *      @buf:   buffer to fill.
 129 *      @count: number of bytes to read.
 130 *      @ppos:  starting offset in file.
 131 *
 132 *      Userspace wants to read an attribute file. The attribute descriptor
 133 *      is in the file's ->d_fsdata. The target object is in the directory's
 134 *      ->d_fsdata.
 135 *
 136 *      We call fill_read_buffer() to allocate and fill the buffer from the
 137 *      object's show() method exactly once (if the read is happening from
 138 *      the beginning of the file). That should fill the entire buffer with
 139 *      all the data the object has to offer for that attribute.
 140 *      We then call flush_read_buffer() to copy the buffer to userspace
 141 *      in the increments specified.
 142 */
 143
 144static ssize_t
 145sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 146{
 147        struct sysfs_buffer * buffer = file->private_data;
 148        ssize_t retval = 0;
 149
 150        down(&buffer->sem);
 151        if (buffer->needs_read_fill) {
 152                if ((retval = fill_read_buffer(file->f_dentry,buffer)))
 153                        goto out;
 154        }
 155        pr_debug("%s: count = %d, ppos = %lld, buf = %s\n",
 156                 __FUNCTION__,count,*ppos,buffer->page);
 157        retval = flush_read_buffer(buffer,buf,count,ppos);
 158out:
 159        up(&buffer->sem);
 160        return retval;
 161}
 162
 163
 164/**
 165 *      fill_write_buffer - copy buffer from userspace.
 166 *      @buffer:        data buffer for file.
 167 *      @userbuf:       data from user.
 168 *      @count:         number of bytes in @userbuf.
 169 *
 170 *      Allocate @buffer->page if it hasn't been already, then
 171 *      copy the user-supplied buffer into it.
 172 */
 173
 174static int 
 175fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count)
 176{
 177        int error;
 178
 179        if (!buffer->page)
 180                buffer->page = (char *)get_zeroed_page(GFP_KERNEL);
 181        if (!buffer->page)
 182                return -ENOMEM;
 183
 184        if (count >= PAGE_SIZE)
 185                count = PAGE_SIZE - 1;
 186        error = copy_from_user(buffer->page,buf,count);
 187        buffer->needs_read_fill = 1;
 188        return error ? -EFAULT : count;
 189}
 190
 191
 192/**
 193 *      flush_write_buffer - push buffer to kobject.
 194 *      @file:          file pointer.
 195 *      @buffer:        data buffer for file.
 196 *
 197 *      Get the correct pointers for the kobject and the attribute we're
 198 *      dealing with, then call the store() method for the attribute, 
 199 *      passing the buffer that we acquired in fill_write_buffer().
 200 */
 201
 202static int 
 203flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
 204{
 205        struct attribute * attr = to_attr(dentry);
 206        struct kobject * kobj = to_kobj(dentry->d_parent);
 207        struct sysfs_ops * ops = buffer->ops;
 208
 209        return ops->store(kobj,attr,buffer->page,count);
 210}
 211
 212
 213/**
 214 *      sysfs_write_file - write an attribute.
 215 *      @file:  file pointer
 216 *      @buf:   data to write
 217 *      @count: number of bytes
 218 *      @ppos:  starting offset
 219 *
 220 *      Similar to sysfs_read_file(), though working in the opposite direction.
 221 *      We allocate and fill the data from the user in fill_write_buffer(),
 222 *      then push it to the kobject in flush_write_buffer().
 223 *      There is no easy way for us to know if userspace is only doing a partial
 224 *      write, so we don't support them. We expect the entire buffer to come
 225 *      on the first write. 
 226 *      Hint: if you're writing a value, first read the file, modify only the
 227 *      the value you're changing, then write entire buffer back. 
 228 */
 229
 230static ssize_t
 231sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 232{
 233        struct sysfs_buffer * buffer = file->private_data;
 234        ssize_t len;
 235
 236        down(&buffer->sem);
 237        len = fill_write_buffer(buffer, buf, count);
 238        if (len > 0)
 239                len = flush_write_buffer(file->f_dentry, buffer, len);
 240        if (len > 0)
 241                *ppos += len;
 242        up(&buffer->sem);
 243        return len;
 244}
 245
 246static int check_perm(struct inode * inode, struct file * file)
 247{
 248        struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
 249        struct attribute * attr = to_attr(file->f_dentry);
 250        struct sysfs_buffer * buffer;
 251        struct sysfs_ops * ops = NULL;
 252        int error = 0;
 253
 254        if (!kobj || !attr)
 255                goto Einval;
 256
 257        /* Grab the module reference for this attribute if we have one */
 258        if (!try_module_get(attr->owner)) {
 259                error = -ENODEV;
 260                goto Done;
 261        }
 262
 263        /* if the kobject has no ktype, then we assume that it is a subsystem
 264         * itself, and use ops for it.
 265         */
 266        if (kobj->kset && kobj->kset->ktype)
 267                ops = kobj->kset->ktype->sysfs_ops;
 268        else if (kobj->ktype)
 269                ops = kobj->ktype->sysfs_ops;
 270        else
 271                ops = &subsys_sysfs_ops;
 272
 273        /* No sysfs operations, either from having no subsystem,
 274         * or the subsystem have no operations.
 275         */
 276        if (!ops)
 277                goto Eaccess;
 278
 279        /* File needs write support.
 280         * The inode's perms must say it's ok, 
 281         * and we must have a store method.
 282         */
 283        if (file->f_mode & FMODE_WRITE) {
 284
 285                if (!(inode->i_mode & S_IWUGO) || !ops->store)
 286                        goto Eaccess;
 287
 288        }
 289
 290        /* File needs read support.
 291         * The inode's perms must say it's ok, and we there
 292         * must be a show method for it.
 293         */
 294        if (file->f_mode & FMODE_READ) {
 295                if (!(inode->i_mode & S_IRUGO) || !ops->show)
 296                        goto Eaccess;
 297        }
 298
 299        /* No error? Great, allocate a buffer for the file, and store it
 300         * it in file->private_data for easy access.
 301         */
 302        buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL);
 303        if (buffer) {
 304                memset(buffer,0,sizeof(struct sysfs_buffer));
 305                init_MUTEX(&buffer->sem);
 306                buffer->needs_read_fill = 1;
 307                buffer->ops = ops;
 308                file->private_data = buffer;
 309        } else
 310                error = -ENOMEM;
 311        goto Done;
 312
 313 Einval:
 314        error = -EINVAL;
 315        goto Done;
 316 Eaccess:
 317        error = -EACCES;
 318        module_put(attr->owner);
 319 Done:
 320        if (error && kobj)
 321                kobject_put(kobj);
 322        return error;
 323}
 324
 325static int sysfs_open_file(struct inode * inode, struct file * filp)
 326{
 327        return check_perm(inode,filp);
 328}
 329
 330static int sysfs_release(struct inode * inode, struct file * filp)
 331{
 332        struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
 333        struct attribute * attr = to_attr(filp->f_dentry);
 334        struct module * owner = attr->owner;
 335        struct sysfs_buffer * buffer = filp->private_data;
 336
 337        if (kobj) 
 338                kobject_put(kobj);
 339        /* After this point, attr should not be accessed. */
 340        module_put(owner);
 341
 342        if (buffer) {
 343                if (buffer->page)
 344                        free_page((unsigned long)buffer->page);
 345                kfree(buffer);
 346        }
 347        return 0;
 348}
 349
 350struct file_operations sysfs_file_operations = {
 351        .read           = sysfs_read_file,
 352        .write          = sysfs_write_file,
 353        .llseek         = generic_file_llseek,
 354        .open           = sysfs_open_file,
 355        .release        = sysfs_release,
 356};
 357
 358
 359int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
 360{
 361        struct sysfs_dirent * parent_sd = dir->d_fsdata;
 362        umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
 363        int error = 0;
 364
 365        down(&dir->d_inode->i_sem);
 366        error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
 367        up(&dir->d_inode->i_sem);
 368
 369        return error;
 370}
 371
 372
 373/**
 374 *      sysfs_create_file - create an attribute file for an object.
 375 *      @kobj:  object we're creating for. 
 376 *      @attr:  atrribute descriptor.
 377 */
 378
 379int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
 380{
 381        BUG_ON(!kobj || !kobj->dentry || !attr);
 382
 383        return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
 384
 385}
 386
 387
 388/**
 389 * sysfs_update_file - update the modified timestamp on an object attribute.
 390 * @kobj: object we're acting for.
 391 * @attr: attribute descriptor.
 392 *
 393 * Also call dnotify for the dentry, which lots of userspace programs
 394 * use.
 395 */
 396int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
 397{
 398        struct dentry * dir = kobj->dentry;
 399        struct dentry * victim;
 400        int res = -ENOENT;
 401
 402        down(&dir->d_inode->i_sem);
 403        victim = sysfs_get_dentry(dir, attr->name);
 404        if (!IS_ERR(victim)) {
 405                /* make sure dentry is really there */
 406                if (victim->d_inode && 
 407                    (victim->d_parent->d_inode == dir->d_inode)) {
 408                        victim->d_inode->i_mtime = CURRENT_TIME;
 409                        dnotify_parent(victim, DN_MODIFY);
 410
 411                        /**
 412                         * Drop reference from initial sysfs_get_dentry().
 413                         */
 414                        dput(victim);
 415                        res = 0;
 416                } else
 417                        d_drop(victim);
 418                
 419                /**
 420                 * Drop the reference acquired from sysfs_get_dentry() above.
 421                 */
 422                dput(victim);
 423        }
 424        up(&dir->d_inode->i_sem);
 425
 426        return res;
 427}
 428
 429
 430/**
 431 *      sysfs_remove_file - remove an object attribute.
 432 *      @kobj:  object we're acting for.
 433 *      @attr:  attribute descriptor.
 434 *
 435 *      Hash the attribute name and kill the victim.
 436 */
 437
 438void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
 439{
 440        sysfs_hash_and_remove(kobj->dentry,attr->name);
 441}
 442
 443
 444EXPORT_SYMBOL_GPL(sysfs_create_file);
 445EXPORT_SYMBOL_GPL(sysfs_remove_file);
 446EXPORT_SYMBOL_GPL(sysfs_update_file);
 447
 448
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.