int ploop_discard(struct ploop_disk_images_data *di, struct ploop_discard_param *param) { int ret; char dev[PATH_MAX]; char mnt[PATH_MAX]; int mounted = 0; if (ploop_lock_dd(di)) return SYSEXIT_LOCK; ret = ploop_find_dev(di->runtime->component_name, di->images[0]->file, dev, sizeof(dev)); if (ret == -1) { ploop_unlock_dd(di); return SYSEXIT_LOCK; } else if (ret == 0) { if (ploop_get_mnt_by_dev(dev, mnt, sizeof(mnt))) { ploop_err(0, "Unable to find mount point for %s", dev); ploop_unlock_dd(di); return SYSEXIT_PARAM; } } else { struct ploop_mount_param mount_param = {}; if (!param->automount) { ploop_err(0, "Unable to discard: image is not mounted"); ploop_unlock_dd(di); return SYSEXIT_PARAM; } ret = auto_mount_image(di, &mount_param); if (ret) { ploop_unlock_dd(di); return ret; } mounted = 1; snprintf(dev, sizeof(dev), "%s", mount_param.device); snprintf(mnt, sizeof(mnt), "%s", mount_param.target); free_mount_param(&mount_param); } ploop_unlock_dd(di); ret = do_ploop_discard(di, dev, mnt, param->minlen_b, param->to_free, param->stop); if (mounted && ploop_lock_dd(di) == 0) { ploop_umount(dev, di); ploop_unlock_dd(di); } return ret; }
int ploop_create_temporary_snapshot(struct ploop_disk_images_data *di, struct ploop_tsnapshot_param *param, int *holder_fd) { int ret; struct ploop_mount_param mount_param = { .ro = 1, }; char component_name[PLOOP_COOKIE_SIZE]; if (di == NULL || param == NULL) return SYSEXIT_PARAM; if (param->guid == NULL) { ploop_err(0, "Snapshot guid is not specified"); return SYSEXIT_PARAM; } if (param->component_name == NULL) { ploop_err(0, "Component name is not specified"); return SYSEXIT_PARAM; } if (ploop_lock_dd(di)) return SYSEXIT_LOCK; ret = do_create_snapshot(di, param->guid, param->snap_dir, 1); if (ret) goto err_unlock; /* FIXME: should be processed from 'struct ploop_mount_param' only ?? */ char *t = di->runtime->component_name; snprintf(component_name, sizeof(component_name), "%s%s", holder_fd == NULL ? TSNAPSHOT_MOUNT_LOCK_MARK : "", param->component_name); di->runtime->component_name = component_name; mount_param.guid = param->guid; mount_param.target = param->target; ret = mount_image(di, &mount_param); di->runtime->component_name = t; if (ret) goto err_merge; strncpy(param->device, mount_param.device, sizeof(param->device)); param->device[sizeof(param->device) - 1] = '\0'; if (holder_fd != NULL) { ret = open_snap_holder(param->device, holder_fd); if (ret) goto err; } ploop_unlock_dd(di); return 0; err: ploop_umount(mount_param.device, di); err_merge: ploop_merge_snapshot_by_guid(di, di->top_guid, NULL); err_unlock: ploop_unlock_dd(di); return ret; } int is_device_inuse(const char *dev) { int count; char fname[PATH_MAX]; char cookie[PLOOP_COOKIE_SIZE] = ""; if (ploop_get_attr(dev, "open_count", &count)) return 1; /* detect if snapshot locked by ploop mount */ snprintf(fname, sizeof(fname), "/sys/block/%s/pstate/cookie", memcmp(dev, "/dev/", 5) == 0 ? dev + 5 : dev); if (read_line_quiet(fname, cookie, sizeof(cookie))) return 1; if (!strncmp(cookie, TSNAPSHOT_MOUNT_LOCK_MARK, sizeof(TSNAPSHOT_MOUNT_LOCK_MARK)-1)) return 1; /* snap holder + mount */ if (count >= 2) return 1; /* if there single reference we should detect is holder is alive */ if (count == 1 && ploop_get_mnt_by_dev(dev, fname, sizeof(fname)) != 0) return 1; return 0; }
static int plooptool_umount(int argc, char **argv) { int i, ret; char *mnt = NULL; char device[PATH_MAX]; struct { char * device; } umountopts = { }; const char *component_name = NULL; while ((i = getopt(argc, argv, "d:m:c:")) != EOF) { switch (i) { case 'd': umountopts.device = optarg; break; case 'm': mnt = optarg; break; case 'c': component_name = optarg; break; default: usage_umount(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc != 1 && !umountopts.device && !mnt) { usage_umount(); return SYSEXIT_PARAM; } if (umountopts.device != NULL) { int len = strlen(umountopts.device); /* if partition is provided, strip it */ if (strcmp(umountopts.device + len - 2, "p1") == 0 && isdigit(umountopts.device[len - 3])) umountopts.device[len - 2] = '\0'; ret = ploop_umount(umountopts.device, NULL); }else if (mnt != NULL) { if (ploop_get_dev_by_mnt(mnt, device, sizeof(device))) { fprintf(stderr, "Unable to find ploop device by %s\n", mnt); return SYSEXIT_PARAM; } ret = ploop_umount(device, NULL); } else if (is_xml_fname(argv[0])) { struct ploop_disk_images_data *di; ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; if (component_name != NULL) ploop_set_component_name(di, component_name); ret = ploop_umount_image(di); ploop_close_dd(di); } else { if (ploop_find_dev(component_name, argv[0], device, sizeof(device)) != 0) { fprintf(stderr, "Image %s is not mounted\n", argv[0]); return SYSEXIT_PARAM; } ret = ploop_umount(device, NULL); } return ret; }