aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-11-28 14:54:30 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-29 20:55:10 -0500
commitccf73cf336dc55bc52748205dee998d2fd4a8808 (patch)
tree8e3a3b9891e6b9d4804299cd23110c91d8f8016e /fs/sysfs
parent517e64f57883bd63c5a4ab8b3d0d3ed68c55d0cf (diff)
sysfs, kernfs: introduce kernfs[_find_and]_get() and kernfs_put()
Introduce kernfs interface for finding, getting and putting sysfs_dirents. * sysfs_find_dirent() is renamed to kernfs_find_ns() and lockdep assertion for sysfs_mutex is added. * sysfs_get_dirent_ns() is renamed to kernfs_find_and_get(). * Macro inline dancing around __sysfs_get/put() are removed and kernfs_get/put() are made proper functions implemented in fs/sysfs/dir.c. While the conversions are mostly equivalent, there's one difference - kernfs_get() doesn't return the input param as its return value. This change is intentional. While passing through the input increases writability in some areas, it is unnecessary and has been shown to cause confusion regarding how the last ref is handled. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/dir.c117
-rw-r--r--fs/sysfs/file.c41
-rw-r--r--fs/sysfs/group.c30
-rw-r--r--fs/sysfs/inode.c5
-rw-r--r--fs/sysfs/mount.c14
-rw-r--r--fs/sysfs/symlink.c16
-rw-r--r--fs/sysfs/sysfs.h22
7 files changed, 118 insertions, 127 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 8f2d577b5f64..0d806efcc9a6 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -240,10 +240,31 @@ static void sysfs_free_ino(unsigned int ino)
240 spin_unlock(&sysfs_ino_lock); 240 spin_unlock(&sysfs_ino_lock);
241} 241}
242 242
243void release_sysfs_dirent(struct sysfs_dirent *sd) 243/**
244 * kernfs_get - get a reference count on a sysfs_dirent
245 * @sd: the target sysfs_dirent
246 */
247void kernfs_get(struct sysfs_dirent *sd)
248{
249 if (sd) {
250 WARN_ON(!atomic_read(&sd->s_count));
251 atomic_inc(&sd->s_count);
252 }
253}
254EXPORT_SYMBOL_GPL(kernfs_get);
255
256/**
257 * kernfs_put - put a reference count on a sysfs_dirent
258 * @sd: the target sysfs_dirent
259 *
260 * Put a reference count of @sd and destroy it if it reached zero.
261 */
262void kernfs_put(struct sysfs_dirent *sd)
244{ 263{
245 struct sysfs_dirent *parent_sd; 264 struct sysfs_dirent *parent_sd;
246 265
266 if (!sd || !atomic_dec_and_test(&sd->s_count))
267 return;
247 repeat: 268 repeat:
248 /* Moving/renaming is always done while holding reference. 269 /* Moving/renaming is always done while holding reference.
249 * sd->s_parent won't change beneath us. 270 * sd->s_parent won't change beneath us.
@@ -255,7 +276,7 @@ void release_sysfs_dirent(struct sysfs_dirent *sd)
255 parent_sd ? parent_sd->s_name : "", sd->s_name); 276 parent_sd ? parent_sd->s_name : "", sd->s_name);
256 277
257 if (sysfs_type(sd) == SYSFS_KOBJ_LINK) 278 if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
258 sysfs_put(sd->s_symlink.target_sd); 279 kernfs_put(sd->s_symlink.target_sd);
259 if (sysfs_type(sd) & SYSFS_COPY_NAME) 280 if (sysfs_type(sd) & SYSFS_COPY_NAME)
260 kfree(sd->s_name); 281 kfree(sd->s_name);
261 if (sd->s_iattr && sd->s_iattr->ia_secdata) 282 if (sd->s_iattr && sd->s_iattr->ia_secdata)
@@ -269,6 +290,7 @@ void release_sysfs_dirent(struct sysfs_dirent *sd)
269 if (sd && atomic_dec_and_test(&sd->s_count)) 290 if (sd && atomic_dec_and_test(&sd->s_count))
270 goto repeat; 291 goto repeat;
271} 292}
293EXPORT_SYMBOL_GPL(kernfs_put);
272 294
273static int sysfs_dentry_delete(const struct dentry *dentry) 295static int sysfs_dentry_delete(const struct dentry *dentry)
274{ 296{
@@ -331,7 +353,7 @@ out_bad:
331 353
332static void sysfs_dentry_release(struct dentry *dentry) 354static void sysfs_dentry_release(struct dentry *dentry)
333{ 355{
334 sysfs_put(dentry->d_fsdata); 356 kernfs_put(dentry->d_fsdata);
335} 357}
336 358
337const struct dentry_operations sysfs_dentry_ops = { 359const struct dentry_operations sysfs_dentry_ops = {
@@ -433,7 +455,8 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
433 return -EINVAL; 455 return -EINVAL;
434 456
435 sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); 457 sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
436 sd->s_parent = sysfs_get(parent_sd); 458 sd->s_parent = parent_sd;
459 kernfs_get(parent_sd);
437 460
438 ret = sysfs_link_sibling(sd); 461 ret = sysfs_link_sibling(sd);
439 if (ret) 462 if (ret)
@@ -553,36 +576,33 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
553 576
554 sysfs_deactivate(sd); 577 sysfs_deactivate(sd);
555 sysfs_unmap_bin_file(sd); 578 sysfs_unmap_bin_file(sd);
556 sysfs_put(sd); 579 kernfs_put(sd);
557 } 580 }
558} 581}
559 582
560/** 583/**
561 * sysfs_find_dirent - find sysfs_dirent with the given name 584 * kernfs_find_ns - find sysfs_dirent with the given name
562 * @parent_sd: sysfs_dirent to search under 585 * @parent: sysfs_dirent to search under
563 * @name: name to look for 586 * @name: name to look for
564 * @ns: the namespace tag to use 587 * @ns: the namespace tag to use
565 *
566 * Look for sysfs_dirent with name @name under @parent_sd.
567 *
568 * LOCKING:
569 * mutex_lock(sysfs_mutex)
570 * 588 *
571 * RETURNS: 589 * Look for sysfs_dirent with name @name under @parent. Returns pointer to
572 * Pointer to sysfs_dirent if found, NULL if not. 590 * the found sysfs_dirent on success, %NULL on failure.
573 */ 591 */
574struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, 592static struct sysfs_dirent *kernfs_find_ns(struct sysfs_dirent *parent,
575 const unsigned char *name, 593 const unsigned char *name,
576 const void *ns) 594 const void *ns)
577{ 595{
578 struct rb_node *node = parent_sd->s_dir.children.rb_node; 596 struct rb_node *node = parent->s_dir.children.rb_node;
579 bool has_ns = parent_sd->s_flags & SYSFS_FLAG_NS; 597 bool has_ns = parent->s_flags & SYSFS_FLAG_NS;
580 unsigned int hash; 598 unsigned int hash;
581 599
600 lockdep_assert_held(&sysfs_mutex);
601
582 if (has_ns != (bool)ns) { 602 if (has_ns != (bool)ns) {
583 WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", 603 WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
584 has_ns ? "required" : "invalid", 604 has_ns ? "required" : "invalid",
585 parent_sd->s_name, name); 605 parent->s_name, name);
586 return NULL; 606 return NULL;
587 } 607 }
588 608
@@ -604,34 +624,28 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
604} 624}
605 625
606/** 626/**
607 * sysfs_get_dirent_ns - find and get sysfs_dirent with the given name 627 * kernfs_find_and_get_ns - find and get sysfs_dirent with the given name
608 * @parent_sd: sysfs_dirent to search under 628 * @parent: sysfs_dirent to search under
609 * @name: name to look for 629 * @name: name to look for
610 * @ns: the namespace tag to use 630 * @ns: the namespace tag to use
611 *
612 * Look for sysfs_dirent with name @name under @parent_sd and get
613 * it if found.
614 *
615 * LOCKING:
616 * Kernel thread context (may sleep). Grabs sysfs_mutex.
617 * 631 *
618 * RETURNS: 632 * Look for sysfs_dirent with name @name under @parent and get a reference
619 * Pointer to sysfs_dirent if found, NULL if not. 633 * if found. This function may sleep and returns pointer to the found
634 * sysfs_dirent on success, %NULL on failure.
620 */ 635 */
621struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, 636struct sysfs_dirent *kernfs_find_and_get_ns(struct sysfs_dirent *parent,
622 const unsigned char *name, 637 const char *name, const void *ns)
623 const void *ns)
624{ 638{
625 struct sysfs_dirent *sd; 639 struct sysfs_dirent *sd;
626 640
627 mutex_lock(&sysfs_mutex); 641 mutex_lock(&sysfs_mutex);
628 sd = sysfs_find_dirent(parent_sd, name, ns); 642 sd = kernfs_find_ns(parent, name, ns);
629 sysfs_get(sd); 643 kernfs_get(sd);
630 mutex_unlock(&sysfs_mutex); 644 mutex_unlock(&sysfs_mutex);
631 645
632 return sd; 646 return sd;
633} 647}
634EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); 648EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns);
635 649
636/** 650/**
637 * kernfs_create_dir_ns - create a directory 651 * kernfs_create_dir_ns - create a directory
@@ -667,7 +681,7 @@ struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent,
667 if (!rc) 681 if (!rc)
668 return sd; 682 return sd;
669 683
670 sysfs_put(sd); 684 kernfs_put(sd);
671 return ERR_PTR(rc); 685 return ERR_PTR(rc);
672} 686}
673 687
@@ -716,14 +730,15 @@ static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry,
716 if (parent_sd->s_flags & SYSFS_FLAG_NS) 730 if (parent_sd->s_flags & SYSFS_FLAG_NS)
717 ns = sysfs_info(dir->i_sb)->ns; 731 ns = sysfs_info(dir->i_sb)->ns;
718 732
719 sd = sysfs_find_dirent(parent_sd, dentry->d_name.name, ns); 733 sd = kernfs_find_ns(parent_sd, dentry->d_name.name, ns);
720 734
721 /* no such entry */ 735 /* no such entry */
722 if (!sd) { 736 if (!sd) {
723 ret = ERR_PTR(-ENOENT); 737 ret = ERR_PTR(-ENOENT);
724 goto out_unlock; 738 goto out_unlock;
725 } 739 }
726 dentry->d_fsdata = sysfs_get(sd); 740 kernfs_get(sd);
741 dentry->d_fsdata = sd;
727 742
728 /* attach dentry and inode */ 743 /* attach dentry and inode */
729 inode = sysfs_get_inode(dir->i_sb, sd); 744 inode = sysfs_get_inode(dir->i_sb, sd);
@@ -859,7 +874,7 @@ int kernfs_remove_by_name_ns(struct sysfs_dirent *dir_sd, const char *name,
859 874
860 sysfs_addrm_start(&acxt); 875 sysfs_addrm_start(&acxt);
861 876
862 sd = sysfs_find_dirent(dir_sd, name, ns); 877 sd = kernfs_find_ns(dir_sd, name, ns);
863 if (sd) 878 if (sd)
864 __kernfs_remove(&acxt, sd); 879 __kernfs_remove(&acxt, sd);
865 880
@@ -925,7 +940,7 @@ int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent,
925 goto out; /* nothing to rename */ 940 goto out; /* nothing to rename */
926 941
927 error = -EEXIST; 942 error = -EEXIST;
928 if (sysfs_find_dirent(new_parent, new_name, new_ns)) 943 if (kernfs_find_ns(new_parent, new_name, new_ns))
929 goto out; 944 goto out;
930 945
931 /* rename sysfs_dirent */ 946 /* rename sysfs_dirent */
@@ -943,8 +958,8 @@ int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent,
943 * Move to the appropriate place in the appropriate directories rbtree. 958 * Move to the appropriate place in the appropriate directories rbtree.
944 */ 959 */
945 sysfs_unlink_sibling(sd); 960 sysfs_unlink_sibling(sd);
946 sysfs_get(new_parent); 961 kernfs_get(new_parent);
947 sysfs_put(sd->s_parent); 962 kernfs_put(sd->s_parent);
948 sd->s_ns = new_ns; 963 sd->s_ns = new_ns;
949 sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); 964 sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
950 sd->s_parent = new_parent; 965 sd->s_parent = new_parent;
@@ -1000,7 +1015,7 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
1000 1015
1001static int sysfs_dir_release(struct inode *inode, struct file *filp) 1016static int sysfs_dir_release(struct inode *inode, struct file *filp)
1002{ 1017{
1003 sysfs_put(filp->private_data); 1018 kernfs_put(filp->private_data);
1004 return 0; 1019 return 0;
1005} 1020}
1006 1021
@@ -1011,7 +1026,7 @@ static struct sysfs_dirent *sysfs_dir_pos(const void *ns,
1011 int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && 1026 int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
1012 pos->s_parent == parent_sd && 1027 pos->s_parent == parent_sd &&
1013 hash == pos->s_hash; 1028 hash == pos->s_hash;
1014 sysfs_put(pos); 1029 kernfs_put(pos);
1015 if (!valid) 1030 if (!valid)
1016 pos = NULL; 1031 pos = NULL;
1017 } 1032 }
@@ -1075,8 +1090,10 @@ static int sysfs_readdir(struct file *file, struct dir_context *ctx)
1075 unsigned int type = dt_type(pos); 1090 unsigned int type = dt_type(pos);
1076 int len = strlen(name); 1091 int len = strlen(name);
1077 ino_t ino = pos->s_ino; 1092 ino_t ino = pos->s_ino;
1093
1078 ctx->pos = pos->s_hash; 1094 ctx->pos = pos->s_hash;
1079 file->private_data = sysfs_get(pos); 1095 file->private_data = pos;
1096 kernfs_get(pos);
1080 1097
1081 mutex_unlock(&sysfs_mutex); 1098 mutex_unlock(&sysfs_mutex);
1082 if (!dir_emit(ctx, name, len, ino, type)) 1099 if (!dir_emit(ctx, name, len, ino, type))
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index e4eca285b390..7f0a79fa2ed8 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -881,19 +881,19 @@ void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
881 struct sysfs_dirent *sd = k->sd, *tmp; 881 struct sysfs_dirent *sd = k->sd, *tmp;
882 882
883 if (sd && dir) 883 if (sd && dir)
884 sd = sysfs_get_dirent(sd, dir); 884 sd = kernfs_find_and_get(sd, dir);
885 else 885 else
886 sysfs_get(sd); 886 kernfs_get(sd);
887 887
888 if (sd && attr) { 888 if (sd && attr) {
889 tmp = sysfs_get_dirent(sd, attr); 889 tmp = kernfs_find_and_get(sd, attr);
890 sysfs_put(sd); 890 kernfs_put(sd);
891 sd = tmp; 891 sd = tmp;
892 } 892 }
893 893
894 if (sd) { 894 if (sd) {
895 kernfs_notify(sd); 895 kernfs_notify(sd);
896 sysfs_put(sd); 896 kernfs_put(sd);
897 } 897 }
898} 898}
899EXPORT_SYMBOL_GPL(sysfs_notify); 899EXPORT_SYMBOL_GPL(sysfs_notify);
@@ -1052,7 +1052,7 @@ struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent,
1052 sysfs_addrm_finish(&acxt); 1052 sysfs_addrm_finish(&acxt);
1053 1053
1054 if (rc) { 1054 if (rc) {
1055 sysfs_put(sd); 1055 kernfs_put(sd);
1056 return ERR_PTR(rc); 1056 return ERR_PTR(rc);
1057 } 1057 }
1058 return sd; 1058 return sd;
@@ -1106,16 +1106,18 @@ int sysfs_add_file_to_group(struct kobject *kobj,
1106 struct sysfs_dirent *dir_sd; 1106 struct sysfs_dirent *dir_sd;
1107 int error; 1107 int error;
1108 1108
1109 if (group) 1109 if (group) {
1110 dir_sd = sysfs_get_dirent(kobj->sd, group); 1110 dir_sd = kernfs_find_and_get(kobj->sd, group);
1111 else 1111 } else {
1112 dir_sd = sysfs_get(kobj->sd); 1112 dir_sd = kobj->sd;
1113 kernfs_get(dir_sd);
1114 }
1113 1115
1114 if (!dir_sd) 1116 if (!dir_sd)
1115 return -ENOENT; 1117 return -ENOENT;
1116 1118
1117 error = sysfs_add_file(dir_sd, attr, false); 1119 error = sysfs_add_file(dir_sd, attr, false);
1118 sysfs_put(dir_sd); 1120 kernfs_put(dir_sd);
1119 1121
1120 return error; 1122 return error;
1121} 1123}
@@ -1135,7 +1137,7 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
1135 struct iattr newattrs; 1137 struct iattr newattrs;
1136 int rc; 1138 int rc;
1137 1139
1138 sd = sysfs_get_dirent(kobj->sd, attr->name); 1140 sd = kernfs_find_and_get(kobj->sd, attr->name);
1139 if (!sd) 1141 if (!sd)
1140 return -ENOENT; 1142 return -ENOENT;
1141 1143
@@ -1144,7 +1146,7 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
1144 1146
1145 rc = kernfs_setattr(sd, &newattrs); 1147 rc = kernfs_setattr(sd, &newattrs);
1146 1148
1147 sysfs_put(sd); 1149 kernfs_put(sd);
1148 return rc; 1150 return rc;
1149} 1151}
1150EXPORT_SYMBOL_GPL(sysfs_chmod_file); 1152EXPORT_SYMBOL_GPL(sysfs_chmod_file);
@@ -1185,13 +1187,16 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
1185{ 1187{
1186 struct sysfs_dirent *dir_sd; 1188 struct sysfs_dirent *dir_sd;
1187 1189
1188 if (group) 1190 if (group) {
1189 dir_sd = sysfs_get_dirent(kobj->sd, group); 1191 dir_sd = kernfs_find_and_get(kobj->sd, group);
1190 else 1192 } else {
1191 dir_sd = sysfs_get(kobj->sd); 1193 dir_sd = kobj->sd;
1194 kernfs_get(dir_sd);
1195 }
1196
1192 if (dir_sd) { 1197 if (dir_sd) {
1193 kernfs_remove_by_name(dir_sd, attr->name); 1198 kernfs_remove_by_name(dir_sd, attr->name);
1194 sysfs_put(dir_sd); 1199 kernfs_put(dir_sd);
1195 } 1200 }
1196} 1201}
1197EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); 1202EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 9f65cd97a2d7..7177532b8f7b 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -108,13 +108,13 @@ static int internal_create_group(struct kobject *kobj, int update,
108 } 108 }
109 } else 109 } else
110 sd = kobj->sd; 110 sd = kobj->sd;
111 sysfs_get(sd); 111 kernfs_get(sd);
112 error = create_files(sd, kobj, grp, update); 112 error = create_files(sd, kobj, grp, update);
113 if (error) { 113 if (error) {
114 if (grp->name) 114 if (grp->name)
115 kernfs_remove(sd); 115 kernfs_remove(sd);
116 } 116 }
117 sysfs_put(sd); 117 kernfs_put(sd);
118 return error; 118 return error;
119} 119}
120 120
@@ -208,21 +208,23 @@ void sysfs_remove_group(struct kobject *kobj,
208 struct sysfs_dirent *sd; 208 struct sysfs_dirent *sd;
209 209
210 if (grp->name) { 210 if (grp->name) {
211 sd = sysfs_get_dirent(dir_sd, grp->name); 211 sd = kernfs_find_and_get(dir_sd, grp->name);
212 if (!sd) { 212 if (!sd) {
213 WARN(!sd, KERN_WARNING 213 WARN(!sd, KERN_WARNING
214 "sysfs group %p not found for kobject '%s'\n", 214 "sysfs group %p not found for kobject '%s'\n",
215 grp, kobject_name(kobj)); 215 grp, kobject_name(kobj));
216 return; 216 return;
217 } 217 }
218 } else 218 } else {
219 sd = sysfs_get(dir_sd); 219 sd = dir_sd;
220 kernfs_get(sd);
221 }
220 222
221 remove_files(sd, kobj, grp); 223 remove_files(sd, kobj, grp);
222 if (grp->name) 224 if (grp->name)
223 kernfs_remove(sd); 225 kernfs_remove(sd);
224 226
225 sysfs_put(sd); 227 kernfs_put(sd);
226} 228}
227EXPORT_SYMBOL_GPL(sysfs_remove_group); 229EXPORT_SYMBOL_GPL(sysfs_remove_group);
228 230
@@ -263,7 +265,7 @@ int sysfs_merge_group(struct kobject *kobj,
263 struct attribute *const *attr; 265 struct attribute *const *attr;
264 int i; 266 int i;
265 267
266 dir_sd = sysfs_get_dirent(kobj->sd, grp->name); 268 dir_sd = kernfs_find_and_get(kobj->sd, grp->name);
267 if (!dir_sd) 269 if (!dir_sd)
268 return -ENOENT; 270 return -ENOENT;
269 271
@@ -273,7 +275,7 @@ int sysfs_merge_group(struct kobject *kobj,
273 while (--i >= 0) 275 while (--i >= 0)
274 kernfs_remove_by_name(dir_sd, (*--attr)->name); 276 kernfs_remove_by_name(dir_sd, (*--attr)->name);
275 } 277 }
276 sysfs_put(dir_sd); 278 kernfs_put(dir_sd);
277 279
278 return error; 280 return error;
279} 281}
@@ -290,11 +292,11 @@ void sysfs_unmerge_group(struct kobject *kobj,
290 struct sysfs_dirent *dir_sd; 292 struct sysfs_dirent *dir_sd;
291 struct attribute *const *attr; 293 struct attribute *const *attr;
292 294
293 dir_sd = sysfs_get_dirent(kobj->sd, grp->name); 295 dir_sd = kernfs_find_and_get(kobj->sd, grp->name);
294 if (dir_sd) { 296 if (dir_sd) {
295 for (attr = grp->attrs; *attr; ++attr) 297 for (attr = grp->attrs; *attr; ++attr)
296 kernfs_remove_by_name(dir_sd, (*attr)->name); 298 kernfs_remove_by_name(dir_sd, (*attr)->name);
297 sysfs_put(dir_sd); 299 kernfs_put(dir_sd);
298 } 300 }
299} 301}
300EXPORT_SYMBOL_GPL(sysfs_unmerge_group); 302EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
@@ -312,12 +314,12 @@ int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
312 struct sysfs_dirent *dir_sd; 314 struct sysfs_dirent *dir_sd;
313 int error = 0; 315 int error = 0;
314 316
315 dir_sd = sysfs_get_dirent(kobj->sd, group_name); 317 dir_sd = kernfs_find_and_get(kobj->sd, group_name);
316 if (!dir_sd) 318 if (!dir_sd)
317 return -ENOENT; 319 return -ENOENT;
318 320
319 error = sysfs_create_link_sd(dir_sd, target, link_name); 321 error = sysfs_create_link_sd(dir_sd, target, link_name);
320 sysfs_put(dir_sd); 322 kernfs_put(dir_sd);
321 323
322 return error; 324 return error;
323} 325}
@@ -334,10 +336,10 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
334{ 336{
335 struct sysfs_dirent *dir_sd; 337 struct sysfs_dirent *dir_sd;
336 338
337 dir_sd = sysfs_get_dirent(kobj->sd, group_name); 339 dir_sd = kernfs_find_and_get(kobj->sd, group_name);
338 if (dir_sd) { 340 if (dir_sd) {
339 kernfs_remove_by_name(dir_sd, link_name); 341 kernfs_remove_by_name(dir_sd, link_name);
340 sysfs_put(dir_sd); 342 kernfs_put(dir_sd);
341 } 343 }
342} 344}
343EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group); 345EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index b3c717ab3496..bfe4478f82bf 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -254,7 +254,8 @@ int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
254 254
255static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) 255static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
256{ 256{
257 inode->i_private = sysfs_get(sd); 257 kernfs_get(sd);
258 inode->i_private = sd;
258 inode->i_mapping->a_ops = &sysfs_aops; 259 inode->i_mapping->a_ops = &sysfs_aops;
259 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; 260 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
260 inode->i_op = &sysfs_inode_operations; 261 inode->i_op = &sysfs_inode_operations;
@@ -321,7 +322,7 @@ void sysfs_evict_inode(struct inode *inode)
321 322
322 truncate_inode_pages(&inode->i_data, 0); 323 truncate_inode_pages(&inode->i_data, 0);
323 clear_inode(inode); 324 clear_inode(inode);
324 sysfs_put(sd); 325 kernfs_put(sd);
325} 326}
326 327
327int sysfs_permission(struct inode *inode, int mask) 328int sysfs_permission(struct inode *inode, int mask)
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 8c24bce2f4ae..852d11519f98 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -184,17 +184,3 @@ out_err:
184 sysfs_dir_cachep = NULL; 184 sysfs_dir_cachep = NULL;
185 goto out; 185 goto out;
186} 186}
187
188#undef sysfs_get
189struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
190{
191 return __sysfs_get(sd);
192}
193EXPORT_SYMBOL_GPL(sysfs_get);
194
195#undef sysfs_put
196void sysfs_put(struct sysfs_dirent *sd)
197{
198 __sysfs_put(sd);
199}
200EXPORT_SYMBOL_GPL(sysfs_put);
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 76efeab6db4e..b137aa3a486c 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -44,7 +44,7 @@ struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
44 if (parent->s_flags & SYSFS_FLAG_NS) 44 if (parent->s_flags & SYSFS_FLAG_NS)
45 sd->s_ns = target->s_ns; 45 sd->s_ns = target->s_ns;
46 sd->s_symlink.target_sd = target; 46 sd->s_symlink.target_sd = target;
47 sysfs_get(target); /* ref owned by symlink */ 47 kernfs_get(target); /* ref owned by symlink */
48 48
49 sysfs_addrm_start(&acxt); 49 sysfs_addrm_start(&acxt);
50 error = sysfs_add_one(&acxt, sd, parent); 50 error = sysfs_add_one(&acxt, sd, parent);
@@ -53,7 +53,7 @@ struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
53 if (!error) 53 if (!error)
54 return sd; 54 return sd;
55 55
56 sysfs_put(sd); 56 kernfs_put(sd);
57 return ERR_PTR(error); 57 return ERR_PTR(error);
58} 58}
59 59
@@ -72,15 +72,17 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
72 * sysfs_remove_dir() for details. 72 * sysfs_remove_dir() for details.
73 */ 73 */
74 spin_lock(&sysfs_symlink_target_lock); 74 spin_lock(&sysfs_symlink_target_lock);
75 if (target->sd) 75 if (target->sd) {
76 target_sd = sysfs_get(target->sd); 76 target_sd = target->sd;
77 kernfs_get(target_sd);
78 }
77 spin_unlock(&sysfs_symlink_target_lock); 79 spin_unlock(&sysfs_symlink_target_lock);
78 80
79 if (!target_sd) 81 if (!target_sd)
80 return -ENOENT; 82 return -ENOENT;
81 83
82 sd = kernfs_create_link(parent_sd, name, target_sd); 84 sd = kernfs_create_link(parent_sd, name, target_sd);
83 sysfs_put(target_sd); 85 kernfs_put(target_sd);
84 86
85 if (!IS_ERR(sd)) 87 if (!IS_ERR(sd))
86 return 0; 88 return 0;
@@ -216,7 +218,7 @@ int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
216 old_ns = targ->sd->s_ns; 218 old_ns = targ->sd->s_ns;
217 219
218 result = -ENOENT; 220 result = -ENOENT;
219 sd = sysfs_get_dirent_ns(parent_sd, old, old_ns); 221 sd = kernfs_find_and_get_ns(parent_sd, old, old_ns);
220 if (!sd) 222 if (!sd)
221 goto out; 223 goto out;
222 224
@@ -229,7 +231,7 @@ int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
229 result = kernfs_rename_ns(sd, parent_sd, new, new_ns); 231 result = kernfs_rename_ns(sd, parent_sd, new, new_ns);
230 232
231out: 233out:
232 sysfs_put(sd); 234 kernfs_put(sd);
233 return result; 235 return result;
234} 236}
235EXPORT_SYMBOL_GPL(sysfs_rename_link_ns); 237EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index e93f8b845611..85315e228408 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -141,30 +141,8 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
141 struct sysfs_dirent *parent_sd); 141 struct sysfs_dirent *parent_sd);
142void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); 142void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
143 143
144struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
145 const unsigned char *name,
146 const void *ns);
147struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); 144struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
148 145
149void release_sysfs_dirent(struct sysfs_dirent *sd);
150
151static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
152{
153 if (sd) {
154 WARN_ON(!atomic_read(&sd->s_count));
155 atomic_inc(&sd->s_count);
156 }
157 return sd;
158}
159#define sysfs_get(sd) __sysfs_get(sd)
160
161static inline void __sysfs_put(struct sysfs_dirent *sd)
162{
163 if (sd && atomic_dec_and_test(&sd->s_count))
164 release_sysfs_dirent(sd);
165}
166#define sysfs_put(sd) __sysfs_put(sd)
167
168/* 146/*
169 * inode.c 147 * inode.c
170 */ 148 */