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