#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 32KB. 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.
* The transaction is shifted right X bits, where X is the difference between
* VDEV_UBERRING_SHIFT [size of the uber ring] and
* VDEV_UBERBLOCK_SHIFT(ashift) [size of each ubersector], to account for the
* previous masking operation to select the ubersector.
* It is then masked with the Y bits, where Y is the difference in between
* VDEV_UBERBLOCK_SHIFT [size of each ubersector] and
* UBERBLOCK_SHIFT [size of a single uberblock]
*
* ashift=9: X=17-10=7, Y=10-10=0
* ashift=12: X=17-12=5, Y=12-10=2
* ashift=14: X=17-14=3, Y=14-10=4
*/
#define VDEV_SUBBLOCK(txg, ashift) \
( (txg >> (VDEV_UBERRING_SHIFT - VDEV_UBERBLOCK_SHIFT(ashift)) ) & \
((1ULL << (VDEV_UBERBLOCK_SHIFT(ashift) - UBERBLOCK_SHIFT)) - 1) \
)
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)
);
}
}