diff options
author | Roland McGrath <roland@gnu.org> | 2001-10-01 01:04:57 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2001-10-01 01:04:57 +0000 |
commit | af3199bd62a9f635e081af23a834bc47fce83bc6 (patch) | |
tree | cf9310d725f132436c2ed3777c86c1497cffd67e | |
parent | dd033a2bbced5e561c0e692bf3da2a43bad435ae (diff) |
2001-09-30 Roland McGrath <roland@frob.com>
* memobj.c: New file.
* Makefile (SRCS): Add it.
* store.h (store_memobj_class, store_memobj_create): Declare them.
-rw-r--r-- | libstore/Makefile | 2 | ||||
-rw-r--r-- | libstore/memobj.c | 188 | ||||
-rw-r--r-- | libstore/store.h | 8 |
3 files changed, 197 insertions, 1 deletions
diff --git a/libstore/Makefile b/libstore/Makefile index 4825f76e..7795b97a 100644 --- a/libstore/Makefile +++ b/libstore/Makefile @@ -26,7 +26,7 @@ libname = libstore SRCS = create.c derive.c make.c rdwr.c set.c device.c file.c stripe.c \ enc.c encode.c decode.c clone.c argp.c std.c kids.c zero.c flags.c \ open.c remap.c xinl.c task.c typed.c copy.c gunzip.c map.c mvol.c \ - bunzip2.c part.c nbd.c + bunzip2.c part.c nbd.c memobj.c LCLHDRS=store.h installhdrs=store.h diff --git a/libstore/memobj.c b/libstore/memobj.c new file mode 100644 index 00000000..6205b596 --- /dev/null +++ b/libstore/memobj.c @@ -0,0 +1,188 @@ +/* Store backend using a Mach memory object + Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <hurd.h> +#include <hurd/store.h> +#include <hurd/sigpreempt.h> +#include <sys/mman.h> +#include <string.h> +#include <assert.h> + + +/* Return a new store in STORE referring to the memory object MEMOBJ. + Consumes the send right MEMOBJ. */ +error_t +store_memobj_create (memory_object_t memobj, int flags, size_t block_size, + const struct store_run *runs, size_t num_runs, + struct store **store) +{ + return _store_create (&store_memobj_class, + memobj, flags, block_size, runs, num_runs, 0, store); +} + + +/* This one is pretty easy. */ +static error_t +memobj_map (const struct store *store, vm_prot_t prot, mach_port_t *memobj) +{ + *memobj = store->port; + return mach_port_mod_refs (mach_task_self (), *memobj, + MACH_PORT_RIGHT_SEND, +1); +} + + +static error_t /* swiped from libpager's pager_memcpy */ +memobj_memcpy (memory_object_t memobj, + vm_offset_t offset, void *other, size_t *size, + vm_prot_t prot) +{ + vm_address_t window = 0; + vm_size_t windowsize = 8 * vm_page_size; + size_t to_copy = *size; + error_t err; + + error_t copy (struct hurd_signal_preemptor *preemptor) + { + while (to_copy > 0) + { + size_t pageoff = offset & (vm_page_size - 1); + + if (window) + /* Deallocate the old window. */ + munmap ((caddr_t) window, windowsize); + + /* Map in and copy a standard-sized window, unless that is + more than the total left to be copied. */ + + if (windowsize > pageoff + to_copy) + windowsize = pageoff + to_copy; + + window = 0; + err = vm_map (mach_task_self (), &window, windowsize, 0, 1, + memobj, offset - pageoff, 0, + prot, prot, VM_INHERIT_NONE); + if (err) + return 0; + + /* Realign the fault preemptor for the new mapping window. */ + preemptor->first = window; + preemptor->last = window + windowsize; + + if (prot == VM_PROT_READ) + memcpy (other, (const void *) window + pageoff, + windowsize - pageoff); + else + memcpy ((void *) window + pageoff, other, windowsize - pageoff); + + offset += windowsize - pageoff; + other += windowsize - pageoff; + to_copy -= windowsize - pageoff; + } + return 0; + } + + jmp_buf buf; + void fault (int signo, long int sigcode, struct sigcontext *scp) + { + assert (scp->sc_error == EKERN_MEMORY_ERROR); + err = EIO; + to_copy -= sigcode - window; + longjmp (buf, 1); + } + + if (to_copy == 0) + /* Short-circuit return if nothing to do. + ERR would not be initialized by the copy loop in this case. */ + return 0; + + if (setjmp (buf) == 0) + hurd_catch_signal (sigmask (SIGSEGV) | sigmask (SIGBUS), + window, window + windowsize, + ©, (sighandler_t) &fault); + + if (window) + munmap ((caddr_t) window, windowsize); + + *size -= to_copy; + + return err; +} + +static error_t +memobj_read (struct store *store, + store_offset_t addr, size_t index, size_t amount, + void **buf, size_t *len) +{ + addr <<= store->log2_block_size; + if (((size_t) addr & (vm_page_size - 1)) == 0) + { + *len = amount; + return vm_map (mach_task_self (), (vm_address_t *) buf, amount, + 0, 1, store->port, addr << store->log2_block_size, 0, + VM_PROT_READ, VM_PROT_ALL, VM_INHERIT_NONE); + } + else + { + error_t err; + int alloced = 0; + if (*len < amount) + { + *buf = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); + if (*buf == MAP_FAILED) + return errno; + alloced = 1; + } + *len = amount; + err = memobj_memcpy (store->port, addr, *buf, len, VM_PROT_READ); + if (err && alloced) + munmap (*buf, amount); + else if (alloced && round_page (*len) < round_page (amount)) + munmap (*buf + round_page (*len), + round_page (amount) - round_page (*len)); + return err; + } +} + +static error_t +memobj_write (struct store *store, + store_offset_t addr, size_t index, + const void *buf, size_t len, size_t *amount) +{ + *amount = len; + return memobj_memcpy (store->port, addr << store->log2_block_size, + (void *) buf, amount, VM_PROT_WRITE); +} + +static error_t +memobj_decode (struct store_enc *enc, const struct store_class *const *classes, + struct store **store) +{ + return store_std_leaf_decode (enc, store_memobj_create, store); +} + +struct store_class store_memobj_class = +{ + STORAGE_MEMORY, "memobj", + map: memobj_map, + read: memobj_read, + write: memobj_write, + allocate_encoding: store_std_leaf_allocate_encoding, + encode: store_std_leaf_encode, + decode: memobj_decode, +}; diff --git a/libstore/store.h b/libstore/store.h index d7f687d3..a8ff49fe 100644 --- a/libstore/store.h +++ b/libstore/store.h @@ -382,6 +382,13 @@ error_t _store_task_create (task_t task, int flags, size_t block_size, corresponding store in STORE. */ error_t store_task_open (const char *name, int flags, struct store **store); +/* Return a new store in STORE referring to the memory object MEMOBJ. + Consumes the send right MEMOBJ. */ +error_t store_memobj_create (memory_object_t memobj, int flags, + size_t block_size, + const struct store_run *runs, size_t num_runs, + struct store **store); + /* Open the network block device NAME (parsed as "HOSTNAME:PORT[/BLOCKSIZE]"), and return the corresponding store in STORE. This opens a socket and initial connection handshake, which determine the size of the device, @@ -509,6 +516,7 @@ extern const struct store_class store_part_class; extern const struct store_class store_file_class; extern const struct store_class store_task_class; extern const struct store_class store_nbd_class; +extern const struct store_class store_memobj_class; extern const struct store_class store_zero_class; extern const struct store_class store_ileave_class; extern const struct store_class store_concat_class; |