提交 bc755553 编写于 作者: T Tejun Heo 提交者: Greg Kroah-Hartman

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: NTejun Heo <tj@kernel.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 ba7443bc
...@@ -21,9 +21,6 @@ DEFINE_MUTEX(sysfs_mutex); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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); ...@@ -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, ...@@ -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 @@ ...@@ -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; ...@@ -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 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册