sysfs, kernfs: make inode number ida per kernfs_root
kernfs is being updated to allow multiple sysfs_dirent hierarchies so that it can also be used by other users. Currently, inode number is allocated using a global ida, sysfs_ino_ida; however, inos for different hierarchies should be handled separately. This patch makes ino allocation per kernfs_root. sysfs_ino_ida is replaced by kernfs_root->ino_ida and sysfs_new_dirent() is updated to take @root and allocate ino from it. ida_simple_get/remove() are used instead of sysfs_ino_lock and sysfs_alloc/free_ino(). Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ba7443bc65
commit
bc755553df
@@ -21,9 +21,6 @@ DEFINE_MUTEX(sysfs_mutex);
|
|||||||
|
|
||||||
#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb)
|
#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb)
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(sysfs_ino_lock);
|
|
||||||
static DEFINE_IDA(sysfs_ino_ida);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_name_hash
|
* sysfs_name_hash
|
||||||
* @name: Null terminated string to hash
|
* @name: Null terminated string to hash
|
||||||
@@ -205,32 +202,6 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
|
|||||||
rwsem_release(&sd->dep_map, 1, _RET_IP_);
|
rwsem_release(&sd->dep_map, 1, _RET_IP_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sysfs_alloc_ino(unsigned int *pino)
|
|
||||||
{
|
|
||||||
int ino, rc;
|
|
||||||
|
|
||||||
retry:
|
|
||||||
spin_lock(&sysfs_ino_lock);
|
|
||||||
rc = ida_get_new_above(&sysfs_ino_ida, 1, &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(unsigned int ino)
|
|
||||||
{
|
|
||||||
spin_lock(&sysfs_ino_lock);
|
|
||||||
ida_remove(&sysfs_ino_ida, ino);
|
|
||||||
spin_unlock(&sysfs_ino_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kernfs_get - get a reference count on a sysfs_dirent
|
* kernfs_get - get a reference count on a sysfs_dirent
|
||||||
* @sd: the target sysfs_dirent
|
* @sd: the target sysfs_dirent
|
||||||
@@ -276,7 +247,7 @@ void kernfs_put(struct sysfs_dirent *sd)
|
|||||||
security_release_secctx(sd->s_iattr->ia_secdata,
|
security_release_secctx(sd->s_iattr->ia_secdata,
|
||||||
sd->s_iattr->ia_secdata_len);
|
sd->s_iattr->ia_secdata_len);
|
||||||
kfree(sd->s_iattr);
|
kfree(sd->s_iattr);
|
||||||
sysfs_free_ino(sd->s_ino);
|
ida_simple_remove(&root->ino_ida, sd->s_ino);
|
||||||
kmem_cache_free(sysfs_dir_cachep, sd);
|
kmem_cache_free(sysfs_dir_cachep, sd);
|
||||||
|
|
||||||
sd = parent_sd;
|
sd = parent_sd;
|
||||||
@@ -285,6 +256,7 @@ void kernfs_put(struct sysfs_dirent *sd)
|
|||||||
goto repeat;
|
goto repeat;
|
||||||
} else {
|
} else {
|
||||||
/* just released the root sd, free @root too */
|
/* just released the root sd, free @root too */
|
||||||
|
ida_destroy(&root->ino_ida);
|
||||||
kfree(root);
|
kfree(root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -360,10 +332,12 @@ const struct dentry_operations sysfs_dentry_ops = {
|
|||||||
.d_release = sysfs_dentry_release,
|
.d_release = sysfs_dentry_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
|
struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root,
|
||||||
|
const char *name, umode_t mode, int type)
|
||||||
{
|
{
|
||||||
char *dup_name = NULL;
|
char *dup_name = NULL;
|
||||||
struct sysfs_dirent *sd;
|
struct sysfs_dirent *sd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (type & SYSFS_COPY_NAME) {
|
if (type & SYSFS_COPY_NAME) {
|
||||||
name = dup_name = kstrdup(name, GFP_KERNEL);
|
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)
|
|||||||
if (!sd)
|
if (!sd)
|
||||||
goto err_out1;
|
goto err_out1;
|
||||||
|
|
||||||
if (sysfs_alloc_ino(&sd->s_ino))
|
ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL);
|
||||||
|
if (ret < 0)
|
||||||
goto err_out2;
|
goto err_out2;
|
||||||
|
sd->s_ino = ret;
|
||||||
|
|
||||||
atomic_set(&sd->s_count, 1);
|
atomic_set(&sd->s_count, 1);
|
||||||
atomic_set(&sd->s_active, 0);
|
atomic_set(&sd->s_active, 0);
|
||||||
@@ -628,8 +604,11 @@ struct kernfs_root *kernfs_create_root(void *priv)
|
|||||||
if (!root)
|
if (!root)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
sd = sysfs_new_dirent("", S_IFDIR | S_IRUGO | S_IXUGO, SYSFS_DIR);
|
ida_init(&root->ino_ida);
|
||||||
|
|
||||||
|
sd = sysfs_new_dirent(root, "", S_IFDIR | S_IRUGO | S_IXUGO, SYSFS_DIR);
|
||||||
if (!sd) {
|
if (!sd) {
|
||||||
|
ida_destroy(&root->ino_ida);
|
||||||
kfree(root);
|
kfree(root);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
@@ -674,7 +653,7 @@ struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent,
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* allocate */
|
/* allocate */
|
||||||
sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
|
sd = sysfs_new_dirent(kernfs_root(parent), name, mode, SYSFS_DIR);
|
||||||
if (!sd)
|
if (!sd)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
@@ -775,8 +775,8 @@ struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent,
|
|||||||
struct sysfs_dirent *sd;
|
struct sysfs_dirent *sd;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
sd = sysfs_new_dirent(name, (mode & S_IALLUGO) | S_IFREG,
|
sd = sysfs_new_dirent(kernfs_root(parent), name,
|
||||||
SYSFS_KOBJ_ATTR);
|
(mode & S_IALLUGO) | S_IFREG, SYSFS_KOBJ_ATTR);
|
||||||
if (!sd)
|
if (!sd)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
@@ -160,7 +160,8 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt);
|
|||||||
int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
|
int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
|
||||||
struct sysfs_dirent *parent_sd);
|
struct sysfs_dirent *parent_sd);
|
||||||
void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
|
void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
|
||||||
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
|
struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root,
|
||||||
|
const char *name, umode_t mode, int type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* file.c
|
* file.c
|
||||||
|
@@ -30,7 +30,8 @@ struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
|
|||||||
struct sysfs_addrm_cxt acxt;
|
struct sysfs_addrm_cxt acxt;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
|
sd = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO,
|
||||||
|
SYSFS_KOBJ_LINK);
|
||||||
if (!sd)
|
if (!sd)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/idr.h>
|
||||||
#include <linux/lockdep.h>
|
#include <linux/lockdep.h>
|
||||||
|
|
||||||
struct file;
|
struct file;
|
||||||
@@ -23,6 +24,9 @@ struct sysfs_dirent;
|
|||||||
struct kernfs_root {
|
struct kernfs_root {
|
||||||
/* published fields */
|
/* published fields */
|
||||||
struct sysfs_dirent *sd;
|
struct sysfs_dirent *sd;
|
||||||
|
|
||||||
|
/* private fields, do not use outside kernfs proper */
|
||||||
|
struct ida ino_ida;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_open_file {
|
struct sysfs_open_file {
|
||||||
|
Reference in New Issue
Block a user