diff options
| author | Jan Kara <jack@suse.cz> | 2007-05-09 07:19:52 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:09:00 -0400 |
| commit | cfc94cdf8e0f14e692a5a40ef3cc10f464b2511b (patch) | |
| tree | 041391e492d909e41e70ac67da53a1025ecf629d /fs/debugfs | |
| parent | 46336009b5009e9fab3bd623a3beb9c7421545ac (diff) | |
debugfs: add rename for debugfs files
Implement debugfs_rename() to allow renaming files/directories in debugfs.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/debugfs')
| -rw-r--r-- | fs/debugfs/inode.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index ec8896b264de..1d533a2ec3a6 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
| @@ -368,6 +368,69 @@ void debugfs_remove(struct dentry *dentry) | |||
| 368 | } | 368 | } |
| 369 | EXPORT_SYMBOL_GPL(debugfs_remove); | 369 | EXPORT_SYMBOL_GPL(debugfs_remove); |
| 370 | 370 | ||
| 371 | /** | ||
| 372 | * debugfs_rename - rename a file/directory in the debugfs filesystem | ||
| 373 | * @old_dir: a pointer to the parent dentry for the renamed object. This | ||
| 374 | * should be a directory dentry. | ||
| 375 | * @old_dentry: dentry of an object to be renamed. | ||
| 376 | * @new_dir: a pointer to the parent dentry where the object should be | ||
| 377 | * moved. This should be a directory dentry. | ||
| 378 | * @new_name: a pointer to a string containing the target name. | ||
| 379 | * | ||
| 380 | * This function renames a file/directory in debugfs. The target must not | ||
| 381 | * exist for rename to succeed. | ||
| 382 | * | ||
| 383 | * This function will return a pointer to old_dentry (which is updated to | ||
| 384 | * reflect renaming) if it succeeds. If an error occurs, %NULL will be | ||
| 385 | * returned. | ||
| 386 | * | ||
| 387 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | ||
| 388 | * returned. | ||
| 389 | */ | ||
| 390 | struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | ||
| 391 | struct dentry *new_dir, const char *new_name) | ||
| 392 | { | ||
| 393 | int error; | ||
| 394 | struct dentry *dentry = NULL, *trap; | ||
| 395 | const char *old_name; | ||
| 396 | |||
| 397 | trap = lock_rename(new_dir, old_dir); | ||
| 398 | /* Source or destination directories don't exist? */ | ||
| 399 | if (!old_dir->d_inode || !new_dir->d_inode) | ||
| 400 | goto exit; | ||
| 401 | /* Source does not exist, cyclic rename, or mountpoint? */ | ||
| 402 | if (!old_dentry->d_inode || old_dentry == trap || | ||
| 403 | d_mountpoint(old_dentry)) | ||
| 404 | goto exit; | ||
| 405 | dentry = lookup_one_len(new_name, new_dir, strlen(new_name)); | ||
| 406 | /* Lookup failed, cyclic rename or target exists? */ | ||
| 407 | if (IS_ERR(dentry) || dentry == trap || dentry->d_inode) | ||
| 408 | goto exit; | ||
| 409 | |||
| 410 | old_name = fsnotify_oldname_init(old_dentry->d_name.name); | ||
| 411 | |||
| 412 | error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, | ||
| 413 | dentry); | ||
| 414 | if (error) { | ||
| 415 | fsnotify_oldname_free(old_name); | ||
| 416 | goto exit; | ||
| 417 | } | ||
| 418 | d_move(old_dentry, dentry); | ||
| 419 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, | ||
| 420 | old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), | ||
| 421 | NULL, old_dentry->d_inode); | ||
| 422 | fsnotify_oldname_free(old_name); | ||
| 423 | unlock_rename(new_dir, old_dir); | ||
| 424 | dput(dentry); | ||
| 425 | return old_dentry; | ||
| 426 | exit: | ||
| 427 | if (dentry && !IS_ERR(dentry)) | ||
| 428 | dput(dentry); | ||
| 429 | unlock_rename(new_dir, old_dir); | ||
| 430 | return NULL; | ||
| 431 | } | ||
| 432 | EXPORT_SYMBOL_GPL(debugfs_rename); | ||
| 433 | |||
| 371 | static decl_subsys(debug, NULL, NULL); | 434 | static decl_subsys(debug, NULL, NULL); |
| 372 | 435 | ||
| 373 | static int __init debugfs_init(void) | 436 | static int __init debugfs_init(void) |
