[CRIU] [PATCH v3 3/4] IPC: restore shared memory
Kir Kolyshkin
kir at openvz.org
Wed Feb 8 13:37:20 EST 2012
On 02/08/2012 09:27 PM, Kinsbursky Stanislav wrote:
>
> Signed-off-by: Stanislav Kinsbursky<skinsbursky at parallels.com>
>
> ---
> ipc_ns.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 107 insertions(+), 2 deletions(-)
>
> diff --git a/ipc_ns.c b/ipc_ns.c
> index eda3399..5c4d27f 100644
> --- a/ipc_ns.c
> +++ b/ipc_ns.c
> @@ -13,6 +13,14 @@
> #include "namespaces.h"
> #include "sysctl.h"
>
> +#ifndef IPC_PRESET
> +#define IPC_PRESET 00040000
> +#endif
> +
> +#ifndef SHM_SET
> +#define SHM_SET 15
> +#endif
> +
> static void print_ipc_seg(const struct ipc_seg *seg)
> {
> pr_info("id: %-10d key: 0x%08x ", seg->id, seg->key);
> @@ -160,8 +168,12 @@ static int dump_ipc_shm(int fd)
> int id, ret;
>
> id = shmctl(i, SHM_STAT,&ds);
> - if (id< 0)
> - continue;
> + if (id< 0) {
> + if (errno == EINVAL)
> + continue;
> + pr_perror("Failed to get stats for IPC shared memory\n");
Remove \n
> + break;
> + }
> ret = dump_ipc_shm_seg(fd, id,&ds);
> if (ret< 0)
> return ret;
> @@ -277,6 +289,96 @@ void show_ipc_var(int fd)
> pr_img_tail(CR_FD_IPCNS);
> }
>
> +static int prepare_ipc_shm_pages(int fd, const struct ipc_shm_entry *shm)
> +{
> + int ret;
> + void *data;
> +
> + data = shmat(shm->seg.id, NULL, 0);
> + if (data == (void *)-1) {
> + pr_err("Failed to attach IPC shared memory\n");
shmat sets errno, so you should use pr_perror() here.
> + return -errno;
> + }
> + ret = read_img_buf(fd, data, round_up(shm->size, sizeof(u32)));
> + if (ret< 0) {
> + pr_err("Failed to read IPC shared memory data\n");
> + return ret;
> + }
> + if (shmdt(data)) {
> + pr_err("Failed to detach IPC shared memory\n");
ditto
> + return -errno;
> + }
> + return 0;
> +}
> +
> +static int prepare_ipc_shm_seg(int fd, const struct ipc_shm_entry *shm)
> +{
> + int ret, id;
> + struct shmid_ds ds;
> +
> + id = shmget(shm->seg.id, shm->size,
> + shm->seg.mode | IPC_CREAT | IPC_EXCL | IPC_PRESET);
> + if (id == -1) {
> pr_err("Failed to create shm segment\n");
ditto
> + return -errno;
> + }
> +
> + if (id != shm->seg.id) {
> + pr_err("Failed to preset id (%d instead of %d)\n",
> + id, shm->seg.id);
> + return -EFAULT;
> + }
> +
> + ret = shmctl(id, SHM_STAT,&ds);
> + if (ret< 0) {
> + pr_err("Failed to stat shm segment\n");
ditto
> + return -errno;
> + }
> +
> + ds.shm_perm.KEY = shm->seg.key;
> + ret = shmctl(id, SHM_SET,&ds);
> + if (ret< 0) {
> + pr_err("Failed to update shm key\n");
ditto
> + return -errno;
> + }
> + ret = prepare_ipc_shm_pages(fd, shm);
> + if (ret< 0) {
> + pr_err("Failed to update shm pages\n");
> return -errno;
Returning -errno here is wrong, you might end up returning -0. Here's why:
prepare_ipc_shm_pages()
calls read_img_buf()
which calls read_img_buf_eof()
which does this:
int ret;
ret = read(fd, ptr, size);
if (ret == size)
return 1;
if (ret == 0)
return 0;
if (ret < 0)
pr_perror("Can't read img file");
else
pr_err("Img trimmed %d/%d\n", ret, size);
return -1;
See, in case read() will read fewer bytes this function returns -1, but
errno is unset since read() hasn't failed.
> + }
> + return 0;
> +}
> +
> +static int prepare_ipc_shm(int pid)
> +{
> + int fd;
> +
> + pr_info("Restoring IPC shared memory\n");
> + fd = open_image_ro(CR_FD_IPCNS_SHM, pid);
> + if (fd< 0)
> + return -1;
> +
> + while (1) {
> + int ret, id;
> + struct ipc_shm_entry shm;
> +
> + ret = read_img_eof(fd,&shm);
> + if (ret< 0)
> + return -EIO;
> + if (ret == 0)
> + break;
> +
> + print_ipc_shm(&shm);
> +
> + ret = prepare_ipc_shm_seg(fd,&shm);
> + if (ret< 0) {
> + pr_err("Failed to prepare shm segment\n");
> + return ret;
> + }
> + }
> + return 0;
> +}
> +
> static int prepare_ipc_var(int pid)
> {
> int fd, ret;
> @@ -304,5 +406,8 @@ int prepare_ipc_ns(int pid)
> ret = prepare_ipc_var(pid);
> if (ret< 0)
> return ret;
> + ret = prepare_ipc_shm(pid);
> + if (ret< 0)
> + return ret;
> return 0;
> }
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list