OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [debugfs/] [inode.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
 
30
#define DEBUGFS_MAGIC   0x64626720
31
 
32
/* declared over in file.c */
33
extern struct file_operations debugfs_file_operations;
34
extern struct inode_operations debugfs_link_operations;
35
 
36
static struct vfsmount *debugfs_mount;
37
static int debugfs_mount_count;
38
 
39
static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev)
40
{
41
        struct inode *inode = new_inode(sb);
42
 
43
        if (inode) {
44
                inode->i_mode = mode;
45
                inode->i_uid = 0;
46
                inode->i_gid = 0;
47
                inode->i_blocks = 0;
48
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
49
                switch (mode & S_IFMT) {
50
                default:
51
                        init_special_inode(inode, mode, dev);
52
                        break;
53
                case S_IFREG:
54
                        inode->i_fop = &debugfs_file_operations;
55
                        break;
56
                case S_IFLNK:
57
                        inode->i_op = &debugfs_link_operations;
58
                        break;
59
                case S_IFDIR:
60
                        inode->i_op = &simple_dir_inode_operations;
61
                        inode->i_fop = &simple_dir_operations;
62
 
63
                        /* directory inodes start off with i_nlink == 2
64
                         * (for "." entry) */
65
                        inc_nlink(inode);
66
                        break;
67
                }
68
        }
69
        return inode;
70
}
71
 
72
/* SMP-safe */
73
static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
74
                         int mode, dev_t dev)
75
{
76
        struct inode *inode;
77
        int error = -EPERM;
78
 
79
        if (dentry->d_inode)
80
                return -EEXIST;
81
 
82
        inode = debugfs_get_inode(dir->i_sb, mode, dev);
83
        if (inode) {
84
                d_instantiate(dentry, inode);
85
                dget(dentry);
86
                error = 0;
87
        }
88
        return error;
89
}
90
 
91
static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
92
{
93
        int res;
94
 
95
        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
96
        res = debugfs_mknod(dir, dentry, mode, 0);
97
        if (!res) {
98
                inc_nlink(dir);
99
                fsnotify_mkdir(dir, dentry);
100
        }
101
        return res;
102
}
103
 
104
static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
105
{
106
        mode = (mode & S_IALLUGO) | S_IFLNK;
107
        return debugfs_mknod(dir, dentry, mode, 0);
108
}
109
 
110
static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
111
{
112
        int res;
113
 
114
        mode = (mode & S_IALLUGO) | S_IFREG;
115
        res = debugfs_mknod(dir, dentry, mode, 0);
116
        if (!res)
117
                fsnotify_create(dir, dentry);
118
        return res;
119
}
120
 
121
static inline int debugfs_positive(struct dentry *dentry)
122
{
123
        return dentry->d_inode && !d_unhashed(dentry);
124
}
125
 
126
static int debug_fill_super(struct super_block *sb, void *data, int silent)
127
{
128
        static struct tree_descr debug_files[] = {{""}};
129
 
130
        return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
131
}
132
 
133
static int debug_get_sb(struct file_system_type *fs_type,
134
                        int flags, const char *dev_name,
135
                        void *data, struct vfsmount *mnt)
136
{
137
        return get_sb_single(fs_type, flags, data, debug_fill_super, mnt);
138
}
139
 
140
static struct file_system_type debug_fs_type = {
141
        .owner =        THIS_MODULE,
142
        .name =         "debugfs",
143
        .get_sb =       debug_get_sb,
144
        .kill_sb =      kill_litter_super,
145
};
146
 
147
static int debugfs_create_by_name(const char *name, mode_t mode,
148
                                  struct dentry *parent,
149
                                  struct dentry **dentry)
150
{
151
        int error = 0;
152
 
153
        /* If the parent is not specified, we create it in the root.
154
         * We need the root dentry to do this, which is in the super
155
         * block. A pointer to that is in the struct vfsmount that we
156
         * have around.
157
         */
158
        if (!parent) {
159
                if (debugfs_mount && debugfs_mount->mnt_sb) {
160
                        parent = debugfs_mount->mnt_sb->s_root;
161
                }
162
        }
163
        if (!parent) {
164
                pr_debug("debugfs: Ah! can not find a parent!\n");
165
                return -EFAULT;
166
        }
167
 
168
        *dentry = NULL;
169
        mutex_lock(&parent->d_inode->i_mutex);
170
        *dentry = lookup_one_len(name, parent, strlen(name));
171
        if (!IS_ERR(*dentry)) {
172
                switch (mode & S_IFMT) {
173
                case S_IFDIR:
174
                        error = debugfs_mkdir(parent->d_inode, *dentry, mode);
175
                        break;
176
                case S_IFLNK:
177
                        error = debugfs_link(parent->d_inode, *dentry, mode);
178
                        break;
179
                default:
180
                        error = debugfs_create(parent->d_inode, *dentry, mode);
181
                        break;
182
                }
183
                dput(*dentry);
184
        } else
185
                error = PTR_ERR(*dentry);
186
        mutex_unlock(&parent->d_inode->i_mutex);
187
 
188
        return error;
189
}
190
 
191
/**
192
 * debugfs_create_file - create a file in the debugfs filesystem
193
 * @name: a pointer to a string containing the name of the file to create.
194
 * @mode: the permission that the file should have
195
 * @parent: a pointer to the parent dentry for this file.  This should be a
196
 *          directory dentry if set.  If this paramater is NULL, then the
197
 *          file will be created in the root of the debugfs filesystem.
198
 * @data: a pointer to something that the caller will want to get to later
199
 *        on.  The inode.i_private pointer will point to this value on
200
 *        the open() call.
201
 * @fops: a pointer to a struct file_operations that should be used for
202
 *        this file.
203
 *
204
 * This is the basic "create a file" function for debugfs.  It allows for a
205
 * wide range of flexibility in createing a file, or a directory (if you
206
 * want to create a directory, the debugfs_create_dir() function is
207
 * recommended to be used instead.)
208
 *
209
 * This function will return a pointer to a dentry if it succeeds.  This
210
 * pointer must be passed to the debugfs_remove() function when the file is
211
 * to be removed (no automatic cleanup happens if your module is unloaded,
212
 * you are responsible here.)  If an error occurs, %NULL will be returned.
213
 *
214
 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
215
 * returned.
216
 */
217
struct dentry *debugfs_create_file(const char *name, mode_t mode,
218
                                   struct dentry *parent, void *data,
219
                                   const struct file_operations *fops)
220
{
221
        struct dentry *dentry = NULL;
222
        int error;
223
 
224
        pr_debug("debugfs: creating file '%s'\n",name);
225
 
226
        error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
227
                              &debugfs_mount_count);
228
        if (error)
229
                goto exit;
230
 
231
        error = debugfs_create_by_name(name, mode, parent, &dentry);
232
        if (error) {
233
                dentry = NULL;
234
                simple_release_fs(&debugfs_mount, &debugfs_mount_count);
235
                goto exit;
236
        }
237
 
238
        if (dentry->d_inode) {
239
                if (data)
240
                        dentry->d_inode->i_private = data;
241
                if (fops)
242
                        dentry->d_inode->i_fop = fops;
243
        }
244
exit:
245
        return dentry;
246
}
247
EXPORT_SYMBOL_GPL(debugfs_create_file);
248
 
249
/**
250
 * debugfs_create_dir - create a directory in the debugfs filesystem
251
 * @name: a pointer to a string containing the name of the directory to
252
 *        create.
253
 * @parent: a pointer to the parent dentry for this file.  This should be a
254
 *          directory dentry if set.  If this paramater is NULL, then the
255
 *          directory will be created in the root of the debugfs filesystem.
256
 *
257
 * This function creates a directory in debugfs with the given name.
258
 *
259
 * This function will return a pointer to a dentry if it succeeds.  This
260
 * pointer must be passed to the debugfs_remove() function when the file is
261
 * to be removed (no automatic cleanup happens if your module is unloaded,
262
 * you are responsible here.)  If an error occurs, %NULL will be returned.
263
 *
264
 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
265
 * returned.
266
 */
267
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
268
{
269
        return debugfs_create_file(name,
270
                                   S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
271
                                   parent, NULL, NULL);
272
}
273
EXPORT_SYMBOL_GPL(debugfs_create_dir);
274
 
275
/**
276
 * debugfs_create_symlink- create a symbolic link in the debugfs filesystem
277
 * @name: a pointer to a string containing the name of the symbolic link to
278
 *        create.
279
 * @parent: a pointer to the parent dentry for this symbolic link.  This
280
 *          should be a directory dentry if set.  If this paramater is NULL,
281
 *          then the symbolic link will be created in the root of the debugfs
282
 *          filesystem.
283
 * @target: a pointer to a string containing the path to the target of the
284
 *          symbolic link.
285
 *
286
 * This function creates a symbolic link with the given name in debugfs that
287
 * links to the given target path.
288
 *
289
 * This function will return a pointer to a dentry if it succeeds.  This
290
 * pointer must be passed to the debugfs_remove() function when the symbolic
291
 * link is to be removed (no automatic cleanup happens if your module is
292
 * unloaded, you are responsible here.)  If an error occurs, %NULL will be
293
 * returned.
294
 *
295
 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
296
 * returned.
297
 */
298
struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
299
                                      const char *target)
300
{
301
        struct dentry *result;
302
        char *link;
303
 
304
        link = kstrdup(target, GFP_KERNEL);
305
        if (!link)
306
                return NULL;
307
 
308
        result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
309
                                     NULL);
310
        if (!result)
311
                kfree(link);
312
        return result;
313
}
314
EXPORT_SYMBOL_GPL(debugfs_create_symlink);
315
 
316
/**
317
 * debugfs_remove - removes a file or directory from the debugfs filesystem
318
 * @dentry: a pointer to a the dentry of the file or directory to be
319
 *          removed.
320
 *
321
 * This function removes a file or directory in debugfs that was previously
322
 * created with a call to another debugfs function (like
323
 * debugfs_create_file() or variants thereof.)
324
 *
325
 * This function is required to be called in order for the file to be
326
 * removed, no automatic cleanup of files will happen when a module is
327
 * removed, you are responsible here.
328
 */
329
void debugfs_remove(struct dentry *dentry)
330
{
331
        struct dentry *parent;
332
        int ret = 0;
333
 
334
        if (!dentry)
335
                return;
336
 
337
        parent = dentry->d_parent;
338
        if (!parent || !parent->d_inode)
339
                return;
340
 
341
        mutex_lock(&parent->d_inode->i_mutex);
342
        if (debugfs_positive(dentry)) {
343
                if (dentry->d_inode) {
344
                        dget(dentry);
345
                        switch (dentry->d_inode->i_mode & S_IFMT) {
346
                        case S_IFDIR:
347
                                ret = simple_rmdir(parent->d_inode, dentry);
348
                                break;
349
                        case S_IFLNK:
350
                                kfree(dentry->d_inode->i_private);
351
                                /* fall through */
352
                        default:
353
                                simple_unlink(parent->d_inode, dentry);
354
                                break;
355
                        }
356
                        if (!ret)
357
                                d_delete(dentry);
358
                        dput(dentry);
359
                }
360
        }
361
        mutex_unlock(&parent->d_inode->i_mutex);
362
        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
363
}
364
EXPORT_SYMBOL_GPL(debugfs_remove);
365
 
366
/**
367
 * debugfs_rename - rename a file/directory in the debugfs filesystem
368
 * @old_dir: a pointer to the parent dentry for the renamed object. This
369
 *          should be a directory dentry.
370
 * @old_dentry: dentry of an object to be renamed.
371
 * @new_dir: a pointer to the parent dentry where the object should be
372
 *          moved. This should be a directory dentry.
373
 * @new_name: a pointer to a string containing the target name.
374
 *
375
 * This function renames a file/directory in debugfs.  The target must not
376
 * exist for rename to succeed.
377
 *
378
 * This function will return a pointer to old_dentry (which is updated to
379
 * reflect renaming) if it succeeds. If an error occurs, %NULL will be
380
 * returned.
381
 *
382
 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
383
 * returned.
384
 */
385
struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
386
                struct dentry *new_dir, const char *new_name)
387
{
388
        int error;
389
        struct dentry *dentry = NULL, *trap;
390
        const char *old_name;
391
 
392
        trap = lock_rename(new_dir, old_dir);
393
        /* Source or destination directories don't exist? */
394
        if (!old_dir->d_inode || !new_dir->d_inode)
395
                goto exit;
396
        /* Source does not exist, cyclic rename, or mountpoint? */
397
        if (!old_dentry->d_inode || old_dentry == trap ||
398
            d_mountpoint(old_dentry))
399
                goto exit;
400
        dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
401
        /* Lookup failed, cyclic rename or target exists? */
402
        if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
403
                goto exit;
404
 
405
        old_name = fsnotify_oldname_init(old_dentry->d_name.name);
406
 
407
        error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
408
                dentry);
409
        if (error) {
410
                fsnotify_oldname_free(old_name);
411
                goto exit;
412
        }
413
        d_move(old_dentry, dentry);
414
        fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
415
                old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
416
                NULL, old_dentry);
417
        fsnotify_oldname_free(old_name);
418
        unlock_rename(new_dir, old_dir);
419
        dput(dentry);
420
        return old_dentry;
421
exit:
422
        if (dentry && !IS_ERR(dentry))
423
                dput(dentry);
424
        unlock_rename(new_dir, old_dir);
425
        return NULL;
426
}
427
EXPORT_SYMBOL_GPL(debugfs_rename);
428
 
429
static decl_subsys(debug, NULL, NULL);
430
 
431
static int __init debugfs_init(void)
432
{
433
        int retval;
434
 
435
        kobj_set_kset_s(&debug_subsys, kernel_subsys);
436
        retval = subsystem_register(&debug_subsys);
437
        if (retval)
438
                return retval;
439
 
440
        retval = register_filesystem(&debug_fs_type);
441
        if (retval)
442
                subsystem_unregister(&debug_subsys);
443
        return retval;
444
}
445
 
446
static void __exit debugfs_exit(void)
447
{
448
        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
449
        unregister_filesystem(&debug_fs_type);
450
        subsystem_unregister(&debug_subsys);
451
}
452
 
453
core_initcall(debugfs_init);
454
module_exit(debugfs_exit);
455
MODULE_LICENSE("GPL");
456
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.