1 /* $NetBSD: v7fs_io_user.c,v 1.4 2011/08/08 11:42:30 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #if HAVE_NBTOOL_CONFIG_H 33 #include "nbtool_config.h" 34 #endif 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __RCSID("$NetBSD: v7fs_io_user.c,v 1.4 2011/08/08 11:42:30 uch Exp $"); 39 #endif /* not lint */ 40 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <errno.h> 45 #include <unistd.h> 46 #include <err.h> 47 #include <sys/mman.h> 48 #include "v7fs.h" 49 #include "v7fs_endian.h" 50 #include "v7fs_impl.h" 51 52 #ifdef V7FS_IO_DEBUG 53 #define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args) 54 #else 55 #define DPRINTF(fmt, args...) ((void)0) 56 #endif 57 58 struct local_io { 59 int fd; 60 size_t size; 61 size_t blksz; 62 uint8_t *addr; 63 } local; 64 65 static bool read_sector(void *, uint8_t *, daddr_t); 66 static bool write_sector(void *, uint8_t *, daddr_t); 67 static bool read_mmap(void *, uint8_t *, daddr_t); 68 static bool write_mmap(void *, uint8_t *, daddr_t); 69 70 int 71 v7fs_io_init(struct v7fs_self **fs, const struct v7fs_mount_device *mount, 72 size_t block_size) 73 { 74 struct v7fs_self *p; 75 76 if (!(p = (struct v7fs_self *)malloc(sizeof(*p)))) 77 return ENOMEM; 78 memset(p, 0, sizeof(*p)); 79 80 /* Endian */ 81 p->endian = mount->endian; 82 #ifdef V7FS_EI 83 v7fs_endian_init(p); 84 #endif 85 local.blksz = block_size; 86 local.fd = mount->device.fd; 87 local.size = mount->sectors * block_size; 88 local.addr = mmap(NULL, local.size, PROT_READ | PROT_WRITE | PROT_NONE, 89 MAP_FILE | MAP_SHARED/*writeback*/, local.fd, 0); 90 if (local.addr == MAP_FAILED) { 91 local.addr = 0; 92 p->io.read = read_sector; 93 p->io.write = write_sector; 94 } else { 95 DPRINTF("mmaped addr=%p\n", local.addr); 96 p->io.read = read_mmap; 97 p->io.write = write_mmap; 98 } 99 100 p->io.cookie = &local; 101 *fs = p; 102 103 return 0; 104 } 105 106 void 107 v7fs_io_fini(struct v7fs_self *fs) 108 { 109 struct local_io *lio = (struct local_io *)fs->io.cookie; 110 111 if (lio->addr) { 112 if (munmap(lio->addr, lio->size) != 0) 113 warn(0); 114 } 115 fsync(lio->fd); 116 117 free(fs); 118 } 119 120 static bool 121 read_sector(void *ctx, uint8_t *buf, daddr_t sector) 122 { 123 struct local_io *lio = (struct local_io *)ctx; 124 size_t blksz = lio->blksz; 125 int fd = lio->fd; 126 127 if ((lseek(fd, (off_t)sector * blksz, SEEK_SET) < 0) || 128 (read(fd, buf, blksz) < (ssize_t)blksz)) { 129 warn("sector=%ld\n", (long)sector); 130 return false; 131 } 132 133 return true; 134 } 135 136 static bool 137 write_sector(void *ctx, uint8_t *buf, daddr_t sector) 138 { 139 struct local_io *lio = (struct local_io *)ctx; 140 size_t blksz = lio->blksz; 141 int fd = lio->fd; 142 143 if ((lseek(fd, (off_t)sector * blksz, SEEK_SET) < 0) || 144 (write(fd, buf, blksz) < (ssize_t)blksz)) { 145 warn("sector=%ld\n", (long)sector); 146 return false; 147 } 148 149 return true; 150 } 151 152 static bool 153 read_mmap(void *ctx, uint8_t *buf, daddr_t sector) 154 { 155 struct local_io *lio = (struct local_io *)ctx; 156 size_t blksz = lio->blksz; 157 158 memcpy(buf, lio->addr + sector * blksz, blksz); 159 160 return true; 161 } 162 163 static bool 164 write_mmap(void *ctx, uint8_t *buf, daddr_t sector) 165 { 166 struct local_io *lio = (struct local_io *)ctx; 167 size_t blksz = lio->blksz; 168 169 memcpy(lio->addr + sector * blksz, buf, blksz); 170 171 return true; 172 } 173