summaryrefslogtreecommitdiff
path: root/storeio
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1999-11-21 04:27:23 +0000
committerRoland McGrath <roland@gnu.org>1999-11-21 04:27:23 +0000
commitd4139b9468005e145ba4c9fffa90b212de05e7d5 (patch)
tree0b2f89e42395f814345f1de6dff41945e21a01ad /storeio
parent1a69c12f73b7df071d87ed26a4e89c26cb7b05eb (diff)
1999-11-20 Roland McGrath <roland@baalperazim.frob.com>
* dev.c (dev_read, dev_write): In DEV->inhibit_cache case, handle zero (i.e. unknown) block_size by treating it as 1. Use shift and bitwise-and rather than multiply and modulus for block size arithmetic, since it's a known power of two.
Diffstat (limited to 'storeio')
-rw-r--r--storeio/dev.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/storeio/dev.c b/storeio/dev.c
index cf557f46..0a713253 100644
--- a/storeio/dev.c
+++ b/storeio/dev.c
@@ -348,12 +348,17 @@ dev_write (struct dev *dev, off_t offs, void *buf, size_t len,
struct store *store = dev->store;
- if (offs % store->block_size != 0 || len % store->block_size != 0)
+ if (store->block_size == 0)
+ /* We don't know the block size, so let the device enforce it. */
+ return store_write (dev->store, offs, buf, len, amount);
+
+ if ((offs & (store->block_size - 1)) != 0
+ || (len & (store->block_size - 1)) != 0)
/* Not whole blocks. No can do. */
- return EINVAL;
+ return EINVAL; /* EIO? */
/* Do a direct write to the store. */
- return store_write (dev->store, offs * store->block_size,
+ return store_write (dev->store, offs << store->log2_block_size,
buf, len, amount);
}
@@ -425,18 +430,25 @@ 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. */
+ Note that in this case we handle non-power-of-two block sizes.
+ We could, that is, but libstore won't have it (see libstore/make.c).
+ If the device does not report a block size, we let any attempt
+ through on the assumption the device will enforce its own limits. */
struct store *store = dev->store;
- if (offs % store->block_size != 0
- || whole_amount % store->block_size != 0)
+ if (store->block_size == 0)
+ /* We don't know the block size, so let the device enforce it. */
+ return store_read (dev->store, offs, whole_amount, buf, len);
+
+ if ((offs & (store->block_size - 1)) != 0
+ || (whole_amount & (store->block_size - 1)) != 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);
+ return store_read (dev->store, offs << store->log2_block_size,
+ whole_amount, buf, len);
}
err = dev_rw (dev, offs, whole_amount, len, buf_read, raw_read);