summaryrefslogtreecommitdiff
path: root/devio
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1995-04-09 19:04:36 +0000
committerMiles Bader <miles@gnu.org>1995-04-09 19:04:36 +0000
commit17825154d7630b9b8786375ccd944da1c16dafb9 (patch)
tree613bee79a96a8acb4d2e8a8f2db16a6c848df687 /devio
parent94991805f81b8e2340eb8fccd1ce59ec35637aa8 (diff)
Read or write partial pages at the end of the device.
Diffstat (limited to 'devio')
-rw-r--r--devio/devpager.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/devio/devpager.c b/devio/devpager.c
index 9ed5bd3e..ab3da34a 100644
--- a/devio/devpager.c
+++ b/devio/devpager.c
@@ -41,26 +41,36 @@ error_t
pager_read_page(struct user_pager_info *upi,
vm_offset_t page, vm_address_t *buf, int *writelock)
{
+ error_t err;
int read; /* bytes actually read */
+ int want = vm_page_size; /* bytes we want to read */
struct dev *dev = (struct dev *)upi;
- error_t err =
- device_read(dev->port,
- 0, page / dev->dev_block_size, vm_page_size,
- (io_buf_ptr_t *)buf, &read);
+
+ if (page + want > dev->size)
+ /* Read a partial page if necessary to avoid reading off the end. */
+ want = dev->size - page;
+
+ err = device_read(dev->port, 0, page / dev->dev_block_size, want,
+ (io_buf_ptr_t *)buf, &read);
#ifdef MSG
if (debug)
{
mutex_lock(&debug_lock);
fprintf(debug, "device_read(%d, %d) [pager] => %s, %s, %d\n",
- page / dev->dev_block_size, vm_page_size,
+ page / dev->dev_block_size, want,
strerror(err), err ? "-" : brep(*buf, read), read);
mutex_unlock(&debug_lock);
}
#endif
+ if (!err && want < vm_page_size)
+ /* Zero anything we didn't read. Allocation only happens in page-size
+ multiples, so we know we can write there. */
+ bzero((char *)*buf + want, vm_page_size - want);
+
*writelock = (dev->flags & DEV_READONLY);
- if (err || read < vm_page_size)
+ if (err || read < want)
return EIO;
else
return 0;
@@ -79,12 +89,16 @@ pager_write_page(struct user_pager_info *upi,
return EROFS;
else
{
+ error_t err;
int written;
- error_t err =
- device_write(dev->port,
- 0, page / dev->dev_block_size,
- (io_buf_ptr_t)buf, vm_page_size,
- &written);
+ int want = vm_page_size;
+
+ if (page + want > dev->size)
+ /* Write a partial page if necessary to avoid reading off the end. */
+ want = dev->size - page;
+
+ err = device_write(dev->port, 0, page / dev->dev_block_size,
+ (io_buf_ptr_t)buf, want, &written);
#ifdef MSG
if (debug)
{
@@ -99,7 +113,7 @@ pager_write_page(struct user_pager_info *upi,
vm_deallocate(mach_task_self(), buf, vm_page_size);
- if (err || written < vm_page_size)
+ if (err || written < want)
return EIO;
else
return 0;