Revision 53c2e716 block/vmdk.c
b/block/vmdk.c | ||
---|---|---|
187 | 187 |
static int vmdk_snapshot_create(const char *filename, const char *backing_file) |
188 | 188 |
{ |
189 | 189 |
int snp_fd, p_fd; |
190 |
int ret; |
|
190 | 191 |
uint32_t p_cid; |
191 | 192 |
char *p_name, *gd_buf, *rgd_buf; |
192 | 193 |
const char *real_filename, *temp_str; |
... | ... | |
211 | 212 |
|
212 | 213 |
snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644); |
213 | 214 |
if (snp_fd < 0) |
214 |
return -1;
|
|
215 |
return -errno;
|
|
215 | 216 |
p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE); |
216 | 217 |
if (p_fd < 0) { |
217 | 218 |
close(snp_fd); |
218 |
return -1;
|
|
219 |
return -errno;
|
|
219 | 220 |
} |
220 | 221 |
|
221 | 222 |
/* read the header */ |
222 |
if (lseek(p_fd, 0x0, SEEK_SET) == -1) |
|
223 |
if (lseek(p_fd, 0x0, SEEK_SET) == -1) { |
|
224 |
ret = -errno; |
|
223 | 225 |
goto fail; |
224 |
if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE) |
|
226 |
} |
|
227 |
if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE) { |
|
228 |
ret = -errno; |
|
225 | 229 |
goto fail; |
230 |
} |
|
226 | 231 |
|
227 | 232 |
/* write the header */ |
228 |
if (lseek(snp_fd, 0x0, SEEK_SET) == -1) |
|
233 |
if (lseek(snp_fd, 0x0, SEEK_SET) == -1) { |
|
234 |
ret = -errno; |
|
229 | 235 |
goto fail; |
230 |
if (write(snp_fd, hdr, HEADER_SIZE) == -1) |
|
236 |
} |
|
237 |
if (write(snp_fd, hdr, HEADER_SIZE) == -1) { |
|
238 |
ret = -errno; |
|
231 | 239 |
goto fail; |
240 |
} |
|
232 | 241 |
|
233 | 242 |
memset(&header, 0, sizeof(header)); |
234 | 243 |
memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC |
235 | 244 |
|
236 |
if (ftruncate(snp_fd, header.grain_offset << 9)) |
|
245 |
if (ftruncate(snp_fd, header.grain_offset << 9)) { |
|
246 |
ret = -errno; |
|
237 | 247 |
goto fail; |
248 |
} |
|
238 | 249 |
/* the descriptor offset = 0x200 */ |
239 |
if (lseek(p_fd, 0x200, SEEK_SET) == -1) |
|
250 |
if (lseek(p_fd, 0x200, SEEK_SET) == -1) { |
|
251 |
ret = -errno; |
|
240 | 252 |
goto fail; |
241 |
if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE) |
|
253 |
} |
|
254 |
if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE) { |
|
255 |
ret = -errno; |
|
242 | 256 |
goto fail; |
257 |
} |
|
243 | 258 |
|
244 | 259 |
if ((p_name = strstr(p_desc,"CID")) != NULL) { |
245 | 260 |
p_name += sizeof("CID"); |
... | ... | |
258 | 273 |
(uint32_t)header.capacity, real_filename); |
259 | 274 |
|
260 | 275 |
/* write the descriptor */ |
261 |
if (lseek(snp_fd, 0x200, SEEK_SET) == -1) |
|
276 |
if (lseek(snp_fd, 0x200, SEEK_SET) == -1) { |
|
277 |
ret = -errno; |
|
262 | 278 |
goto fail; |
263 |
if (write(snp_fd, s_desc, strlen(s_desc)) == -1) |
|
279 |
} |
|
280 |
if (write(snp_fd, s_desc, strlen(s_desc)) == -1) { |
|
281 |
ret = -errno; |
|
264 | 282 |
goto fail; |
283 |
} |
|
265 | 284 |
|
266 | 285 |
gd_offset = header.gd_offset * SECTOR_SIZE; // offset of GD table |
267 | 286 |
rgd_offset = header.rgd_offset * SECTOR_SIZE; // offset of RGD table |
... | ... | |
271 | 290 |
* 512 GTE per GT, each GTE points to grain |
272 | 291 |
*/ |
273 | 292 |
gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE; |
274 |
if (!gt_size) |
|
293 |
if (!gt_size) { |
|
294 |
ret = -EINVAL; |
|
275 | 295 |
goto fail; |
296 |
} |
|
276 | 297 |
gde_entries = (uint32_t)(capacity / gt_size); // number of gde/rgde |
277 | 298 |
gd_size = gde_entries * sizeof(uint32_t); |
278 | 299 |
|
279 | 300 |
/* write RGD */ |
280 | 301 |
rgd_buf = qemu_malloc(gd_size); |
281 |
if (lseek(p_fd, rgd_offset, SEEK_SET) == -1) |
|
302 |
if (lseek(p_fd, rgd_offset, SEEK_SET) == -1) { |
|
303 |
ret = -errno; |
|
282 | 304 |
goto fail_rgd; |
283 |
if (read(p_fd, rgd_buf, gd_size) != gd_size) |
|
305 |
} |
|
306 |
if (read(p_fd, rgd_buf, gd_size) != gd_size) { |
|
307 |
ret = -errno; |
|
284 | 308 |
goto fail_rgd; |
285 |
if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1) |
|
309 |
} |
|
310 |
if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1) { |
|
311 |
ret = -errno; |
|
286 | 312 |
goto fail_rgd; |
287 |
if (write(snp_fd, rgd_buf, gd_size) == -1) |
|
313 |
} |
|
314 |
if (write(snp_fd, rgd_buf, gd_size) == -1) { |
|
315 |
ret = -errno; |
|
288 | 316 |
goto fail_rgd; |
317 |
} |
|
289 | 318 |
qemu_free(rgd_buf); |
290 | 319 |
|
291 | 320 |
/* write GD */ |
292 | 321 |
gd_buf = qemu_malloc(gd_size); |
293 |
if (lseek(p_fd, gd_offset, SEEK_SET) == -1) |
|
322 |
if (lseek(p_fd, gd_offset, SEEK_SET) == -1) { |
|
323 |
ret = -errno; |
|
294 | 324 |
goto fail_gd; |
295 |
if (read(p_fd, gd_buf, gd_size) != gd_size) |
|
325 |
} |
|
326 |
if (read(p_fd, gd_buf, gd_size) != gd_size) { |
|
327 |
ret = -errno; |
|
296 | 328 |
goto fail_gd; |
297 |
if (lseek(snp_fd, gd_offset, SEEK_SET) == -1) |
|
329 |
} |
|
330 |
if (lseek(snp_fd, gd_offset, SEEK_SET) == -1) { |
|
331 |
ret = -errno; |
|
298 | 332 |
goto fail_gd; |
299 |
if (write(snp_fd, gd_buf, gd_size) == -1) |
|
333 |
} |
|
334 |
if (write(snp_fd, gd_buf, gd_size) == -1) { |
|
335 |
ret = -errno; |
|
300 | 336 |
goto fail_gd; |
337 |
} |
|
301 | 338 |
qemu_free(gd_buf); |
302 | 339 |
|
303 | 340 |
close(p_fd); |
... | ... | |
311 | 348 |
fail: |
312 | 349 |
close(p_fd); |
313 | 350 |
close(snp_fd); |
314 |
return -1;
|
|
351 |
return ret;
|
|
315 | 352 |
} |
316 | 353 |
|
317 | 354 |
static void vmdk_parent_close(BlockDriverState *bs) |
Also available in: Unified diff