#include <sys/param.h>
#include <err.h>
#include <stdalign.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define UBERBLOCK_SHIFT (10) /* Each uberblock should be padded to 1KB */
#define VDEV_UBERRING_SHIFT (17) /* The entire ring of uberblocks is 128KB */
#define VDEV_UBERBLOCK_RING (128 << 10)
#define MAX_UBERBLOCK_SHIFT (15) /* The largest sector size we support is 16KB. Was 13 (8KB) */
/* Calculate the uberblock shift based on ashift bounded by UBERBLOCK_SHIFT and MAX_UBERBLOCK_SHIFT */
#define VDEV_UBERBLOCK_SHIFT(ashift) \
MIN(MAX(ashift, UBERBLOCK_SHIFT), \
MAX_UBERBLOCK_SHIFT)
/* How many sectors are available for uberblocks. This used to determine the number of uberblocks */
#define VDEV_UBERBLOCK_COUNT(ashift) \
(VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT(ashift))
/* How big is an uberblock, this will need to be renamed to ubersector or something */
#define VDEV_UBERBLOCK_SIZE(ashift) (1ULL << VDEV_UBERBLOCK_SHIFT(ashift))
/*
* Mask the transaction id [txg] to calculate the offset within the selected
* ubersector to write the next uberblock. This is done round-robin to avoid
* writing to the same ubersector for sequential uberblocks.
* Will be a mask of X 1 bits, shifted left by Y bits.
* X is equal to the difference in between the ashift [sector size] and
* UBERBLOCK_SHIFT [uberblock size].
* Y is the difference between VDEV_UBERRING_SHIFT [size of the uber ring] and
* VDEV_UBERBLOCK_SHIFT(ashift) [size of each ubersector]
*
* ashift=9: X=10-10=0, Y=17-10=7: 0x0000000
* ashift=12: X=12-10=2, Y=17-12=5: 0x1100000
* ashift=14: X=14-10=4, Y=17-14=3: 0x1111000
*/
#define VDEV_SUBBLOCK(txg, ashift) \
((txg & \
( \
((1ULL << (VDEV_UBERBLOCK_SHIFT(ashift) - UBERBLOCK_SHIFT)) - 1) << \
(VDEV_UBERRING_SHIFT - VDEV_UBERBLOCK_SHIFT(ashift)) \
) \
) >> (VDEV_UBERRING_SHIFT - VDEV_UBERBLOCK_SHIFT(ashift)) \
)
int
main(int argc, char *argv[])
{
unsigned long long txg, n, ashift;
const char *errstr;
txg = 0;
if (argc > 1) {
ashift = strtonum(argv[1], 9, 15, &errstr);
if (errstr != NULL) {
errx(1, "ashift is %s: %s", errstr, argv[1]);
}
} else {
ashift = 12;
}
for (txg = 0; txg < 256; txg++) {
printf("txg=%llu n=%llu\tblock=%2llu\tsubblock=%llu\n",
txg,
txg & (VDEV_UBERBLOCK_COUNT(UBERBLOCK_SHIFT) - 1),
txg & (VDEV_UBERBLOCK_COUNT(ashift) - 1),
VDEV_SUBBLOCK(txg, ashift)
);
}
}