diff options
author | Roland McGrath <roland@gnu.org> | 1999-01-27 20:46:47 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1999-01-27 20:46:47 +0000 |
commit | 8e8f1f026b493aeea075d4f1cbc05bbf0dd6cec6 (patch) | |
tree | fe387c55550994e63545bb880b143bc6e2f4661d | |
parent | 917384c096a24625c84ab8901901a45e2f2f055f (diff) |
1999-01-27 Roland McGrath <roland@baalperazim.frob.com>
* storeio.c (options): New option -c/--no-cache.
(inhibit_cache): New variable.
(parse_opt): Make -c set it.
(trivfs_append_args): Report --no-cache if set.
(check_open_hook): Pass inhibit_cache flag to dev_open.
* dev.h (struct dev): New member `inhibit_cache'.
(dev_open): Update decl.
* dev.c (dev_open): Take new arg inhibit_cache, store in new dev.
If set, don't initialize buf_offs, io_lock, pager, pager_lock.
(dev_read, dev_write): If DEV->inhibit_cache is set, allow only
whole-block i/o: EINVAL for non-whole-block attempts.
* pager.c (dev_get_memory_object): If DEV->inhibit_cache is set, don't
make our own pager; if store_map returns EOPNOTSUPP, so do we.
-rw-r--r-- | storeio/dev.c | 68 | ||||
-rw-r--r-- | storeio/dev.h | 27 | ||||
-rw-r--r-- | storeio/pager.c | 4 | ||||
-rw-r--r-- | storeio/storeio.c | 22 |
4 files changed, 91 insertions, 30 deletions
diff --git a/storeio/dev.c b/storeio/dev.c index 2f81f32a..30828556 100644 --- a/storeio/dev.c +++ b/storeio/dev.c @@ -1,6 +1,6 @@ /* store `device' I/O - Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -138,7 +138,8 @@ dev_buf_rw (struct dev *dev, size_t buf_offs, size_t *io_offs, size_t *len, desired block size, and must be a multiple of the device block size. If an error occurs, the error code is returned, otherwise 0. */ error_t -dev_open (struct store_parsed *name, int flags, struct dev **dev) +dev_open (struct store_parsed *name, int flags, int inhibit_cache, + struct dev **dev) { error_t err; struct dev *new = malloc (sizeof (struct dev)); @@ -161,12 +162,16 @@ dev_open (struct store_parsed *name, int flags, struct dev **dev) return ENOMEM; } - new->buf_offs = -1; - rwlock_init (&new->io_lock); + new->inhibit_cache = inhibit_cache; new->owner = 0; - new->block_mask = (1 << new->store->log2_block_size) - 1; - new->pager = 0; - mutex_init (&new->pager_lock); + if (!inhibit_cache) + { + new->buf_offs = -1; + rwlock_init (&new->io_lock); + new->block_mask = (1 << new->store->log2_block_size) - 1; + new->pager = 0; + mutex_init (&new->pager_lock); + } *dev = new; return 0; @@ -176,13 +181,16 @@ dev_open (struct store_parsed *name, int flags, struct dev **dev) void dev_close (struct dev *dev) { - if (dev->pager != NULL) - pager_shutdown (dev->pager); + if (!dev->inhibit_cache) + { + if (dev->pager != NULL) + pager_shutdown (dev->pager); - dev_buf_discard (dev); + dev_buf_discard (dev); - vm_deallocate (mach_task_self (), - (vm_address_t)dev->buf, dev->store->block_size); + vm_deallocate (mach_task_self (), + (vm_address_t)dev->buf, dev->store->block_size); + } store_free (dev->store); @@ -196,6 +204,9 @@ dev_sync(struct dev *dev, int wait) { error_t err; + if (dev->inhibit_cache) + return 0; + /* Sync any paged backing store. */ if (dev->pager != NULL) pager_sync (dev->pager, wait); @@ -330,6 +341,22 @@ dev_write (struct dev *dev, off_t offs, void *buf, size_t len, buf + io_offs, len, amount); } + if (dev->inhibit_cache) + { + /* Under --no-cache, we permit only whole-block writes. + Note that in this case we handle non-power-of-two block sizes. */ + + struct store *store = dev->store; + + if (offs % store->block_size != 0 || len % store->block_size != 0) + /* Not whole blocks. No can do. */ + return EINVAL; + + /* Do a direct write to the store. */ + return store_write (dev->store, offs * store->block_size, + buf, len, amount); + } + return dev_rw (dev, offs, len, amount, buf_write, raw_write); } @@ -397,6 +424,23 @@ dev_read (struct dev *dev, off_t offs, size_t whole_amount, } } + if (dev->inhibit_cache) + { + /* Under --no-cache, we permit only whole-block reads. + Note that in this case we handle non-power-of-two block sizes. */ + + struct store *store = dev->store; + + if (offs % store->block_size != 0 + || whole_amount % store->block_size != 0) + /* Not whole blocks. No can do. */ + return EINVAL; + + /* Do a direct read from the store. */ + return store_read (dev->store, offs * store->block_size, whole_amount, + buf, len); + } + err = dev_rw (dev, offs, whole_amount, len, buf_read, raw_read); if (err && allocated_buf) vm_deallocate (mach_task_self (), (vm_address_t)*buf, whole_amount); diff --git a/storeio/dev.h b/storeio/dev.h index 7927f80d..a4321399 100644 --- a/storeio/dev.h +++ b/storeio/dev.h @@ -1,6 +1,6 @@ /* store `device' I/O - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -32,6 +32,20 @@ struct dev /* The device to which we're doing io. */ struct store *store; + /* The current owner of the open device. For terminals, this affects + controlling terminal behavior (see term_become_ctty). For all objects + this affects old-style async IO. Negative values represent pgrps. This + has nothing to do with the owner of a file (as returned by io_stat, and + as used for various permission checks by filesystems). An owner of 0 + indicates that there is no owner. */ + pid_t owner; + + /* Nonzero iff the --no-cache flag was given. + If this is set, the remaining members are not used at all + and don't need to be initialized or cleaned up. */ + int inhibit_cache; + + /* A bitmask corresponding to the part of an offset that lies within a device block. */ unsigned block_mask; @@ -50,21 +64,14 @@ struct dev struct pager *pager; struct mutex pager_lock; - - /* The current owner of the open device. For terminals, this affects - controlling terminal behavior (see term_become_ctty). For all objects - this affects old-style async IO. Negative values represent pgrps. This - has nothing to do with the owner of a file (as returned by io_stat, and - as used for various permission checks by filesystems). An owner of 0 - indicates that there is no owner. */ - pid_t owner; }; /* Returns a pointer to a new device structure in DEV for the device NAME, with the given FLAGS. If BLOCK_SIZE is non-zero, it should be the desired block size, and must be a multiple of the device block size. If an error occurs, the error code is returned, otherwise 0. */ -error_t dev_open (struct store_parsed *name, int flags, struct dev **dev); +error_t dev_open (struct store_parsed *name, int flags, int inhibit_cache, + struct dev **dev); /* Free DEV and any resources it consumes. */ void dev_close (struct dev *dev); diff --git a/storeio/pager.c b/storeio/pager.c index 28b5a4e0..e85104c5 100644 --- a/storeio/pager.c +++ b/storeio/pager.c @@ -1,6 +1,6 @@ /* Paging interface for storeio devices - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1995, 96, 97, 99 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -217,7 +217,7 @@ dev_get_memory_object (struct dev *dev, vm_prot_t prot, memory_object_t *memobj) { error_t err = store_map (dev->store, prot, memobj); - if (err == EOPNOTSUPP) + if (err == EOPNOTSUPP && !dev->inhibit_cache) { int created = 0; diff --git a/storeio/storeio.c b/storeio/storeio.c index 20a2b000..3990387c 100644 --- a/storeio/storeio.c +++ b/storeio/storeio.c @@ -1,6 +1,6 @@ /* A translator for doing I/O to stores - Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1995, 96, 97, 98, 99 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -35,8 +35,9 @@ static struct argp_option options[] = { - {"readonly", 'r', 0, 0, "Disallow writing"}, - {"writable", 'w', 0, 0, "Allow writing"}, + {"readonly", 'r', 0, 0,"Disallow writing"}, + {"writable", 'w', 0, 0,"Allow writing"}, + {"no-cache", 'c', 0, 0,"Never cache data--user io does direct device io"}, {"rdev", 'n', "ID", 0, "The stat rdev number for this node; may be either a" " single integer, or of the form MAJOR,MINOR"}, @@ -53,10 +54,13 @@ static struct mutex device_lock; /* Desired store parameters specified by the user. */ struct store_parsed *store_name; -static int readonly = 0; +static int readonly; + +/* Nonzero if user gave --no-cache flag. */ +static int inhibit_cache; /* A unixy device number to return when the device is stat'd. */ -static int rdev = 0; +static int rdev; /* Parse a single option. */ static error_t @@ -67,6 +71,8 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'r': readonly = 1; break; case 'w': readonly = 0; break; + case 'c': inhibit_cache = 1; break; + case 'n': { char *start = arg, *end; @@ -147,6 +153,9 @@ trivfs_append_args (struct trivfs_control *trivfs_control, err = argz_add (argz, argz_len, buf); } + if (!err && inhibit_cache) + err = argz_add (argz, argz_len, "--no-cache"); + if (! err) err = argz_add (argz, argz_len, readonly ? "--readonly" : "--writable"); @@ -173,7 +182,8 @@ check_open_hook (struct trivfs_control *trivfs_control, if (device == NULL) /* Try and open the device. */ { - err = dev_open (store_name, readonly ? STORE_READONLY : 0, &device); + err = dev_open (store_name, readonly ? STORE_READONLY : 0, inhibit_cache, + &device); if (err) device = NULL; if (err && (flags & (O_READ|O_WRITE)) == 0) |