[Devel] [RFC v14][PATCH 52/54] sysvipc-sem: restart
Oren Laadan
orenl at cs.columbia.edu
Tue Apr 28 16:24:22 PDT 2009
The semaphores are restored by creating each 'sem object read from the
checkpoint image. Each semaphore array (sem->sem_base) is checked for
validity of contents before copies to the corresponding semaphore.
TODO: this patch does not handle semaphore-undo -- this data should be
restored per-task while iterating through the tasks.
Signed-off-by: Oren Laadan <orenl at cs.columbia.edu>
---
ipc/checkpoint.c | 2 -
ipc/checkpoint_sem.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++
ipc/util.h | 3 +
3 files changed, 119 insertions(+), 2 deletions(-)
diff --git a/ipc/checkpoint.c b/ipc/checkpoint.c
index 7a2f4a5..e14dea6 100644
--- a/ipc/checkpoint.c
+++ b/ipc/checkpoint.c
@@ -213,12 +213,10 @@ static int do_restore_ipc_ns(struct ckpt_ctx *ctx)
goto out;
ret = restore_ipc_any(ctx, IPC_MSG_IDS,
CKPT_HDR_IPC_MSG, restore_ipc_msg);
-#if 0 /* NEXT FEW PATCHES */
if (ret < 0)
goto out;
ret = restore_ipc_any(ctx, IPC_SEM_IDS,
CKPT_HDR_IPC_SEM, restore_ipc_sem);
-#endif
out:
ckpt_hdr_put(ctx, h);
return ret;
diff --git a/ipc/checkpoint_sem.c b/ipc/checkpoint_sem.c
index fc6ea44..0065202 100644
--- a/ipc/checkpoint_sem.c
+++ b/ipc/checkpoint_sem.c
@@ -99,3 +99,119 @@ int checkpoint_ipc_sem(int id, void *p, void *data)
ckpt_hdr_put(ctx, h);
return ret;
}
+
+/************************************************************************
+ * ipc restart
+ */
+
+static int load_ipc_sem_hdr(struct ckpt_ctx *ctx,
+ struct ckpt_hdr_ipc_sem *h,
+ struct sem_array *sem)
+{
+ int ret = 0;
+
+ ret = restore_load_ipc_perms(&h->perms, &sem->sem_perm);
+ if (ret < 0)
+ return ret;
+
+ ckpt_debug("sem: nsems %u\n", h->sem_nsems);
+
+ sem->sem_otime = h->sem_otime;
+ sem->sem_ctime = h->sem_ctime;
+ sem->sem_nsems = h->sem_nsems;
+
+ return 0;
+}
+
+/**
+ * ckpt_read_sem_array - read the state of a semaphore array
+ * @ctx: checkpoint context
+ * @sem: semphore array
+ *
+ * Expect the data in an array of 'struct sem': {32 bit, 32 bit}.
+ * See comment in ckpt_write_sem_array().
+ *
+ * The sem-undo information is not restored per ipc_ns, but rather per task.
+ */
+static struct sem *restore_sem_array(struct ckpt_ctx *ctx, int nsems)
+{
+ struct sem *sma;
+ int i, ret;
+
+ sma = kmalloc(nsems * sizeof(*sma), GFP_KERNEL);
+ ret = _ckpt_read_buffer(ctx, sma, nsems * sizeof(*sma));
+ if (ret < 0)
+ goto out;
+
+ /* validate sem array contents */
+ for (i = 0; i < nsems; i++) {
+ if (sma[i].semval < 0 || sma[i].sempid < 0) {
+ ret = -EINVAL;
+ break;
+ }
+ }
+ out:
+ if (ret < 0) {
+ kfree(sma);
+ sma = ERR_PTR(ret);
+ }
+ return sma;
+}
+
+int restore_ipc_sem(struct ckpt_ctx *ctx)
+{
+ struct ckpt_hdr_ipc_sem *h;
+ struct kern_ipc_perm *perms;
+ struct sem_array *sem;
+ struct sem *sma = NULL;
+ struct ipc_ids *sem_ids = ¤t->nsproxy->ipc_ns->ids[IPC_SEM_IDS];
+ int semflag, ret;
+
+ h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_IPC_SEM);
+ if (IS_ERR(h))
+ return PTR_ERR(h);
+
+ ret = -EINVAL;
+ if (h->perms.id < 0)
+ goto out;
+ if (h->sem_nsems < 0)
+ goto out;
+
+ /* read sempahore array state */
+ sma = restore_sem_array(ctx, h->sem_nsems);
+ if (IS_ERR(sma)) {
+ ret = PTR_ERR(sma);
+ goto out;
+ }
+
+ /* restore the message queue now */
+ semflag = h->perms.mode | IPC_CREAT | IPC_EXCL;
+ ckpt_debug("sem: do_semget key %d flag %#x id %d\n",
+ h->perms.key, semflag, h->perms.id);
+ ret = do_semget(h->perms.key, h->sem_nsems, semflag, h->perms.id);
+ ckpt_debug("sem: do_msgget ret %d\n", ret);
+ if (ret < 0)
+ goto out;
+
+ down_write(&sem_ids->rw_mutex);
+
+ /* we are the sole owners/users of this ipc_ns, it can't go away */
+ perms = ipc_lock(sem_ids, h->perms.id);
+ BUG_ON(IS_ERR(perms)); /* ipc_ns is private to us */
+
+ sem = container_of(perms, struct sem_array, sem_perm);
+ memcpy(sem->sem_base, sma, sem->sem_nsems * sizeof(*sma));
+
+ ret = load_ipc_sem_hdr(ctx, h, sem);
+ ipc_unlock(perms);
+
+ if (ret < 0) {
+ ckpt_debug("sem: need to remove (%d)\n", ret);
+ freeary(current->nsproxy->ipc_ns, perms);
+ }
+ up_write(&sem_ids->rw_mutex);
+ out:
+ kfree(sma);
+ ckpt_hdr_put(ctx, h);
+ return ret;
+}
diff --git a/ipc/util.h b/ipc/util.h
index 5b7cead..54f9acb 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -184,6 +184,8 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
/* for checkpoint/restart */
extern int do_shmget(key_t key, size_t size, int shmflg, int req_id);
extern int do_msgget(key_t key, int msgflg, int req_id);
+extern int do_semget(key_t key, int nsems, int semflg, int req_id);
+
extern void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp);
extern void freeary(struct ipc_namespace *, struct kern_ipc_perm *);
@@ -202,6 +204,7 @@ extern int checkpoint_ipc_msg(int id, void *p, void *data);
extern int restore_ipc_msg(struct ckpt_ctx *ctx);
extern int checkpoint_ipc_sem(int id, void *p, void *data);
+extern int restore_ipc_sem(struct ckpt_ctx *ctx);
#endif
#endif
--
1.5.4.3
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list