1/* $NetBSD: v7fs_io_user.c,v 1.3 2011/08/03 16:21:52 dholland 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.3 2011/08/03 16:21:52 dholland 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 58struct local_io { 59 int fd; 60 size_t size; 61 size_t blksz; 62 uint8_t *addr; 63} local; 64 65static bool read_sector(void *, uint8_t *, daddr_t); 66static bool write_sector(void *, uint8_t *, daddr_t); 67static bool read_mmap(void *, uint8_t *, daddr_t); 68static bool write_mmap(void *, uint8_t *, daddr_t); 69 70int 71v7fs_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 106void 107v7fs_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 120static bool 121read_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 136static bool 137write_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 152static bool 153read_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 163static bool 164write_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