aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-06-13 15:27:22 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-11 19:09:08 -0400
commit608e266a2d4e62c1b98c1c573064b6afe8c06a58 (patch)
tree73d670ab6c315b42273bc9d2731ec2b8e7c199af
parentf0b0af4792d751106e2003f96af76fa95e10c68d (diff)
sysfs: make kobj point to sysfs_dirent instead of dentry
As kobj sysfs dentries and inodes are gonna be made reclaimable, dentry can't be used as naming token for sysfs file/directory, replace kobj->dentry with kobj->sd. The only external interface change is shadow directory handling. All other changes are contained in kobj and sysfs. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/sysfs/bin.c6
-rw-r--r--fs/sysfs/dir.c119
-rw-r--r--fs/sysfs/file.c47
-rw-r--r--fs/sysfs/group.c55
-rw-r--r--fs/sysfs/inode.c11
-rw-r--r--fs/sysfs/symlink.c22
-rw-r--r--fs/sysfs/sysfs.h10
-rw-r--r--include/linux/kobject.h9
-rw-r--r--include/linux/sysfs.h19
-rw-r--r--lib/kobject.c10
10 files changed, 156 insertions, 152 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 3c5574a40b09..55796bdacd3d 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -234,9 +234,9 @@ const struct file_operations bin_fops = {
234 234
235int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) 235int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
236{ 236{
237 BUG_ON(!kobj || !kobj->dentry || !attr); 237 BUG_ON(!kobj || !kobj->sd || !attr);
238 238
239 return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR); 239 return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
240} 240}
241 241
242 242
@@ -248,7 +248,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
248 248
249void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) 249void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
250{ 250{
251 if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) { 251 if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) {
252 printk(KERN_ERR "%s: " 252 printk(KERN_ERR "%s: "
253 "bad dentry or inode or no such file: \"%s\"\n", 253 "bad dentry or inode or no such file: \"%s\"\n",
254 __FUNCTION__, attr->attr.name); 254 __FUNCTION__, attr->attr.name);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 4762a9aa0b27..31b6cf30636d 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -368,9 +368,10 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
368 return sd; 368 return sd;
369} 369}
370 370
371static int create_dir(struct kobject *kobj, struct dentry *parent, 371static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
372 const char *name, struct dentry **p_dentry) 372 const char *name, struct sysfs_dirent **p_sd)
373{ 373{
374 struct dentry *parent = parent_sd->s_dentry;
374 int error; 375 int error;
375 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 376 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
376 struct dentry *dentry; 377 struct dentry *dentry;
@@ -409,14 +410,14 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
409 410
410 /* link in */ 411 /* link in */
411 error = -EEXIST; 412 error = -EEXIST;
412 if (sysfs_find_dirent(parent->d_fsdata, name)) 413 if (sysfs_find_dirent(parent_sd, name))
413 goto out_iput; 414 goto out_iput;
414 415
415 sysfs_instantiate(dentry, inode); 416 sysfs_instantiate(dentry, inode);
416 inc_nlink(parent->d_inode); 417 inc_nlink(parent->d_inode);
417 sysfs_attach_dirent(sd, parent->d_fsdata, dentry); 418 sysfs_attach_dirent(sd, parent_sd, dentry);
418 419
419 *p_dentry = dentry; 420 *p_sd = sd;
420 error = 0; 421 error = 0;
421 goto out_unlock; /* pin directory dentry in core */ 422 goto out_unlock; /* pin directory dentry in core */
422 423
@@ -433,38 +434,37 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
433 return error; 434 return error;
434} 435}
435 436
436 437int sysfs_create_subdir(struct kobject *kobj, const char *name,
437int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d) 438 struct sysfs_dirent **p_sd)
438{ 439{
439 return create_dir(k,k->dentry,n,d); 440 return create_dir(kobj, kobj->sd, name, p_sd);
440} 441}
441 442
442/** 443/**
443 * sysfs_create_dir - create a directory for an object. 444 * sysfs_create_dir - create a directory for an object.
444 * @kobj: object we're creating directory for. 445 * @kobj: object we're creating directory for.
445 * @shadow_parent: parent parent object. 446 * @shadow_parent: parent object.
446 */ 447 */
447 448int sysfs_create_dir(struct kobject *kobj,
448int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent) 449 struct sysfs_dirent *shadow_parent_sd)
449{ 450{
450 struct dentry * dentry = NULL; 451 struct sysfs_dirent *parent_sd, *sd;
451 struct dentry * parent;
452 int error = 0; 452 int error = 0;
453 453
454 BUG_ON(!kobj); 454 BUG_ON(!kobj);
455 455
456 if (shadow_parent) 456 if (shadow_parent_sd)
457 parent = shadow_parent; 457 parent_sd = shadow_parent_sd;
458 else if (kobj->parent) 458 else if (kobj->parent)
459 parent = kobj->parent->dentry; 459 parent_sd = kobj->parent->sd;
460 else if (sysfs_mount && sysfs_mount->mnt_sb) 460 else if (sysfs_mount && sysfs_mount->mnt_sb)
461 parent = sysfs_mount->mnt_sb->s_root; 461 parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
462 else 462 else
463 return -EFAULT; 463 return -EFAULT;
464 464
465 error = create_dir(kobj,parent,kobject_name(kobj),&dentry); 465 error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
466 if (!error) 466 if (!error)
467 kobj->dentry = dentry; 467 kobj->sd = sd;
468 return error; 468 return error;
469} 469}
470 470
@@ -525,18 +525,16 @@ const struct inode_operations sysfs_dir_inode_operations = {
525 .setattr = sysfs_setattr, 525 .setattr = sysfs_setattr,
526}; 526};
527 527
528static void remove_dir(struct dentry * d) 528static void remove_dir(struct sysfs_dirent *sd)
529{ 529{
530 struct dentry *parent = d->d_parent; 530 struct dentry *parent = sd->s_parent->s_dentry;
531 struct sysfs_dirent *sd = d->d_fsdata;
532 531
533 mutex_lock(&parent->d_inode->i_mutex); 532 mutex_lock(&parent->d_inode->i_mutex);
534 533
535 sysfs_unlink_sibling(sd); 534 sysfs_unlink_sibling(sd);
536 sd->s_flags |= SYSFS_FLAG_REMOVED; 535 sd->s_flags |= SYSFS_FLAG_REMOVED;
537 536
538 pr_debug(" o %s removing done (%d)\n",d->d_name.name, 537 pr_debug(" o %s removing done\n", sd->s_name);
539 atomic_read(&d->d_count));
540 538
541 mutex_unlock(&parent->d_inode->i_mutex); 539 mutex_unlock(&parent->d_inode->i_mutex);
542 540
@@ -545,25 +543,26 @@ static void remove_dir(struct dentry * d)
545 sysfs_put(sd); 543 sysfs_put(sd);
546} 544}
547 545
548void sysfs_remove_subdir(struct dentry * d) 546void sysfs_remove_subdir(struct sysfs_dirent *sd)
549{ 547{
550 remove_dir(d); 548 remove_dir(sd);
551} 549}
552 550
553 551
554static void __sysfs_remove_dir(struct dentry *dentry) 552static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
555{ 553{
556 struct sysfs_dirent *removed = NULL; 554 struct sysfs_dirent *removed = NULL;
557 struct sysfs_dirent *parent_sd;
558 struct sysfs_dirent **pos; 555 struct sysfs_dirent **pos;
556 struct dentry *dir;
559 557
560 if (!dentry) 558 if (!dir_sd)
561 return; 559 return;
562 560
563 pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); 561 dir = dir_sd->s_dentry;
564 mutex_lock(&dentry->d_inode->i_mutex); 562
565 parent_sd = dentry->d_fsdata; 563 pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
566 pos = &parent_sd->s_children; 564 mutex_lock(&dir->d_inode->i_mutex);
565 pos = &dir_sd->s_children;
567 while (*pos) { 566 while (*pos) {
568 struct sysfs_dirent *sd = *pos; 567 struct sysfs_dirent *sd = *pos;
569 568
@@ -575,7 +574,7 @@ static void __sysfs_remove_dir(struct dentry *dentry)
575 } else 574 } else
576 pos = &(*pos)->s_sibling; 575 pos = &(*pos)->s_sibling;
577 } 576 }
578 mutex_unlock(&dentry->d_inode->i_mutex); 577 mutex_unlock(&dir->d_inode->i_mutex);
579 578
580 while (removed) { 579 while (removed) {
581 struct sysfs_dirent *sd = removed; 580 struct sysfs_dirent *sd = removed;
@@ -588,7 +587,7 @@ static void __sysfs_remove_dir(struct dentry *dentry)
588 sysfs_put(sd); 587 sysfs_put(sd);
589 } 588 }
590 589
591 remove_dir(dentry); 590 remove_dir(dir_sd);
592} 591}
593 592
594/** 593/**
@@ -602,25 +601,25 @@ static void __sysfs_remove_dir(struct dentry *dentry)
602 601
603void sysfs_remove_dir(struct kobject * kobj) 602void sysfs_remove_dir(struct kobject * kobj)
604{ 603{
605 struct dentry *d = kobj->dentry; 604 struct sysfs_dirent *sd = kobj->sd;
606 605
607 spin_lock(&kobj_sysfs_assoc_lock); 606 spin_lock(&kobj_sysfs_assoc_lock);
608 kobj->dentry = NULL; 607 kobj->sd = NULL;
609 spin_unlock(&kobj_sysfs_assoc_lock); 608 spin_unlock(&kobj_sysfs_assoc_lock);
610 609
611 __sysfs_remove_dir(d); 610 __sysfs_remove_dir(sd);
612} 611}
613 612
614int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, 613int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
615 const char *new_name) 614 const char *new_name)
616{ 615{
617 struct sysfs_dirent *sd = kobj->dentry->d_fsdata; 616 struct sysfs_dirent *sd = kobj->sd;
618 struct sysfs_dirent *parent_sd = new_parent->d_fsdata; 617 struct dentry *new_parent = new_parent_sd->s_dentry;
619 struct dentry *new_dentry; 618 struct dentry *new_dentry;
620 char *dup_name; 619 char *dup_name;
621 int error; 620 int error;
622 621
623 if (!new_parent) 622 if (!new_parent_sd)
624 return -EFAULT; 623 return -EFAULT;
625 624
626 down_write(&sysfs_rename_sem); 625 down_write(&sysfs_rename_sem);
@@ -637,9 +636,9 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
637 * shadows of the same directory 636 * shadows of the same directory
638 */ 637 */
639 error = -EINVAL; 638 error = -EINVAL;
640 if (kobj->dentry->d_parent->d_inode != new_parent->d_inode || 639 if (sd->s_parent->s_dentry->d_inode != new_parent->d_inode ||
641 new_dentry->d_parent->d_inode != new_parent->d_inode || 640 new_dentry->d_parent->d_inode != new_parent->d_inode ||
642 new_dentry == kobj->dentry) 641 new_dentry == sd->s_dentry)
643 goto out_dput; 642 goto out_dput;
644 643
645 error = -EEXIST; 644 error = -EEXIST;
@@ -661,12 +660,12 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
661 660
662 /* move under the new parent */ 661 /* move under the new parent */
663 d_add(new_dentry, NULL); 662 d_add(new_dentry, NULL);
664 d_move(kobj->dentry, new_dentry); 663 d_move(sd->s_dentry, new_dentry);
665 664
666 sysfs_unlink_sibling(sd); 665 sysfs_unlink_sibling(sd);
667 sysfs_get(parent_sd); 666 sysfs_get(new_parent_sd);
668 sysfs_put(sd->s_parent); 667 sysfs_put(sd->s_parent);
669 sd->s_parent = parent_sd; 668 sd->s_parent = new_parent_sd;
670 sysfs_link_sibling(sd); 669 sysfs_link_sibling(sd);
671 670
672 error = 0; 671 error = 0;
@@ -691,9 +690,9 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
691 int error; 690 int error;
692 691
693 old_parent_dentry = kobj->parent ? 692 old_parent_dentry = kobj->parent ?
694 kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; 693 kobj->parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root;
695 new_parent_dentry = new_parent ? 694 new_parent_dentry = new_parent ?
696 new_parent->dentry : sysfs_mount->mnt_sb->s_root; 695 new_parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root;
697 696
698 if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) 697 if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
699 return 0; /* nothing to move */ 698 return 0; /* nothing to move */
@@ -705,7 +704,7 @@ again:
705 } 704 }
706 705
707 new_parent_sd = new_parent_dentry->d_fsdata; 706 new_parent_sd = new_parent_dentry->d_fsdata;
708 sd = kobj->dentry->d_fsdata; 707 sd = kobj->sd;
709 708
710 new_dentry = lookup_one_len(kobj->name, new_parent_dentry, 709 new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
711 strlen(kobj->name)); 710 strlen(kobj->name));
@@ -715,7 +714,7 @@ again:
715 } else 714 } else
716 error = 0; 715 error = 0;
717 d_add(new_dentry, NULL); 716 d_add(new_dentry, NULL);
718 d_move(kobj->dentry, new_dentry); 717 d_move(sd->s_dentry, new_dentry);
719 dput(new_dentry); 718 dput(new_dentry);
720 719
721 /* Remove from old parent's list and insert into new parent's list. */ 720 /* Remove from old parent's list and insert into new parent's list. */
@@ -885,7 +884,7 @@ int sysfs_make_shadowed_dir(struct kobject *kobj,
885 struct inode *inode; 884 struct inode *inode;
886 struct inode_operations *i_op; 885 struct inode_operations *i_op;
887 886
888 inode = kobj->dentry->d_inode; 887 inode = kobj->sd->s_dentry->d_inode;
889 if (inode->i_op != &sysfs_dir_inode_operations) 888 if (inode->i_op != &sysfs_dir_inode_operations)
890 return -EINVAL; 889 return -EINVAL;
891 890
@@ -912,16 +911,16 @@ int sysfs_make_shadowed_dir(struct kobject *kobj,
912 * directory. 911 * directory.
913 */ 912 */
914 913
915struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) 914struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
916{ 915{
917 struct dentry *dir = kobj->dentry; 916 struct dentry *dir = kobj->sd->s_dentry;
918 struct inode *inode = dir->d_inode; 917 struct inode *inode = dir->d_inode;
919 struct dentry *parent = dir->d_parent; 918 struct dentry *parent = dir->d_parent;
920 struct sysfs_dirent *parent_sd = parent->d_fsdata; 919 struct sysfs_dirent *parent_sd = parent->d_fsdata;
921 struct dentry *shadow; 920 struct dentry *shadow;
922 struct sysfs_dirent *sd; 921 struct sysfs_dirent *sd;
923 922
924 shadow = ERR_PTR(-EINVAL); 923 sd = ERR_PTR(-EINVAL);
925 if (!sysfs_is_shadowed_inode(inode)) 924 if (!sysfs_is_shadowed_inode(inode))
926 goto out; 925 goto out;
927 926
@@ -944,25 +943,25 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
944 dget(shadow); /* Extra count - pin the dentry in core */ 943 dget(shadow); /* Extra count - pin the dentry in core */
945 944
946out: 945out:
947 return shadow; 946 return sd;
948nomem: 947nomem:
949 dput(shadow); 948 dput(shadow);
950 shadow = ERR_PTR(-ENOMEM); 949 sd = ERR_PTR(-ENOMEM);
951 goto out; 950 goto out;
952} 951}
953 952
954/** 953/**
955 * sysfs_remove_shadow_dir - remove an object's directory. 954 * sysfs_remove_shadow_dir - remove an object's directory.
956 * @shadow: dentry of shadow directory 955 * @shadow_sd: sysfs_dirent of shadow directory
957 * 956 *
958 * The only thing special about this is that we remove any files in 957 * The only thing special about this is that we remove any files in
959 * the directory before we remove the directory, and we've inlined 958 * the directory before we remove the directory, and we've inlined
960 * what used to be sysfs_rmdir() below, instead of calling separately. 959 * what used to be sysfs_rmdir() below, instead of calling separately.
961 */ 960 */
962 961
963void sysfs_remove_shadow_dir(struct dentry *shadow) 962void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd)
964{ 963{
965 __sysfs_remove_dir(shadow); 964 __sysfs_remove_dir(shadow_sd);
966} 965}
967 966
968const struct file_operations sysfs_dir_operations = { 967const struct file_operations sysfs_dir_operations = {
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index e448b88e313e..20703b9ee064 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -385,7 +385,7 @@ static struct dentry *step_down(struct dentry *dir, const char * name)
385 385
386void sysfs_notify(struct kobject * k, char *dir, char *attr) 386void sysfs_notify(struct kobject * k, char *dir, char *attr)
387{ 387{
388 struct dentry *de = k->dentry; 388 struct dentry *de = k->sd->s_dentry;
389 if (de) 389 if (de)
390 dget(de); 390 dget(de);
391 if (de && dir) 391 if (de && dir)
@@ -412,16 +412,17 @@ const struct file_operations sysfs_file_operations = {
412}; 412};
413 413
414 414
415int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) 415int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
416 int type)
416{ 417{
417 struct sysfs_dirent * parent_sd = dir->d_fsdata; 418 struct dentry *dir = dir_sd->s_dentry;
418 umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; 419 umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
419 struct sysfs_dirent *sd; 420 struct sysfs_dirent *sd;
420 int error = 0; 421 int error = 0;
421 422
422 mutex_lock(&dir->d_inode->i_mutex); 423 mutex_lock(&dir->d_inode->i_mutex);
423 424
424 if (sysfs_find_dirent(parent_sd, attr->name)) { 425 if (sysfs_find_dirent(dir_sd, attr->name)) {
425 error = -EEXIST; 426 error = -EEXIST;
426 goto out_unlock; 427 goto out_unlock;
427 } 428 }
@@ -432,7 +433,7 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
432 goto out_unlock; 433 goto out_unlock;
433 } 434 }
434 sd->s_elem.attr.attr = (void *)attr; 435 sd->s_elem.attr.attr = (void *)attr;
435 sysfs_attach_dirent(sd, parent_sd, NULL); 436 sysfs_attach_dirent(sd, dir_sd, NULL);
436 437
437 out_unlock: 438 out_unlock:
438 mutex_unlock(&dir->d_inode->i_mutex); 439 mutex_unlock(&dir->d_inode->i_mutex);
@@ -448,9 +449,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
448 449
449int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) 450int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
450{ 451{
451 BUG_ON(!kobj || !kobj->dentry || !attr); 452 BUG_ON(!kobj || !kobj->sd || !attr);
452 453
453 return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR); 454 return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
454 455
455} 456}
456 457
@@ -464,16 +465,16 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
464int sysfs_add_file_to_group(struct kobject *kobj, 465int sysfs_add_file_to_group(struct kobject *kobj,
465 const struct attribute *attr, const char *group) 466 const struct attribute *attr, const char *group)
466{ 467{
467 struct dentry *dir; 468 struct sysfs_dirent *dir_sd;
468 int error; 469 int error;
469 470
470 dir = lookup_one_len(group, kobj->dentry, strlen(group)); 471 dir_sd = sysfs_get_dirent(kobj->sd, group);
471 if (IS_ERR(dir)) 472 if (!dir_sd)
472 error = PTR_ERR(dir); 473 return -ENOENT;
473 else { 474
474 error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR); 475 error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR);
475 dput(dir); 476 sysfs_put(dir_sd);
476 } 477
477 return error; 478 return error;
478} 479}
479EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); 480EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
@@ -486,7 +487,7 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
486 */ 487 */
487int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) 488int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
488{ 489{
489 struct dentry * dir = kobj->dentry; 490 struct dentry *dir = kobj->sd->s_dentry;
490 struct dentry * victim; 491 struct dentry * victim;
491 int res = -ENOENT; 492 int res = -ENOENT;
492 493
@@ -522,7 +523,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
522 */ 523 */
523int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) 524int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
524{ 525{
525 struct dentry *dir = kobj->dentry; 526 struct dentry *dir = kobj->sd->s_dentry;
526 struct dentry *victim; 527 struct dentry *victim;
527 struct inode * inode; 528 struct inode * inode;
528 struct iattr newattrs; 529 struct iattr newattrs;
@@ -560,7 +561,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
560 561
561void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) 562void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
562{ 563{
563 sysfs_hash_and_remove(kobj->dentry, attr->name); 564 sysfs_hash_and_remove(kobj->sd, attr->name);
564} 565}
565 566
566 567
@@ -573,12 +574,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
573void sysfs_remove_file_from_group(struct kobject *kobj, 574void sysfs_remove_file_from_group(struct kobject *kobj,
574 const struct attribute *attr, const char *group) 575 const struct attribute *attr, const char *group)
575{ 576{
576 struct dentry *dir; 577 struct sysfs_dirent *dir_sd;
577 578
578 dir = lookup_one_len(group, kobj->dentry, strlen(group)); 579 dir_sd = sysfs_get_dirent(kobj->sd, group);
579 if (!IS_ERR(dir)) { 580 if (dir_sd) {
580 sysfs_hash_and_remove(dir, attr->name); 581 sysfs_hash_and_remove(dir_sd, attr->name);
581 dput(dir); 582 sysfs_put(dir_sd);
582 } 583 }
583} 584}
584EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); 585EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 52eed2a7a5ef..f318b73c790c 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -18,26 +18,25 @@
18#include "sysfs.h" 18#include "sysfs.h"
19 19
20 20
21static void remove_files(struct dentry * dir, 21static void remove_files(struct sysfs_dirent *dir_sd,
22 const struct attribute_group * grp) 22 const struct attribute_group *grp)
23{ 23{
24 struct attribute *const* attr; 24 struct attribute *const* attr;
25 25
26 for (attr = grp->attrs; *attr; attr++) 26 for (attr = grp->attrs; *attr; attr++)
27 sysfs_hash_and_remove(dir,(*attr)->name); 27 sysfs_hash_and_remove(dir_sd, (*attr)->name);
28} 28}
29 29
30static int create_files(struct dentry * dir, 30static int create_files(struct sysfs_dirent *dir_sd,
31 const struct attribute_group * grp) 31 const struct attribute_group *grp)
32{ 32{
33 struct attribute *const* attr; 33 struct attribute *const* attr;
34 int error = 0; 34 int error = 0;
35 35
36 for (attr = grp->attrs; *attr && !error; attr++) { 36 for (attr = grp->attrs; *attr && !error; attr++)
37 error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR); 37 error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
38 }
39 if (error) 38 if (error)
40 remove_files(dir,grp); 39 remove_files(dir_sd, grp);
41 return error; 40 return error;
42} 41}
43 42
@@ -45,44 +44,44 @@ static int create_files(struct dentry * dir,
45int sysfs_create_group(struct kobject * kobj, 44int sysfs_create_group(struct kobject * kobj,
46 const struct attribute_group * grp) 45 const struct attribute_group * grp)
47{ 46{
48 struct dentry * dir; 47 struct sysfs_dirent *sd;
49 int error; 48 int error;
50 49
51 BUG_ON(!kobj || !kobj->dentry); 50 BUG_ON(!kobj || !kobj->sd);
52 51
53 if (grp->name) { 52 if (grp->name) {
54 error = sysfs_create_subdir(kobj,grp->name,&dir); 53 error = sysfs_create_subdir(kobj, grp->name, &sd);
55 if (error) 54 if (error)
56 return error; 55 return error;
57 } else 56 } else
58 dir = kobj->dentry; 57 sd = kobj->sd;
59 dir = dget(dir); 58 sysfs_get(sd);
60 if ((error = create_files(dir,grp))) { 59 error = create_files(sd, grp);
60 if (error) {
61 if (grp->name) 61 if (grp->name)
62 sysfs_remove_subdir(dir); 62 sysfs_remove_subdir(sd);
63 } 63 }
64 dput(dir); 64 sysfs_put(sd);
65 return error; 65 return error;
66} 66}
67 67
68void sysfs_remove_group(struct kobject * kobj, 68void sysfs_remove_group(struct kobject * kobj,
69 const struct attribute_group * grp) 69 const struct attribute_group * grp)
70{ 70{
71 struct dentry * dir; 71 struct sysfs_dirent *dir_sd = kobj->sd;
72 struct sysfs_dirent *sd;
72 73
73 if (grp->name) { 74 if (grp->name) {
74 dir = lookup_one_len_kern(grp->name, kobj->dentry, 75 sd = sysfs_get_dirent(dir_sd, grp->name);
75 strlen(grp->name)); 76 BUG_ON(!sd);
76 BUG_ON(IS_ERR(dir)); 77 } else
77 } 78 sd = sysfs_get(dir_sd);
78 else
79 dir = dget(kobj->dentry);
80 79
81 remove_files(dir,grp); 80 remove_files(sd, grp);
82 if (grp->name) 81 if (grp->name)
83 sysfs_remove_subdir(dir); 82 sysfs_remove_subdir(sd);
84 /* release the ref. taken in this routine */ 83
85 dput(dir); 84 sysfs_put(sd);
86} 85}
87 86
88 87
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index e2f6ef138d20..1be853706e99 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -275,22 +275,23 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd)
275 } 275 }
276} 276}
277 277
278int sysfs_hash_and_remove(struct dentry * dir, const char * name) 278int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
279{ 279{
280 struct dentry *dir;
280 struct sysfs_dirent **pos, *sd; 281 struct sysfs_dirent **pos, *sd;
281 struct sysfs_dirent *parent_sd;
282 int found = 0; 282 int found = 0;
283 283
284 if (!dir) 284 if (!dir_sd)
285 return -ENOENT; 285 return -ENOENT;
286 286
287 dir = dir_sd->s_dentry;
288
287 if (dir->d_inode == NULL) 289 if (dir->d_inode == NULL)
288 /* no inode means this hasn't been made visible yet */ 290 /* no inode means this hasn't been made visible yet */
289 return -ENOENT; 291 return -ENOENT;
290 292
291 parent_sd = dir->d_fsdata;
292 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 293 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
293 for (pos = &parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) { 294 for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
294 sd = *pos; 295 sd = *pos;
295 296
296 if (!sysfs_type(sd)) 297 if (!sysfs_type(sd))
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 45b62e229627..43cc5222f136 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -66,7 +66,6 @@ static int sysfs_add_link(struct sysfs_dirent * parent_sd, const char * name,
66 */ 66 */
67int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) 67int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
68{ 68{
69 struct dentry *dentry = NULL;
70 struct sysfs_dirent *parent_sd = NULL; 69 struct sysfs_dirent *parent_sd = NULL;
71 struct sysfs_dirent *target_sd = NULL; 70 struct sysfs_dirent *target_sd = NULL;
72 int error = -EEXIST; 71 int error = -EEXIST;
@@ -75,29 +74,28 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
75 74
76 if (!kobj) { 75 if (!kobj) {
77 if (sysfs_mount && sysfs_mount->mnt_sb) 76 if (sysfs_mount && sysfs_mount->mnt_sb)
78 dentry = sysfs_mount->mnt_sb->s_root; 77 parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
79 } else 78 } else
80 dentry = kobj->dentry; 79 parent_sd = kobj->sd;
81 80
82 if (!dentry) 81 if (!parent_sd)
83 return -EFAULT; 82 return -EFAULT;
84 parent_sd = dentry->d_fsdata;
85 83
86 /* target->dentry can go away beneath us but is protected with 84 /* target->sd can go away beneath us but is protected with
87 * kobj_sysfs_assoc_lock. Fetch target_sd from it. 85 * kobj_sysfs_assoc_lock. Fetch target_sd from it.
88 */ 86 */
89 spin_lock(&kobj_sysfs_assoc_lock); 87 spin_lock(&kobj_sysfs_assoc_lock);
90 if (target->dentry) 88 if (target->sd)
91 target_sd = sysfs_get(target->dentry->d_fsdata); 89 target_sd = sysfs_get(target->sd);
92 spin_unlock(&kobj_sysfs_assoc_lock); 90 spin_unlock(&kobj_sysfs_assoc_lock);
93 91
94 if (!target_sd) 92 if (!target_sd)
95 return -ENOENT; 93 return -ENOENT;
96 94
97 mutex_lock(&dentry->d_inode->i_mutex); 95 mutex_lock(&parent_sd->s_dentry->d_inode->i_mutex);
98 if (!sysfs_find_dirent(dentry->d_fsdata, name)) 96 if (!sysfs_find_dirent(parent_sd, name))
99 error = sysfs_add_link(parent_sd, name, target_sd); 97 error = sysfs_add_link(parent_sd, name, target_sd);
100 mutex_unlock(&dentry->d_inode->i_mutex); 98 mutex_unlock(&parent_sd->s_dentry->d_inode->i_mutex);
101 99
102 if (error) 100 if (error)
103 sysfs_put(target_sd); 101 sysfs_put(target_sd);
@@ -114,7 +112,7 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
114 112
115void sysfs_remove_link(struct kobject * kobj, const char * name) 113void sysfs_remove_link(struct kobject * kobj, const char * name)
116{ 114{
117 sysfs_hash_and_remove(kobj->dentry,name); 115 sysfs_hash_and_remove(kobj->sd, name);
118} 116}
119 117
120static int sysfs_get_target_path(struct sysfs_dirent * parent_sd, 118static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index f1629b4520aa..27a5f4b4e3b0 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -69,12 +69,14 @@ extern void sysfs_attach_dirent(struct sysfs_dirent *sd,
69 struct sysfs_dirent *parent_sd, 69 struct sysfs_dirent *parent_sd,
70 struct dentry *dentry); 70 struct dentry *dentry);
71 71
72extern int sysfs_add_file(struct dentry *, const struct attribute *, int); 72extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
73extern int sysfs_hash_and_remove(struct dentry * dir, const char * name); 73 const struct attribute *attr, int type);
74extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
74extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name); 75extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
75 76
76extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); 77extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
77extern void sysfs_remove_subdir(struct dentry *); 78 struct sysfs_dirent **p_sd);
79extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
78 80
79extern void sysfs_drop_dentry(struct sysfs_dirent *sd); 81extern void sysfs_drop_dentry(struct sysfs_dirent *sd);
80extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); 82extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index c288e41ba331..06cbf41d32d2 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -55,7 +55,7 @@ struct kobject {
55 struct kobject * parent; 55 struct kobject * parent;
56 struct kset * kset; 56 struct kset * kset;
57 struct kobj_type * ktype; 57 struct kobj_type * ktype;
58 struct dentry * dentry; 58 struct sysfs_dirent * sd;
59 wait_queue_head_t poll; 59 wait_queue_head_t poll;
60}; 60};
61 61
@@ -71,13 +71,14 @@ extern void kobject_init(struct kobject *);
71extern void kobject_cleanup(struct kobject *); 71extern void kobject_cleanup(struct kobject *);
72 72
73extern int __must_check kobject_add(struct kobject *); 73extern int __must_check kobject_add(struct kobject *);
74extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *); 74extern int __must_check kobject_shadow_add(struct kobject *kobj,
75 struct sysfs_dirent *shadow_parent);
75extern void kobject_del(struct kobject *); 76extern void kobject_del(struct kobject *);
76 77
77extern int __must_check kobject_rename(struct kobject *, const char *new_name); 78extern int __must_check kobject_rename(struct kobject *, const char *new_name);
78extern int __must_check kobject_shadow_rename(struct kobject *kobj, 79extern int __must_check kobject_shadow_rename(struct kobject *kobj,
79 struct dentry *new_parent, 80 struct sysfs_dirent *new_parent,
80 const char *new_name); 81 const char *new_name);
81extern int __must_check kobject_move(struct kobject *, struct kobject *); 82extern int __must_check kobject_move(struct kobject *, struct kobject *);
82 83
83extern int __must_check kobject_register(struct kobject *); 84extern int __must_check kobject_register(struct kobject *);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 2a6df6444e69..4c43030fae5d 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -19,6 +19,7 @@ struct kobject;
19struct module; 19struct module;
20struct nameidata; 20struct nameidata;
21struct dentry; 21struct dentry;
22struct sysfs_dirent;
22 23
23/* FIXME 24/* FIXME
24 * The *owner field is no longer used, but leave around 25 * The *owner field is no longer used, but leave around
@@ -92,13 +93,14 @@ extern int sysfs_schedule_callback(struct kobject *kobj,
92 void (*func)(void *), void *data, struct module *owner); 93 void (*func)(void *), void *data, struct module *owner);
93 94
94extern int __must_check 95extern int __must_check
95sysfs_create_dir(struct kobject *, struct dentry *); 96sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd);
96 97
97extern void 98extern void
98sysfs_remove_dir(struct kobject *); 99sysfs_remove_dir(struct kobject *);
99 100
100extern int __must_check 101extern int __must_check
101sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name); 102sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
103 const char *new_name);
102 104
103extern int __must_check 105extern int __must_check
104sysfs_move_dir(struct kobject *, struct kobject *); 106sysfs_move_dir(struct kobject *, struct kobject *);
@@ -138,8 +140,8 @@ void sysfs_notify(struct kobject * k, char *dir, char *attr);
138 140
139extern int sysfs_make_shadowed_dir(struct kobject *kobj, 141extern int sysfs_make_shadowed_dir(struct kobject *kobj,
140 void * (*follow_link)(struct dentry *, struct nameidata *)); 142 void * (*follow_link)(struct dentry *, struct nameidata *));
141extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj); 143extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj);
142extern void sysfs_remove_shadow_dir(struct dentry *dir); 144extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd);
143 145
144extern int __must_check sysfs_init(void); 146extern int __must_check sysfs_init(void);
145 147
@@ -151,7 +153,8 @@ static inline int sysfs_schedule_callback(struct kobject *kobj,
151 return -ENOSYS; 153 return -ENOSYS;
152} 154}
153 155
154static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow) 156static inline int sysfs_create_dir(struct kobject *kobj,
157 struct sysfs_dirent *shadow_parent_sd)
155{ 158{
156 return 0; 159 return 0;
157} 160}
@@ -161,9 +164,9 @@ static inline void sysfs_remove_dir(struct kobject * k)
161 ; 164 ;
162} 165}
163 166
164static inline int sysfs_rename_dir(struct kobject * k, 167static inline int sysfs_rename_dir(struct kobject *kobj,
165 struct dentry *new_parent, 168 struct sysfs_dirent *new_parent_sd,
166 const char *new_name) 169 const char *new_name)
167{ 170{
168 return 0; 171 return 0;
169} 172}
diff --git a/lib/kobject.c b/lib/kobject.c
index b4ebd7631700..4b08e0ff95c8 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -44,7 +44,7 @@ static int populate_dir(struct kobject * kobj)
44 return error; 44 return error;
45} 45}
46 46
47static int create_dir(struct kobject * kobj, struct dentry *shadow_parent) 47static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
48{ 48{
49 int error = 0; 49 int error = 0;
50 if (kobject_name(kobj)) { 50 if (kobject_name(kobj)) {
@@ -162,7 +162,7 @@ static void unlink(struct kobject * kobj)
162 * @shadow_parent: sysfs directory to add to. 162 * @shadow_parent: sysfs directory to add to.
163 */ 163 */
164 164
165int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) 165int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
166{ 166{
167 int error = 0; 167 int error = 0;
168 struct kobject * parent; 168 struct kobject * parent;
@@ -338,7 +338,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
338 /* Note : if we want to send the new name alone, not the full path, 338 /* Note : if we want to send the new name alone, not the full path,
339 * we could probably use kobject_name(kobj); */ 339 * we could probably use kobject_name(kobj); */
340 340
341 error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name); 341 error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name);
342 342
343 /* This function is mostly/only used for network interface. 343 /* This function is mostly/only used for network interface.
344 * Some hotplug package track interfaces by their name and 344 * Some hotplug package track interfaces by their name and
@@ -361,8 +361,8 @@ out:
361 * @new_name: object's new name 361 * @new_name: object's new name
362 */ 362 */
363 363
364int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent, 364int kobject_shadow_rename(struct kobject *kobj,
365 const char *new_name) 365 struct sysfs_dirent *new_parent, const char *new_name)
366{ 366{
367 int error = 0; 367 int error = 0;
368 368