linux/fs/debugfs/inode.c
<<
>>
Prefs
   1/*
   2 *  file.c - part of debugfs, a tiny little debug file system
   3 *
   4 *  Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
   5 *  Copyright (C) 2004 IBM Inc.
   6 *
   7 *      This program is free software; you can redistribute it and/or
   8 *      modify it under the terms of the GNU General Public License version
   9 *      2 as published by the Free Software Foundation.
  10 *
  11 *  debugfs is for people to use instead of /proc or /sys.
  12 *  See Documentation/DocBook/kernel-api for more details.
  13 *
  14 */
  15
  16/* uncomment to get debug messages from the debug filesystem, ah the irony. */
  17/* #define DEBUG */
  18
  19#include <linux/module.h>
  20#include <linux/fs.h>
  21#include <linux/mount.h>
  22#include <linux/pagemap.h>
  23#include <linux/init.h>
  24#include <linux/kobject.h>
  25#include <linux/namei.h>
  26#include <linux/debugfs.h>
  27#include <linux/fsnotify.h>
  28#include <linux/string.h>
  29#include <linux/magic.h>
  30
  31static struct vfsmount *debugfs_mount;
  32static int debugfs_mount_count;
  33
  34static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev)
  35{
  36        struct inode *inode = new_inode(sb);
  37
  38        if (inode) {
  39                inode->i_mode = mode;
  40                inode->i_uid = 0;
  41                inode->i_gid = 0;
  42                inode->i_blocks = 0;
  43                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  44                switch (mode & S_IFMT) {
  45                default:
  46                        init_special_inode(inode, mode, dev);
  47                        break;
  48                case S_IFREG:
  49                        inode->i_fop = &debugfs_file_operations;
  50                        break;
  51                case S_IFLNK:
  52                        inode->i_op = &debugfs_link_operations;
  53                        break;
  54                case S_IFDIR:
  55                        inode->i_op = &simple_dir_inode_operations;
  56                        inode->i_fop = &simple_dir_operations;
  57
  58                        /* directory inodes start off with i_nlink == 2
  59                         * (for "." entry) */
  60                        inc_nlink(inode);
  61                        break;
  62                }
  63        }
  64        return inode; 
  65}
  66
  67/* SMP-safe */
  68static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
  69                         int mode, dev_t dev)
  70{
  71        struct inode *inode;
  72        int error = -EPERM;
  73
  74        if (dentry->d_inode)
  75                return -EEXIST;
  76
  77        inode = debugfs_get_inode(dir->i_sb, mode, dev);
  78        if (inode) {
  79                d_instantiate(dentry, inode);
  80                dget(dentry);
  81                error = 0;
  82        }
  83        return error;
  84}
  85
  86static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  87{
  88        int res;
  89
  90        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
  91        res = debugfs_mknod(dir, dentry, mode, 0);
  92        if (!res) {
  93                inc_nlink(dir);
  94                fsnotify_mkdir(dir, dentry);
  95        }
  96        return res;
  97}
  98
  99static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
 100{
 101        mode = (mode & S_IALLUGO) | S_IFLNK;
 102        return debugfs_mknod(dir, dentry, mode, 0);
 103}
 104
 105static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
 106{
 107        int res;
 108
 109        mode = (mode & S_IALLUGO) | S_IFREG;
 110        res = debugfs_mknod(dir, dentry, mode, 0);
 111        if (!res)
 112                fsnotify_create(dir, dentry);
 113        return res;
 114}
 115
 116static inline int debugfs_positive(struct dentry *dentry)
 117{
 118        return dentry->d_inode && !d_unhashed(dentry);
 119}
 120
 121static int debug_fill_super(struct super_block *sb, void *data, int silent)
 122{
 123        static struct tree_descr debug_files[] = {{""}};
 124
 125        return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
 126}
 127
 128static int debug_get_sb(struct file_system_type *fs_type,
 129                        int flags, const char *dev_name,
 130                        void *data, struct vfsmount *mnt)
 131{
 132        return get_sb_single(fs_type, flags, data, debug_fill_super, mnt);
 133}
 134
 135static struct file_system_type debug_fs_type = {
 136        .owner =        THIS_MODULE,
 137        .name =         "debugfs",
 138        .get_sb =       debug_get_sb,
 139        .kill_sb =      kill_litter_super,
 140};
 141
 142static int debugfs_create_by_name(const char *name, mode_t mode,
 143                                  struct dentry *parent,
 144                                  struct dentry **dentry)
 145{
 146        int error = 0;
 147
 148        /* If the parent is not specified, we create it in the root.
 149         * We need the root dentry to do this, which is in the super 
 150         * block. A pointer to that is in the struct vfsmount that we
 151         * have around.
 152         */
 153        if (!parent) {
 154                if (debugfs_mount && debugfs_mount->mnt_sb) {
 155                        parent = debugfs_mount->mnt_sb->s_root;
 156                }
 157        }
 158        if (!parent) {
 159                pr_debug("debugfs: Ah! can not find a parent!\n");
 160                return -EFAULT;
 161        }
 162
 163        *dentry = NULL;
 164        mutex_lock(&parent->d_inode->i_mutex);
 165        *dentry = lookup_one_len(name, parent, strlen(name));
 166        if (!IS_ERR(*dentry)) {
 167                switch (mode & S_IFMT) {
 168                case S_IFDIR:
 169                        error = debugfs_mkdir(parent->d_inode, *dentry, mode);
 170                        break;
 171                case S_IFLNK:
 172                        error = debugfs_link(parent->d_inode, *dentry, mode);
 173                        break;
 174                default:
 175                        error = debugfs_create(parent->d_inode, *dentry, mode);
 176                        break;
 177                }
 178                dput(*dentry);
 179        } else
 180                error = PTR_ERR(*dentry);
 181        mutex_unlock(&parent->d_inode->i_mutex);
 182
 183        return error;
 184}
 185
 186/**
 187 * debugfs_create_file - create a file in the debugfs filesystem
 188 * @name: a pointer to a string containing the name of the file to create.
 189 * @mode: the permission that the file should have
 190 * @parent: a pointer to the parent dentry for this file.  This should be a
 191 *          directory dentry if set.  If this paramater is NULL, then the
 192 *          file will be created in the root of the debugfs filesystem.
 193 * @data: a pointer to something that the caller will want to get to later
 194 *        on.  The inode.i_private pointer will point to this value on
 195 *        the open() call.
 196 * @fops: a pointer to a struct file_operations that should be used for
 197 *        this file.
 198 *
 199 * This is the basic "create a file" function for debugfs.  It allows for a
 200 * wide range of flexibility in createing a file, or a directory (if you
 201 * want to create a directory, the debugfs_create_dir() function is
 202 * recommended to be used instead.)
 203 *
 204 * This function will return a pointer to a dentry if it succeeds.  This
 205 * pointer must be passed to the debugfs_remove() function when the file is
 206 * to be removed (no automatic cleanup happens if your module is unloaded,
 207 * you are responsible here.)  If an error occurs, %NULL will be returned.
 208 *
 209 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
 210 * returned.
 211 */
 212struct dentry *debugfs_create_file(const char *name, mode_t mode,
 213                                   struct dentry *parent, void *data,
 214                                   const struct file_operations *fops)
 215{
 216        struct dentry *dentry = NULL;
 217        int error;
 218
 219        pr_debug("debugfs: creating file '%s'\n",name);
 220
 221        error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
 222                              &debugfs_mount_count);
 223        if (error)
 224                goto exit;
 225
 226        error = debugfs_create_by_name(name, mode, parent, &dentry);
 227        if (error) {
 228                dentry = NULL;
 229                simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 230                goto exit;
 231        }
 232
 233        if (dentry->d_inode) {
 234                if (data)
 235                        dentry->d_inode->i_private = data;
 236                if (fops)
 237                        dentry->d_inode->i_fop = fops;
 238        }
 239exit:
 240        return dentry;
 241}
 242EXPORT_SYMBOL_GPL(debugfs_create_file);
 243
 244/**
 245 * debugfs_create_dir - create a directory in the debugfs filesystem
 246 * @name: a pointer to a string containing the name of the directory to
 247 *        create.
 248 * @parent: a pointer to the parent dentry for this file.  This should be a
 249 *          directory dentry if set.  If this paramater is NULL, then the
 250 *          directory will be created in the root of the debugfs filesystem.
 251 *
 252 * This function creates a directory in debugfs with the given name.
 253 *
 254 * This function will return a pointer to a dentry if it succeeds.  This
 255 * pointer must be passed to the debugfs_remove() function when the file is
 256 * to be removed (no automatic cleanup happens if your module is unloaded,
 257 * you are responsible here.)  If an error occurs, %NULL will be returned.
 258 *
 259 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
 260 * returned.
 261 */
 262struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 263{
 264        return debugfs_create_file(name, 
 265                                   S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
 266                                   parent, NULL, NULL);
 267}
 268EXPORT_SYMBOL_GPL(debugfs_create_dir);
 269
 270/**
 271 * debugfs_create_symlink- create a symbolic link in the debugfs filesystem
 272 * @name: a pointer to a string containing the name of the symbolic link to
 273 *        create.
 274 * @parent: a pointer to the parent dentry for this symbolic link.  This
 275 *          should be a directory dentry if set.  If this paramater is NULL,
 276 *          then the symbolic link will be created in the root of the debugfs
 277 *          filesystem.
 278 * @target: a pointer to a string containing the path to the target of the
 279 *          symbolic link.
 280 *
 281 * This function creates a symbolic link with the given name in debugfs that
 282 * links to the given target path.
 283 *
 284 * This function will return a pointer to a dentry if it succeeds.  This
 285 * pointer must be passed to the debugfs_remove() function when the symbolic
 286 * link is to be removed (no automatic cleanup happens if your module is
 287 * unloaded, you are responsible here.)  If an error occurs, %NULL will be
 288 * returned.
 289 *
 290 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
 291 * returned.
 292 */
 293struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
 294                                      const char *target)
 295{
 296        struct dentry *result;
 297        char *link;
 298
 299        link = kstrdup(target, GFP_KERNEL);
 300        if (!link)
 301                return NULL;
 302
 303        result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
 304                                     NULL);
 305        if (!result)
 306                kfree(link);
 307        return result;
 308}
 309EXPORT_SYMBOL_GPL(debugfs_create_symlink);
 310
 311static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)
 312{
 313        int ret = 0;
 314
 315        if (debugfs_positive(dentry)) {
 316                if (dentry->d_inode) {
 317                        dget(dentry);
 318                        switch (dentry->d_inode->i_mode & S_IFMT) {
 319                        case S_IFDIR:
 320                                ret = simple_rmdir(parent->d_inode, dentry);
 321                                break;
 322                        case S_IFLNK:
 323                                kfree(dentry->d_inode->i_private);
 324                                /* fall through */
 325                        default:
 326                                simple_unlink(parent->d_inode, dentry);
 327                                break;
 328                        }
 329                        if (!ret)
 330                                d_delete(dentry);
 331                        dput(dentry);
 332                }
 333        }
 334}
 335
 336/**
 337 * debugfs_remove - removes a file or directory from the debugfs filesystem
 338 * @dentry: a pointer to a the dentry of the file or directory to be
 339 *          removed.
 340 *
 341 * This function removes a file or directory in debugfs that was previously
 342 * created with a call to another debugfs function (like
 343 * debugfs_create_file() or variants thereof.)
 344 *
 345 * This function is required to be called in order for the file to be
 346 * removed, no automatic cleanup of files will happen when a module is
 347 * removed, you are responsible here.
 348 */
 349void debugfs_remove(struct dentry *dentry)
 350{
 351        struct dentry *parent;
 352        
 353        if (!dentry)
 354                return;
 355
 356        parent = dentry->d_parent;
 357        if (!parent || !parent->d_inode)
 358                return;
 359
 360        mutex_lock(&parent->d_inode->i_mutex);
 361        __debugfs_remove(dentry, parent);
 362        mutex_unlock(&parent->d_inode->i_mutex);
 363        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 364}
 365EXPORT_SYMBOL_GPL(debugfs_remove);
 366
 367/**
 368 * debugfs_remove_recursive - recursively removes a directory
 369 * @dentry: a pointer to a the dentry of the directory to be removed.
 370 *
 371 * This function recursively removes a directory tree in debugfs that
 372 * was previously created with a call to another debugfs function
 373 * (like debugfs_create_file() or variants thereof.)
 374 *
 375 * This function is required to be called in order for the file to be
 376 * removed, no automatic cleanup of files will happen when a module is
 377 * removed, you are responsible here.
 378 */
 379void debugfs_remove_recursive(struct dentry *dentry)
 380{
 381        struct dentry *child;
 382        struct dentry *parent;
 383
 384        if (!dentry)
 385                return;
 386
 387        parent = dentry->d_parent;
 388        if (!parent || !parent->d_inode)
 389                return;
 390
 391        parent = dentry;
 392        mutex_lock(&parent->d_inode->i_mutex);
 393
 394        while (1) {
 395                /*
 396                 * When all dentries under "parent" has been removed,
 397                 * walk up the tree until we reach our starting point.
 398                 */
 399                if (list_empty(&parent->d_subdirs)) {
 400                        mutex_unlock(&parent->d_inode->i_mutex);
 401                        if (parent == dentry)
 402                                break;
 403                        parent = parent->d_parent;
 404                        mutex_lock(&parent->d_inode->i_mutex);
 405                }
 406                child = list_entry(parent->d_subdirs.next, struct dentry,
 407                                d_u.d_child);
 408
 409                /*
 410                 * If "child" isn't empty, walk down the tree and
 411                 * remove all its descendants first.
 412                 */
 413                if (!list_empty(&child->d_subdirs)) {
 414                        mutex_unlock(&parent->d_inode->i_mutex);
 415                        parent = child;
 416                        mutex_lock(&parent->d_inode->i_mutex);
 417                        continue;
 418                }
 419                __debugfs_remove(child, parent);
 420                if (parent->d_subdirs.next == &child->d_u.d_child) {
 421                        /*
 422                         * Avoid infinite loop if we fail to remove
 423                         * one dentry.
 424                         */
 425                        mutex_unlock(&parent->d_inode->i_mutex);
 426                        break;
 427                }
 428                simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 429        }
 430
 431        parent = dentry->d_parent;
 432        mutex_lock(&parent->d_inode->i_mutex);
 433        __debugfs_remove(dentry, parent);
 434        mutex_unlock(&parent->d_inode->i_mutex);
 435        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 436}
 437EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
 438
 439/**
 440 * debugfs_rename - rename a file/directory in the debugfs filesystem
 441 * @old_dir: a pointer to the parent dentry for the renamed object. This
 442 *          should be a directory dentry.
 443 * @old_dentry: dentry of an object to be renamed.
 444 * @new_dir: a pointer to the parent dentry where the object should be
 445 *          moved. This should be a directory dentry.
 446 * @new_name: a pointer to a string containing the target name.
 447 *
 448 * This function renames a file/directory in debugfs.  The target must not
 449 * exist for rename to succeed.
 450 *
 451 * This function will return a pointer to old_dentry (which is updated to
 452 * reflect renaming) if it succeeds. If an error occurs, %NULL will be
 453 * returned.
 454 *
 455 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
 456 * returned.
 457 */
 458struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
 459                struct dentry *new_dir, const char *new_name)
 460{
 461        int error;
 462        struct dentry *dentry = NULL, *trap;
 463        const char *old_name;
 464
 465        trap = lock_rename(new_dir, old_dir);
 466        /* Source or destination directories don't exist? */
 467        if (!old_dir->d_inode || !new_dir->d_inode)
 468                goto exit;
 469        /* Source does not exist, cyclic rename, or mountpoint? */
 470        if (!old_dentry->d_inode || old_dentry == trap ||
 471            d_mountpoint(old_dentry))
 472                goto exit;
 473        dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
 474        /* Lookup failed, cyclic rename or target exists? */
 475        if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
 476                goto exit;
 477
 478        old_name = fsnotify_oldname_init(old_dentry->d_name.name);
 479
 480        error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
 481                dentry);
 482        if (error) {
 483                fsnotify_oldname_free(old_name);
 484                goto exit;
 485        }
 486        d_move(old_dentry, dentry);
 487        fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
 488                old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
 489                NULL, old_dentry);
 490        fsnotify_oldname_free(old_name);
 491        unlock_rename(new_dir, old_dir);
 492        dput(dentry);
 493        return old_dentry;
 494exit:
 495        if (dentry && !IS_ERR(dentry))
 496                dput(dentry);
 497        unlock_rename(new_dir, old_dir);
 498        return NULL;
 499}
 500EXPORT_SYMBOL_GPL(debugfs_rename);
 501
 502static struct kobject *debug_kobj;
 503
 504static int __init debugfs_init(void)
 505{
 506        int retval;
 507
 508        debug_kobj = kobject_create_and_add("debug", kernel_kobj);
 509        if (!debug_kobj)
 510                return -EINVAL;
 511
 512        retval = register_filesystem(&debug_fs_type);
 513        if (retval)
 514                kobject_put(debug_kobj);
 515        return retval;
 516}
 517
 518static void __exit debugfs_exit(void)
 519{
 520        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 521        unregister_filesystem(&debug_fs_type);
 522        kobject_put(debug_kobj);
 523}
 524
 525core_initcall(debugfs_init);
 526module_exit(debugfs_exit);
 527MODULE_LICENSE("GPL");
 528
 529
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.