static int freeze(struct ploop_copy_handle *h) { int ret; ret = ioctl(h->partfd, PLOOP_IOC_FREEZE); if (ret) { if (errno == EINVAL) ret = freeze_fs(h); else ploop_err(errno, "Failed to freeze device"); if (ret) goto err; } else { ploop_log(0, "Freezing device..."); h->dev_frozen = 1; } ploop_dbg(3, "IOC_SYNC"); ret = ioctl_device(h->devfd, PLOOP_IOC_SYNC, 0); if (ret) goto err; return 0; err: ploop_copy_release(h); return ret; }
int ploop_copy_stop(struct ploop_copy_handle *h) { int ret; struct ploop_copy_stat stat = {}; int iter; ploop_log(3, "pcopy last"); ret = freeze_fs(h); if (ret) goto err; iter = 1; for (;;) { ret = ploop_copy_next_iteration(h, &stat); if (ret) goto err; else if (stat.xferred == 0) break; if (iter++ > 2) { ploop_err(0, "Too many iterations on frozen FS, aborting"); return SYSEXIT_LOOP; } } /* Must clear dirty flag on ploop1 image. */ if (!h->raw) { struct ploop_pvd_header *vh = get_free_iobuf(h); if (PREAD(&h->idelta, vh, 4096, 0)) { ret = SYSEXIT_READ; goto err; } vh->m_DiskInUse = 0; ploop_dbg(4, "Update header"); ret = send_buf(h, vh, 4096, 0); if (ret) goto err; } ploop_dbg(4, "IOCTL TRACK_STOP"); ret = ioctl(h->devfd, PLOOP_IOC_TRACK_STOP, 0); if (ret) goto err; h->tracker_on = 0; ploop_dbg(4, "SEND 0 0 (close)"); send_async(h, NULL, 0, 0); pthread_join(h->send_th, NULL); h->send_th = 0; ploop_dbg(4, "pcopy stop done"); err: ploop_copy_release(h); return ret; }