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.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 2544aae6f583..f09626cc568a 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -9,12 +9,42 @@
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/kobject.h> 10#include <linux/kobject.h>
11#include <linux/namei.h> 11#include <linux/namei.h>
12#include <linux/idr.h>
12#include <asm/semaphore.h> 13#include <asm/semaphore.h>
13#include "sysfs.h" 14#include "sysfs.h"
14 15
15DECLARE_RWSEM(sysfs_rename_sem); 16DECLARE_RWSEM(sysfs_rename_sem);
16spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED; 17spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;
17 18
19static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
20static DEFINE_IDA(sysfs_ino_ida);
21
22int sysfs_alloc_ino(ino_t *pino)
23{
24 int ino, rc;
25
26 retry:
27 spin_lock(&sysfs_ino_lock);
28 rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
29 spin_unlock(&sysfs_ino_lock);
30
31 if (rc == -EAGAIN) {
32 if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
33 goto retry;
34 rc = -ENOMEM;
35 }
36
37 *pino = ino;
38 return rc;
39}
40
41static void sysfs_free_ino(ino_t ino)
42{
43 spin_lock(&sysfs_ino_lock);
44 ida_remove(&sysfs_ino_ida, ino);
45 spin_unlock(&sysfs_ino_lock);
46}
47
18void release_sysfs_dirent(struct sysfs_dirent * sd) 48void release_sysfs_dirent(struct sysfs_dirent * sd)
19{ 49{
20 if (sd->s_type & SYSFS_KOBJ_LINK) { 50 if (sd->s_type & SYSFS_KOBJ_LINK) {
@@ -24,6 +54,7 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
24 kfree(sl); 54 kfree(sl);
25 } 55 }
26 kfree(sd->s_iattr); 56 kfree(sd->s_iattr);
57 sysfs_free_ino(sd->s_ino);
27 kmem_cache_free(sysfs_dir_cachep, sd); 58 kmem_cache_free(sysfs_dir_cachep, sd);
28} 59}
29 60
@@ -54,14 +85,6 @@ static struct dentry_operations sysfs_dentry_ops = {
54 .d_iput = sysfs_d_iput, 85 .d_iput = sysfs_d_iput,
55}; 86};
56 87
57static unsigned int sysfs_inode_counter;
58ino_t sysfs_get_inum(void)
59{
60 if (unlikely(sysfs_inode_counter < 3))
61 sysfs_inode_counter = 3;
62 return sysfs_inode_counter++;
63}
64
65/* 88/*
66 * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent 89 * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
67 */ 90 */
@@ -73,7 +96,11 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element)
73 if (!sd) 96 if (!sd)
74 return NULL; 97 return NULL;
75 98
76 sd->s_ino = sysfs_get_inum(); 99 if (sysfs_alloc_ino(&sd->s_ino)) {
100 kmem_cache_free(sysfs_dir_cachep, sd);
101 return NULL;
102 }
103
77 atomic_set(&sd->s_count, 1); 104 atomic_set(&sd->s_count, 1);
78 atomic_set(&sd->s_event, 1); 105 atomic_set(&sd->s_event, 1);
79 INIT_LIST_HEAD(&sd->s_children); 106 INIT_LIST_HEAD(&sd->s_children);