diff options
Diffstat (limited to 'kernel/utsname.c')
-rw-r--r-- | kernel/utsname.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/kernel/utsname.c b/kernel/utsname.c new file mode 100644 index 0000000..815237a --- /dev/null +++ b/kernel/utsname.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2004 IBM Corporation + * + * Author: Serge Hallyn <serue@us.ibm.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ + +#include <linux/module.h> +#include <linux/uts.h> +#include <linux/utsname.h> +#include <linux/err.h> +#include <linux/slab.h> + +/* + * Clone a new ns copying an original utsname, setting refcount to 1 + * @old_ns: namespace to clone + * Return NULL on error (failure to kmalloc), new ns otherwise + */ +static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) +{ + struct uts_namespace *ns; + + ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); + if (!ns) + return ERR_PTR(-ENOMEM); + + down_read(&uts_sem); + memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); + up_read(&uts_sem); + kref_init(&ns->kref); + return ns; +} + +/* + * Copy task tsk's utsname namespace, or clone it if flags + * specifies CLONE_NEWUTS. In latter case, changes to the + * utsname of this process won't be seen by parent, and vice + * versa. + */ +struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns) +{ + struct uts_namespace *new_ns; + + BUG_ON(!old_ns); + get_uts_ns(old_ns); + + if (!(flags & CLONE_NEWUTS)) + return old_ns; + + new_ns = clone_uts_ns(old_ns); + + put_uts_ns(old_ns); + return new_ns; +} + +void free_uts_ns(struct kref *kref) +{ + struct uts_namespace *ns; + + ns = container_of(kref, struct uts_namespace, kref); + kfree(ns); +} |