[CRIU] [PATCH v3 3/4] IPC: restore shared memory

Kinsbursky Stanislav skinsbursky at openvz.org
Thu Feb 9 03:17:41 EST 2012


08.02.2012 22:37, Kir Kolyshkin пишет:
> 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

Yep. Thanks.

>> +			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.

And again.

>> +		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

And again.

>> +		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

And again.

>> +		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

And again.

>> +		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

And again.

>> +		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.

And again.

-- 
Best regards,
Stanislav Kinsbursky




More information about the CRIU mailing list