aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/debugfs/file.c12
-rw-r--r--fs/debugfs/inode.c82
-rw-r--r--fs/partitions/check.c9
3 files changed, 87 insertions, 16 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
21static ssize_t default_read_file(struct file *file, char __user *buf, 22static 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
48static 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
54const struct inode_operations debugfs_link_operations = {
55 .readlink = generic_readlink,
56 .follow_link = debugfs_follow_link,
57};
58
47static void debugfs_u8_set(void *data, u64 val) 59static 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 */
32extern struct file_operations debugfs_file_operations; 33extern struct file_operations debugfs_file_operations;
34extern struct inode_operations debugfs_link_operations;
33 35
34static struct vfsmount *debugfs_mount; 36static struct vfsmount *debugfs_mount;
35static int debugfs_mount_count; 37static 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
104static 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
99static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) 110static 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 */
201struct dentry *debugfs_create_file(const char *name, mode_t mode, 217struct 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 */
253struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) 267struct 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)
259EXPORT_SYMBOL_GPL(debugfs_create_dir); 273EXPORT_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 */
298struct 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}
314EXPORT_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);
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index ac32a2e8540c..22d38ffc9ef0 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -358,8 +358,7 @@ void delete_partition(struct gendisk *disk, int part)
358 p->ios[0] = p->ios[1] = 0; 358 p->ios[0] = p->ios[1] = 0;
359 p->sectors[0] = p->sectors[1] = 0; 359 p->sectors[0] = p->sectors[1] = 0;
360 sysfs_remove_link(&p->kobj, "subsystem"); 360 sysfs_remove_link(&p->kobj, "subsystem");
361 if (p->holder_dir) 361 kobject_unregister(p->holder_dir);
362 kobject_unregister(p->holder_dir);
363 kobject_uevent(&p->kobj, KOBJ_REMOVE); 362 kobject_uevent(&p->kobj, KOBJ_REMOVE);
364 kobject_del(&p->kobj); 363 kobject_del(&p->kobj);
365 kobject_put(&p->kobj); 364 kobject_put(&p->kobj);
@@ -603,10 +602,8 @@ void del_gendisk(struct gendisk *disk)
603 disk->stamp = 0; 602 disk->stamp = 0;
604 603
605 kobject_uevent(&disk->kobj, KOBJ_REMOVE); 604 kobject_uevent(&disk->kobj, KOBJ_REMOVE);
606 if (disk->holder_dir) 605 kobject_unregister(disk->holder_dir);
607 kobject_unregister(disk->holder_dir); 606 kobject_unregister(disk->slave_dir);
608 if (disk->slave_dir)
609 kobject_unregister(disk->slave_dir);
610 if (disk->driverfs_dev) { 607 if (disk->driverfs_dev) {
611 char *disk_name = make_block_name(disk); 608 char *disk_name = make_block_name(disk);
612 sysfs_remove_link(&disk->kobj, "device"); 609 sysfs_remove_link(&disk->kobj, "device");