summaryrefslogtreecommitdiff
path: root/serverboot/file_io.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1999-07-20 20:02:34 +0000
committerRoland McGrath <roland@gnu.org>1999-07-20 20:02:34 +0000
commit18627d5854da713b6c8c8184675696533c101a81 (patch)
tree0355dba12725f3ed7918050968ef58f0d187baec /serverboot/file_io.c
parentb744bdfbe2022b2a031b304cf9297c97c83cd403 (diff)
1999-07-20 Roland McGrath <roland@baalperazim.frob.com>
* ext2_file_io.c, ffs_file_io.c, minix_file_io.c: Remove fs-specific routines *_page_{read,write}_file_direct. Moved to ... * file_io.c (page_read_file_direct, page_write_file_direct): Don't call fs-specific routine, these are not fs-specific. Instead, replaced with former fs-specific routines (which were all identical). Read and write more than a fs block when disk blocks are contiguous.
Diffstat (limited to 'serverboot/file_io.c')
-rw-r--r--serverboot/file_io.c164
1 files changed, 128 insertions, 36 deletions
diff --git a/serverboot/file_io.c b/serverboot/file_io.c
index 141fdcfe..99966f95 100644
--- a/serverboot/file_io.c
+++ b/serverboot/file_io.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 1994 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
* All rights reserved.
@@ -156,41 +156,6 @@ add_file_direct(fdp, fp)
}
}
-int
-page_read_file_direct(fdp, offset, size, addr, size_read)
- register struct file_direct *fdp;
- vm_offset_t offset;
- vm_size_t size;
- vm_offset_t *addr; /* out */
- mach_msg_type_number_t *size_read; /* out */
-{
- switch (fdp->f_fstype) {
- case EXT2_FS:
- return ext2_page_read_file_direct(fdp, offset, size, addr, size_read);
- case MINIX_FS:
- return minix_page_read_file_direct(fdp, offset, size, addr, size_read);
- default:
- return ffs_page_read_file_direct(fdp, offset, size, addr, size_read);
- }
-}
-
-int
-page_write_file_direct(fdp, offset, addr, size, size_written)
- register struct file_direct *fdp;
- vm_offset_t offset;
- vm_offset_t addr;
- vm_size_t size;
- vm_offset_t *size_written; /* out */
-{
- switch (fdp->f_fstype) {
- case EXT2_FS:
- return ext2_page_write_file_direct(fdp, offset, addr, size, size_written);
- case MINIX_FS:
- return minix_page_write_file_direct(fdp, offset, addr, size, size_written);
- default:
- return ffs_page_write_file_direct(fdp, offset, addr, size, size_written);
- }
-}
int
remove_file_direct(fdp)
@@ -223,3 +188,130 @@ file_is_structured(fp)
return (fp)->u.ffs.ffs_fs != 0;
}
}
+
+/*
+ * Special read and write routines for default pager.
+ * Assume that all offsets and sizes are multiples
+ * of DEV_BSIZE.
+ */
+
+#define fdir_blkoff(fdp, offset) /* offset % fd_bsize */ \
+ ((offset) & ((fdp)->fd_bsize - 1))
+#define fdir_lblkno(fdp, offset) /* offset / fd_bsize */ \
+ ((offset) >> (fdp)->fd_bshift)
+
+#define fdir_fsbtodb(fdp, block) /* offset * fd_bsize / DEV_BSIZE */ \
+ ((block) << (fdp)->fd_fsbtodb)
+
+/*
+ * Read all or part of a data block, and
+ * return a pointer to the appropriate part.
+ * Caller must deallocate the block when done.
+ */
+int
+page_read_file_direct(fdp, offset, size, addr, size_read)
+ register struct file_direct *fdp;
+ vm_offset_t offset;
+ vm_size_t size;
+ vm_offset_t *addr; /* out */
+ mach_msg_type_number_t *size_read; /* out */
+{
+ vm_offset_t off;
+ register daddr_t file_block;
+ daddr_t disk_block;
+
+ if (offset % DEV_BSIZE != 0 ||
+ size % DEV_BSIZE != 0)
+ panic("page_read_file_direct");
+
+ if (offset >= (fdp->fd_size << fdp->fd_bshift))
+ return (FS_NOT_IN_FILE);
+
+ off = fdir_blkoff(fdp, offset);
+ file_block = fdir_lblkno(fdp, offset);
+
+ if (file_is_device(fdp)) {
+ disk_block = file_block;
+ } else {
+ disk_block = fdp->fd_blocks[file_block];
+ if (disk_block == 0)
+ return (FS_NOT_IN_FILE);
+
+ if (size > fdp->fd_bsize) {
+ /* Read only as much as is contiguous on disk. */
+ daddr_t b = file_block + 1;
+ while (b < file_block + fdp->fd_size &&
+ fdp->fd_blocks[b] == disk_block + fdir_fsbtodb(fdp, 1))
+ ++b;
+ size = (b - file_block) * fdp->fd_bsize;
+ }
+ }
+
+ return (device_read(fdp->fd_dev,
+ 0,
+ (recnum_t) (fdir_fsbtodb(fdp, disk_block) + btodb(off)),
+ (int) size,
+ (char **) addr,
+ size_read));
+}
+
+/*
+ * Write all or part of a data block, and
+ * return the amount written.
+ */
+int
+page_write_file_direct(fdp, offset, addr, size, size_written)
+ register struct file_direct *fdp;
+ vm_offset_t offset;
+ vm_offset_t addr;
+ vm_size_t size;
+ vm_offset_t *size_written; /* out */
+{
+ vm_offset_t off;
+ register daddr_t file_block;
+ daddr_t disk_block;
+ int rc, num_written;
+ vm_offset_t block_size;
+
+ if (offset % DEV_BSIZE != 0 ||
+ size % DEV_BSIZE != 0)
+ panic("page_write_file");
+
+ if (offset >= (fdp->fd_size << fdp->fd_bshift))
+ return (FS_NOT_IN_FILE);
+
+ off = fdir_blkoff(fdp, offset);
+ file_block = fdir_lblkno(fdp, offset);
+
+ if (file_is_device(fdp)) {
+ disk_block = file_block;
+ } else {
+ disk_block = fdp->fd_blocks[file_block];
+ if (disk_block == 0)
+ return (FS_NOT_IN_FILE);
+
+ if (size > fdp->fd_bsize) {
+ /* Write only as much as is contiguous on disk. */
+ daddr_t b = file_block + 1;
+ while (b < file_block + fdp->fd_size &&
+ fdp->fd_blocks[b] == disk_block + fdir_fsbtodb(fdp, 1))
+ ++b;
+ size = (b - file_block) * fdp->fd_bsize;
+ }
+ }
+
+ /*
+ * Write the data. Wait for completion to keep
+ * reads from getting ahead of writes and reading
+ * stale data.
+ */
+ rc = device_write(
+ fdp->fd_dev,
+ 0,
+ (recnum_t) (fdir_fsbtodb(fdp, disk_block) + btodb(off)),
+ (char *) addr,
+ size,
+ &num_written);
+ *size_written = num_written;
+ return rc;
+}