diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/debugfs/file.c | 12 | ||||
-rw-r--r-- | fs/debugfs/inode.c | 82 | ||||
-rw-r--r-- | fs/partitions/check.c | 9 |
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 | ||
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); |
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"); |