diff options
author | Miles Bader <miles@gnu.org> | 1996-03-20 00:22:14 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1996-03-20 00:22:14 +0000 |
commit | 52af976a7077d31aad3715cc229c1b51533ce395 (patch) | |
tree | 2a03bf0a9c4d4d5e5aa7b5b026a77897039f5961 /libstore | |
parent | 24f1bcac8891fcf7d7d26847cca95d9662cca158 (diff) |
Formerly stripe.c.~4~
Diffstat (limited to 'libstore')
-rw-r--r-- | libstore/stripe.c | 85 |
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, |