aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/kernfs/dir.c47
-rw-r--r--fs/kernfs/file.c4
-rw-r--r--fs/kernfs/kernfs-internal.h3
-rw-r--r--fs/kernfs/symlink.c3
-rw-r--r--include/linux/kernfs.h4
5 files changed, 23 insertions, 38 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 246740a741ef..eaffa83719d5 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -21,9 +21,6 @@ DEFINE_MUTEX(sysfs_mutex);
21 21
22#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb) 22#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb)
23 23
24static DEFINE_SPINLOCK(sysfs_ino_lock);
25static DEFINE_IDA(sysfs_ino_ida);
26
27/** 24/**
28 * sysfs_name_hash 25 * sysfs_name_hash
29 * @name: Null terminated string to hash 26 * @name: Null terminated string to hash
@@ -205,32 +202,6 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
205 rwsem_release(&sd->dep_map, 1, _RET_IP_); 202 rwsem_release(&sd->dep_map, 1, _RET_IP_);
206} 203}
207 204
208static int sysfs_alloc_ino(unsigned int *pino)
209{
210 int ino, rc;
211
212 retry:
213 spin_lock(&sysfs_ino_lock);
214 rc = ida_get_new_above(&sysfs_ino_ida, 1, &ino);
215 spin_unlock(&sysfs_ino_lock);
216
217 if (rc == -EAGAIN) {
218 if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
219 goto retry;
220 rc = -ENOMEM;
221 }
222
223 *pino = ino;
224 return rc;
225}
226
227static void sysfs_free_ino(unsigned int ino)
228{
229 spin_lock(&sysfs_ino_lock);
230 ida_remove(&sysfs_ino_ida, ino);
231 spin_unlock(&sysfs_ino_lock);
232}
233
234/** 205/**
235 * kernfs_get - get a reference count on a sysfs_dirent 206 * kernfs_get - get a reference count on a sysfs_dirent
236 * @sd: the target sysfs_dirent 207 * @sd: the target sysfs_dirent
@@ -276,7 +247,7 @@ void kernfs_put(struct sysfs_dirent *sd)
276 security_release_secctx(sd->s_iattr->ia_secdata, 247 security_release_secctx(sd->s_iattr->ia_secdata,
277 sd->s_iattr->ia_secdata_len); 248 sd->s_iattr->ia_secdata_len);
278 kfree(sd->s_iattr); 249 kfree(sd->s_iattr);
279 sysfs_free_ino(sd->s_ino); 250 ida_simple_remove(&root->ino_ida, sd->s_ino);
280 kmem_cache_free(sysfs_dir_cachep, sd); 251 kmem_cache_free(sysfs_dir_cachep, sd);
281 252
282 sd = parent_sd; 253 sd = parent_sd;
@@ -285,6 +256,7 @@ void kernfs_put(struct sysfs_dirent *sd)
285 goto repeat; 256 goto repeat;
286 } else { 257 } else {
287 /* just released the root sd, free @root too */ 258 /* just released the root sd, free @root too */
259 ida_destroy(&root->ino_ida);
288 kfree(root); 260 kfree(root);
289 } 261 }
290} 262}
@@ -360,10 +332,12 @@ const struct dentry_operations sysfs_dentry_ops = {
360 .d_release = sysfs_dentry_release, 332 .d_release = sysfs_dentry_release,
361}; 333};
362 334
363struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) 335struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root,
336 const char *name, umode_t mode, int type)
364{ 337{
365 char *dup_name = NULL; 338 char *dup_name = NULL;
366 struct sysfs_dirent *sd; 339 struct sysfs_dirent *sd;
340 int ret;
367 341
368 if (type & SYSFS_COPY_NAME) { 342 if (type & SYSFS_COPY_NAME) {
369 name = dup_name = kstrdup(name, GFP_KERNEL); 343 name = dup_name = kstrdup(name, GFP_KERNEL);
@@ -375,8 +349,10 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
375 if (!sd) 349 if (!sd)
376 goto err_out1; 350 goto err_out1;
377 351
378 if (sysfs_alloc_ino(&sd->s_ino)) 352 ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL);
353 if (ret < 0)
379 goto err_out2; 354 goto err_out2;
355 sd->s_ino = ret;
380 356
381 atomic_set(&sd->s_count, 1); 357 atomic_set(&sd->s_count, 1);
382 atomic_set(&sd->s_active, 0); 358 atomic_set(&sd->s_active, 0);
@@ -628,8 +604,11 @@ struct kernfs_root *kernfs_create_root(void *priv)
628 if (!root) 604 if (!root)
629 return ERR_PTR(-ENOMEM); 605 return ERR_PTR(-ENOMEM);
630 606
631 sd = sysfs_new_dirent("", S_IFDIR | S_IRUGO | S_IXUGO, SYSFS_DIR); 607 ida_init(&root->ino_ida);
608
609 sd = sysfs_new_dirent(root, "", S_IFDIR | S_IRUGO | S_IXUGO, SYSFS_DIR);
632 if (!sd) { 610 if (!sd) {
611 ida_destroy(&root->ino_ida);
633 kfree(root); 612 kfree(root);
634 return ERR_PTR(-ENOMEM); 613 return ERR_PTR(-ENOMEM);
635 } 614 }
@@ -674,7 +653,7 @@ struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent,
674 int rc; 653 int rc;
675 654
676 /* allocate */ 655 /* allocate */
677 sd = sysfs_new_dirent(name, mode, SYSFS_DIR); 656 sd = sysfs_new_dirent(kernfs_root(parent), name, mode, SYSFS_DIR);
678 if (!sd) 657 if (!sd)
679 return ERR_PTR(-ENOMEM); 658 return ERR_PTR(-ENOMEM);
680 659
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index fa172e86047f..990c97fa7045 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -775,8 +775,8 @@ struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent,
775 struct sysfs_dirent *sd; 775 struct sysfs_dirent *sd;
776 int rc; 776 int rc;
777 777
778 sd = sysfs_new_dirent(name, (mode & S_IALLUGO) | S_IFREG, 778 sd = sysfs_new_dirent(kernfs_root(parent), name,
779 SYSFS_KOBJ_ATTR); 779 (mode & S_IALLUGO) | S_IFREG, SYSFS_KOBJ_ATTR);
780 if (!sd) 780 if (!sd)
781 return ERR_PTR(-ENOMEM); 781 return ERR_PTR(-ENOMEM);
782 782
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 7dfe06278350..466943d576f1 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -160,7 +160,8 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt);
160int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, 160int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
161 struct sysfs_dirent *parent_sd); 161 struct sysfs_dirent *parent_sd);
162void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); 162void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
163struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); 163struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root,
164 const char *name, umode_t mode, int type);
164 165
165/* 166/*
166 * file.c 167 * file.c
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index af3570bb4303..004c16465594 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -30,7 +30,8 @@ struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
30 struct sysfs_addrm_cxt acxt; 30 struct sysfs_addrm_cxt acxt;
31 int error; 31 int error;
32 32
33 sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); 33 sd = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO,
34 SYSFS_KOBJ_LINK);
34 if (!sd) 35 if (!sd)
35 return ERR_PTR(-ENOMEM); 36 return ERR_PTR(-ENOMEM);
36 37
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index f75548b8ed7a..fad8b986800f 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -11,6 +11,7 @@
11#include <linux/err.h> 11#include <linux/err.h>
12#include <linux/list.h> 12#include <linux/list.h>
13#include <linux/mutex.h> 13#include <linux/mutex.h>
14#include <linux/idr.h>
14#include <linux/lockdep.h> 15#include <linux/lockdep.h>
15 16
16struct file; 17struct file;
@@ -23,6 +24,9 @@ struct sysfs_dirent;
23struct kernfs_root { 24struct kernfs_root {
24 /* published fields */ 25 /* published fields */
25 struct sysfs_dirent *sd; 26 struct sysfs_dirent *sd;
27
28 /* private fields, do not use outside kernfs proper */
29 struct ida ino_ida;
26}; 30};
27 31
28struct sysfs_open_file { 32struct sysfs_open_file {