summaryrefslogtreecommitdiff
path: root/libstore
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1996-03-20 00:22:14 +0000
committerMiles Bader <miles@gnu.org>1996-03-20 00:22:14 +0000
commit52af976a7077d31aad3715cc229c1b51533ce395 (patch)
tree2a03bf0a9c4d4d5e5aa7b5b026a77897039f5961 /libstore
parent24f1bcac8891fcf7d7d26847cca95d9662cca158 (diff)
Formerly stripe.c.~4~
Diffstat (limited to 'libstore')
-rw-r--r--libstore/stripe.c85
1 files changed, 52 insertions, 33 deletions
diff --git a/libstore/stripe.c b/libstore/stripe.c
index d810f7b0..0032060d 100644
--- a/libstore/stripe.c
+++ b/libstore/stripe.c
@@ -30,13 +30,27 @@ struct stripe_info
int dealloc : 1;
};
+/* Return ADDR adjust for any block size difference between STORE and
+ STRIPE. We assume that STORE's block size is no less than STRIPE's. */
+static inline off_t
+addr_adj (off_t addr, struct store *store, struct store *stripe)
+{
+ unsigned common_bs = store->block_shift;
+ unsigned stripe_bs = stripe->block_shift;
+ if (common_bs == stripe_bs)
+ return addr;
+ else
+ return addr << (common_bs - stripe_bs);
+}
+
static error_t
stripe_read (struct store *store,
off_t addr, size_t index, mach_msg_type_number_t amount,
char **buf, mach_msg_type_number_t *len)
{
struct stripe_info *info = store->hook;
- return store_read (info->stripes[index], addr, amount, buf, len);
+ struct store *stripe = info->stripes[index];
+ return store_read (stripe, addr_adj (addr, store, stripe), amount, buf, len);
}
static error_t
@@ -44,25 +58,27 @@ stripe_write (struct store *store,
off_t addr, size_t index, char *buf, mach_msg_type_number_t len,
mach_msg_type_number_t *amount)
{
- struct store **stripes = store->hook;
- return store_write (stripes[index], addr, buf, len, amount);
+ struct stripe_info *info = store->hook;
+ struct store *stripe = info->stripes[index];
+ return
+ store_write (stripe, addr_adj (addr, store, stripe), buf, len, amount);
}
static struct store_meths
stripe_meths = {stripe_read, stripe_write};
/* Return a new store in STORE that interleaves all the stores in STRIPES
- (NUM_STRIPES of them) every INTERLEAVE blocks (every store in STRIPES must
- have the same block size). If DEALLOC is true, then the striped stores
- are freed when this store is (in any case, the array STRIPES is copied,
- and so should be freed by the caller). */
+ (NUM_STRIPES of them) every INTERLEAVE bytes; INTERLEAVE must be an
+ integer multiple of each stripe's block size. If DEALLOC is true, then
+ the striped stores are freed when this store is (in any case, the array
+ STRIPES is copied, and so should be freed by the caller). */
error_t
store_ileave_create (struct store **stripes, size_t num_stripes, int dealloc,
off_t interleave, struct store **store)
{
size_t i;
error_t err = EINVAL; /* default error */
- off_t block_size = 0, min_end = 0;
+ off_t block_size = 1, min_end = 0;
off_t runs[num_stripes * 2];
struct stripe_info *info = malloc (sizeof (struct stripe_info));
@@ -78,27 +94,31 @@ store_ileave_create (struct store **stripes, size_t num_stripes, int dealloc,
return ENOMEM;
}
- if (interleave == 0)
+ /* Find a common block size. */
+ for (i = 0; i < num_stripes; i++)
+ block_size = lcm (block_size, stripes[i]->block_size);
+
+ if (interleave < block_size || (interleave % block_size) != 0)
goto barf;
+ interleave /= block_size;
+
for (i = 0; i < num_stripes; i++)
{
+ /* The stripe's end adjusted to the common block size. */
+ off_t end = stripes[i]->end;
+
runs[i * 2] = 0;
runs[i * 2 + 1] = interleave;
- if (block_size == 0)
- {
- block_size = stripes[i]->block_size;
- min_end = stripes[i]->end;
- }
- else
- {
- if (block_size != stripes[i]->block_size)
- /* Mismatched block sizes; barf. */
- goto barf;
- if (min_end > stripes[i]->end)
- /* Only use as much space as the smallest stripe has. */
- min_end = stripes[i]->end;
- }
+
+ if (stripes[i]->block_size != block_size)
+ end /= (block_size / stripes[i]->block_size);
+
+ if (min_end < 0)
+ min_end = end;
+ else if (min_end > end)
+ /* Only use as much space as the smallest stripe has. */
+ min_end = end;
}
*store = _make_store (0, &stripe_meths, MACH_PORT_NULL, block_size,
@@ -109,6 +129,7 @@ store_ileave_create (struct store **stripes, size_t num_stripes, int dealloc,
goto barf;
}
+ (*store)->wrap_dst = interleave;
(*store)->hook = info;
bcopy (stripes, info->stripes, num_stripes * sizeof *stripes);
@@ -121,17 +142,16 @@ store_ileave_create (struct store **stripes, size_t num_stripes, int dealloc,
}
/* Return a new store in STORE that concatenates all the stores in STORES
- (NUM_STORES of them) every store in STRIPES must have the same block size.
- If DEALLOC is true, then the sub-stores are freed when this store is (in
- any case, the array STORES is copied, and so should be freed by the
- caller). */
+ (NUM_STORES of them). If DEALLOC is true, then the sub-stores are freed
+ when this store is (in any case, the array STORES is copied, and so should
+ be freed by the caller). */
error_t
store_concat_create (struct store **stores, size_t num_stores, int dealloc,
struct store **store)
{
size_t i;
error_t err = EINVAL; /* default error */
- off_t block_size = 0;
+ off_t block_size = 1;
off_t runs[num_stores * 2];
struct stripe_info *info = malloc (sizeof (struct stripe_info));
@@ -147,15 +167,14 @@ store_concat_create (struct store **stores, size_t num_stores, int dealloc,
return ENOMEM;
}
+ /* Find a common block size. */
+ for (i = 0; i < num_stripes; i++)
+ block_size = lcm (block_size, stripes[i]->block_size);
+
for (i = 0; i < num_stores; i++)
{
runs[i * 2] = 0;
runs[i * 2 + 1] = stores[i]->end;
- if (block_size == 0)
- block_size = stores[i]->block_size;
- else if (block_size != stores[i]->block_size)
- /* Mismatched block sizes; barf. */
- goto barf;
}
*store = _make_store (0, &stripe_meths, MACH_PORT_NULL, block_size,