Signed-off-by: Oren Laadan <[email protected]>
---
 restart.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 64 insertions(+), 10 deletions(-)

diff --git a/restart.c b/restart.c
index 5871bbf..2efe879 100644
--- a/restart.c
+++ b/restart.c
@@ -79,6 +79,10 @@ static char usage_str[] =
 "     --inspect          inspect image on-the-fly for error records\n"
 "  -v,--verbose          verbose output\n"
 "  -d,--debug            debugging output\n"
+"     --warn-COND        warn on condition COND, but proceed anyways\n"
+"     --fail-COND        warn on condition COND, and abort operation\n"
+"        COND=any:        any condition\n"
+"        COND=pidzero:    task with sid/pgid zero in a --no-pidns restart\n"
 "";
 
 /*
@@ -359,8 +363,13 @@ struct args {
        int infd;
        char *logfile;
        int logfd;
+       long warn;
+       long fail;
 };
 
+#define CKPT_COND_PIDZERO  0x1
+#define CKPT_COND_ANY      ULONG_MAX
+
 static void usage(char *str)
 {
        fprintf(stderr, "%s", str);
@@ -379,6 +388,37 @@ static int str2num(char *str)
        return num;
 }
 
+static long cond_to_mask(const char *cond)
+{
+       static struct {
+               char *cond;
+               long mask;
+       } conditions[] = {
+               {"pidzero", CKPT_COND_PIDZERO},
+               {"any", CKPT_COND_ANY},
+               {NULL, 0}
+       };
+
+       int i;
+
+       for (i = 0; conditions[i].cond; i++)
+               if (!strcmp(cond, conditions[i].cond))
+                       return conditions[i].mask;
+
+       printf("restart: invalid warn/fail condition '%s'\n", cond);
+       exit(1);
+}
+
+static inline int ckpt_cond_warn(struct ckpt_ctx *ctx, long mask)
+{
+       return (ctx->args->warn & mask);
+}
+               
+static inline int ckpt_cond_fail(struct ckpt_ctx *ctx, long mask)
+{
+       return (ctx->args->fail & mask);
+}
+
 static void parse_args(struct args *args, int argc, char *argv[])
 {
        static struct option opts[] = {
@@ -401,10 +441,13 @@ static void parse_args(struct args *args, int argc, char 
*argv[])
                { "freezer",    required_argument,      NULL, 'F' },
                { "verbose",    no_argument,            NULL, 'v' },
                { "debug",      no_argument,            NULL, 'd' },
+               { "warn-pidzero",       no_argument,    NULL, 9 },
+               { "fail-pidzero",       no_argument,    NULL, 10 },
                { NULL,         0,                      NULL, 0 }
        };
        static char optc[] = "hdvpPwWF:r:i:l:";
 
+       int optind;
        int sig;
 
        /* defaults */
@@ -414,7 +457,7 @@ static void parse_args(struct args *args, int argc, char 
*argv[])
        args->logfd = -1;
 
        while (1) {
-               int c = getopt_long(argc, argv, optc, opts, NULL);
+               int c = getopt_long(argc, argv, optc, opts, &optind);
                if (c == -1)
                        break;
                switch (c) {
@@ -494,6 +537,12 @@ static void parse_args(struct args *args, int argc, char 
*argv[])
                case 'F':
                        args->freezer = optarg;
                        break;
+               case 9:
+                       args->warn |= cond_to_mask(&opts[optind].name[5]);
+                       break;
+               case 10:
+                       args->fail |= cond_to_mask(&opts[optind].name[5]);
+                       break;
                default:
                        usage(usage_str);
                }
@@ -1171,15 +1220,21 @@ static int ckpt_setup_task(struct ckpt_ctx *ctx, pid_t 
pid, pid_t ppid)
        return 0;
 }
 
-static inline int ckpt_valid_pid(pid_t pid, int pidns, char *which, int i)
+static int ckpt_valid_pid(struct ckpt_ctx *ctx, pid_t pid, char *which, int i)
 {
        if (pid < 0) {
                ckpt_err("Invalid %s %d (for task#%d)\n", which, pid, i);
                return 0;
        }
-       if (!pidns && pid == 0) {
-               ckpt_err("Zero %s (task#%d) requires pid-ns\n", which, i + 1);
-               return 0;
+       if (!ctx->args->pidns && pid == 0) {
+               if (ckpt_cond_fail(ctx, CKPT_COND_PIDZERO)) {
+                       ckpt_err("[err] task # %d with %s zero"
+                                " (requires --pidns)\n", i + 1, which);
+                       return 0;
+               } else if (ckpt_cond_warn(ctx, CKPT_COND_PIDZERO)) {
+                       ckpt_err("[warn] task # %d with %s zero"
+                                " (consider --pidns)\n", i + 1, which);
+               }
        }
        return 1;
 }
@@ -1188,7 +1243,6 @@ static int ckpt_init_tree(struct ckpt_ctx *ctx)
 {
        struct ckpt_pids *pids_arr = ctx->pids_arr;
        int pids_nr = ctx->pids_nr;
-       int pidns = ctx->args->pidns;
        struct task *task;
        pid_t root_pid;
        pid_t root_sid;
@@ -1225,13 +1279,13 @@ static int ckpt_init_tree(struct ckpt_ctx *ctx)
 
                task->flags = 0;
 
-               if (!ckpt_valid_pid(pids_arr[i].vpid, pidns, "pid", i))
+               if (!ckpt_valid_pid(ctx, pids_arr[i].vpid, "pid", i))
                        return -1;
-               else if (!ckpt_valid_pid(pids_arr[i].vtgid, pidns, "tgid", i))
+               else if (!ckpt_valid_pid(ctx, pids_arr[i].vtgid, "tgid", i))
                        return -1;
-               else if (!ckpt_valid_pid(pids_arr[i].vsid, pidns, "sid", i))
+               else if (!ckpt_valid_pid(ctx, pids_arr[i].vsid, "sid", i))
                        return -1;
-               else if (!ckpt_valid_pid(pids_arr[i].vpgid, pidns, "pgid", i))
+               else if (!ckpt_valid_pid(ctx, pids_arr[i].vpgid, "pgid", i))
                        return -1;
 
                /* zero references to root_sid (root_sid != root_pid) */
-- 
1.6.0.4

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to