summaryrefslogtreecommitdiff
path: root/storeio/dev.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1999-01-27 20:46:47 +0000
committerRoland McGrath <roland@gnu.org>1999-01-27 20:46:47 +0000
commit8e8f1f026b493aeea075d4f1cbc05bbf0dd6cec6 (patch)
treefe387c55550994e63545bb880b143bc6e2f4661d /storeio/dev.c
parent917384c096a24625c84ab8901901a45e2f2f055f (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.
Diffstat (limited to 'storeio/dev.c')
-rw-r--r--storeio/dev.c68
1 files changed, 56 insertions, 12 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);