Skip to content

Commit

Permalink
fix struct user_info export's sysfs interaction
Browse files Browse the repository at this point in the history
Clean up the use of ksets and kobjects. Kobjects are instances of
objects (like struct user_info), ksets are collections of objects of a
similar type (like the uids directory containing the user_info directories).
So, use kobjects for the user_info directories, and a kset for the "uids"
directory.

On object cleanup, the final kobject_put() was missing.

Cc: Dhaval Giani <dhaval@linux.vnet.ibm.com>
Cc: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Kay Sievers authored and Greg Kroah-Hartman committed Jan 25, 2008
1 parent 386f275 commit eb41d94
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 65 deletions.
9 changes: 2 additions & 7 deletions include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -552,18 +552,13 @@ struct user_struct {
#ifdef CONFIG_FAIR_USER_SCHED
struct task_group *tg;
#ifdef CONFIG_SYSFS
struct kset kset;
struct subsys_attribute user_attr;
struct kobject kobj;
struct work_struct work;
#endif
#endif
};

#ifdef CONFIG_FAIR_USER_SCHED
extern int uids_kobject_init(void);
#else
static inline int uids_kobject_init(void) { return 0; }
#endif
extern int uids_sysfs_init(void);

extern struct user_struct *find_user(uid_t);

Expand Down
7 changes: 2 additions & 5 deletions kernel/ksysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,8 @@ static int __init ksysfs_init(void)
goto group_exit;
}

/*
* Create "/sys/kernel/uids" directory and corresponding root user's
* directory under it.
*/
error = uids_kobject_init();
/* create the /sys/kernel/uids/ directory */
error = uids_sysfs_init();
if (error)
goto notes_exit;

Expand Down
104 changes: 51 additions & 53 deletions kernel/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ static void sched_switch_user(struct task_struct *p) { }

#if defined(CONFIG_FAIR_USER_SCHED) && defined(CONFIG_SYSFS)

static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */
static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */
static DEFINE_MUTEX(uids_mutex);

static inline void uids_mutex_lock(void)
Expand All @@ -128,86 +128,84 @@ static inline void uids_mutex_unlock(void)
mutex_unlock(&uids_mutex);
}

/* return cpu shares held by the user */
static ssize_t cpu_shares_show(struct kset *kset, char *buffer)
/* uid directory attributes */
static ssize_t cpu_shares_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
struct user_struct *up = container_of(kset, struct user_struct, kset);
struct user_struct *up = container_of(kobj, struct user_struct, kobj);

return sprintf(buffer, "%lu\n", sched_group_shares(up->tg));
return sprintf(buf, "%lu\n", sched_group_shares(up->tg));
}

/* modify cpu shares held by the user */
static ssize_t cpu_shares_store(struct kset *kset, const char *buffer,
size_t size)
static ssize_t cpu_shares_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t size)
{
struct user_struct *up = container_of(kset, struct user_struct, kset);
struct user_struct *up = container_of(kobj, struct user_struct, kobj);
unsigned long shares;
int rc;

sscanf(buffer, "%lu", &shares);
sscanf(buf, "%lu", &shares);

rc = sched_group_set_shares(up->tg, shares);

return (rc ? rc : size);
}

static void user_attr_init(struct subsys_attribute *sa, char *name, int mode)
static struct kobj_attribute cpu_share_attr =
__ATTR(cpu_share, 0644, cpu_shares_show, cpu_shares_store);

/* default attributes per uid directory */
static struct attribute *uids_attributes[] = {
&cpu_share_attr.attr,
NULL
};

/* the lifetime of user_struct is not managed by the core (now) */
static void uids_release(struct kobject *kobj)
{
sa->attr.name = name;
sa->attr.mode = mode;
sa->show = cpu_shares_show;
sa->store = cpu_shares_store;
return;
}

/* Create "/sys/kernel/uids/<uid>" directory and
* "/sys/kernel/uids/<uid>/cpu_share" file for this user.
*/
static int user_kobject_create(struct user_struct *up)
static struct kobj_type uids_ktype = {
.sysfs_ops = &kobj_sysfs_ops,
.default_attrs = uids_attributes,
.release = uids_release,
};

/* create /sys/kernel/uids/<uid>/cpu_share file for this user */
static int uids_user_create(struct user_struct *up)
{
struct kset *kset = &up->kset;
struct kobject *kobj = &kset->kobj;
struct kobject *kobj = &up->kobj;
int error;

memset(kset, 0, sizeof(struct kset));
kobj->parent = &uids_kobject; /* create under /sys/kernel/uids dir */
kobject_set_name(kobj, "%d", up->uid);
kset_init(kset);
user_attr_init(&up->user_attr, "cpu_share", 0644);

memset(kobj, 0, sizeof(struct kobject));
kobj->ktype = &uids_ktype;
kobj->kset = uids_kset;
kobject_init(kobj);
kobject_set_name(&up->kobj, "%d", up->uid);
error = kobject_add(kobj);
if (error)
goto done;

error = sysfs_create_file(kobj, &up->user_attr.attr);
if (error)
kobject_del(kobj);

kobject_uevent(kobj, KOBJ_ADD);

done:
return error;
}

/* create these in sysfs filesystem:
/* create these entries in sysfs:
* "/sys/kernel/uids" directory
* "/sys/kernel/uids/0" directory (for root user)
* "/sys/kernel/uids/0/cpu_share" file (for root user)
*/
int __init uids_kobject_init(void)
int __init uids_sysfs_init(void)
{
int error;
uids_kset = kset_create_and_add("uids", NULL, &kernel_kset->kobj);
if (!uids_kset)
return -ENOMEM;

/* create under /sys/kernel dir */
uids_kobject.parent = &kernel_kset->kobj;
uids_kobject.kset = kernel_kset;
kobject_set_name(&uids_kobject, "uids");
kobject_init(&uids_kobject);

error = kobject_add(&uids_kobject);
if (!error)
error = user_kobject_create(&root_user);

return error;
return uids_user_create(&root_user);
}

/* work function to remove sysfs directory for a user and free up
Expand All @@ -216,7 +214,6 @@ int __init uids_kobject_init(void)
static void remove_user_sysfs_dir(struct work_struct *w)
{
struct user_struct *up = container_of(w, struct user_struct, work);
struct kobject *kobj = &up->kset.kobj;
unsigned long flags;
int remove_user = 0;

Expand All @@ -238,9 +235,9 @@ static void remove_user_sysfs_dir(struct work_struct *w)
if (!remove_user)
goto done;

sysfs_remove_file(kobj, &up->user_attr.attr);
kobject_uevent(kobj, KOBJ_REMOVE);
kobject_del(kobj);
kobject_uevent(&up->kobj, KOBJ_REMOVE);
kobject_del(&up->kobj);
kobject_put(&up->kobj);

sched_destroy_user(up);
key_put(up->uid_keyring);
Expand All @@ -267,7 +264,8 @@ static inline void free_user(struct user_struct *up, unsigned long flags)

#else /* CONFIG_FAIR_USER_SCHED && CONFIG_SYSFS */

static inline int user_kobject_create(struct user_struct *up) { return 0; }
int uids_sysfs_init(void) { return 0; }
static inline int uids_user_create(struct user_struct *up) { return 0; }
static inline void uids_mutex_lock(void) { }
static inline void uids_mutex_unlock(void) { }

Expand Down Expand Up @@ -324,7 +322,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
struct hlist_head *hashent = uidhashentry(ns, uid);
struct user_struct *up;

/* Make uid_hash_find() + user_kobject_create() + uid_hash_insert()
/* Make uid_hash_find() + uids_user_create() + uid_hash_insert()
* atomic.
*/
uids_mutex_lock();
Expand Down Expand Up @@ -370,7 +368,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
return NULL;
}

if (user_kobject_create(new)) {
if (uids_user_create(new)) {
sched_destroy_user(new);
key_put(new->uid_keyring);
key_put(new->session_keyring);
Expand Down

0 comments on commit eb41d94

Please sign in to comment.