linux/fs/sysfs/dir.c
<<
>>
Prefs
   1/*
   2 * fs/sysfs/dir.c - sysfs core and dir operation implementation
   3 *
   4 * Copyright (c) 2001-3 Patrick Mochel
   5 * Copyright (c) 2007 SUSE Linux Products GmbH
   6 * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
   7 *
   8 * This file is released under the GPLv2.
   9 *
  10 * Please see Documentation/filesystems/sysfs.txt for more information.
  11 */
  12
  13#undef DEBUG
  14
  15#include <linux/fs.h>
  16#include <linux/mount.h>
  17#include <linux/module.h>
  18#include <linux/kobject.h>
  19#include <linux/namei.h>
  20#include <linux/idr.h>
  21#include <linux/completion.h>
  22#include <linux/mutex.h>
  23#include <linux/slab.h>
  24#include <linux/security.h>
  25#include <linux/hash.h>
  26#include "sysfs.h"
  27
  28DEFINE_MUTEX(sysfs_mutex);
  29DEFINE_SPINLOCK(sysfs_assoc_lock);
  30
  31#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb);
  32
  33static DEFINE_SPINLOCK(sysfs_ino_lock);
  34static DEFINE_IDA(sysfs_ino_ida);
  35
  36/**
  37 *      sysfs_name_hash
  38 *      @ns:   Namespace tag to hash
  39 *      @name: Null terminated string to hash
  40 *
  41 *      Returns 31 bit hash of ns + name (so it fits in an off_t )
  42 */
  43static unsigned int sysfs_name_hash(const void *ns, const char *name)
  44{
  45        unsigned long hash = init_name_hash();
  46        unsigned int len = strlen(name);
  47        while (len--)
  48                hash = partial_name_hash(*name++, hash);
  49        hash = ( end_name_hash(hash) ^ hash_ptr( (void *)ns, 31 ) );
  50        hash &= 0x7fffffffU;
  51        /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */
  52        if (hash < 1)
  53                hash += 2;
  54        if (hash >= INT_MAX)
  55                hash = INT_MAX - 1;
  56        return hash;
  57}
  58
  59static int sysfs_name_compare(unsigned int hash, const void *ns,
  60        const char *name, const struct sysfs_dirent *sd)
  61{
  62        if (hash != sd->s_hash)
  63                return hash - sd->s_hash;
  64        if (ns != sd->s_ns)
  65                return ns - sd->s_ns;
  66        return strcmp(name, sd->s_name);
  67}
  68
  69static int sysfs_sd_compare(const struct sysfs_dirent *left,
  70                            const struct sysfs_dirent *right)
  71{
  72        return sysfs_name_compare(left->s_hash, left->s_ns, left->s_name,
  73                                  right);
  74}
  75
  76/**
  77 *      sysfs_link_subling - link sysfs_dirent into sibling rbtree
  78 *      @sd: sysfs_dirent of interest
  79 *
  80 *      Link @sd into its sibling rbtree which starts from
  81 *      sd->s_parent->s_dir.children.
  82 *
  83 *      Locking:
  84 *      mutex_lock(sysfs_mutex)
  85 *
  86 *      RETURNS:
  87 *      0 on susccess -EEXIST on failure.
  88 */
  89static int sysfs_link_sibling(struct sysfs_dirent *sd)
  90{
  91        struct rb_node **node = &sd->s_parent->s_dir.children.rb_node;
  92        struct rb_node *parent = NULL;
  93
  94        if (sysfs_type(sd) == SYSFS_DIR)
  95                sd->s_parent->s_dir.subdirs++;
  96
  97        while (*node) {
  98                struct sysfs_dirent *pos;
  99                int result;
 100
 101                pos = to_sysfs_dirent(*node);
 102                parent = *node;
 103                result = sysfs_sd_compare(sd, pos);
 104                if (result < 0)
 105                        node = &pos->s_rb.rb_left;
 106                else if (result > 0)
 107                        node = &pos->s_rb.rb_right;
 108                else
 109                        return -EEXIST;
 110        }
 111        /* add new node and rebalance the tree */
 112        rb_link_node(&sd->s_rb, parent, node);
 113        rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children);
 114        return 0;
 115}
 116
 117/**
 118 *      sysfs_unlink_sibling - unlink sysfs_dirent from sibling rbtree
 119 *      @sd: sysfs_dirent of interest
 120 *
 121 *      Unlink @sd from its sibling rbtree which starts from
 122 *      sd->s_parent->s_dir.children.
 123 *
 124 *      Locking:
 125 *      mutex_lock(sysfs_mutex)
 126 */
 127static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
 128{
 129        if (sysfs_type(sd) == SYSFS_DIR)
 130                sd->s_parent->s_dir.subdirs--;
 131
 132        rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
 133}
 134
 135#ifdef CONFIG_DEBUG_LOCK_ALLOC
 136
 137/* Test for attributes that want to ignore lockdep for read-locking */
 138static bool ignore_lockdep(struct sysfs_dirent *sd)
 139{
 140        return sysfs_type(sd) == SYSFS_KOBJ_ATTR &&
 141                        sd->s_attr.attr->ignore_lockdep;
 142}
 143
 144#else
 145
 146static inline bool ignore_lockdep(struct sysfs_dirent *sd)
 147{
 148        return true;
 149}
 150
 151#endif
 152
 153/**
 154 *      sysfs_get_active - get an active reference to sysfs_dirent
 155 *      @sd: sysfs_dirent to get an active reference to
 156 *
 157 *      Get an active reference of @sd.  This function is noop if @sd
 158 *      is NULL.
 159 *
 160 *      RETURNS:
 161 *      Pointer to @sd on success, NULL on failure.
 162 */
 163struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
 164{
 165        if (unlikely(!sd))
 166                return NULL;
 167
 168        while (1) {
 169                int v, t;
 170
 171                v = atomic_read(&sd->s_active);
 172                if (unlikely(v < 0))
 173                        return NULL;
 174
 175                t = atomic_cmpxchg(&sd->s_active, v, v + 1);
 176                if (likely(t == v))
 177                        break;
 178                if (t < 0)
 179                        return NULL;
 180
 181                cpu_relax();
 182        }
 183
 184        if (likely(!ignore_lockdep(sd)))
 185                rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
 186        return sd;
 187}
 188
 189/**
 190 *      sysfs_put_active - put an active reference to sysfs_dirent
 191 *      @sd: sysfs_dirent to put an active reference to
 192 *
 193 *      Put an active reference to @sd.  This function is noop if @sd
 194 *      is NULL.
 195 */
 196void sysfs_put_active(struct sysfs_dirent *sd)
 197{
 198        int v;
 199
 200        if (unlikely(!sd))
 201                return;
 202
 203        if (likely(!ignore_lockdep(sd)))
 204                rwsem_release(&sd->dep_map, 1, _RET_IP_);
 205        v = atomic_dec_return(&sd->s_active);
 206        if (likely(v != SD_DEACTIVATED_BIAS))
 207                return;
 208
 209        /* atomic_dec_return() is a mb(), we'll always see the updated
 210         * sd->u.completion.
 211         */
 212        complete(sd->u.completion);
 213}
 214
 215/**
 216 *      sysfs_deactivate - deactivate sysfs_dirent
 217 *      @sd: sysfs_dirent to deactivate
 218 *
 219 *      Deny new active references and drain existing ones.
 220 */
 221static void sysfs_deactivate(struct sysfs_dirent *sd)
 222{
 223        DECLARE_COMPLETION_ONSTACK(wait);
 224        int v;
 225
 226        BUG_ON(!(sd->s_flags & SYSFS_FLAG_REMOVED));
 227
 228        if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF))
 229                return;
 230
 231        sd->u.completion = (void *)&wait;
 232
 233        rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
 234        /* atomic_add_return() is a mb(), put_active() will always see
 235         * the updated sd->u.completion.
 236         */
 237        v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
 238
 239        if (v != SD_DEACTIVATED_BIAS) {
 240                lock_contended(&sd->dep_map, _RET_IP_);
 241                wait_for_completion(&wait);
 242        }
 243
 244        lock_acquired(&sd->dep_map, _RET_IP_);
 245        rwsem_release(&sd->dep_map, 1, _RET_IP_);
 246}
 247
 248static int sysfs_alloc_ino(unsigned int *pino)
 249{
 250        int ino, rc;
 251
 252 retry:
 253        spin_lock(&sysfs_ino_lock);
 254        rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
 255        spin_unlock(&sysfs_ino_lock);
 256
 257        if (rc == -EAGAIN) {
 258                if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
 259                        goto retry;
 260                rc = -ENOMEM;
 261        }
 262
 263        *pino = ino;
 264        return rc;
 265}
 266
 267static void sysfs_free_ino(unsigned int ino)
 268{
 269        spin_lock(&sysfs_ino_lock);
 270        ida_remove(&sysfs_ino_ida, ino);
 271        spin_unlock(&sysfs_ino_lock);
 272}
 273
 274void release_sysfs_dirent(struct sysfs_dirent * sd)
 275{
 276        struct sysfs_dirent *parent_sd;
 277
 278 repeat:
 279        /* Moving/renaming is always done while holding reference.
 280         * sd->s_parent won't change beneath us.
 281         */
 282        parent_sd = sd->s_parent;
 283
 284        if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
 285                sysfs_put(sd->s_symlink.target_sd);
 286        if (sysfs_type(sd) & SYSFS_COPY_NAME)
 287                kfree(sd->s_name);
 288        if (sd->s_iattr && sd->s_iattr->ia_secdata)
 289                security_release_secctx(sd->s_iattr->ia_secdata,
 290                                        sd->s_iattr->ia_secdata_len);
 291        kfree(sd->s_iattr);
 292        sysfs_free_ino(sd->s_ino);
 293        kmem_cache_free(sysfs_dir_cachep, sd);
 294
 295        sd = parent_sd;
 296        if (sd && atomic_dec_and_test(&sd->s_count))
 297                goto repeat;
 298}
 299
 300static int sysfs_dentry_delete(const struct dentry *dentry)
 301{
 302        struct sysfs_dirent *sd = dentry->d_fsdata;
 303        return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED));
 304}
 305
 306static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
 307{
 308        struct sysfs_dirent *sd;
 309        int is_dir;
 310        int type;
 311
 312        if (flags & LOOKUP_RCU)
 313                return -ECHILD;
 314
 315        sd = dentry->d_fsdata;
 316        mutex_lock(&sysfs_mutex);
 317
 318        /* The sysfs dirent has been deleted */
 319        if (sd->s_flags & SYSFS_FLAG_REMOVED)
 320                goto out_bad;
 321
 322        /* The sysfs dirent has been moved? */
 323        if (dentry->d_parent->d_fsdata != sd->s_parent)
 324                goto out_bad;
 325
 326        /* The sysfs dirent has been renamed */
 327        if (strcmp(dentry->d_name.name, sd->s_name) != 0)
 328                goto out_bad;
 329
 330        /* The sysfs dirent has been moved to a different namespace */
 331        type = KOBJ_NS_TYPE_NONE;
 332        if (sd->s_parent) {
 333                type = sysfs_ns_type(sd->s_parent);
 334                if (type != KOBJ_NS_TYPE_NONE &&
 335                                sysfs_info(dentry->d_sb)->ns[type] != sd->s_ns)
 336                        goto out_bad;
 337        }
 338
 339        mutex_unlock(&sysfs_mutex);
 340out_valid:
 341        return 1;
 342out_bad:
 343        /* Remove the dentry from the dcache hashes.
 344         * If this is a deleted dentry we use d_drop instead of d_delete
 345         * so sysfs doesn't need to cope with negative dentries.
 346         *
 347         * If this is a dentry that has simply been renamed we
 348         * use d_drop to remove it from the dcache lookup on its
 349         * old parent.  If this dentry persists later when a lookup
 350         * is performed at its new name the dentry will be readded
 351         * to the dcache hashes.
 352         */
 353        is_dir = (sysfs_type(sd) == SYSFS_DIR);
 354        mutex_unlock(&sysfs_mutex);
 355        if (is_dir) {
 356                /* If we have submounts we must allow the vfs caches
 357                 * to lie about the state of the filesystem to prevent
 358                 * leaks and other nasty things.
 359                 */
 360                if (have_submounts(dentry))
 361                        goto out_valid;
 362                shrink_dcache_parent(dentry);
 363        }
 364        d_drop(dentry);
 365        return 0;
 366}
 367
 368static void sysfs_dentry_release(struct dentry *dentry)
 369{
 370        sysfs_put(dentry->d_fsdata);
 371}
 372
 373const struct dentry_operations sysfs_dentry_ops = {
 374        .d_revalidate   = sysfs_dentry_revalidate,
 375        .d_delete       = sysfs_dentry_delete,
 376        .d_release      = sysfs_dentry_release,
 377};
 378
 379struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
 380{
 381        char *dup_name = NULL;
 382        struct sysfs_dirent *sd;
 383
 384        if (type & SYSFS_COPY_NAME) {
 385                name = dup_name = kstrdup(name, GFP_KERNEL);
 386                if (!name)
 387                        return NULL;
 388        }
 389
 390        sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
 391        if (!sd)
 392                goto err_out1;
 393
 394        if (sysfs_alloc_ino(&sd->s_ino))
 395                goto err_out2;
 396
 397        atomic_set(&sd->s_count, 1);
 398        atomic_set(&sd->s_active, 0);
 399
 400        sd->s_name = name;
 401        sd->s_mode = mode;
 402        sd->s_flags = type;
 403
 404        return sd;
 405
 406 err_out2:
 407        kmem_cache_free(sysfs_dir_cachep, sd);
 408 err_out1:
 409        kfree(dup_name);
 410        return NULL;
 411}
 412
 413/**
 414 *      sysfs_addrm_start - prepare for sysfs_dirent add/remove
 415 *      @acxt: pointer to sysfs_addrm_cxt to be used
 416 *      @parent_sd: parent sysfs_dirent
 417 *
 418 *      This function is called when the caller is about to add or
 419 *      remove sysfs_dirent under @parent_sd.  This function acquires
 420 *      sysfs_mutex.  @acxt is used to keep and pass context to
 421 *      other addrm functions.
 422 *
 423 *      LOCKING:
 424 *      Kernel thread context (may sleep).  sysfs_mutex is locked on
 425 *      return.
 426 */
 427void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
 428                       struct sysfs_dirent *parent_sd)
 429{
 430        memset(acxt, 0, sizeof(*acxt));
 431        acxt->parent_sd = parent_sd;
 432
 433        mutex_lock(&sysfs_mutex);
 434}
 435
 436/**
 437 *      __sysfs_add_one - add sysfs_dirent to parent without warning
 438 *      @acxt: addrm context to use
 439 *      @sd: sysfs_dirent to be added
 440 *
 441 *      Get @acxt->parent_sd and set sd->s_parent to it and increment
 442 *      nlink of parent inode if @sd is a directory and link into the
 443 *      children list of the parent.
 444 *
 445 *      This function should be called between calls to
 446 *      sysfs_addrm_start() and sysfs_addrm_finish() and should be
 447 *      passed the same @acxt as passed to sysfs_addrm_start().
 448 *
 449 *      LOCKING:
 450 *      Determined by sysfs_addrm_start().
 451 *
 452 *      RETURNS:
 453 *      0 on success, -EEXIST if entry with the given name already
 454 *      exists.
 455 */
 456int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 457{
 458        struct sysfs_inode_attrs *ps_iattr;
 459        int ret;
 460
 461        if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
 462                WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
 463                        sysfs_ns_type(acxt->parent_sd)? "required": "invalid",
 464                        acxt->parent_sd->s_name, sd->s_name);
 465                return -EINVAL;
 466        }
 467
 468        sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
 469        sd->s_parent = sysfs_get(acxt->parent_sd);
 470
 471        ret = sysfs_link_sibling(sd);
 472        if (ret)
 473                return ret;
 474
 475        /* Update timestamps on the parent */
 476        ps_iattr = acxt->parent_sd->s_iattr;
 477        if (ps_iattr) {
 478                struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
 479                ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
 480        }
 481
 482        return 0;
 483}
 484
 485/**
 486 *      sysfs_pathname - return full path to sysfs dirent
 487 *      @sd: sysfs_dirent whose path we want
 488 *      @path: caller allocated buffer
 489 *
 490 *      Gives the name "/" to the sysfs_root entry; any path returned
 491 *      is relative to wherever sysfs is mounted.
 492 *
 493 *      XXX: does no error checking on @path size
 494 */
 495static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
 496{
 497        if (sd->s_parent) {
 498                sysfs_pathname(sd->s_parent, path);
 499                strcat(path, "/");
 500        }
 501        strcat(path, sd->s_name);
 502        return path;
 503}
 504
 505/**
 506 *      sysfs_add_one - add sysfs_dirent to parent
 507 *      @acxt: addrm context to use
 508 *      @sd: sysfs_dirent to be added
 509 *
 510 *      Get @acxt->parent_sd and set sd->s_parent to it and increment
 511 *      nlink of parent inode if @sd is a directory and link into the
 512 *      children list of the parent.
 513 *
 514 *      This function should be called between calls to
 515 *      sysfs_addrm_start() and sysfs_addrm_finish() and should be
 516 *      passed the same @acxt as passed to sysfs_addrm_start().
 517 *
 518 *      LOCKING:
 519 *      Determined by sysfs_addrm_start().
 520 *
 521 *      RETURNS:
 522 *      0 on success, -EEXIST if entry with the given name already
 523 *      exists.
 524 */
 525int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 526{
 527        int ret;
 528
 529        ret = __sysfs_add_one(acxt, sd);
 530        if (ret == -EEXIST) {
 531                char *path = kzalloc(PATH_MAX, GFP_KERNEL);
 532                WARN(1, KERN_WARNING
 533                     "sysfs: cannot create duplicate filename '%s'\n",
 534                     (path == NULL) ? sd->s_name :
 535                     strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
 536                            sd->s_name));
 537                kfree(path);
 538        }
 539
 540        return ret;
 541}
 542
 543/**
 544 *      sysfs_remove_one - remove sysfs_dirent from parent
 545 *      @acxt: addrm context to use
 546 *      @sd: sysfs_dirent to be removed
 547 *
 548 *      Mark @sd removed and drop nlink of parent inode if @sd is a
 549 *      directory.  @sd is unlinked from the children list.
 550 *
 551 *      This function should be called between calls to
 552 *      sysfs_addrm_start() and sysfs_addrm_finish() and should be
 553 *      passed the same @acxt as passed to sysfs_addrm_start().
 554 *
 555 *      LOCKING:
 556 *      Determined by sysfs_addrm_start().
 557 */
 558void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 559{
 560        struct sysfs_inode_attrs *ps_iattr;
 561
 562        BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED);
 563
 564        sysfs_unlink_sibling(sd);
 565
 566        /* Update timestamps on the parent */
 567        ps_iattr = acxt->parent_sd->s_iattr;
 568        if (ps_iattr) {
 569                struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
 570                ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
 571        }
 572
 573        sd->s_flags |= SYSFS_FLAG_REMOVED;
 574        sd->u.removed_list = acxt->removed;
 575        acxt->removed = sd;
 576}
 577
 578/**
 579 *      sysfs_addrm_finish - finish up sysfs_dirent add/remove
 580 *      @acxt: addrm context to finish up
 581 *
 582 *      Finish up sysfs_dirent add/remove.  Resources acquired by
 583 *      sysfs_addrm_start() are released and removed sysfs_dirents are
 584 *      cleaned up.
 585 *
 586 *      LOCKING:
 587 *      sysfs_mutex is released.
 588 */
 589void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
 590{
 591        /* release resources acquired by sysfs_addrm_start() */
 592        mutex_unlock(&sysfs_mutex);
 593
 594        /* kill removed sysfs_dirents */
 595        while (acxt->removed) {
 596                struct sysfs_dirent *sd = acxt->removed;
 597
 598                acxt->removed = sd->u.removed_list;
 599
 600                sysfs_deactivate(sd);
 601                unmap_bin_file(sd);
 602                sysfs_put(sd);
 603        }
 604}
 605
 606/**
 607 *      sysfs_find_dirent - find sysfs_dirent with the given name
 608 *      @parent_sd: sysfs_dirent to search under
 609 *      @name: name to look for
 610 *
 611 *      Look for sysfs_dirent with name @name under @parent_sd.
 612 *
 613 *      LOCKING:
 614 *      mutex_lock(sysfs_mutex)
 615 *
 616 *      RETURNS:
 617 *      Pointer to sysfs_dirent if found, NULL if not.
 618 */
 619struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
 620                                       const void *ns,
 621                                       const unsigned char *name)
 622{
 623        struct rb_node *node = parent_sd->s_dir.children.rb_node;
 624        unsigned int hash;
 625
 626        if (!!sysfs_ns_type(parent_sd) != !!ns) {
 627                WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
 628                        sysfs_ns_type(parent_sd)? "required": "invalid",
 629                        parent_sd->s_name, name);
 630                return NULL;
 631        }
 632
 633        hash = sysfs_name_hash(ns, name);
 634        while (node) {
 635                struct sysfs_dirent *sd;
 636                int result;
 637
 638                sd = to_sysfs_dirent(node);
 639                result = sysfs_name_compare(hash, ns, name, sd);
 640                if (result < 0)
 641                        node = node->rb_left;
 642                else if (result > 0)
 643                        node = node->rb_right;
 644                else
 645                        return sd;
 646        }
 647        return NULL;
 648}
 649
 650/**
 651 *      sysfs_get_dirent - find and get sysfs_dirent with the given name
 652 *      @parent_sd: sysfs_dirent to search under
 653 *      @name: name to look for
 654 *
 655 *      Look for sysfs_dirent with name @name under @parent_sd and get
 656 *      it if found.
 657 *
 658 *      LOCKING:
 659 *      Kernel thread context (may sleep).  Grabs sysfs_mutex.
 660 *
 661 *      RETURNS:
 662 *      Pointer to sysfs_dirent if found, NULL if not.
 663 */
 664struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
 665                                      const void *ns,
 666                                      const unsigned char *name)
 667{
 668        struct sysfs_dirent *sd;
 669
 670        mutex_lock(&sysfs_mutex);
 671        sd = sysfs_find_dirent(parent_sd, ns, name);
 672        sysfs_get(sd);
 673        mutex_unlock(&sysfs_mutex);
 674
 675        return sd;
 676}
 677EXPORT_SYMBOL_GPL(sysfs_get_dirent);
 678
 679static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
 680        enum kobj_ns_type type, const void *ns, const char *name,
 681        struct sysfs_dirent **p_sd)
 682{
 683        umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
 684        struct sysfs_addrm_cxt acxt;
 685        struct sysfs_dirent *sd;
 686        int rc;
 687
 688        /* allocate */
 689        sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
 690        if (!sd)
 691                return -ENOMEM;
 692
 693        sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT);
 694        sd->s_ns = ns;
 695        sd->s_dir.kobj = kobj;
 696
 697        /* link in */
 698        sysfs_addrm_start(&acxt, parent_sd);
 699        rc = sysfs_add_one(&acxt, sd);
 700        sysfs_addrm_finish(&acxt);
 701
 702        if (rc == 0)
 703                *p_sd = sd;
 704        else
 705                sysfs_put(sd);
 706
 707        return rc;
 708}
 709
 710int sysfs_create_subdir(struct kobject *kobj, const char *name,
 711                        struct sysfs_dirent **p_sd)
 712{
 713        return create_dir(kobj, kobj->sd,
 714                          KOBJ_NS_TYPE_NONE, NULL, name, p_sd);
 715}
 716
 717/**
 718 *      sysfs_read_ns_type: return associated ns_type
 719 *      @kobj: the kobject being queried
 720 *
 721 *      Each kobject can be tagged with exactly one namespace type
 722 *      (i.e. network or user).  Return the ns_type associated with
 723 *      this object if any
 724 */
 725static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj)
 726{
 727        const struct kobj_ns_type_operations *ops;
 728        enum kobj_ns_type type;
 729
 730        ops = kobj_child_ns_ops(kobj);
 731        if (!ops)
 732                return KOBJ_NS_TYPE_NONE;
 733
 734        type = ops->type;
 735        BUG_ON(type <= KOBJ_NS_TYPE_NONE);
 736        BUG_ON(type >= KOBJ_NS_TYPES);
 737        BUG_ON(!kobj_ns_type_registered(type));
 738
 739        return type;
 740}
 741
 742/**
 743 *      sysfs_create_dir - create a directory for an object.
 744 *      @kobj:          object we're creating directory for. 
 745 */
 746int sysfs_create_dir(struct kobject * kobj)
 747{
 748        enum kobj_ns_type type;
 749        struct sysfs_dirent *parent_sd, *sd;
 750        const void *ns = NULL;
 751        int error = 0;
 752
 753        BUG_ON(!kobj);
 754
 755        if (kobj->parent)
 756                parent_sd = kobj->parent->sd;
 757        else
 758                parent_sd = &sysfs_root;
 759
 760        if (!parent_sd)
 761                return -ENOENT;
 762
 763        if (sysfs_ns_type(parent_sd))
 764                ns = kobj->ktype->namespace(kobj);
 765        type = sysfs_read_ns_type(kobj);
 766
 767        error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd);
 768        if (!error)
 769                kobj->sd = sd;
 770        return error;
 771}
 772
 773static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
 774                                unsigned int flags)
 775{
 776        struct dentry *ret = NULL;
 777        struct dentry *parent = dentry->d_parent;
 778        struct sysfs_dirent *parent_sd = parent->d_fsdata;
 779        struct sysfs_dirent *sd;
 780        struct inode *inode;
 781        enum kobj_ns_type type;
 782        const void *ns;
 783
 784        mutex_lock(&sysfs_mutex);
 785
 786        type = sysfs_ns_type(parent_sd);
 787        ns = sysfs_info(dir->i_sb)->ns[type];
 788
 789        sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name);
 790
 791        /* no such entry */
 792        if (!sd) {
 793                ret = ERR_PTR(-ENOENT);
 794                goto out_unlock;
 795        }
 796        dentry->d_fsdata = sysfs_get(sd);
 797
 798        /* attach dentry and inode */
 799        inode = sysfs_get_inode(dir->i_sb, sd);
 800        if (!inode) {
 801                ret = ERR_PTR(-ENOMEM);
 802                goto out_unlock;
 803        }
 804
 805        /* instantiate and hash dentry */
 806        ret = d_materialise_unique(dentry, inode);
 807 out_unlock:
 808        mutex_unlock(&sysfs_mutex);
 809        return ret;
 810}
 811
 812const struct inode_operations sysfs_dir_inode_operations = {
 813        .lookup         = sysfs_lookup,
 814        .permission     = sysfs_permission,
 815        .setattr        = sysfs_setattr,
 816        .getattr        = sysfs_getattr,
 817        .setxattr       = sysfs_setxattr,
 818};
 819
 820static void remove_dir(struct sysfs_dirent *sd)
 821{
 822        struct sysfs_addrm_cxt acxt;
 823
 824        sysfs_addrm_start(&acxt, sd->s_parent);
 825        sysfs_remove_one(&acxt, sd);
 826        sysfs_addrm_finish(&acxt);
 827}
 828
 829void sysfs_remove_subdir(struct sysfs_dirent *sd)
 830{
 831        remove_dir(sd);
 832}
 833
 834
 835static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
 836{
 837        struct sysfs_addrm_cxt acxt;
 838        struct rb_node *pos;
 839
 840        if (!dir_sd)
 841                return;
 842
 843        pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
 844        sysfs_addrm_start(&acxt, dir_sd);
 845        pos = rb_first(&dir_sd->s_dir.children);
 846        while (pos) {
 847                struct sysfs_dirent *sd = to_sysfs_dirent(pos);
 848                pos = rb_next(pos);
 849                if (sysfs_type(sd) != SYSFS_DIR)
 850                        sysfs_remove_one(&acxt, sd);
 851        }
 852        sysfs_addrm_finish(&acxt);
 853
 854        remove_dir(dir_sd);
 855}
 856
 857/**
 858 *      sysfs_remove_dir - remove an object's directory.
 859 *      @kobj:  object.
 860 *
 861 *      The only thing special about this is that we remove any files in
 862 *      the directory before we remove the directory, and we've inlined
 863 *      what used to be sysfs_rmdir() below, instead of calling separately.
 864 */
 865
 866void sysfs_remove_dir(struct kobject * kobj)
 867{
 868        struct sysfs_dirent *sd = kobj->sd;
 869
 870        spin_lock(&sysfs_assoc_lock);
 871        kobj->sd = NULL;
 872        spin_unlock(&sysfs_assoc_lock);
 873
 874        __sysfs_remove_dir(sd);
 875}
 876
 877int sysfs_rename(struct sysfs_dirent *sd,
 878        struct sysfs_dirent *new_parent_sd, const void *new_ns,
 879        const char *new_name)
 880{
 881        int error;
 882
 883        mutex_lock(&sysfs_mutex);
 884
 885        error = 0;
 886        if ((sd->s_parent == new_parent_sd) && (sd->s_ns == new_ns) &&
 887            (strcmp(sd->s_name, new_name) == 0))
 888                goto out;       /* nothing to rename */
 889
 890        error = -EEXIST;
 891        if (sysfs_find_dirent(new_parent_sd, new_ns, new_name))
 892                goto out;
 893
 894        /* rename sysfs_dirent */
 895        if (strcmp(sd->s_name, new_name) != 0) {
 896                error = -ENOMEM;
 897                new_name = kstrdup(new_name, GFP_KERNEL);
 898                if (!new_name)
 899                        goto out;
 900
 901                kfree(sd->s_name);
 902                sd->s_name = new_name;
 903        }
 904
 905        /* Move to the appropriate place in the appropriate directories rbtree. */
 906        sysfs_unlink_sibling(sd);
 907        sysfs_get(new_parent_sd);
 908        sysfs_put(sd->s_parent);
 909        sd->s_ns = new_ns;
 910        sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
 911        sd->s_parent = new_parent_sd;
 912        sysfs_link_sibling(sd);
 913
 914        error = 0;
 915 out:
 916        mutex_unlock(&sysfs_mutex);
 917        return error;
 918}
 919
 920int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
 921{
 922        struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
 923        const void *new_ns = NULL;
 924
 925        if (sysfs_ns_type(parent_sd))
 926                new_ns = kobj->ktype->namespace(kobj);
 927
 928        return sysfs_rename(kobj->sd, parent_sd, new_ns, new_name);
 929}
 930
 931int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
 932{
 933        struct sysfs_dirent *sd = kobj->sd;
 934        struct sysfs_dirent *new_parent_sd;
 935        const void *new_ns = NULL;
 936
 937        BUG_ON(!sd->s_parent);
 938        if (sysfs_ns_type(sd->s_parent))
 939                new_ns = kobj->ktype->namespace(kobj);
 940        new_parent_sd = new_parent_kobj && new_parent_kobj->sd ?
 941                new_parent_kobj->sd : &sysfs_root;
 942
 943        return sysfs_rename(sd, new_parent_sd, new_ns, sd->s_name);
 944}
 945
 946/* Relationship between s_mode and the DT_xxx types */
 947static inline unsigned char dt_type(struct sysfs_dirent *sd)
 948{
 949        return (sd->s_mode >> 12) & 15;
 950}
 951
 952static int sysfs_dir_release(struct inode *inode, struct file *filp)
 953{
 954        sysfs_put(filp->private_data);
 955        return 0;
 956}
 957
 958static struct sysfs_dirent *sysfs_dir_pos(const void *ns,
 959        struct sysfs_dirent *parent_sd, loff_t hash, struct sysfs_dirent *pos)
 960{
 961        if (pos) {
 962                int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
 963                        pos->s_parent == parent_sd &&
 964                        hash == pos->s_hash;
 965                sysfs_put(pos);
 966                if (!valid)
 967                        pos = NULL;
 968        }
 969        if (!pos && (hash > 1) && (hash < INT_MAX)) {
 970                struct rb_node *node = parent_sd->s_dir.children.rb_node;
 971                while (node) {
 972                        pos = to_sysfs_dirent(node);
 973
 974                        if (hash < pos->s_hash)
 975                                node = node->rb_left;
 976                        else if (hash > pos->s_hash)
 977                                node = node->rb_right;
 978                        else
 979                                break;
 980                }
 981        }
 982        /* Skip over entries in the wrong namespace */
 983        while (pos && pos->s_ns != ns) {
 984                struct rb_node *node = rb_next(&pos->s_rb);
 985                if (!node)
 986                        pos = NULL;
 987                else
 988                        pos = to_sysfs_dirent(node);
 989        }
 990        return pos;
 991}
 992
 993static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns,
 994        struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
 995{
 996        pos = sysfs_dir_pos(ns, parent_sd, ino, pos);
 997        if (pos) do {
 998                struct rb_node *node = rb_next(&pos->s_rb);
 999                if (!node)
1000                        pos = NULL;
1001                else
1002                        pos = to_sysfs_dirent(node);
1003        } while (pos && pos->s_ns != ns);
1004        return pos;
1005}
1006
1007static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
1008{
1009        struct dentry *dentry = filp->f_path.dentry;
1010        struct sysfs_dirent * parent_sd = dentry->d_fsdata;
1011        struct sysfs_dirent *pos = filp->private_data;
1012        enum kobj_ns_type type;
1013        const void *ns;
1014        ino_t ino;
1015
1016        type = sysfs_ns_type(parent_sd);
1017        ns = sysfs_info(dentry->d_sb)->ns[type];
1018
1019        if (filp->f_pos == 0) {
1020                ino = parent_sd->s_ino;
1021                if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0)
1022                        filp->f_pos++;
1023        }
1024        if (filp->f_pos == 1) {
1025                if (parent_sd->s_parent)
1026                        ino = parent_sd->s_parent->s_ino;
1027                else
1028                        ino = parent_sd->s_ino;
1029                if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
1030                        filp->f_pos++;
1031        }
1032        mutex_lock(&sysfs_mutex);
1033        for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
1034             pos;
1035             pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) {
1036                const char * name;
1037                unsigned int type;
1038                int len, ret;
1039
1040                name = pos->s_name;
1041                len = strlen(name);
1042                ino = pos->s_ino;
1043                type = dt_type(pos);
1044                filp->f_pos = pos->s_hash;
1045                filp->private_data = sysfs_get(pos);
1046
1047                mutex_unlock(&sysfs_mutex);
1048                ret = filldir(dirent, name, len, filp->f_pos, ino, type);
1049                mutex_lock(&sysfs_mutex);
1050                if (ret < 0)
1051                        break;
1052        }
1053        mutex_unlock(&sysfs_mutex);
1054        if ((filp->f_pos > 1) && !pos) { /* EOF */
1055                filp->f_pos = INT_MAX;
1056                filp->private_data = NULL;
1057        }
1058        return 0;
1059}
1060
1061
1062const struct file_operations sysfs_dir_operations = {
1063        .read           = generic_read_dir,
1064        .readdir        = sysfs_readdir,
1065        .release        = sysfs_dir_release,
1066        .llseek         = generic_file_llseek,
1067};
1068
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.