--- /dev/null
+/* lafs_validate_geometry.
+ * When adding a device to a LaFS we need to check the geometry
+ * parameters are all valid and consistent, and we need to set
+ * defaults.
+ * That is done here and used by mkfs and 'lafs'.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <lafs/lafs.h>
+
+int is_pow2(long num)
+{
+ return (num & (num-1)) == 0;
+}
+
+
+char *lafs_validate_geometry(long *block_bytes,
+ long *segment_bytes,
+ long *stride_bytes,
+ int *width,
+ long long device_bytes)
+{
+ char *error = NULL;
+
+ if (*block_bytes == 0)
+ *block_bytes = 1024;
+
+ if (*block_bytes < 512 || *block_bytes > 4096 ||
+ !is_pow2(*block_bytes)) {
+ asprintf(&error, "block size %ld is illegal - must be "
+ "power of 2 in range 512..4096",
+ *block_bytes);
+ return error;
+ }
+
+ if (*width == 0)
+ *width = 1;
+ if (*width < 1 || *width > 128) {
+ asprintf(&error, "width %d is illegal - must be in range 1..128",
+ *width);
+ return error;
+ }
+
+ if (*stride_bytes == 0)
+ *stride_bytes = *block_bytes;
+
+ if (*stride_bytes < 0 || (*stride_bytes % *block_bytes) != 0) {
+ asprintf(&error, "stride %ld is illegal - must be "
+ "a multiple of block size",
+ *stride_bytes);
+ return error;
+ }
+
+ /* segment size must be a multiple of block size and of width.
+ * It must either be a multiple or a sub-multiple of stride size
+ */
+ if (*segment_bytes == 0) {
+ /* choose maximum size ?? */
+ long seg;
+ long blocks = 65536 / *width;
+ blocks *= *width;
+ seg = *block_bytes * blocks;
+ if (seg * 17 > device_bytes) {
+ blocks = device_bytes / 16 / *block_bytes / *width;
+ blocks *= *width;
+ seg = *block_bytes * blocks;
+ }
+ if (*stride_bytes < seg) {
+ seg /= *stride_bytes;
+ seg *= *stride_bytes;
+ } else {
+ if ((*stride_bytes % seg) != 0) {
+ asprintf(&error, "explicit segment size must be "
+ "given with large stride");
+ return error;
+ }
+ }
+ *segment_bytes = seg;
+ }
+
+ if (*segment_bytes * 8 > device_bytes)
+ asprintf(&error, "segment size too large for device.");
+ else if (*segment_bytes < *block_bytes * 8)
+ asprintf(&error, "segment must hold at least 8 blocks.");
+ else if (*segment_bytes % *block_bytes)
+ asprintf(&error, "segment size must be a multiple of block size");
+ else if (*segment_bytes % *width)
+ asprintf(&error, "segment size must be a multiple of width");
+ else if (*segment_bytes > *stride_bytes &&
+ (*segment_bytes % *stride_bytes))
+ asprintf(&error, "segment size must be a multiple of stride size");
+ else if (*segment_bytes < *stride_bytes &&
+ (*stride_bytes % *segment_bytes))
+ asprintf(&error, "segment size must be a divisor of stride size");
+
+ return error;
+}
*valp = val;
}
-int is_pow2(long num)
-{
- return (num & (num-1)) == 0;
-}
-
-
-void validate_parameters(long *block_bytes, long *segment_bytes, long *stride_bytes,
- int *width, long long device_bytes)
-{
-
- if (*block_bytes == 0)
- *block_bytes = 1024;
-
- if (*block_bytes < 512 || *block_bytes > 4096 ||
- !is_pow2(*block_bytes)) {
- fprintf(stderr, "lafs.mkfs: block size %ld is illegal - must be power of 2 in range 512..4096\n",
- *block_bytes);
- exit(2);
- }
-
- if (*width == 0)
- *width = 1;
- if (*width < 1 || *width > 128) {
- fprintf(stderr, "lafs.mkfs: width %d is illegal - must be in range 1..128\n", *width);
- exit(2);
- }
-
- if (*stride_bytes == 0)
- *stride_bytes = *block_bytes;
-
- if (*stride_bytes < 0 || (*stride_bytes % *block_bytes) != 0) {
- fprintf(stderr, "lafs.mkfs: stride %ld is illegal - must be a multiple of block size\n",
- *stride_bytes);
- exit(2);
- }
-
- /* segment size must be a multiple of block size and of width.
- * It must either be a multiple or a sub-multiple of stride size
- */
- if (*segment_bytes == 0) {
- /* choose maximum size ?? */
- long seg;
- long blocks = 65536 / *width;
- blocks *= *width;
- seg = *block_bytes * blocks;
- if (seg * 17 > device_bytes) {
- blocks = device_bytes / 16 / *block_bytes / *width;
- blocks *= *width;
- seg = *block_bytes * blocks;
- }
- if (*stride_bytes < seg) {
- seg /= *stride_bytes;
- seg *= *stride_bytes;
- } else {
- if ((*stride_bytes % seg) != 0) {
- fprintf(stderr, "lafs.mkfs: explicit segment size must be given with large stride\n");
- exit(2);
- }
- }
- *segment_bytes = seg;
- }
-
- if (*segment_bytes * 8 > device_bytes) {
- fprintf(stderr, "lafs.mkfs: segment size too large for device.\n");
- exit(2);
- }
-
- if (*segment_bytes < *block_bytes * 8) {
- fprintf(stderr, "lafs.mkfs: segment must hold at least 8 blocks.\n");
- exit(2);
- }
-
- if (*segment_bytes % *block_bytes) {
- fprintf(stderr, "lafs.mkfs: segment size must be a multiple of block size\n");
- exit(2);
- }
- if (*segment_bytes % *width) {
- fprintf(stderr, "lafs.mkfs: segment size must be a multiple of width\n");
- exit(2);
- }
- if (*segment_bytes > *stride_bytes &&
- (*segment_bytes % *stride_bytes)) {
- fprintf(stderr, "lafs.mkfs: segment size must be a multiple of stride size\n");
- exit(2);
- }
- if (*segment_bytes < *stride_bytes &&
- (*stride_bytes % *segment_bytes)) {
- fprintf(stderr, "lafs.mkfs: segment size must be a divisor of stride size\n");
- exit(2);
- }
-}
-
int open_device(char *devname, long long *device_bytes, int regular_file)
{
/* must be able to get an exclusive open on the device and its size
int regular_file = 0;
int opt;
int dev_fd;
+ char *error;
struct lafs *lafs;
struct lafs_device *dev;
struct lafs_ino *ifile, *imfile, *rootdir, *orphans, *segmap;
dev_fd = open_device(devname, &device_bytes, regular_file);
/* Validate parameters */
- validate_parameters(&block_bytes, &segment_bytes, &stride_bytes, &width,
- device_bytes);
+ error = lafs_validate_geometry(&block_bytes, &segment_bytes,
+ &stride_bytes, &width,
+ device_bytes);
+ if (error) {
+ fprintf(stderr, "mkfs.lafs: %s\n", error);
+ free(error);
+ exit(2);
+ }
/* Create filesystem handle */
lafs = lafs_alloc();