1/* $NetBSD: v7fs_io_kern.c,v 1.5 2017/08/27 06:18:16 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 2004, 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#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: v7fs_io_kern.c,v 1.5 2017/08/27 06:18:16 skrll Exp $"); 34 35#if defined _KERNEL_OPT 36#include "opt_v7fs.h" 37#endif 38 39#include <sys/param.h> 40#include <sys/types.h> 41#include <sys/systm.h> 42#include <sys/buf.h> 43#include <sys/kmem.h> 44#include <sys/kauth.h> 45#include <sys/mutex.h> 46 47#include <fs/v7fs/v7fs.h> 48#include "v7fs_endian.h" 49#include "v7fs_impl.h" 50 51#ifdef V7FS_IO_DEBUG 52#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args) 53#else 54#define DPRINTF(fmt, args...) ((void)0) 55#endif 56 57struct local_io { 58 struct vnode *vp; 59 kauth_cred_t cred; 60}; 61 62static bool v7fs_os_read_n(void *, uint8_t *, daddr_t, int); 63static bool v7fs_os_read(void *, uint8_t *, daddr_t); 64static bool v7fs_os_write_n(void *, uint8_t *, daddr_t, int); 65static bool v7fs_os_write(void *, uint8_t *, daddr_t); 66static void v7fs_os_lock(void *); 67static void v7fs_os_unlock(void *); 68static bool lock_init(struct lock_ops *); 69 70int 71v7fs_io_init(struct v7fs_self **fs, 72 const struct v7fs_mount_device *mount_device, size_t block_size) 73{ 74 struct vnode *vp = mount_device->device.vnode; 75 struct v7fs_self *p; 76 struct local_io *local; 77 int error = 0; 78 79 p = kmem_zalloc(sizeof(*p), KM_SLEEP); 80 p->scratch_free = -1; 81 p->scratch_remain = V7FS_SELF_NSCRATCH; 82 83 /* Endian */ 84 p->endian = mount_device->endian; 85#ifdef V7FS_EI 86 v7fs_endian_init(p); 87#endif 88 /* IO */ 89 local = kmem_zalloc(sizeof(*local), KM_SLEEP); 90 p->io.read = v7fs_os_read; 91 p->io.read_n = v7fs_os_read_n; 92 p->io.write = v7fs_os_write; 93 p->io.write_n = v7fs_os_write_n; 94 p->scratch_free = -1; /* free all scratch buffer */ 95 96 p->io.cookie = local; 97 local->vp = vp; 98 local->cred = NOCRED; /* upper layer check cred. */ 99 100 /*LOCK */ 101 error = ENOMEM; 102 if (!lock_init(&p->sb_lock)) 103 goto errexit; 104 if (!lock_init(&p->ilist_lock)) 105 goto errexit; 106 if (!lock_init(&p->mem_lock)) 107 goto errexit; 108 error = 0; 109 110 *fs = p; 111 return 0; 112 113errexit: 114 v7fs_io_fini(p); 115 return error; 116} 117 118static bool 119lock_init(struct lock_ops *ops) 120{ 121 ops->cookie = kmem_zalloc(sizeof(kmutex_t), KM_SLEEP); 122 mutex_init(ops->cookie, MUTEX_DEFAULT, IPL_NONE); 123 ops->lock = v7fs_os_lock; 124 ops->unlock = v7fs_os_unlock; 125 return true; 126} 127 128void 129v7fs_io_fini(struct v7fs_self *fs) 130{ 131 if (fs->io.cookie) { 132 kmem_free(fs->io.cookie, sizeof(struct local_io)); 133 } 134 if (fs->sb_lock.cookie) { 135 mutex_destroy(fs->sb_lock.cookie); 136 kmem_free(fs->sb_lock.cookie, sizeof(kmutex_t)); 137 } 138 if (fs->ilist_lock.cookie) { 139 mutex_destroy(fs->ilist_lock.cookie); 140 kmem_free(fs->ilist_lock.cookie, sizeof(kmutex_t)); 141 } 142 if (fs->mem_lock.cookie) { 143 mutex_destroy(fs->mem_lock.cookie); 144 kmem_free(fs->mem_lock.cookie, sizeof(kmutex_t)); 145 } 146 kmem_free(fs, sizeof(*fs)); 147} 148 149static bool 150v7fs_os_read_n(void *self, uint8_t *buf, daddr_t block, int count) 151{ 152 int i; 153 154 for (i = 0; i < count; i++) { 155 if (!v7fs_os_read(self, buf, block)) 156 return false; 157 buf += DEV_BSIZE; 158 block++; 159 } 160 161 return true; 162} 163 164static bool 165v7fs_os_read(void *self, uint8_t *buf, daddr_t block) 166{ 167 struct local_io *bio = (struct local_io *)self; 168 struct buf *bp = NULL; 169 170 if (bread(bio->vp, block, DEV_BSIZE, 0, &bp) != 0) 171 goto error_exit; 172 memcpy(buf, bp->b_data, DEV_BSIZE); 173 brelse(bp, 0); 174 175 return true; 176error_exit: 177 DPRINTF("block %ld read failed.\n", (long)block); 178 179 if (bp != NULL) 180 brelse(bp, 0); 181 return false; 182} 183 184static bool 185v7fs_os_write_n(void *self, uint8_t *buf, daddr_t block, int count) 186{ 187 int i; 188 189 for (i = 0; i < count; i++) { 190 if (!v7fs_os_write(self, buf, block)) 191 return false; 192 buf += DEV_BSIZE; 193 block++; 194 } 195 196 return true; 197} 198 199static bool 200v7fs_os_write(void *self, uint8_t *buf, daddr_t block) 201{ 202 struct local_io *bio = (struct local_io *)self; 203 struct buf *bp; 204 205 if ((bp = getblk(bio->vp, block, DEV_BSIZE, 0, 0)) == 0) { 206 DPRINTF("getblk failed. block=%ld\n", (long)block); 207 return false; 208 } 209 210 memcpy(bp->b_data, buf, DEV_BSIZE); 211 212 if (bwrite(bp) != 0) { 213 DPRINTF("bwrite failed. block=%ld\n", (long)block); 214 return false; 215 } 216 217 return true; 218} 219 220static void 221v7fs_os_lock(void *self) 222{ 223 224 mutex_enter((kmutex_t *)self); 225} 226 227static void 228v7fs_os_unlock(void *self) 229{ 230 231 mutex_exit((kmutex_t *)self); 232} 233