diff options
-rw-r--r-- | fs/kernfs/dir.c | 47 | ||||
-rw-r--r-- | fs/kernfs/file.c | 4 | ||||
-rw-r--r-- | fs/kernfs/kernfs-internal.h | 3 | ||||
-rw-r--r-- | fs/kernfs/symlink.c | 3 | ||||
-rw-r--r-- | include/linux/kernfs.h | 4 |
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 | ||
24 | static DEFINE_SPINLOCK(sysfs_ino_lock); | ||
25 | static 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 | ||
208 | static 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 | |||
227 | static 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 | ||
363 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | 335 | struct 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); | |||
160 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, | 160 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, |
161 | struct sysfs_dirent *parent_sd); | 161 | struct sysfs_dirent *parent_sd); |
162 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | 162 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); |
163 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); | 163 | struct 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 | ||
16 | struct file; | 17 | struct file; |
@@ -23,6 +24,9 @@ struct sysfs_dirent; | |||
23 | struct kernfs_root { | 24 | struct 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 | ||
28 | struct sysfs_open_file { | 32 | struct sysfs_open_file { |