Skip to content

Commit

Permalink
sysfs: allocate inode number using ida
Browse files Browse the repository at this point in the history
sysfs used simple incrementing allocator which is not guaranteed to be
unique.  This patch makes sysfs use ida to give each sd a unique and
packed inode number.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Tejun Heo authored and Greg Kroah-Hartman committed Jul 11, 2007
1 parent fa7f912 commit 2b611bb
Showing 1 changed file with 36 additions and 9 deletions.
45 changes: 36 additions & 9 deletions fs/sysfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,42 @@
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/namei.h>
#include <linux/idr.h>
#include <asm/semaphore.h>
#include "sysfs.h"

DECLARE_RWSEM(sysfs_rename_sem);
spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;

static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_IDA(sysfs_ino_ida);

int sysfs_alloc_ino(ino_t *pino)
{
int ino, rc;

retry:
spin_lock(&sysfs_ino_lock);
rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
spin_unlock(&sysfs_ino_lock);

if (rc == -EAGAIN) {
if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
goto retry;
rc = -ENOMEM;
}

*pino = ino;
return rc;
}

static void sysfs_free_ino(ino_t ino)
{
spin_lock(&sysfs_ino_lock);
ida_remove(&sysfs_ino_ida, ino);
spin_unlock(&sysfs_ino_lock);
}

void release_sysfs_dirent(struct sysfs_dirent * sd)
{
if (sd->s_type & SYSFS_KOBJ_LINK) {
Expand All @@ -24,6 +54,7 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
kfree(sl);
}
kfree(sd->s_iattr);
sysfs_free_ino(sd->s_ino);
kmem_cache_free(sysfs_dir_cachep, sd);
}

Expand Down Expand Up @@ -54,14 +85,6 @@ static struct dentry_operations sysfs_dentry_ops = {
.d_iput = sysfs_d_iput,
};

static unsigned int sysfs_inode_counter;
ino_t sysfs_get_inum(void)
{
if (unlikely(sysfs_inode_counter < 3))
sysfs_inode_counter = 3;
return sysfs_inode_counter++;
}

/*
* Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
*/
Expand All @@ -73,7 +96,11 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element)
if (!sd)
return NULL;

sd->s_ino = sysfs_get_inum();
if (sysfs_alloc_ino(&sd->s_ino)) {
kmem_cache_free(sysfs_dir_cachep, sd);
return NULL;
}

atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_event, 1);
INIT_LIST_HEAD(&sd->s_children);
Expand Down

0 comments on commit 2b611bb

Please sign in to comment.