2019-10-09 18:06:43 +02:00
|
|
|
#include <libcbd.h>
|
|
|
|
|
|
|
|
#include <cbdutil.h>
|
|
|
|
|
|
|
|
static void
|
2019-10-10 22:21:36 +02:00
|
|
|
pblk_write(int fd, u64 pblk, u32 count, const u8* data)
|
2019-10-09 18:06:43 +02:00
|
|
|
{
|
2019-10-10 22:21:36 +02:00
|
|
|
off_t pos;
|
2019-10-09 18:06:43 +02:00
|
|
|
size_t remain;
|
|
|
|
ssize_t ret;
|
|
|
|
|
2019-10-10 22:21:36 +02:00
|
|
|
pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET);
|
|
|
|
if (pos == (off_t)-1) {
|
2019-10-09 18:06:43 +02:00
|
|
|
error("Failed to seek\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
remain = count * PBLK_SIZE;
|
|
|
|
while (remain) {
|
|
|
|
ret = write(fd, data, count * PBLK_SIZE);
|
|
|
|
if (ret <= 0) {
|
|
|
|
error("Failed to write\n");
|
|
|
|
}
|
|
|
|
remain -= ret;
|
|
|
|
data += ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
cbd_format(const char* dev,
|
2019-10-10 22:21:36 +02:00
|
|
|
uint64_t psize, uint16_t lshift, uint64_t lsize)
|
2019-10-09 18:06:43 +02:00
|
|
|
{
|
|
|
|
int devfd;
|
2019-10-10 22:21:36 +02:00
|
|
|
uint32_t lblk_size;
|
2019-10-09 18:06:43 +02:00
|
|
|
struct cbd_header header;
|
|
|
|
uint8_t pblkbuf[PBLK_SIZE];
|
|
|
|
uint64_t pblk;
|
|
|
|
uint64_t zone_idx;
|
|
|
|
|
|
|
|
devfd = open(dev, O_RDWR);
|
|
|
|
if (devfd < 0) {
|
|
|
|
error("Cannot open device\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!psize) {
|
2019-10-10 22:21:36 +02:00
|
|
|
off_t pos;
|
|
|
|
pos = lseek(devfd, 0, SEEK_END);
|
|
|
|
if (pos == (off_t)-1) {
|
2019-10-09 18:06:43 +02:00
|
|
|
error("Cannot seek device\n");
|
|
|
|
}
|
2019-10-10 22:21:36 +02:00
|
|
|
psize = pos / PBLK_SIZE * PBLK_SIZE;
|
2019-10-09 18:06:43 +02:00
|
|
|
}
|
|
|
|
if (!lshift) {
|
|
|
|
lshift = CBD_DEFAULT_LOGICAL_BLOCK_SHIFT;
|
|
|
|
}
|
2019-10-10 22:21:36 +02:00
|
|
|
lblk_size = 1 << (lshift + PBLK_SHIFT);
|
|
|
|
if (!lsize) {
|
|
|
|
/* XXX: Why is the cast needed here? */
|
|
|
|
lsize = (uint64_t)(psize * CBD_DEFAULT_COMPRESSION_FACTOR) / lblk_size * lblk_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (psize % PBLK_SIZE) {
|
|
|
|
error("Physical size %lu is not a multiple of %u bytes\n", (ulong)psize, (uint)PBLK_SIZE);
|
|
|
|
}
|
|
|
|
if (lshift < LBLK_SHIFT_MIN || lshift > LBLK_SHIFT_MAX) {
|
|
|
|
error("Logical shift %hu is not in [%u,%u]\n", (ushort)lshift, (uint)LBLK_SHIFT_MIN, (uint)LBLK_SHIFT_MAX);
|
|
|
|
}
|
|
|
|
if (lsize % (1 << (lshift + PBLK_SHIFT))) {
|
|
|
|
error("Logical size %lu is not a multiple of %u bytes\n", (ulong)psize, (uint)lblk_size);
|
|
|
|
}
|
2019-10-09 18:06:43 +02:00
|
|
|
|
|
|
|
printf("%s: paramaters...\n", __func__);
|
2019-10-10 22:21:36 +02:00
|
|
|
printf(" psize=%lu\n", (unsigned long)psize);
|
|
|
|
printf(" lshift=%hu\n", (unsigned short)lshift);
|
|
|
|
printf(" lsize=%lu\n", (unsigned long)lsize);
|
2019-10-09 18:06:43 +02:00
|
|
|
memset(&header, 0, sizeof(header));
|
|
|
|
memcpy(header.magic, CBD_MAGIC, sizeof(header.magic));
|
|
|
|
header.version_major = CBD_VERSION_MAJOR;
|
|
|
|
header.version_minor = CBD_VERSION_MINOR;
|
|
|
|
header.params.algorithm = CBD_ALG_LZ4;
|
|
|
|
header.params.compression = 1;
|
|
|
|
header.params.lblk_shift = lshift;
|
2019-10-10 22:21:36 +02:00
|
|
|
header.params.nr_pblk = psize / PBLK_SIZE;
|
2019-10-09 18:06:43 +02:00
|
|
|
/* XXX: Initial estimate */
|
2019-10-10 22:21:36 +02:00
|
|
|
header.params.lblk_per_zone = zone_data_len(&header.params) * (lsize / lblk_size) / (psize / PBLK_SIZE);
|
2019-10-09 18:06:43 +02:00
|
|
|
printf(" initial estimate for lblk_per_zone: %lu\n", (unsigned long)header.params.lblk_per_zone);
|
2019-10-10 22:21:36 +02:00
|
|
|
header.params.nr_zones = ((psize >> PBLK_SHIFT) - CBD_HEADER_BLOCKS) / zone_len(&header.params);
|
|
|
|
header.params.lblk_per_zone = DIV_ROUND_UP(lsize / lblk_size, header.params.nr_zones);
|
2019-10-09 18:06:43 +02:00
|
|
|
printf("%s: parameters...\n", __func__);
|
|
|
|
printf(" lblk_shift=%hu\n", (unsigned short)header.params.lblk_shift);
|
|
|
|
printf(" nr_pblk=%lu\n", (unsigned long)header.params.nr_pblk);
|
|
|
|
printf(" nr_zones=%lu\n", (unsigned long)header.params.nr_zones);
|
|
|
|
printf(" lblk_per_zone=%lu\n", (unsigned long)header.params.lblk_per_zone);
|
|
|
|
|
|
|
|
memset(pblkbuf, 0, sizeof(pblkbuf));
|
|
|
|
cbd_header_put(pblkbuf, &header);
|
|
|
|
|
2019-10-10 22:21:36 +02:00
|
|
|
pblk = 0;
|
2019-10-09 18:06:43 +02:00
|
|
|
pblk_write(devfd, pblk, 1, pblkbuf);
|
|
|
|
pblk += CBD_HEADER_BLOCKS;
|
|
|
|
|
|
|
|
printf("Writing %lu zones starting at %lu\n",
|
|
|
|
(unsigned long)header.params.nr_zones, (unsigned long)pblk);
|
|
|
|
|
|
|
|
memset(pblkbuf, 0, sizeof(pblkbuf));
|
|
|
|
for (zone_idx = 0; zone_idx < header.params.nr_zones; ++zone_idx) {
|
|
|
|
uint32_t count;
|
|
|
|
uint32_t n;
|
|
|
|
pblk = zone_off(&header.params, zone_idx);
|
|
|
|
count = zone_metadata_len(&header.params);
|
|
|
|
printf(" Zone %lu pblk=%lu count=%u\n",
|
|
|
|
(unsigned long)zone_idx, (unsigned long)pblk, (unsigned int)count);
|
|
|
|
for (n = 0; n < count; ++n) {
|
|
|
|
pblk_write(devfd, pblk + n, 1, pblkbuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|