summaryrefslogtreecommitdiff
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
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.
-rw-r--r--storeio/dev.c68
-rw-r--r--storeio/dev.h27
-rw-r--r--storeio/pager.c4
-rw-r--r--storeio/storeio.c22
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)