diff options
Diffstat (limited to 'fs/debugfs/inode.c')
-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 ec8896b264d..1d533a2ec3a 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) |