From 3564d8678a2134185e5e6e83083de027b359ca28 Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Thu, 16 Aug 2007 03:06:50 +0000 Subject: [PATCH] Add support for a separate filesystem tag, and in the process improve the support for network contexts. git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2589 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- compat.h | 5 ++ configure.ac | 1 + contrib/manifest.dat.pathsubst | 1 + ensc_wrappers/wrappers-vserver.hc | 26 ++++++ kernel/switch.h | 10 +-- kernel/tag_cmd.h | 14 +++ lib/Makefile-files | 10 ++- lib/getvserverbyctx-compat.hc | 2 +- lib/getvserverbyctx-v13.hc | 2 +- lib/getvserverctx.c | 19 +++- lib/issupported.c | 5 +- lib/issupportedstring.c | 2 +- lib/nidopt2nid.c | 18 +++- lib/syscall_getvci-v21.hc | 2 +- lib/syscall_getvci.c | 2 +- lib/syscall_tagcreate.c | 39 ++++++++ lib/syscall_tagmigrate-v23.hc | 27 ++++++ lib/syscall_tagmigrate.c | 39 ++++++++ lib/syscall_tasktag-v23.hc | 27 ++++++ lib/syscall_tasktag.c | 39 ++++++++ lib/tagopt2tag.c | 57 ++++++++++++ lib/virtual.h | 1 + lib/vserver-internal.h | 21 ++++- lib/vserver.h | 26 +++++- lib/xidopt2xid.c | 2 +- scripts/chcontext | 7 +- scripts/util-vserver-vars.pathsubst | 1 + scripts/vserver.functions | 14 +++ scripts/vserver.start | 1 + scripts/vserver.suexec | 2 + src/Makefile-files | 8 +- src/vserver-info.c | 35 ++++++-- src/vtag.c | 172 ++++++++++++++++++++++++++++++++++++ vserver-start/main.c | 2 +- 34 files changed, 605 insertions(+), 34 deletions(-) create mode 100644 kernel/tag_cmd.h create mode 100644 lib/syscall_tagcreate.c create mode 100644 lib/syscall_tagmigrate-v23.hc create mode 100644 lib/syscall_tagmigrate.c create mode 100644 lib/syscall_tasktag-v23.hc create mode 100644 lib/syscall_tasktag.c create mode 100644 lib/tagopt2tag.c create mode 100644 src/vtag.c diff --git a/compat.h b/compat.h index 43d920c..b4315c4 100644 --- a/compat.h +++ b/compat.h @@ -87,6 +87,11 @@ typedef uint32_t xid_t; typedef uint32_t nid_t; #endif +#ifndef HAVE_TAG_T +#include +typedef uint32_t tag_t; +#endif + #if defined(__dietlibc__) #define TEMP_FAILURE_RETRY(expression) \ diff --git a/configure.ac b/configure.ac index 5caea3a..bb30072 100644 --- a/configure.ac +++ b/configure.ac @@ -295,6 +295,7 @@ AC_CHECK_FUNCS([vserver]) AC_CHECK_DECLS(MS_MOVE,,,[#include ]) AC_CHECK_TYPES(xid_t,,,[#include ]) AC_CHECK_TYPES(nid_t,,,[#include ]) +AC_CHECK_TYPES(tag_t,,,[#include ]) AC_CHECK_HEADERS([sys/capability.h]) diff --git a/contrib/manifest.dat.pathsubst b/contrib/manifest.dat.pathsubst index 08eca55..ab8e256 100644 --- a/contrib/manifest.dat.pathsubst +++ b/contrib/manifest.dat.pathsubst @@ -121,6 +121,7 @@ legacy @SBINDIR@/vserver-copy core @SBINDIR@/vserver-info base @SBINDIR@/vserver-stat base @SBINDIR@/vsomething +core @SBINDIR@/vtag base @SBINDIR@/vtop core @SBINDIR@/vuname build @SBINDIR@/vupdateworld diff --git a/ensc_wrappers/wrappers-vserver.hc b/ensc_wrappers/wrappers-vserver.hc index a1e1e0a..d86dbcf 100644 --- a/ensc_wrappers/wrappers-vserver.hc +++ b/ensc_wrappers/wrappers-vserver.hc @@ -64,6 +64,14 @@ Evc_net_create(nid_t nid) return res; } +inline static WRAPPER_DECL tag_t +Evc_tag_create(tag_t tag) +{ + register tag_t res = vc_tag_create(tag); + FatalErrnoError(res==VC_NOCTX, "vc_tag_create()"); + return res; +} + inline static WRAPPER_DECL void Evc_ctx_migrate(xid_t xid, uint_least64_t flags) { @@ -77,6 +85,12 @@ Evc_net_migrate(nid_t nid) } inline static WRAPPER_DECL void +Evc_tag_migrate(tag_t tag) +{ + FatalErrnoError(vc_tag_migrate(tag)==-1, "vc_tag_migrate()"); +} + +inline static WRAPPER_DECL void Evc_get_cflags(xid_t xid, struct vc_ctx_flags *flags) { FatalErrnoError(vc_get_cflags(xid, flags)==-1, "vc_get_cflags()"); @@ -180,3 +194,15 @@ Evc_nidopt2nid(char const *id, bool honor_static) } return rc; } + +inline static WRAPPER_DECL tag_t +Evc_tagopt2tag(char const *id, bool honor_static) +{ + char const * err; + tag_t rc = vc_tagopt2tag(id, honor_static, &err); + if (__builtin_expect(rc==VC_NOCTX,0)) { + ENSC_DETAIL1(msg, "vc_tagopt2tag", id, 1); + FatalErrnoErrorFail(msg); + } + return rc; +} diff --git a/kernel/switch.h b/kernel/switch.h index 95eb6b4..ee6defc 100644 --- a/kernel/switch.h +++ b/kernel/switch.h @@ -8,7 +8,7 @@ #define VC_COMMAND(c) (((c) >> 16) & 0xFF) #define VC_VERSION(c) ((c) & 0xFFF) -#define VC_CMD(c,i,v) ((((VC_CAT_ ## c) & 0x3F) << 24) \ +#define VC_CMD(c, i, v) ((((VC_CAT_ ## c) & 0x3F) << 24) \ | (((i) & 0xFF) << 16) | ((v) & 0xFFF)) /* @@ -31,7 +31,7 @@ NETWORK| |VNET |NETALT |NETMIG |NETCTL | | |SERIAL | | | 24| 25| 26| 27| 28| 29| | 30| 31| -------+-------+-------+-------+-------+-------+-------+ +-------+-------+ - DISK | | | | |DLIMIT | | |INODE | | + DISK | | | |TAGMIG |DLIMIT | | |INODE | | VFS | 32| 33| 34| 35| 36| 37| | 38| 39| -------+-------+-------+-------+-------+-------+-------+ +-------+-------+ OTHER |VSTAT | | | | | | |VINFO | | @@ -65,6 +65,7 @@ #define VC_CAT_NETMIG 27 #define VC_CAT_NETCTRL 28 +#define VC_CAT_TAGMIG 35 #define VC_CAT_DLIMIT 36 #define VC_CAT_INODE 38 @@ -79,11 +80,6 @@ #define VC_CAT_SYSTEST 61 #define VC_CAT_COMPAT 63 -/* interface version */ - -#define VCI_VERSION 0x00020102 -#define VCI_LEGACY_VERSION 0x000100FF - /* query version */ #define VCMD_get_version VC_CMD(VERSION, 0, 0) diff --git a/kernel/tag_cmd.h b/kernel/tag_cmd.h new file mode 100644 index 0000000..27ef60b --- /dev/null +++ b/kernel/tag_cmd.h @@ -0,0 +1,14 @@ +#ifndef _VX_TAG_CMD_H +#define _VX_TAG_CMD_H + + +/* vinfo commands */ + +#define VCMD_task_tag VC_CMD(VINFO, 3, 0) + + +/* context commands */ + +#define VCMD_tag_migrate VC_CMD(TAGMIG, 1, 0) + +#endif /* _VX_TAG_CMD_H */ diff --git a/lib/Makefile-files b/lib/Makefile-files index 670e56b..e33f1d5 100644 --- a/lib/Makefile-files +++ b/lib/Makefile-files @@ -34,7 +34,8 @@ lib_management_SRCS = lib/comparevserverbyid.c \ lib/getvservername.c \ lib/getvservervdir.c \ lib/xidopt2xid.c \ - lib/nidopt2nid.c + lib/nidopt2nid.c \ + lib/tagopt2tag.c lib_v11_SRCS = lib/syscall_rlimit.c \ lib/syscall_rlimit-v11.hc \ lib/syscall_kill.c \ @@ -145,6 +146,12 @@ lib_v22_SRCS = lib/syscall_setsched-v22.hc \ lib_netv2_SRCS = lib/syscall_netadd-netv2.hc \ lib/syscall_netremove-netv2.hc +lib_v23_SRCS = lib/syscall_tagmigrate-v23.hc \ + lib/syscall_tagmigrate.c \ + lib/syscall_tagcreate.c \ + lib/syscall_tasktag-v23.hc \ + lib/syscall_tasktag.c + if ENSC_HAVE_C99_COMPILER lib_v13_SRCS += lib/syscall_adddlimit-v13.hc \ lib/syscall_adddlimit.c \ @@ -192,6 +199,7 @@ lib_SRCS = lib/syscall.c \ $(lib_v21_SRCS) \ $(lib_v22_SRCS) \ $(lib_netv2_SRCS) \ + $(lib_v23_SRCS) \ $(ensc_fmt_SRCS) include_HEADERS += lib/vserver.h diff --git a/lib/getvserverbyctx-compat.hc b/lib/getvserverbyctx-compat.hc index 79ceef6..3e7fde2 100644 --- a/lib/getvserverbyctx-compat.hc +++ b/lib/getvserverbyctx-compat.hc @@ -96,7 +96,7 @@ vc_getVserverByCtx_compat(xid_t ctx, vcCfgStyle *style, char const *revdir, // check if expected ctx == actual ctx (but only when this check is // request) if (validate_result && - vc_getVserverCtx(path, vcCFG_RECENT_FULL, false, 0)!=ctx) return 0; + vc_getVserverCtx(path, vcCFG_RECENT_FULL, false, 0, vcCTX_XID)!=ctx) return 0; if (style) *style = vcCFG_RECENT_FULL; return strdup(path); diff --git a/lib/getvserverbyctx-v13.hc b/lib/getvserverbyctx-v13.hc index d9f601b..4d2e09b 100644 --- a/lib/getvserverbyctx-v13.hc +++ b/lib/getvserverbyctx-v13.hc @@ -28,7 +28,7 @@ vc_getVserverByCtx_v13(xid_t ctx, vcCfgStyle *style, char const UNUSED *revdir, if (vc_get_vhi_name(ctx, vcVHI_CONTEXT, buf, sizeof buf)!=-1 && (!validate_result || - vc_getVserverCtx(buf, vcCFG_RECENT_FULL, false, 0)==ctx)) { + vc_getVserverCtx(buf, vcCFG_RECENT_FULL, false, 0, vcCTX_XID)==ctx)) { if (style) *style = vcCFG_RECENT_FULL; return strdup(buf); } diff --git a/lib/getvserverctx.c b/lib/getvserverctx.c index 59c3963..fda8d73 100644 --- a/lib/getvserverctx.c +++ b/lib/getvserverctx.c @@ -120,10 +120,11 @@ getCtxFromFile(char const *pathname) } xid_t -vc_getVserverCtx(char const *id, vcCfgStyle style, bool honor_static, bool *is_running) +vc_getVserverCtx(char const *id, vcCfgStyle style, bool honor_static, bool *is_running, + vcCtxType type) { size_t l1 = strlen(id); - char buf[sizeof(CONFDIR "//") + l1 + sizeof("/context")]; + char buf[sizeof(CONFDIR "//") + l1 + sizeof("/ncontext")]; if (style==vcCFG_NONE || style==vcCFG_AUTO) style = vc_getVserverCfgStyle(id); @@ -151,7 +152,7 @@ vc_getVserverCtx(char const *id, vcCfgStyle style, bool honor_static, bool *is_r // when context information could be read, we have to verify that // it belongs to a running vserver and the both vservers are // identically - if (res!=VC_NOCTX) { + if (res!=VC_NOCTX && type == vcCTX_XID) { char *cur_name; struct vc_vx_info info; @@ -180,7 +181,17 @@ vc_getVserverCtx(char const *id, vcCfgStyle style, bool honor_static, bool *is_r *is_running = res!=VC_NOCTX; if (res==VC_NOCTX && honor_static) { - memcpy(buf+idx, "/context", 9); // appends '\0' too + switch (type) { + case vcCTX_XID: + memcpy(buf+idx, "/context", 9); // appends '\0' too + break; + case vcCTX_NID: + memcpy(buf+idx, "/ncontext", 10); + break; + case vcCTX_TAG: + memcpy(buf+idx, "/tag", 5); + break; + } res = getCtxFromFile(buf); } diff --git a/lib/issupported.c b/lib/issupported.c index 73bf813..45b1c24 100644 --- a/lib/issupported.c +++ b/lib/issupported.c @@ -26,8 +26,10 @@ bool vc_isSupported(vcFeatureSet feature) { - int ver = vc_get_version(); + int ver = vc_get_version(); + vc_vci_t conf = vc_get_vci(); if (ver==-1) return false; + if (conf==(vc_vci_t)-1) conf = 0; switch (feature) { case vcFEATURE_COMPAT : return true; @@ -44,6 +46,7 @@ vc_isSupported(vcFeatureSet feature) case vcFEATURE_SCHED : return ver >= 0x00020000; // todo case vcFEATURE_VNET : return ver >= 0x00020001; case vcFEATURE_VSTAT : return ver >= 0x00020103; + case vcFEATURE_PPTAG : return conf & VC_VCI_PPTAG; default : assert(false); } diff --git a/lib/issupportedstring.c b/lib/issupportedstring.c index a4ef2f9..e9526f9 100644 --- a/lib/issupportedstring.c +++ b/lib/issupportedstring.c @@ -34,7 +34,7 @@ static struct { DECL(VKILL), DECL(IATTR), DECL(RLIMIT), DECL(COMPAT), DECL(MIGRATE), DECL(NAMESPACE), DECL(SCHED), DECL(VINFO), DECL(VHI), DECL(VSHELPER0), DECL(VSHELPER), DECL(VWAIT), - DECL(VNET), DECL(VSTAT), + DECL(VNET), DECL(VSTAT), DECL(PPTAG), }; bool diff --git a/lib/nidopt2nid.c b/lib/nidopt2nid.c index d3fd8c6..2f6388a 100644 --- a/lib/nidopt2nid.c +++ b/lib/nidopt2nid.c @@ -24,6 +24,13 @@ #include #include +static nid_t +getVserverNid(char const *id, bool honor_static, char const **err) +{ + *err = "vc_getVserverCtx"; + return vc_getVserverCtx(id, vcCFG_AUTO, honor_static, 0, vcCTX_NID); +} + nid_t vc_nidopt2nid(char const *str, bool honor_static, char const **err_info) { @@ -32,7 +39,16 @@ vc_nidopt2nid(char const *str, bool honor_static, char const **err_info) err = "vc_get_task_nid()"; if (strcmp(str,"self")==0) res = vc_get_task_nid(0); - else res = vc_xidopt2xid(str, honor_static, &err); + else if (str[0]==':') res = getVserverNid(str+1, honor_static, &err); + else { + char * endptr; + nid_t nid = strtol(str, &endptr, 10); + + if (endptr!=str && (*endptr=='\0' || *endptr=='\n')) + res = nid; + else + res = getVserverNid(str, honor_static, &err); + } if (res==VC_NOCTX && err_info) *err_info = err; diff --git a/lib/syscall_getvci-v21.hc b/lib/syscall_getvci-v21.hc index b7794f1..74a629f 100644 --- a/lib/syscall_getvci-v21.hc +++ b/lib/syscall_getvci-v21.hc @@ -20,7 +20,7 @@ # include #endif -static inline ALWAYSINLINE int +static inline ALWAYSINLINE vc_vci_t vc_get_vci_v21(int UNUSED tmp) { return vserver(VCMD_get_vci, 0, 0); diff --git a/lib/syscall_getvci.c b/lib/syscall_getvci.c index e9b28dc..42875f0 100644 --- a/lib/syscall_getvci.c +++ b/lib/syscall_getvci.c @@ -30,7 +30,7 @@ #if defined(VC_ENABLE_API_V21) -int +vc_vci_t vc_get_vci() { CALL_VC(CALL_VC_V21(vc_get_vci, 0)); diff --git a/lib/syscall_tagcreate.c b/lib/syscall_tagcreate.c new file mode 100644 index 0000000..752731a --- /dev/null +++ b/lib/syscall_tagcreate.c @@ -0,0 +1,39 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "vserver.h" +#include "virtual.h" +#include "vserver-internal.h" + +#if defined(VC_ENABLE_API_V23) +# include "syscall_tagmigrate-v23.hc" +#endif + +#if defined(VC_ENABLE_API_V23) + +int +vc_tag_create(tag_t tag) +{ + CALL_VC(CALL_VC_TAG(vc_tag_migrate, tag)); +} + +#endif diff --git a/lib/syscall_tagmigrate-v23.hc b/lib/syscall_tagmigrate-v23.hc new file mode 100644 index 0000000..bb718c8 --- /dev/null +++ b/lib/syscall_tagmigrate-v23.hc @@ -0,0 +1,27 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +static inline ALWAYSINLINE int +vc_tag_migrate_tag(tag_t tag) +{ + return vserver(VCMD_tag_migrate, TAG_USER2KERNEL(tag), NULL); +} diff --git a/lib/syscall_tagmigrate.c b/lib/syscall_tagmigrate.c new file mode 100644 index 0000000..d5a9e46 --- /dev/null +++ b/lib/syscall_tagmigrate.c @@ -0,0 +1,39 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "vserver.h" +#include "virtual.h" +#include "vserver-internal.h" + +#if defined(VC_ENABLE_API_V23) +# include "syscall_tagmigrate-v23.hc" +#endif + +#if defined(VC_ENABLE_API_V23) + +int +vc_tag_migrate(tag_t tag) +{ + CALL_VC(CALL_VC_TAG(vc_tag_migrate, tag)); +} + +#endif diff --git a/lib/syscall_tasktag-v23.hc b/lib/syscall_tasktag-v23.hc new file mode 100644 index 0000000..e01b35a --- /dev/null +++ b/lib/syscall_tasktag-v23.hc @@ -0,0 +1,27 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +static inline ALWAYSINLINE tag_t +vc_get_task_tag_tag(pid_t pid) +{ + return vserver(VCMD_task_tag, pid, NULL); +} diff --git a/lib/syscall_tasktag.c b/lib/syscall_tasktag.c new file mode 100644 index 0000000..f5d6c35 --- /dev/null +++ b/lib/syscall_tasktag.c @@ -0,0 +1,39 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "vserver.h" +#include "virtual.h" +#include "vserver-internal.h" + +#if defined(VC_ENABLE_API_V23) +# include "syscall_tasktag-v23.hc" +#endif + +#if defined(VC_ENABLE_API_V23) + +tag_t +vc_get_task_tag(pid_t pid) +{ + CALL_VC(CALL_VC_TAG(vc_get_task_tag, pid)); +} + +#endif diff --git a/lib/tagopt2tag.c b/lib/tagopt2tag.c new file mode 100644 index 0000000..7f4b6aa --- /dev/null +++ b/lib/tagopt2tag.c @@ -0,0 +1,57 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "vserver.h" +#include +#include + +static tag_t +getVserverTag(char const *id, bool honor_static, char const **err) +{ + *err = "vc_getVserverCtx"; + return vc_getVserverCtx(id, vcCFG_AUTO, honor_static, 0, vcCTX_TAG); +} + +tag_t +vc_tagopt2tag(char const *str, bool honor_static, char const **err_info) +{ + char const * err; + tag_t res = VC_NOCTX; + + err = "vc_task_tag()"; + if (strcmp(str,"self")==0) res = vc_get_task_tag(0); + else if (str[0]==':') res = getVserverTag(str+1, honor_static, &err); + else { + char * endptr; + tag_t tag = strtol(str, &endptr, 10); + + if (endptr!=str && (*endptr=='\0' || *endptr=='\n')) + res = tag; + else + res = getVserverTag(str, honor_static, &err); + } + + if (res==VC_NOCTX && err_info) *err_info = err; + + return res; +} diff --git a/lib/virtual.h b/lib/virtual.h index aadf2fa..857be66 100644 --- a/lib/virtual.h +++ b/lib/virtual.h @@ -31,6 +31,7 @@ #include #include #include +#include #include diff --git a/lib/vserver-internal.h b/lib/vserver-internal.h index 4e71afd..e1cd60c 100644 --- a/lib/vserver-internal.h +++ b/lib/vserver-internal.h @@ -50,7 +50,7 @@ inline static ALWAYSINLINE void vc_noop0() {} # define CALL_VC(...) \ do { \ int ver = utilvserver_checkCompatVersion(); \ - uint_least32_t UNUSED conf = utilvserver_checkCompatConfig(); \ + vc_vci_t UNUSED conf = utilvserver_checkCompatConfig(); \ if (ver==-1) return -1; \ VC_SUFFIX, __VA_ARGS__, VC_PREFIX; \ errno = ENOSYS; \ @@ -120,6 +120,12 @@ inline static ALWAYSINLINE void vc_noop0() {} # define CALL_VC_SPACES(F,...) CALL_VC_NOOP #endif +#if defined(VC_ENABLE_API_V23) +# define CALL_VC_TAG(F,...) CALL_VC_GENERAL_CONFIG(VC_VCI_PPTAG, tag, F, __VA_ARGS__) +#else +# define CALL_VC_TAG(F,...) CALL_VC_NOOP +#endif + #ifdef VC_ENABLE_API_V22 # define CALL_VC_V22(F,...) CALL_VC_GENERAL(0x00020200, v22, F, __VA_ARGS__) #else @@ -179,6 +185,19 @@ inline static ALWAYSINLINE void vc_noop0() {} #endif #if 1 +# define TAG_KERNEL2USER(X) (((X)==(uint32_t)(-1)) ? VC_NOCTX : \ + ((X)==(uint32_t)(-2)) ? VC_SAMECTX : \ + (tag_t)(X)) + +# define TAG_USER2KERNEL(X) (((X)==VC_DYNAMIC_XID) ? (uint32_t)(-1) : \ + ((X)==VC_SAMECTX) ? (uint32_t)(-2) : \ + (uint32_t)(X)) +#else +# define TAG_USER2KERNEL(X) (X) +# define TAG_KERNEL2USER(X) (X) +#endif + +#if 1 # define EXT2FLAGS_USER2KERNEL(X) (((X) & ~(VC_IMMUTABLE_FILE_FL|VC_IMMUTABLE_LINK_FL)) | \ ((X) & VC_IMMUTABLE_FILE_FL ? EXT2_IMMUTABLE_FILE_FL : 0) | \ ((X) & VC_IMMUTABLE_LINK_FL ? EXT2_IMMUTABLE_LINK_FL : 0)) diff --git a/lib/vserver.h b/lib/vserver.h index ee53775..d403677 100644 --- a/lib/vserver.h +++ b/lib/vserver.h @@ -267,6 +267,7 @@ #define VC_VCI_NO_DYNAMIC (1 << 0) #define VC_VCI_SPACES (1 << 10) #define VC_VCI_NETV2 (1 << 11) +#define VC_VCI_PPTAG (1 << 28) // the device mapping flags @@ -323,6 +324,7 @@ #ifdef IS_DOXYGEN typedef an_unsigned_integer_type xid_t; typedef an_unsigned_integer_type nid_t; +typedef an_unsigned_integer_type tag_t; #endif #ifdef __cplusplus @@ -349,11 +351,12 @@ extern "C" { */ int vc_get_version(); + typedef uint64_t vc_vci_t; /** \brief Returns the kernel configuration bits * \ingroup syscalls * \returns The kernel configuration bits */ - int vc_get_vci(); + vc_vci_t vc_get_vci(); /** \brief Moves current process into a context * \ingroup syscalls @@ -769,6 +772,15 @@ extern "C" { uint_least32_t flags, struct vc_ctx_dlimit *limits) VC_ATTR_NONNULL((1)); + /** Get the filesystem tag for a process. */ + tag_t vc_get_task_tag(pid_t pid); + + /** Create a new filesystem tag space. */ + int vc_tag_create(tag_t tag); + + /** Migrate to an existing filesystem tag space. */ + int vc_tag_migrate(tag_t tag); + /* scheduler related syscalls */ struct vc_set_sched { uint_least32_t set_mask; @@ -931,7 +943,7 @@ extern "C" { vcFEATURE_COMPAT, vcFEATURE_MIGRATE, vcFEATURE_NAMESPACE, vcFEATURE_SCHED, vcFEATURE_VINFO, vcFEATURE_VHI, vcFEATURE_VSHELPER0, vcFEATURE_VSHELPER, vcFEATURE_VWAIT, - vcFEATURE_VNET, vcFEATURE_VSTAT } + vcFEATURE_VNET, vcFEATURE_VSTAT, vcFEATURE_PPTAG, } vcFeatureSet; bool vc_isSupported(vcFeatureSet) VC_ATTR_CONST; @@ -962,6 +974,8 @@ extern "C" { xid_t vc_xidopt2xid(char const *, bool honor_static, char const **err_info); /** Maps a nid given at '--nid' options to a nid_t */ nid_t vc_nidopt2nid(char const *, bool honor_static, char const **err_info); + /** Maps a tag given at '--tag' options to a tag_t */ + tag_t vc_tagopt2tag(char const *, bool honor_static, char const **err_info); vcCfgStyle vc_getVserverCfgStyle(char const *id); @@ -984,6 +998,11 @@ extern "C" { * allocated and must be freed by the caller. */ char * vc_getVserverVdir(char const *id, vcCfgStyle style, bool physical); + typedef enum { vcCTX_XID = 1, + vcCTX_NID, + vcCTX_TAG, + } vcCtxType; + /** Returns the ctx of the given vserver. When vserver is not running and * 'honor_static' is false, VC_NOCTX will be returned. Else, when * 'honor_static' is true and a static assignment exists, those value will @@ -992,7 +1011,8 @@ extern "C" { * When 'is_running' is not null, the status of the vserver will be * assigned to this variable. */ xid_t vc_getVserverCtx(char const *id, vcCfgStyle style, - bool honor_static, bool /*@null@*/ *is_running); + bool honor_static, bool /*@null@*/ *is_running, + vcCtxType type); /** Resolves the cfg-path of the vserver owning the given ctx. 'revdir' will be used as the directory holding the mapping-links; when NULL, the diff --git a/lib/xidopt2xid.c b/lib/xidopt2xid.c index 80a51e5..3bef404 100644 --- a/lib/xidopt2xid.c +++ b/lib/xidopt2xid.c @@ -28,7 +28,7 @@ static xid_t getVserverXid(char const *id, bool honor_static, char const **err) { *err = "vc_getVserverCtx"; - return vc_getVserverCtx(id, vcCFG_AUTO, honor_static, 0); + return vc_getVserverCtx(id, vcCFG_AUTO, honor_static, 0, vcCTX_XID); } xid_t diff --git a/scripts/chcontext b/scripts/chcontext index 93b0959..2caa42c 100755 --- a/scripts/chcontext +++ b/scripts/chcontext @@ -134,7 +134,8 @@ while true; do shift done -create_cmd=( $_VCONTEXT --create --silentexist +create_cmd=( ${OPT_CTX:+$_VTAG --create --tag "$OPT_CTX" --silentexist --} + $_VCONTEXT --create --silentexist ${OPT_SILENT:+--silent} ${OPT_CTX:+--xid "$OPT_CTX"} ) @@ -157,7 +158,9 @@ chain_cmd=( "${chain_cmd[@]}" ${OPT_CAPS:+--bcap "${OPT_CAPS[*]}"} ${OPT_FLAGS:+--flag "${OPT_FLAGS[*]}"} ) -migrate_cmd=( $_VCONTEXT +migrate_cmd=( $_VTAG --migrate --tag "$OPT_CTX" + -- + $_VCONTEXT ${OPT_SILENT:+--silent} ${OPT_DISCONNECT:+--disconnect} $OPT_INITPID ) diff --git a/scripts/util-vserver-vars.pathsubst b/scripts/util-vserver-vars.pathsubst index 3803564..2e6afbb 100644 --- a/scripts/util-vserver-vars.pathsubst +++ b/scripts/util-vserver-vars.pathsubst @@ -99,6 +99,7 @@ _VSHELPER="$__PKGLIBDIR/vshelper" _VSHELPER_SYNC="$__PKGLIBDIR/vshelper-sync" _VSOMETHING="$__SBINDIR/vsomething" _VSYSCTL="$__PKGLIBDIR/vsysctl" +_VTAG="$__SBINDIR/vtag" _VWAIT="$__SBINDIR/vwait" _VUNAME="$__SBINDIR/vuname" _VUNIFY="$__PKGLIBDIR/vunify" diff --git a/scripts/vserver.functions b/scripts/vserver.functions index 5bfda35..30e82f0 100644 --- a/scripts/vserver.functions +++ b/scripts/vserver.functions @@ -43,6 +43,8 @@ declare -a OPTS_VCONTEXT_ENTER=() declare -a OPTS_VATTRIBUTE=( --flag fakeinit ) declare -a OPTS_VSCHED=() declare -a OPTS_ENV=() +declare -a OPTS_VTAG_CREATE=() +declare -a OPTS_VTAG_ENTER=() declare -a STOPCMD_PREPARE=() @@ -599,6 +601,17 @@ function _generateInterfaceOptions _HAVE_INTERFACE_OPTIONS=1 } +function _generateTagOptions +{ + local vdir="$1" + local tag + + getFileValue tag "$vdir/tag" "$vdir/context" || return 0 + + OPTS_VTAG_CREATE=( --tag "$tag" ) + OPTS_VTAG_ENTER=( --tag "$tag" ) +} + function enableInterfaces { local i=0 @@ -712,6 +725,7 @@ function generateOptions _generateChcontextOptions "$1" _generateScheduleOptions "$1" _generatePersonalityOptions "$1" + _generateTagOptions "$1" if test -n "$_IS_FAKEINIT"; then CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit ) diff --git a/scripts/vserver.start b/scripts/vserver.start index 1ade946..63b02a9 100644 --- a/scripts/vserver.start +++ b/scripts/vserver.start @@ -132,6 +132,7 @@ if $_VSERVER_INFO - FEATURE migrate; then ${NICE_CMD[@]} \ $_CHBIND "${CHBIND_OPTS[@]}" -- \ $_EXEC_ULIMIT "$VSERVER_DIR"/ulimits \ + $_VTAG --create "${OPTS_VTAG_CREATE[@]}" -- \ $_VCONTEXT --create "${OPTS_VCONTEXT_CREATE[@]}" -- \ ${OPTION_STRACE:+$_STRACE -fF -o /tmp/vserver-start.$$} \ ${USE_VNAMESPACE:+$_VNAMESPACE --set -- } \ diff --git a/scripts/vserver.suexec b/scripts/vserver.suexec index b91f7f3..8b19f53 100644 --- a/scripts/vserver.suexec +++ b/scripts/vserver.suexec @@ -37,6 +37,7 @@ if $_VSERVER_INFO - FEATURE migrate; then $_CHBIND "${CHBIND_OPTS[@]}" \ $_EXEC_ULIMIT "$VSERVER_DIR/ulimits" \ ${USE_VNAMESPACE:+$_VNAMESPACE --enter "$S_CONTEXT" -- } \ + $_VTAG --migrate "${OPTS_VTAG_ENTER[@]}" -- \ $_VCONTEXT $SILENT_OPT --migrate --chroot \ --xid "$S_CONTEXT" --uid "$user" "${OPTS_VCONTEXT_ENTER[@]}" -- \ "$@" @@ -44,6 +45,7 @@ if $_VSERVER_INFO - FEATURE migrate; then exec \ $_CHBIND "${CHBIND_OPTS[@]}" \ $_EXEC_ULIMIT "$VSERVER_DIR/ulimits" \ + $_VTAG --migrate "${OPTS_VTAG_ENTER[@]}" -- \ $_VCONTEXT --create "${OPTS_VCONTEXT_CREATE[@]}" -- \ $_VUNAME --xid self --dir "$VSERVER_DIR"/uts --missingok -- \ $_VUNAME --xid self --set -t context="$VSERVER_DIR" -- \ diff --git a/src/Makefile-files b/src/Makefile-files index dad36c1..5b4a6ad 100644 --- a/src/Makefile-files +++ b/src/Makefile-files @@ -81,7 +81,8 @@ DIETPROGS += src/chcontext-compat \ src/vdevmap \ src/vsysctl \ src/vclone \ - src/h2ext + src/h2ext \ + src/vtag if ENSC_CAN_BEECRYPT_WITH_DIETLIBC DIETPROGS += src/vhashify @@ -161,6 +162,7 @@ sbin_PROGRAMS += src/exec-cd \ src/nattribute \ src/naddress \ src/vdevmap \ + src/vtag \ $(src_sbin_CXX_X_PROGS) if ENSC_HAVE_C99_COMPILER @@ -342,6 +344,10 @@ src_h2ext_SOURCES = src/h2ext.c src_h2ext_LDADD = $(LIBINTERNAL) $(VSERVER_LDADDS) src_h2ext_LDFLAGS = $(VSERVER_LDFLGS) +src_vtag_SOURCES = src/vtag.c +src_vtag_LDADD = $(VSERVER_LDADDS) +src_vtag_LDFLAGS = $(VSERVER_LDADDS) + EXTRA_PROGRAMS += $(src_sbin_CXX_PROGS) $(src_pkglib_CXX_PROGS) TESTS_ENVIRONMENT += srctestsuitedir=$(top_builddir)/src/testsuite diff --git a/src/vserver-info.c b/src/vserver-info.c index 36465fd..d28bf28 100644 --- a/src/vserver-info.c +++ b/src/vserver-info.c @@ -53,6 +53,7 @@ typedef enum { tgNONE,tgCONTEXT, tgID, tgRUNNING, tgXID, tgUTS, tgSYSINFO, tgFEATURE, tgCANONIFY, tgVERIFYCAP, tgXIDTYPE, tgVERIFYPROC, + tgNID, tgTAG, } VserverTag; static struct { @@ -82,6 +83,8 @@ static struct { { "VERIFYCAP", tgVERIFYCAP, "test if the kernel supports linux capabilities" }, { "VERIFYPROC", tgVERIFYPROC, "test if /proc can be read by contexts!=0" }, { "XIDTYPE", tgXIDTYPE, "returns the type of the given XID" }, + { "NID", tgNID, "outputs the network context-id of the given pid" }, + { "TAG", tgTAG, "outputs the filesystem tag of the given pid" }, }; int wrapper_exit_code = 1; @@ -230,13 +233,13 @@ getAPIVer(char *buf) return buf; } -static char * -getXid(char *buf, char const *pid_str) +static inline char * +getCtxId(char *buf, const char *pid_str, xid_t (*get_id)(pid_t pid), const char *err_str) { pid_t pid = atoi(pid_str); - xid_t xid = vc_get_task_xid(pid); + xid_t xid = get_id(pid); - if (xid==VC_NOCTX) perror("vc_get_task_xid()"); + if (xid==VC_NOCTX) perror(err_str); else { utilvserver_fmt_long(buf, xid); return buf; @@ -246,6 +249,24 @@ getXid(char *buf, char const *pid_str) } static char * +getXid(char *buf, char const *pid_str) +{ + return getCtxId(buf, pid_str, vc_get_task_xid, "vc_get_task_xid()"); +} + +static char * +getNid(char *buf, const char *pid_str) +{ + return getCtxId(buf, pid_str, vc_get_task_nid, "vc_get_task_nid()"); +} + +static char * +getTag(char *buf, const char *pid_str) +{ + return getCtxId(buf, pid_str, vc_get_task_tag, "vc_get_task_tag()"); +} + +static char * getPXid(char UNUSED *buf, char const UNUSED *vserver) { // TODO: implement me when available @@ -434,7 +455,7 @@ static char * getContext(char *buf, char const *vserver, bool allow_only_static) { xid_t xid = vc_getVserverCtx(vserver, vcCFG_AUTO, - allow_only_static, 0); + allow_only_static, 0, vcCTX_XID); if (xid==VC_NOCTX) return 0; utilvserver_fmt_long(buf, xid); @@ -502,7 +523,7 @@ execQuery(char const *vserver, VserverTag tag, int argc, char *argv[]) if (isNumber(vserver, &xid, true) && xid>=0) res = (vc_get_vx_info(xid, &info)==-1) ? 0 : "1"; else - res = (vc_getVserverCtx(vserver, vcCFG_AUTO, false, 0)==VC_NOCTX) ? 0 : "1"; + res = (vc_getVserverCtx(vserver, vcCFG_AUTO, false, 0, vcCTX_XID)==VC_NOCTX) ? 0 : "1"; break; } @@ -522,6 +543,8 @@ execQuery(char const *vserver, VserverTag tag, int argc, char *argv[]) case tgFEATURE : return testFeature(argc,argv); break; case tgVERIFYCAP : return verifyCap() ? 0 : 1; break; case tgVERIFYPROC : return verifyProc() ? 0 : 1; break; + case tgNID : res = getNid(buf, vserver); break; + case tgTAG : res = getTag(buf, vserver); break; default : { diff --git a/src/vtag.c b/src/vtag.c new file mode 100644 index 0000000..3aa6cc4 --- /dev/null +++ b/src/vtag.c @@ -0,0 +1,172 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "util.h" + +#include +#include +#include +#include + + +#define ENSC_WRAPPERS_PREFIX "vtag: " +#define ENSC_WRAPPERS_VSERVER 1 +#include + +#define CMD_HELP 0x1000 +#define CMD_VERSION 0x1001 +#define CMD_TAG 0x4000 +#define CMD_CREATE 0x4001 +#define CMD_MIGRATE 0x4002 +#define CMD_SILENTEXIST 0x4003 + + +struct option const +CMDLINE_OPTIONS[] = { + { "help", no_argument, 0, CMD_HELP }, + { "version", no_argument, 0, CMD_VERSION }, + { "tag", required_argument, 0, CMD_TAG }, + { "create", no_argument, 0, CMD_CREATE }, + { "migrate", no_argument, 0, CMD_MIGRATE }, + { "silentexist", no_argument, 0, CMD_SILENTEXIST }, + { 0,0,0,0 }, +}; + +struct Arguments { + bool do_create; + bool do_migrate; + bool is_silentexist; + int verbosity; + tag_t tag; +}; + +int wrapper_exit_code = 255; + +static void +showHelp(int fd, char const *cmd, int res) +{ + WRITE_MSG(fd, "Usage:\n "); + WRITE_STR(fd, cmd); + WRITE_MSG(fd, + " (--create|--migrate) --tag * [--] *\n " + "\n" + " can be:\n" + " --silentexist ... be silent when context exists already; useful\n" + " for '--create' only\n" + "\n" + "'vtag --create' exits with code 254 iff the context exists already.\n" + "\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n"); + + exit(res); +} + +static void +showVersion() +{ + WRITE_MSG(1, + "vtag " VERSION " -- sets the process's filesystem tag\n" + "This program is part of " PACKAGE_STRING "\n\n" + "Copyright (C) 2007 Daniel Hokka Zakrisson\n" + VERSION_COPYRIGHT_DISCLAIMER); + exit(0); +} + +static inline ALWAYSINLINE int +doit(struct Arguments const *args, char *argv[]) +{ + tag_t tag; + + if (!vc_isSupported(vcFEATURE_PPTAG)) + goto exec; + + if (args->do_create) { + tag = vc_tag_create(args->tag); + if (tag==VC_NOCTX) { + switch (errno) { + case EEXIST : + if (!args->is_silentexist) + perror(ENSC_WRAPPERS_PREFIX "vc_tag_create()"); + return 254; + default : + perror(ENSC_WRAPPERS_PREFIX "vc_tag_create()"); + return wrapper_exit_code; + } + } + } + else + tag = args->tag; + + if (args->do_migrate) + Evc_tag_migrate(tag); + +exec: + execvp(argv[optind], argv+optind); + + PERROR_Q(ENSC_WRAPPERS_PREFIX "execvp", argv[optind]); + return wrapper_exit_code; +} + +int main (int argc, char *argv[]) +{ + struct Arguments args = { + .tag = VC_NOCTX, + .do_create = false, + .do_migrate = false, + .is_silentexist = false, + .verbosity = 1, + }; + + while (1) { + int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); + if (c==-1) break; + + switch (c) { + case CMD_HELP : showHelp(1, argv[0], 0); + case CMD_VERSION : showVersion(); + case CMD_CREATE : args.do_create = true; break; + case CMD_MIGRATE : args.do_migrate = true; break; + case CMD_SILENTEXIST : args.is_silentexist = true; break; + case CMD_TAG : args.tag = Evc_tagopt2tag(optarg,true); break; + + default : + WRITE_MSG(2, "Try '"); + WRITE_STR(2, argv[0]); + WRITE_MSG(2, " --help' for more information.\n"); + return wrapper_exit_code; + break; + } + } + + if (!args.do_create && !args.do_migrate) + WRITE_MSG(2, "Neither '--create' nor '--migrate' specified; try '--help' for more information\n"); + else if (args.do_create && args.do_migrate) + WRITE_MSG(2, "Can not specify '--create' and '--migrate' at the same time; try '--help' for more information\n"); + else if (args.tag==VC_NOCTX) + WRITE_MSG(2, "You must specify the tag with '--tag'; try '--help' for more information\n"); + else if (optind>=argc) + WRITE_MSG(2, "No command given; use '--help' for more information.\n"); + else + return doit(&args, argv); + + return wrapper_exit_code; +} diff --git a/vserver-start/main.c b/vserver-start/main.c index 953daf2..634a734 100644 --- a/vserver-start/main.c +++ b/vserver-start/main.c @@ -115,7 +115,7 @@ checkConstraints() struct vc_vx_info info; xid = vc_getVserverCtx(opts.VSERVER_DIR, vcCFG_RECENT_FULL, - true, &is_running); + true, &is_running, vcCTX_XID); if (xid!=VC_NOCTX && vc_get_vx_info(xid, &info)!=-1) { WRITE_MSG(2, "vserver.start: vserver '"); -- 1.8.1.5