diff options
-rw-r--r-- | libstore/stripe.c | 187 |
1 files changed, 136 insertions, 51 deletions
diff --git a/libstore/stripe.c b/libstore/stripe.c index 6058e9d8..485bfd6f 100644 --- a/libstore/stripe.c +++ b/libstore/stripe.c @@ -20,74 +20,159 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <stdlib.h> + #include "store.h" - -static error_t -ileave_read (struct store *store, - off_t addr, size_t index, mach_msg_type_number_t amount, - char **buf, mach_msg_type_number_t *len) -{ - return io_read (store->port, buf, len, addr * store->block_size, amount); -} -static error_t -file_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 stripe_info { - return io_write (store->port, buf, len, addr * store->block_size, amount); -} - -static struct store_meths -file_meths = {file_read, file_write}; - + struct store **stripes; + int dealloc : 1; +}; + static error_t -file_byte_read (struct store *store, off_t addr, mach_msg_type_number_t amount, - char **buf, mach_msg_type_number_t *len) +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) { - return io_read (store->port, buf, len, addr, amount); + struct stripe_info *info = store->hook; + return store_read (info->stripes[index], addr, amount, buf, len); } static error_t -file_byte_write (struct store *store, - off_t addr, char *buf, mach_msg_type_number_t len, - mach_msg_type_number_t *amount) +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) { - return io_write (store->port, buf, len, addr, amount); + struct store **stripes = store->hook; + return store_write (stripes[index], addr, buf, len, amount); } static struct store_meths -file_byte_meths = {file_byte_read, file_byte_write}; +stripe_meths = {stripe_read, stripe_write}; -/* Return a new store in STORE referring to the mach file FILE. Consumes - the send right FILE. */ +/* 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). */ error_t -store_file_create (file_t file, struct store **store) +store_ileave_create (struct store **stripes, size_t num_stripes, int dealloc, + off_t interleave, struct store **store) { - off_t runs[2]; - struct stat stat; - error_t err = io_stat (file, &stat); - - if (err) - return err; - - runs[0] = 0; - runs[1] = stat.st_size; - - return _store_file_create (file, 1, runs, 2, store); + size_t i; + error_t err = EINVAL; /* default error */ + off_t block_size = 0, min_end = 0; + off_t runs[num_stripes * 2]; + struct stripe_info *info = malloc (sizeof (struct stripe_info)); + + if (info == 0) + return ENOMEM; + + info->stripes = malloc (sizeof (struct store *) * num_stripes); + info->dealloc = dealloc; + + if (info->stripes == 0) + { + free (info); + return ENOMEM; + } + + if (interleave == 0) + goto barf; + + for (i = 0; i < num_stripes; i++) + { + 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; + } + } + + *store = _make_store (0, &stripe_meths, MACH_PORT_NULL, block_size, + runs, num_stripes * 2, min_end); + if (! *store) + { + err = ENOMEM; + goto barf; + } + + (*store)->hook = info; + bcopy (stripes, info->stripes, num_stripes * sizeof *stripes); + + return 0; + + barf: + free (info->stripes); + free (info); + return err; } -/* Like store_file_create, but doesn't query the file for information. */ +/* 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). */ error_t -_store_file_create (file_t file, size_t block_size, - off_t *runs, unsigned runs_len, - struct store **store) +store_concat_create (struct store **stores, size_t num_stores, int dealloc, + struct store **store) { - if (block_size == 1) - *store = _make_store (STORAGE_HURD_FILE, &file_byte_meths, file, 1, - runs, runs_len); - else - *store = _make_store (STORAGE_HURD_FILE, &file_meths, file, block_size, - runs, runs_len); - return *store ? 0 : ENOMEM; + size_t i; + error_t err = EINVAL; /* default error */ + off_t block_size = 0; + off_t runs[num_stores * 2]; + struct stripe_info *info = malloc (sizeof (struct stripe_info)); + + if (info == 0) + return ENOMEM; + + info->stripes = malloc (sizeof (struct store *) * num_stores); + info->dealloc = dealloc; + + if (info->stripes == 0) + { + free (info); + return ENOMEM; + } + + 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, + runs, num_stores * 2, 0); + if (! *store) + { + err = ENOMEM; + goto barf; + } + + (*store)->hook = info; + bcopy (stores, info->stripes, num_stores * sizeof *stores); + + return 0; + + barf: + free (info->stripes); + free (info); + return err; } |