aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index d23e66dfba74..671868914b5b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -406,22 +406,19 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
406/** 406/**
407 * sysfs_addrm_start - prepare for sysfs_dirent add/remove 407 * sysfs_addrm_start - prepare for sysfs_dirent add/remove
408 * @acxt: pointer to sysfs_addrm_cxt to be used 408 * @acxt: pointer to sysfs_addrm_cxt to be used
409 * @parent_sd: parent sysfs_dirent
410 * 409 *
411 * This function is called when the caller is about to add or 410 * This function is called when the caller is about to add or remove
412 * remove sysfs_dirent under @parent_sd. This function acquires 411 * sysfs_dirent. This function acquires sysfs_mutex. @acxt is used
413 * sysfs_mutex. @acxt is used to keep and pass context to 412 * to keep and pass context to other addrm functions.
414 * other addrm functions.
415 * 413 *
416 * LOCKING: 414 * LOCKING:
417 * Kernel thread context (may sleep). sysfs_mutex is locked on 415 * Kernel thread context (may sleep). sysfs_mutex is locked on
418 * return. 416 * return.
419 */ 417 */
420void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, 418void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt)
421 struct sysfs_dirent *parent_sd) 419 __acquires(sysfs_mutex)
422{ 420{
423 memset(acxt, 0, sizeof(*acxt)); 421 memset(acxt, 0, sizeof(*acxt));
424 acxt->parent_sd = parent_sd;
425 422
426 mutex_lock(&sysfs_mutex); 423 mutex_lock(&sysfs_mutex);
427} 424}
@@ -430,10 +427,11 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
430 * __sysfs_add_one - add sysfs_dirent to parent without warning 427 * __sysfs_add_one - add sysfs_dirent to parent without warning
431 * @acxt: addrm context to use 428 * @acxt: addrm context to use
432 * @sd: sysfs_dirent to be added 429 * @sd: sysfs_dirent to be added
430 * @parent_sd: the parent sysfs_dirent to add @sd to
433 * 431 *
434 * Get @acxt->parent_sd and set sd->s_parent to it and increment 432 * Get @parent_sd and set @sd->s_parent to it and increment nlink of
435 * nlink of parent inode if @sd is a directory and link into the 433 * the parent inode if @sd is a directory and link into the children
436 * children list of the parent. 434 * list of the parent.
437 * 435 *
438 * This function should be called between calls to 436 * This function should be called between calls to
439 * sysfs_addrm_start() and sysfs_addrm_finish() and should be 437 * sysfs_addrm_start() and sysfs_addrm_finish() and should be
@@ -446,20 +444,21 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
446 * 0 on success, -EEXIST if entry with the given name already 444 * 0 on success, -EEXIST if entry with the given name already
447 * exists. 445 * exists.
448 */ 446 */
449int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 447int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
448 struct sysfs_dirent *parent_sd)
450{ 449{
451 struct sysfs_inode_attrs *ps_iattr; 450 struct sysfs_inode_attrs *ps_iattr;
452 int ret; 451 int ret;
453 452
454 sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); 453 sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
455 sd->s_parent = sysfs_get(acxt->parent_sd); 454 sd->s_parent = sysfs_get(parent_sd);
456 455
457 ret = sysfs_link_sibling(sd); 456 ret = sysfs_link_sibling(sd);
458 if (ret) 457 if (ret)
459 return ret; 458 return ret;
460 459
461 /* Update timestamps on the parent */ 460 /* Update timestamps on the parent */
462 ps_iattr = acxt->parent_sd->s_iattr; 461 ps_iattr = parent_sd->s_iattr;
463 if (ps_iattr) { 462 if (ps_iattr) {
464 struct iattr *ps_iattrs = &ps_iattr->ia_iattr; 463 struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
465 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; 464 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
@@ -493,10 +492,11 @@ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
493 * sysfs_add_one - add sysfs_dirent to parent 492 * sysfs_add_one - add sysfs_dirent to parent
494 * @acxt: addrm context to use 493 * @acxt: addrm context to use
495 * @sd: sysfs_dirent to be added 494 * @sd: sysfs_dirent to be added
495 * @parent_sd: the parent sysfs_dirent to add @sd to
496 * 496 *
497 * Get @acxt->parent_sd and set sd->s_parent to it and increment 497 * Get @parent_sd and set @sd->s_parent to it and increment nlink of
498 * nlink of parent inode if @sd is a directory and link into the 498 * the parent inode if @sd is a directory and link into the children
499 * children list of the parent. 499 * list of the parent.
500 * 500 *
501 * This function should be called between calls to 501 * This function should be called between calls to
502 * sysfs_addrm_start() and sysfs_addrm_finish() and should be 502 * sysfs_addrm_start() and sysfs_addrm_finish() and should be
@@ -509,17 +509,18 @@ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
509 * 0 on success, -EEXIST if entry with the given name already 509 * 0 on success, -EEXIST if entry with the given name already
510 * exists. 510 * exists.
511 */ 511 */
512int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 512int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
513 struct sysfs_dirent *parent_sd)
513{ 514{
514 int ret; 515 int ret;
515 516
516 ret = __sysfs_add_one(acxt, sd); 517 ret = __sysfs_add_one(acxt, sd, parent_sd);
517 if (ret == -EEXIST) { 518 if (ret == -EEXIST) {
518 char *path = kzalloc(PATH_MAX, GFP_KERNEL); 519 char *path = kzalloc(PATH_MAX, GFP_KERNEL);
519 WARN(1, KERN_WARNING 520 WARN(1, KERN_WARNING
520 "sysfs: cannot create duplicate filename '%s'\n", 521 "sysfs: cannot create duplicate filename '%s'\n",
521 (path == NULL) ? sd->s_name 522 (path == NULL) ? sd->s_name
522 : (sysfs_pathname(acxt->parent_sd, path), 523 : (sysfs_pathname(parent_sd, path),
523 strlcat(path, "/", PATH_MAX), 524 strlcat(path, "/", PATH_MAX),
524 strlcat(path, sd->s_name, PATH_MAX), 525 strlcat(path, sd->s_name, PATH_MAX),
525 path)); 526 path));
@@ -553,7 +554,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
553 sysfs_unlink_sibling(sd); 554 sysfs_unlink_sibling(sd);
554 555
555 /* Update timestamps on the parent */ 556 /* Update timestamps on the parent */
556 ps_iattr = acxt->parent_sd->s_iattr; 557 ps_iattr = sd->s_parent->s_iattr;
557 if (ps_iattr) { 558 if (ps_iattr) {
558 struct iattr *ps_iattrs = &ps_iattr->ia_iattr; 559 struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
559 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; 560 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
@@ -576,6 +577,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
576 * sysfs_mutex is released. 577 * sysfs_mutex is released.
577 */ 578 */
578void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) 579void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
580 __releases(sysfs_mutex)
579{ 581{
580 /* release resources acquired by sysfs_addrm_start() */ 582 /* release resources acquired by sysfs_addrm_start() */
581 mutex_unlock(&sysfs_mutex); 583 mutex_unlock(&sysfs_mutex);
@@ -678,8 +680,8 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
678 sd->s_dir.kobj = kobj; 680 sd->s_dir.kobj = kobj;
679 681
680 /* link in */ 682 /* link in */
681 sysfs_addrm_start(&acxt, parent_sd); 683 sysfs_addrm_start(&acxt);
682 rc = sysfs_add_one(&acxt, sd); 684 rc = sysfs_add_one(&acxt, sd, parent_sd);
683 sysfs_addrm_finish(&acxt); 685 sysfs_addrm_finish(&acxt);
684 686
685 if (rc == 0) 687 if (rc == 0)
@@ -772,7 +774,7 @@ static void remove_dir(struct sysfs_dirent *sd)
772{ 774{
773 struct sysfs_addrm_cxt acxt; 775 struct sysfs_addrm_cxt acxt;
774 776
775 sysfs_addrm_start(&acxt, sd->s_parent); 777 sysfs_addrm_start(&acxt);
776 sysfs_remove_one(&acxt, sd); 778 sysfs_remove_one(&acxt, sd);
777 sysfs_addrm_finish(&acxt); 779 sysfs_addrm_finish(&acxt);
778} 780}
@@ -792,7 +794,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
792 return; 794 return;
793 795
794 pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); 796 pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
795 sysfs_addrm_start(&acxt, dir_sd); 797 sysfs_addrm_start(&acxt);
796 pos = rb_first(&dir_sd->s_dir.children); 798 pos = rb_first(&dir_sd->s_dir.children);
797 while (pos) { 799 while (pos) {
798 struct sysfs_dirent *sd = to_sysfs_dirent(pos); 800 struct sysfs_dirent *sd = to_sysfs_dirent(pos);