Home | History | Annotate | Line # | Download | only in v7fs
      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