[systemd-devel] [RFC] iscsiadm, iscsid: newroot command to survive switch_root
Chris Leech
cleech at redhat.com
Mon Dec 10 14:08:34 PST 2012
When started from initramfs, iscsid needs to be able to chroot itself
to the runtime filesystem before the switch_root occurs. In the
initramfs "iscsiadm --newroot {root fs mount before switch}" should be
called before the switch_root.
---
usr/iscsiadm.c | 30 +++++++++++++++++++++++++++++-
usr/mgmt_ipc.c | 11 +++++++++++
usr/mgmt_ipc.h | 6 +++++-
3 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 8f9de05..7b601b3 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -111,9 +111,10 @@ static struct option const long_options[] =
{"packetsize", required_argument, NULL, 'b'},
{"count", required_argument, NULL, 'c'},
{"interval", required_argument, NULL, 'i'},
+ {"newroot", required_argument, NULL, 'N'},
{NULL, 0, NULL, 0},
};
-static char *short_options = "RlDVhm:a:b:c:C:p:P:T:H:i:I:U:k:L:d:r:n:v:o:sSt:u";
+static char *short_options = "RlDVhm:a:b:c:C:p:P:T:H:i:I:U:k:L:d:r:n:v:o:sSt:uN:";
static void usage(int status)
{
@@ -251,6 +252,22 @@ static void kill_iscsid(int priority)
}
}
+static void do_newroot(char *newroot)
+{
+ iscsiadm_req_t req;
+ iscsiadm_rsp_t rsp;
+ int rc;
+
+ memset(&req, 0, sizeof(req));
+ req.command = MGMT_IPC_NEWROOT;
+ strncpy(req.u.newroot.path, newroot, PATH_MAX);
+ rc = iscsid_exec_req(&req, &rsp, 0);
+ if (rc) {
+ iscsi_err_print_msg(rc);
+ log_error("Could not send NEWROOT command");
+ }
+}
+
/*
* TODO: we can display how the ifaces are related to node records.
* And we can add a scsi_host mode which would display how
@@ -2411,6 +2428,7 @@ main(int argc, char **argv)
uint32_t host_no = -1;
struct user_param *param;
struct list_head params;
+ char *newroot = NULL;
INIT_LIST_HEAD(¶ms);
INIT_LIST_HEAD(&ifaces);
@@ -2433,6 +2451,9 @@ main(int argc, char **argv)
while ((ch = getopt_long(argc, argv, short_options,
long_options, &longindex)) >= 0) {
switch (ch) {
+ case 'N':
+ newroot = strndup(optarg, PATH_MAX);
+ break;
case 'k':
killiscsid = atoi(optarg);
if (killiscsid < 0) {
@@ -2579,6 +2600,13 @@ main(int argc, char **argv)
goto free_ifaces;
}
+ if (newroot) {
+ do_newroot(newroot);
+ free(newroot);
+ newroot = NULL;
+ goto free_ifaces;
+ }
+
if (mode < 0)
usage(ISCSI_ERR_INVAL);
diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c
index f34f688..b4170ce 100644
--- a/usr/mgmt_ipc.c
+++ b/usr/mgmt_ipc.c
@@ -226,6 +226,16 @@ mgmt_ipc_immediate_stop(queue_task_t *qtask)
}
static int
+mgmt_ipc_newroot(queue_task_t *qtask)
+{
+ char *newroot = qtask->req.u.newroot.path;
+ if (chdir(newroot) || chroot(".") || chdir("/"))
+ return ISCSI_ERR;
+ mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+ return ISCSI_SUCCESS;
+}
+
+static int
mgmt_ipc_conn_remove(queue_task_t *qtask)
{
return ISCSI_ERR;
@@ -534,6 +544,7 @@ static mgmt_ipc_fn_t * mgmt_ipc_functions[__MGMT_IPC_MAX_COMMAND] = {
[MGMT_IPC_NOTIFY_DEL_NODE] = mgmt_ipc_notify_del_node,
[MGMT_IPC_NOTIFY_ADD_PORTAL] = mgmt_ipc_notify_add_portal,
[MGMT_IPC_NOTIFY_DEL_PORTAL] = mgmt_ipc_notify_del_portal,
+[MGMT_IPC_NEWROOT] = mgmt_ipc_newroot,
};
void mgmt_ipc_handle(int accept_fd)
diff --git a/usr/mgmt_ipc.h b/usr/mgmt_ipc.h
index 55972ed..102ffff 100644
--- a/usr/mgmt_ipc.h
+++ b/usr/mgmt_ipc.h
@@ -22,6 +22,7 @@
#include "types.h"
#include "iscsi_if.h"
#include "config.h"
+#include "limits.h"
#define ISCSIADM_NAMESPACE "ISCSIADM_ABSTRACT_NAMESPACE"
#define PEERUSER_MAX 64
@@ -46,6 +47,7 @@ typedef enum iscsiadm_cmd {
MGMT_IPC_NOTIFY_DEL_NODE = 17,
MGMT_IPC_NOTIFY_ADD_PORTAL = 18,
MGMT_IPC_NOTIFY_DEL_PORTAL = 19,
+ MGMT_IPC_NEWROOT = 20,
__MGMT_IPC_MAX_COMMAND
} iscsiadm_cmd_e;
@@ -75,8 +77,10 @@ typedef struct iscsiadm_req {
int param;
/* TODO: make this variable len to support */
char value[IFNAMSIZ + 1];
-
} set_host_param;
+ struct ipc_msg_newroot {
+ char path[PATH_MAX + 1];
+ } newroot;
} u;
} iscsiadm_req_t;
--
1.7.11.7
More information about the systemd-devel
mailing list