mdb_handle_t mdb_handle_add(mdb_handle_map_t *hmap, void *data) { int index; MDB_CHECKARG(hmap && data, MDB_HANDLE_INVALID); if ((index = freemap_alloc(&hmap->freemap)) == HANDLE_INDEX_INVALID) { return MDB_HANDLE_INVALID; } return index_alloc(&hmap->indextbl, index, data); }
int ploop_balloon_check_and_repair(const char *device, const char *mount_point, int repair) { int ret, fd = -1; int balloonfd = -1; __u32 n_free_blocks; __u32 freezed_a_h; __u32 dev_start; /* /sys/block/ploop0/ploop0p1/start */ struct ploop_balloon_ctl b_ctl; struct stat st; struct pfiemap *pfiemap = NULL; struct freemap *freemap = NULL; struct freemap *rangemap = NULL; struct relocmap *relocmap = NULL; struct ploop_freeblks_ctl *freeblks = NULL; struct ploop_relocblks_ctl *relocblks= NULL; char *msg = repair ? "repair" : "check"; __u32 *reverse_map = NULL; __u32 reverse_map_len; int top_level; int entries_used; struct delta delta = {}; int drop_state = 0; ret = get_balloon(mount_point, &st, &balloonfd); if (ret) return ret; if (st.st_size == 0) { ploop_log(0, "Nothing to do: hidden balloon is empty"); close(balloonfd); return 0; } pfiemap = fiemap_alloc(128); freemap = freemap_alloc(128); rangemap = freemap_alloc(128); relocmap = relocmap_alloc(128); if (!pfiemap || !freemap || !rangemap || !relocmap) { ret = SYSEXIT_MALLOC; goto err; } fd = open_device(device); if (fd == -1) { ret = SYSEXIT_OPEN; goto err; } memset(&b_ctl, 0, sizeof(b_ctl)); /* block other maintenance ops even if we only check balloon */ b_ctl.inflate = 1; ret = ioctl_device(fd, PLOOP_IOC_BALLOON, &b_ctl); if (ret) goto err; switch (b_ctl.mntn_type) { case PLOOP_MNTN_BALLOON: drop_state = 1; ret = open_top_delta(device, &delta, &top_level); if (ret) goto err; reverse_map_len = delta.l2_size + delta.l2_size; reverse_map = alloc_reverse_map(reverse_map_len); if (reverse_map == NULL) { ret = SYSEXIT_MALLOC; goto err; } break; case PLOOP_MNTN_MERGE: case PLOOP_MNTN_GROW: case PLOOP_MNTN_TRACK: ploop_err(0, "Can't %s hidden balloon while another " "maintenance operation is in progress (%s)", msg, mntn2str(b_ctl.mntn_type)); ret = SYSEXIT_EBUSY; goto err; case PLOOP_MNTN_FBLOADED: case PLOOP_MNTN_RELOC: ploop_err(0, "Can't %s hidden balloon before previous " "balloon operation (%s) is completed. Use " "\"ploop-balloon complete\".", msg, mntn2str(b_ctl.mntn_type)); ret = SYSEXIT_EBUSY; goto err; case PLOOP_MNTN_OFF: ploop_err(0, "Error: mntn_type is PLOOP_MNTN_OFF after " "IOC_BALLOON"); ret = SYSEXIT_PROTOCOL; goto err; default: ploop_err(0, "Error: unknown mntn_type (%u)", b_ctl.mntn_type); ret = SYSEXIT_PROTOCOL; goto err; } if (dev_num2dev_start(device, st.st_dev, &dev_start)) { ploop_err(0, "Can't find out offset from start of ploop " "device (%s) to start of partition where fs (%s) " "resides", device, mount_point); ret = SYSEXIT_SYSFS; goto err; } ret = fiemap_get(balloonfd, S2B(dev_start), 0, st.st_size, &pfiemap); if (ret) goto err; fiemap_adjust(pfiemap, delta.blocksize); ret = fiemap_build_rmap(pfiemap, reverse_map, reverse_map_len, &delta); if (ret) goto err; ret = rmap2freemap(reverse_map, 0, reverse_map_len, &freemap, &entries_used); if (ret) goto err; if (entries_used == 0) { ploop_log(0, "No free blocks found"); goto err; } ret = freemap2freeblks(freemap, top_level, &freeblks, &n_free_blocks); if (ret) goto err; if (!repair) { ploop_log(0, "Found %u free blocks. Consider using " "\"ploop-balloon repair\"", n_free_blocks); ret = 0; goto err; } else { ploop_log(0, "Found %u free blocks", n_free_blocks); } ret = ioctl_device(fd, PLOOP_IOC_FREEBLKS, freeblks); if (ret) goto err; drop_state = 0; freezed_a_h = freeblks->alloc_head; if (freezed_a_h > reverse_map_len) { ploop_err(0, "Image corrupted: a_h=%u > rlen=%u", freezed_a_h, reverse_map_len); ret = SYSEXIT_PLOOPFMT; goto err; } ret = range_build(freezed_a_h, n_free_blocks, reverse_map, reverse_map_len, &delta, freemap, &rangemap, &relocmap); if (ret) goto err; ret = relocmap2relocblks(relocmap, top_level, freezed_a_h, n_free_blocks, &relocblks); if (ret) goto err; ret = ioctl_device(fd, PLOOP_IOC_RELOCBLKS, relocblks); if (ret) goto err; ploop_log(0, "TRUNCATED: %u cluster-blocks (%llu bytes)", relocblks->alloc_head, (unsigned long long)(relocblks->alloc_head * S2B(delta.blocksize))); err: if (drop_state) { memset(&b_ctl, 0, sizeof(b_ctl)); (void)ioctl_device(fd, PLOOP_IOC_BALLOON, &b_ctl); } // FIXME: close_delta() if (balloonfd >= 0) close(balloonfd); if (fd >= 0) close(fd); free(pfiemap); free(freemap); free(rangemap); free(relocmap); free(reverse_map); free(freeblks); free(relocblks); return ret; }
static int ploop_balloon_relocation(int fd, struct ploop_balloon_ctl *b_ctl, const char *device) { int ret = -1; __u32 n_free_blocks = 0; __u32 freezed_a_h; struct freemap *freemap = NULL; struct freemap *rangemap = NULL; struct relocmap *relocmap = NULL; struct ploop_freeblks_ctl *freeblks = NULL; struct ploop_relocblks_ctl *relocblks = NULL;; __u32 *reverse_map = NULL; __u32 reverse_map_len; int top_level; struct delta delta = {}; freemap = freemap_alloc(128); rangemap = freemap_alloc(128); relocmap = relocmap_alloc(128); if (freemap == NULL || rangemap == NULL || relocmap == NULL) { ret = SYSEXIT_MALLOC; goto err; } top_level = b_ctl->level; freezed_a_h = b_ctl->alloc_head; if (b_ctl->mntn_type == PLOOP_MNTN_RELOC) goto reloc; if (b_ctl->mntn_type != PLOOP_MNTN_FBLOADED) { ploop_err(0, "Error: non-suitable mntn_type (%u)", b_ctl->mntn_type); ret = SYSEXIT_PROTOCOL; goto err; } ret = freeblks_alloc(&freeblks, 0); if (ret) goto err; ret = ioctl_device(fd, PLOOP_IOC_FBGET, freeblks); if (ret) goto err; if (freeblks->n_extents == 0) goto reloc; ret = freeblks_alloc(&freeblks, freeblks->n_extents); if (ret) goto err; ret = ioctl_device(fd, PLOOP_IOC_FBGET, freeblks); if (ret) goto err; ret = freeblks2freemap(freeblks, &freemap, &n_free_blocks); if (ret) goto err; ret = open_top_delta(device, &delta, &top_level); if (ret) goto err; reverse_map_len = delta.l2_size + delta.l2_size; reverse_map = alloc_reverse_map(reverse_map_len); if (reverse_map == NULL) { close_delta(&delta); ret = SYSEXIT_MALLOC; goto err; } ret = range_build(freezed_a_h, n_free_blocks, reverse_map, reverse_map_len, &delta, freemap, &rangemap, &relocmap); close_delta(&delta); if (ret) goto err; reloc: ret = relocmap2relocblks(relocmap, top_level, freezed_a_h, n_free_blocks, &relocblks); if (ret) goto err; ret = ioctl_device(fd, PLOOP_IOC_RELOCBLKS, relocblks); if (ret) goto err; ploop_log(0, "TRUNCATED: %u cluster-blocks (%llu bytes)", relocblks->alloc_head, (unsigned long long)(relocblks->alloc_head * S2B(delta.blocksize))); err: free(freemap); free(rangemap); free(relocmap); free(reverse_map); free(freeblks); free(relocblks); return ret; }
int ploop_balloon_change_size(const char *device, int balloonfd, off_t new_size) { int fd = -1; int ret; off_t old_size; __u32 dev_start; /* /sys/block/ploop0/ploop0p1/start */ __u32 n_free_blocks; __u32 freezed_a_h; struct ploop_balloon_ctl b_ctl; struct stat st; struct pfiemap *pfiemap = NULL; struct freemap *freemap = NULL; struct freemap *rangemap = NULL; struct relocmap *relocmap = NULL; struct ploop_freeblks_ctl *freeblks = NULL; struct ploop_relocblks_ctl *relocblks = NULL; __u32 *reverse_map = NULL; __u32 reverse_map_len; int top_level; struct delta delta = { .fd = -1 }; int entries_used; int drop_state = 0; if (fstat(balloonfd, &st)) { ploop_err(errno, "Can't get balloon file size"); return SYSEXIT_FSTAT; } old_size = st.st_size; new_size = (S2B(new_size) + st.st_blksize - 1) & ~(st.st_blksize - 1); ploop_log(0, "Changing balloon size old_size=%ld new_size=%ld", (long)old_size, (long)new_size); pfiemap = fiemap_alloc(128); freemap = freemap_alloc(128); rangemap = freemap_alloc(128); relocmap = relocmap_alloc(128); if (!pfiemap || !freemap || !rangemap || !relocmap) { ret = SYSEXIT_MALLOC; goto err; } fd = open_device(device); if (fd == -1) { ret = SYSEXIT_OPEN; goto err; } memset(&b_ctl, 0, sizeof(b_ctl)); if (old_size < new_size) b_ctl.inflate = 1; ret = ioctl_device(fd, PLOOP_IOC_BALLOON, &b_ctl); if (ret) goto err; drop_state = 1; if (old_size >= new_size) { ret = do_truncate(balloonfd, b_ctl.mntn_type, old_size, new_size); goto err; } if (dev_num2dev_start(device, st.st_dev, &dev_start)) { ploop_err(0, "Can't find out offset from start of ploop " "device (%s) to start of partition", device); ret = SYSEXIT_SYSFS; goto err; } ret = open_top_delta(device, &delta, &top_level); if (ret) goto err; ret = do_inflate(balloonfd, b_ctl.mntn_type, old_size, &new_size, &drop_state); if (ret) goto err; reverse_map_len = delta.l2_size + delta.l2_size; reverse_map = alloc_reverse_map(reverse_map_len); if (reverse_map == NULL) { ret = SYSEXIT_MALLOC; goto err; } ret = fiemap_get(balloonfd, S2B(dev_start), old_size, new_size, &pfiemap); if (ret) goto err; fiemap_adjust(pfiemap, delta.blocksize); ret = fiemap_build_rmap(pfiemap, reverse_map, reverse_map_len, &delta); if (ret) goto err; ret = rmap2freemap(reverse_map, 0, reverse_map_len, &freemap, &entries_used); if (ret) goto err; if (entries_used == 0) { drop_state = 1; ploop_log(0, "No unused cluster blocks found"); goto out; } ret = freemap2freeblks(freemap, top_level, &freeblks, &n_free_blocks); if (ret) goto err; ret = ioctl_device(fd, PLOOP_IOC_FREEBLKS, freeblks); if (ret) goto err; freezed_a_h = freeblks->alloc_head; if (freezed_a_h > reverse_map_len) { ploop_err(0, "Image corrupted: a_h=%u > rlen=%u", freezed_a_h, reverse_map_len); ret = SYSEXIT_PLOOPFMT; goto err; } ret = range_build(freezed_a_h, n_free_blocks, reverse_map, reverse_map_len, &delta, freemap, &rangemap, &relocmap); if (ret) goto err; ret = relocmap2relocblks(relocmap, top_level, freezed_a_h, n_free_blocks, &relocblks); if (ret) goto err; ret = ioctl_device(fd, PLOOP_IOC_RELOCBLKS, relocblks); if (ret) goto err; ploop_log(0, "TRUNCATED: %u cluster-blocks (%llu bytes)", relocblks->alloc_head, (unsigned long long)(relocblks->alloc_head * S2B(delta.blocksize))); out: ret = 0; err: if (drop_state) { memset(&b_ctl, 0, sizeof(b_ctl)); (void)ioctl_device(fd, PLOOP_IOC_BALLOON, &b_ctl); } if (fd != -1) close(fd); free(pfiemap); free(freemap); free(rangemap); free(relocmap); free(reverse_map); free(freeblks); free(relocblks); if (delta.fd != -1) close_delta(&delta); return ret; } int ploop_balloon_get_state(const char *device, __u32 *state) { int fd, ret; struct ploop_balloon_ctl b_ctl; fd = open_device(device); if (fd == -1) return SYSEXIT_OPEN; bzero(&b_ctl, sizeof(b_ctl)); b_ctl.keep_intact = 1; ret = ioctl_device(fd, PLOOP_IOC_BALLOON, &b_ctl); if (ret) goto err; *state = b_ctl.mntn_type; err: close(fd); return ret; }