}
if (!p) {
- int size = sizeof(struct btrfs_chunk) * (*info_count+1);
- struct chunk_info *res = realloc(*info_ptr, size);
+ int tmp = sizeof(struct btrfs_chunk) * (*info_count + 1);
+ struct chunk_info *res = realloc(*info_ptr, tmp);
if (!res) {
free(*info_ptr);
return 1;
}
- off += sh->len;
+ off += btrfs_search_header_len(sh);
- sk->min_objectid = sh->objectid;
- sk->min_type = sh->type;
- sk->min_offset = sh->offset+1;
+ sk->min_objectid = btrfs_search_header_objectid(sh);
+ sk->min_type = btrfs_search_header_type(sh);
+ sk->min_offset = btrfs_search_header_offset(sh)+1;
}
if (!sk->min_offset) /* overflow */
sargs->total_spaces = 0;
ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
- if (ret) {
+ if (ret < 0) {
error("cannot get space info on '%s': %s", path,
strerror(errno));
free(sargs);
sargs->total_spaces = 0;
ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
- if (ret) {
+ if (ret < 0) {
error("cannot get space info with %u slots: %s",
count, strerror(errno));
free(sargs);
}
/*
- * This function computes the space occuped by a *single* RAID5/RAID6 chunk.
+ * This function computes the space occupied by a *single* RAID5/RAID6 chunk.
* The computation is performed on the basis of the number of stripes
* which compose the chunk, which could be different from the number of devices
* if a disk is added later.
u64 free_estimated = 0;
u64 free_min = 0;
int max_data_ratio = 1;
+ int mixed = 0;
sargs = load_space_info(fd, path);
if (!sargs) {
l_global_reserve_used = sargs->spaces[i].used_bytes;
}
if ((flags & (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA))
- == (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA)) {
- warning("MIXED blockgroups not handled");
+ == (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA)) {
+ mixed = 1;
}
-
if (flags & BTRFS_BLOCK_GROUP_DATA) {
r_data_used += sargs->spaces[i].used_bytes * ratio;
r_data_chunks += sargs->spaces[i].total_bytes * ratio;
}
}
- r_total_chunks = r_data_chunks + r_metadata_chunks + r_system_chunks;
- r_total_used = r_data_used + r_metadata_used + r_system_used;
+ r_total_chunks = r_data_chunks + r_system_chunks;
+ r_total_used = r_data_used + r_system_used;
+ if (!mixed) {
+ r_total_chunks += r_metadata_chunks;
+ r_total_used += r_metadata_used;
+ }
r_total_unused = r_total_size - r_total_chunks;
/* Raw / Logical = raid factor, >= 1 */
data_ratio = (double)r_data_chunks / l_data_chunks;
- metadata_ratio = (double)r_metadata_chunks / l_metadata_chunks;
+ if (mixed)
+ metadata_ratio = data_ratio;
+ else
+ metadata_ratio = (double)r_metadata_chunks / l_metadata_chunks;
#if 0
/* add the raid5/6 allocated space */
* In non-mixed case there's no difference.
*/
free_estimated = (r_data_chunks - r_data_used) / data_ratio;
+ /*
+ * For mixed-bg the metadata are left out in calculations thus global
+ * reserve would be lost. Part of it could be permanently allocated,
+ * we have to subtract the used bytes so we don't go under zero free.
+ */
+ if (mixed)
+ free_estimated -= l_global_reserve - l_global_reserve_used;
free_min = free_estimated;
/* Chop unallocatable space */
}
for (i = 0, ndevs = 0 ; i <= fi_args.max_id ; i++) {
- BUG_ON(ndevs >= fi_args.num_devices);
+ if (ndevs >= fi_args.num_devices) {
+ error("unexpected number of devices: %d >= %llu", ndevs,
+ (unsigned long long)fi_args.num_devices);
+ goto out;
+ }
memset(&dev_info, 0, sizeof(dev_info));
ret = get_device_info(fd, i, &dev_info);
continue;
if (ret) {
error("cannot get info about device devid=%d", i);
- free(info);
- return ret;
+ goto out;
}
info[ndevs].devid = dev_info.devid;
++ndevs;
}
- BUG_ON(ndevs != fi_args.num_devices);
+ if (ndevs != fi_args.num_devices) {
+ error("unexpected number of devices: %d != %llu", ndevs,
+ (unsigned long long)fi_args.num_devices);
+ goto out;
+ }
+
qsort(info, fi_args.num_devices,
sizeof(struct device_info), cmp_device_info);
*device_info_ptr = info;
return 0;
+
+out:
+ free(info);
+ return ret;
}
int load_chunk_and_device_info(int fd, struct chunk_info **chunkinfo,
unit_mode = get_unit_mode_from_arg(&argc, argv, 1);
- optind = 1;
while (1) {
int c;
printf(" Device size: %*s%10s\n",
(int)(20 - strlen("Device size")), "",
pretty_size_mode(devinfo->device_size, unit_mode));
-#if 0
- /*
- * The term has not seen an agreement and we don't want to change it
- * once it's in non-development branches or even released.
- */
- printf(" FS occupied: %*s%10s\n",
- (int)(20 - strlen("FS occupied")), "",
- pretty_size_mode(devinfo->size, unit_mode));
-#endif
+ printf(" Device slack: %*s%10s\n",
+ (int)(20 - strlen("Device slack")), "",
+ pretty_size_mode(devinfo->device_size - devinfo->size,
+ unit_mode));
}