static int do_ploop_discard(struct ploop_disk_images_data *di, const char *device, const char *mount_point, __u64 minlen_b, __u64 to_free, const int *stop) { int fd, ret; int blocksize; __u32 cluster; if (ploop_get_attr(device, "block_size", &blocksize)) { ploop_err(0, "Can't find block size"); return SYSEXIT_SYSFS; } cluster = S2B(blocksize); if (to_free == 0) to_free = ~0ULL; to_free = to_free / cluster; if (!to_free) { ploop_err(0, "Can't shrink by less than %d bytes", cluster); return SYSEXIT_PARAM; } fd = open_device(device); if (fd == -1) return SYSEXIT_OPEN; ret = __ploop_discard(di, fd, device, mount_point, minlen_b, cluster, to_free, NULL, stop); close(fd); return ret; }
static int get_image_info(const char *device, char **send_from_p, char **format_p, int *blocksize) { int top_level; if (ploop_get_attr(device, "top", &top_level)) { ploop_err(0, "Can't find top delta"); return SYSEXIT_SYSFS; } if (ploop_get_attr(device, "block_size", blocksize)) { ploop_err(0, "Can't find block size"); return SYSEXIT_SYSFS; } if (find_delta_names(device, top_level, top_level, send_from_p, format_p)) { ploop_err(errno, "find_delta_names"); return SYSEXIT_SYSFS; } return 0; }
static int open_top_delta(const char *device, struct delta *delta, int *lvl) { char *image = NULL; char *fmt = NULL; if (ploop_get_attr(device, "top", lvl)) { ploop_err(0, "Can't find top delta"); return(SYSEXIT_SYSFS); } if (find_delta_names(device, *lvl, *lvl, &image, &fmt)) return(SYSEXIT_SYSFS); if (strcmp(fmt, "raw") == 0) { ploop_err(0, "Ballooning for raw format is not supported"); return(SYSEXIT_PARAM); } if (open_delta(delta, image, O_RDONLY|O_DIRECT, OD_ALLOW_DIRTY)) { ploop_err(errno, "open_delta"); return(SYSEXIT_OPEN); } return 0; }
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; }