diff options
Diffstat (limited to 'fs/debugfs')
| -rw-r--r-- | fs/debugfs/file.c | 12 | ||||
| -rw-r--r-- | fs/debugfs/inode.c | 82 |
2 files changed, 84 insertions, 10 deletions
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 8d130cc85322..682f928b7f4d 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
| 18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 19 | #include <linux/namei.h> | ||
| 19 | #include <linux/debugfs.h> | 20 | #include <linux/debugfs.h> |
| 20 | 21 | ||
| 21 | static ssize_t default_read_file(struct file *file, char __user *buf, | 22 | static ssize_t default_read_file(struct file *file, char __user *buf, |
| @@ -44,6 +45,17 @@ const struct file_operations debugfs_file_operations = { | |||
| 44 | .open = default_open, | 45 | .open = default_open, |
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 48 | static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
| 49 | { | ||
| 50 | nd_set_link(nd, dentry->d_inode->i_private); | ||
| 51 | return NULL; | ||
| 52 | } | ||
| 53 | |||
| 54 | const struct inode_operations debugfs_link_operations = { | ||
| 55 | .readlink = generic_readlink, | ||
| 56 | .follow_link = debugfs_follow_link, | ||
| 57 | }; | ||
| 58 | |||
| 47 | static void debugfs_u8_set(void *data, u64 val) | 59 | static void debugfs_u8_set(void *data, u64 val) |
| 48 | { | 60 | { |
| 49 | *(u8 *)data = val; | 61 | *(u8 *)data = val; |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index c692487346ea..7b324cfebcb1 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
| @@ -25,11 +25,13 @@ | |||
| 25 | #include <linux/namei.h> | 25 | #include <linux/namei.h> |
| 26 | #include <linux/debugfs.h> | 26 | #include <linux/debugfs.h> |
| 27 | #include <linux/fsnotify.h> | 27 | #include <linux/fsnotify.h> |
| 28 | #include <linux/string.h> | ||
| 28 | 29 | ||
| 29 | #define DEBUGFS_MAGIC 0x64626720 | 30 | #define DEBUGFS_MAGIC 0x64626720 |
| 30 | 31 | ||
| 31 | /* declared over in file.c */ | 32 | /* declared over in file.c */ |
| 32 | extern struct file_operations debugfs_file_operations; | 33 | extern struct file_operations debugfs_file_operations; |
| 34 | extern struct inode_operations debugfs_link_operations; | ||
| 33 | 35 | ||
| 34 | static struct vfsmount *debugfs_mount; | 36 | static struct vfsmount *debugfs_mount; |
| 35 | static int debugfs_mount_count; | 37 | static int debugfs_mount_count; |
| @@ -51,6 +53,9 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d | |||
| 51 | case S_IFREG: | 53 | case S_IFREG: |
| 52 | inode->i_fop = &debugfs_file_operations; | 54 | inode->i_fop = &debugfs_file_operations; |
| 53 | break; | 55 | break; |
| 56 | case S_IFLNK: | ||
| 57 | inode->i_op = &debugfs_link_operations; | ||
| 58 | break; | ||
| 54 | case S_IFDIR: | 59 | case S_IFDIR: |
| 55 | inode->i_op = &simple_dir_inode_operations; | 60 | inode->i_op = &simple_dir_inode_operations; |
| 56 | inode->i_fop = &simple_dir_operations; | 61 | inode->i_fop = &simple_dir_operations; |
| @@ -96,6 +101,12 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 96 | return res; | 101 | return res; |
| 97 | } | 102 | } |
| 98 | 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 | |||
| 99 | static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) | 110 | static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) |
| 100 | { | 111 | { |
| 101 | int res; | 112 | int res; |
| @@ -158,10 +169,17 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
| 158 | mutex_lock(&parent->d_inode->i_mutex); | 169 | mutex_lock(&parent->d_inode->i_mutex); |
| 159 | *dentry = lookup_one_len(name, parent, strlen(name)); | 170 | *dentry = lookup_one_len(name, parent, strlen(name)); |
| 160 | if (!IS_ERR(*dentry)) { | 171 | if (!IS_ERR(*dentry)) { |
| 161 | if ((mode & S_IFMT) == S_IFDIR) | 172 | switch (mode & S_IFMT) { |
| 173 | case S_IFDIR: | ||
| 162 | error = debugfs_mkdir(parent->d_inode, *dentry, mode); | 174 | error = debugfs_mkdir(parent->d_inode, *dentry, mode); |
| 163 | else | 175 | break; |
| 176 | case S_IFLNK: | ||
| 177 | error = debugfs_link(parent->d_inode, *dentry, mode); | ||
| 178 | break; | ||
| 179 | default: | ||
| 164 | error = debugfs_create(parent->d_inode, *dentry, mode); | 180 | error = debugfs_create(parent->d_inode, *dentry, mode); |
| 181 | break; | ||
| 182 | } | ||
| 165 | dput(*dentry); | 183 | dput(*dentry); |
| 166 | } else | 184 | } else |
| 167 | error = PTR_ERR(*dentry); | 185 | error = PTR_ERR(*dentry); |
| @@ -194,9 +212,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
| 194 | * you are responsible here.) If an error occurs, %NULL will be returned. | 212 | * you are responsible here.) If an error occurs, %NULL will be returned. |
| 195 | * | 213 | * |
| 196 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | 214 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
| 197 | * returned. It is not wise to check for this value, but rather, check for | 215 | * returned. |
| 198 | * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling | ||
| 199 | * code. | ||
| 200 | */ | 216 | */ |
| 201 | struct dentry *debugfs_create_file(const char *name, mode_t mode, | 217 | struct dentry *debugfs_create_file(const char *name, mode_t mode, |
| 202 | struct dentry *parent, void *data, | 218 | struct dentry *parent, void *data, |
| @@ -246,9 +262,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); | |||
| 246 | * you are responsible here.) If an error occurs, %NULL will be returned. | 262 | * you are responsible here.) If an error occurs, %NULL will be returned. |
| 247 | * | 263 | * |
| 248 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | 264 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
| 249 | * returned. It is not wise to check for this value, but rather, check for | 265 | * returned. |
| 250 | * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling | ||
| 251 | * code. | ||
| 252 | */ | 266 | */ |
| 253 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) | 267 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) |
| 254 | { | 268 | { |
| @@ -259,6 +273,47 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) | |||
| 259 | EXPORT_SYMBOL_GPL(debugfs_create_dir); | 273 | EXPORT_SYMBOL_GPL(debugfs_create_dir); |
| 260 | 274 | ||
| 261 | /** | 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 | /** | ||
| 262 | * debugfs_remove - removes a file or directory from the debugfs filesystem | 317 | * debugfs_remove - removes a file or directory from the debugfs filesystem |
| 263 | * @dentry: a pointer to a the dentry of the file or directory to be | 318 | * @dentry: a pointer to a the dentry of the file or directory to be |
| 264 | * removed. | 319 | * removed. |
| @@ -287,15 +342,22 @@ void debugfs_remove(struct dentry *dentry) | |||
| 287 | if (debugfs_positive(dentry)) { | 342 | if (debugfs_positive(dentry)) { |
| 288 | if (dentry->d_inode) { | 343 | if (dentry->d_inode) { |
| 289 | dget(dentry); | 344 | dget(dentry); |
| 290 | if (S_ISDIR(dentry->d_inode->i_mode)) { | 345 | switch (dentry->d_inode->i_mode & S_IFMT) { |
| 346 | case S_IFDIR: | ||
| 291 | ret = simple_rmdir(parent->d_inode, dentry); | 347 | ret = simple_rmdir(parent->d_inode, dentry); |
| 292 | if (ret) | 348 | if (ret) |
| 293 | printk(KERN_ERR | 349 | printk(KERN_ERR |
| 294 | "DebugFS rmdir on %s failed : " | 350 | "DebugFS rmdir on %s failed : " |
| 295 | "directory not empty.\n", | 351 | "directory not empty.\n", |
| 296 | dentry->d_name.name); | 352 | dentry->d_name.name); |
| 297 | } else | 353 | break; |
| 354 | case S_IFLNK: | ||
| 355 | kfree(dentry->d_inode->i_private); | ||
| 356 | /* fall through */ | ||
| 357 | default: | ||
| 298 | simple_unlink(parent->d_inode, dentry); | 358 | simple_unlink(parent->d_inode, dentry); |
| 359 | break; | ||
| 360 | } | ||
| 299 | if (!ret) | 361 | if (!ret) |
| 300 | d_delete(dentry); | 362 | d_delete(dentry); |
| 301 | dput(dentry); | 363 | dput(dentry); |
