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 57 struct local_io { 58 struct vnode *vp; 59 kauth_cred_t cred; 60 }; 61 62 static bool v7fs_os_read_n(void *, uint8_t *, daddr_t, int); 63 static bool v7fs_os_read(void *, uint8_t *, daddr_t); 64 static bool v7fs_os_write_n(void *, uint8_t *, daddr_t, int); 65 static bool v7fs_os_write(void *, uint8_t *, daddr_t); 66 static void v7fs_os_lock(void *); 67 static void v7fs_os_unlock(void *); 68 static bool lock_init(struct lock_ops *); 69 70 int 71 v7fs_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 113 errexit: 114 v7fs_io_fini(p); 115 return error; 116 } 117 118 static bool 119 lock_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 128 void 129 v7fs_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 149 static bool 150 v7fs_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 164 static bool 165 v7fs_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; 176 error_exit: 177 DPRINTF("block %ld read failed.\n", (long)block); 178 179 if (bp != NULL) 180 brelse(bp, 0); 181 return false; 182 } 183 184 static bool 185 v7fs_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 199 static bool 200 v7fs_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 220 static void 221 v7fs_os_lock(void *self) 222 { 223 224 mutex_enter((kmutex_t *)self); 225 } 226 227 static void 228 v7fs_os_unlock(void *self) 229 { 230 231 mutex_exit((kmutex_t *)self); 232 } 233