1*0a6a1f1dSLionel Sambuc /* $NetBSD: v7fs_io_kern.c,v 1.3 2015/03/28 19:24:05 maxv Exp $ */
29f988b79SJean-Baptiste Boric
39f988b79SJean-Baptiste Boric /*-
49f988b79SJean-Baptiste Boric * Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
59f988b79SJean-Baptiste Boric * All rights reserved.
69f988b79SJean-Baptiste Boric *
79f988b79SJean-Baptiste Boric * This code is derived from software contributed to The NetBSD Foundation
89f988b79SJean-Baptiste Boric * by UCHIYAMA Yasushi.
99f988b79SJean-Baptiste Boric *
109f988b79SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
119f988b79SJean-Baptiste Boric * modification, are permitted provided that the following conditions
129f988b79SJean-Baptiste Boric * are met:
139f988b79SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
149f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
159f988b79SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
169f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
179f988b79SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
189f988b79SJean-Baptiste Boric *
199f988b79SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209f988b79SJean-Baptiste Boric * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219f988b79SJean-Baptiste Boric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229f988b79SJean-Baptiste Boric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239f988b79SJean-Baptiste Boric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249f988b79SJean-Baptiste Boric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259f988b79SJean-Baptiste Boric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269f988b79SJean-Baptiste Boric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279f988b79SJean-Baptiste Boric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289f988b79SJean-Baptiste Boric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299f988b79SJean-Baptiste Boric * POSSIBILITY OF SUCH DAMAGE.
309f988b79SJean-Baptiste Boric */
319f988b79SJean-Baptiste Boric
329f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
33*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: v7fs_io_kern.c,v 1.3 2015/03/28 19:24:05 maxv Exp $");
349f988b79SJean-Baptiste Boric #if defined _KERNEL_OPT
359f988b79SJean-Baptiste Boric #include "opt_v7fs.h"
369f988b79SJean-Baptiste Boric #endif
379f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
389f988b79SJean-Baptiste Boric
39*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: v7fs_io_kern.c,v 1.3 2015/03/28 19:24:05 maxv Exp $");
409f988b79SJean-Baptiste Boric
419f988b79SJean-Baptiste Boric #include <sys/param.h>
429f988b79SJean-Baptiste Boric #include <sys/types.h>
439f988b79SJean-Baptiste Boric #include <sys/systm.h>
449f988b79SJean-Baptiste Boric #include <sys/buf.h>
459f988b79SJean-Baptiste Boric #include <sys/kmem.h>
469f988b79SJean-Baptiste Boric #include <sys/kauth.h>
479f988b79SJean-Baptiste Boric #include <sys/mutex.h>
489f988b79SJean-Baptiste Boric
499f988b79SJean-Baptiste Boric #include <fs/v7fs/v7fs.h>
509f988b79SJean-Baptiste Boric #include "v7fs_endian.h"
519f988b79SJean-Baptiste Boric #include "v7fs_impl.h"
529f988b79SJean-Baptiste Boric
539f988b79SJean-Baptiste Boric #ifdef V7FS_IO_DEBUG
549f988b79SJean-Baptiste Boric #define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
559f988b79SJean-Baptiste Boric #else
569f988b79SJean-Baptiste Boric #define DPRINTF(fmt, args...) ((void)0)
579f988b79SJean-Baptiste Boric #endif
589f988b79SJean-Baptiste Boric
599f988b79SJean-Baptiste Boric struct local_io {
609f988b79SJean-Baptiste Boric struct vnode *vp;
619f988b79SJean-Baptiste Boric kauth_cred_t cred;
629f988b79SJean-Baptiste Boric };
639f988b79SJean-Baptiste Boric
649f988b79SJean-Baptiste Boric static bool v7fs_os_read_n(void *, uint8_t *, daddr_t, int);
659f988b79SJean-Baptiste Boric static bool v7fs_os_read(void *, uint8_t *, daddr_t);
669f988b79SJean-Baptiste Boric static bool v7fs_os_write_n(void *, uint8_t *, daddr_t, int);
679f988b79SJean-Baptiste Boric static bool v7fs_os_write(void *, uint8_t *, daddr_t);
689f988b79SJean-Baptiste Boric static void v7fs_os_lock(void *);
699f988b79SJean-Baptiste Boric static void v7fs_os_unlock(void *);
709f988b79SJean-Baptiste Boric static bool lock_init(struct lock_ops *);
719f988b79SJean-Baptiste Boric
729f988b79SJean-Baptiste Boric int
v7fs_io_init(struct v7fs_self ** fs,const struct v7fs_mount_device * mount_device,size_t block_size)739f988b79SJean-Baptiste Boric v7fs_io_init(struct v7fs_self **fs,
749f988b79SJean-Baptiste Boric const struct v7fs_mount_device *mount_device, size_t block_size)
759f988b79SJean-Baptiste Boric {
769f988b79SJean-Baptiste Boric struct vnode *vp = mount_device->device.vnode;
779f988b79SJean-Baptiste Boric struct v7fs_self *p;
789f988b79SJean-Baptiste Boric struct local_io *local;
799f988b79SJean-Baptiste Boric int error = 0;
809f988b79SJean-Baptiste Boric
819f988b79SJean-Baptiste Boric if ((p = kmem_zalloc(sizeof(*p), KM_SLEEP)) == NULL)
829f988b79SJean-Baptiste Boric return ENOMEM;
839f988b79SJean-Baptiste Boric
849f988b79SJean-Baptiste Boric p->scratch_free = -1;
859f988b79SJean-Baptiste Boric p->scratch_remain = V7FS_SELF_NSCRATCH;
869f988b79SJean-Baptiste Boric
879f988b79SJean-Baptiste Boric /* Endian */
889f988b79SJean-Baptiste Boric p->endian = mount_device->endian;
899f988b79SJean-Baptiste Boric #ifdef V7FS_EI
909f988b79SJean-Baptiste Boric v7fs_endian_init(p);
919f988b79SJean-Baptiste Boric #endif
929f988b79SJean-Baptiste Boric /* IO */
939f988b79SJean-Baptiste Boric if ((local = kmem_zalloc(sizeof(*local), KM_SLEEP)) == NULL) {
949f988b79SJean-Baptiste Boric error = ENOMEM;
959f988b79SJean-Baptiste Boric goto errexit;
969f988b79SJean-Baptiste Boric }
979f988b79SJean-Baptiste Boric p->io.read = v7fs_os_read;
989f988b79SJean-Baptiste Boric p->io.read_n = v7fs_os_read_n;
999f988b79SJean-Baptiste Boric p->io.write = v7fs_os_write;
1009f988b79SJean-Baptiste Boric p->io.write_n = v7fs_os_write_n;
1019f988b79SJean-Baptiste Boric p->scratch_free = -1; /* free all scratch buffer */
1029f988b79SJean-Baptiste Boric
1039f988b79SJean-Baptiste Boric p->io.cookie = local;
1049f988b79SJean-Baptiste Boric local->vp = vp;
1059f988b79SJean-Baptiste Boric local->cred = NOCRED; /* upper layer check cred. */
1069f988b79SJean-Baptiste Boric
1079f988b79SJean-Baptiste Boric /*LOCK */
1089f988b79SJean-Baptiste Boric error = ENOMEM;
1099f988b79SJean-Baptiste Boric if (!lock_init(&p->sb_lock))
1109f988b79SJean-Baptiste Boric goto errexit;
1119f988b79SJean-Baptiste Boric if (!lock_init(&p->ilist_lock))
1129f988b79SJean-Baptiste Boric goto errexit;
1139f988b79SJean-Baptiste Boric if (!lock_init(&p->mem_lock))
1149f988b79SJean-Baptiste Boric goto errexit;
1159f988b79SJean-Baptiste Boric error = 0;
1169f988b79SJean-Baptiste Boric
1179f988b79SJean-Baptiste Boric *fs = p;
1189f988b79SJean-Baptiste Boric return 0;
1199f988b79SJean-Baptiste Boric
1209f988b79SJean-Baptiste Boric errexit:
1219f988b79SJean-Baptiste Boric v7fs_io_fini(p);
1229f988b79SJean-Baptiste Boric return error;
1239f988b79SJean-Baptiste Boric }
1249f988b79SJean-Baptiste Boric
1259f988b79SJean-Baptiste Boric static bool
lock_init(struct lock_ops * ops)1269f988b79SJean-Baptiste Boric lock_init(struct lock_ops *ops)
1279f988b79SJean-Baptiste Boric {
1289f988b79SJean-Baptiste Boric if ((ops->cookie = kmem_zalloc(sizeof(kmutex_t), KM_SLEEP)) == NULL) {
1299f988b79SJean-Baptiste Boric return false;
1309f988b79SJean-Baptiste Boric }
1319f988b79SJean-Baptiste Boric mutex_init(ops->cookie, MUTEX_DEFAULT, IPL_NONE);
1329f988b79SJean-Baptiste Boric ops->lock = v7fs_os_lock;
1339f988b79SJean-Baptiste Boric ops->unlock = v7fs_os_unlock;
1349f988b79SJean-Baptiste Boric return true;
1359f988b79SJean-Baptiste Boric }
1369f988b79SJean-Baptiste Boric
1379f988b79SJean-Baptiste Boric void
v7fs_io_fini(struct v7fs_self * fs)1389f988b79SJean-Baptiste Boric v7fs_io_fini(struct v7fs_self *fs)
1399f988b79SJean-Baptiste Boric {
1409f988b79SJean-Baptiste Boric if (fs->io.cookie) {
1419f988b79SJean-Baptiste Boric kmem_free(fs->io.cookie, sizeof(struct local_io));
1429f988b79SJean-Baptiste Boric }
1439f988b79SJean-Baptiste Boric if (fs->sb_lock.cookie) {
1449f988b79SJean-Baptiste Boric mutex_destroy(fs->sb_lock.cookie);
1459f988b79SJean-Baptiste Boric kmem_free(fs->sb_lock.cookie, sizeof(kmutex_t));
1469f988b79SJean-Baptiste Boric }
1479f988b79SJean-Baptiste Boric if (fs->ilist_lock.cookie) {
1489f988b79SJean-Baptiste Boric mutex_destroy(fs->ilist_lock.cookie);
1499f988b79SJean-Baptiste Boric kmem_free(fs->ilist_lock.cookie, sizeof(kmutex_t));
1509f988b79SJean-Baptiste Boric }
1519f988b79SJean-Baptiste Boric if (fs->mem_lock.cookie) {
1529f988b79SJean-Baptiste Boric mutex_destroy(fs->mem_lock.cookie);
1539f988b79SJean-Baptiste Boric kmem_free(fs->mem_lock.cookie, sizeof(kmutex_t));
1549f988b79SJean-Baptiste Boric }
1559f988b79SJean-Baptiste Boric kmem_free(fs, sizeof(*fs));
1569f988b79SJean-Baptiste Boric }
1579f988b79SJean-Baptiste Boric
1589f988b79SJean-Baptiste Boric static bool
v7fs_os_read_n(void * self,uint8_t * buf,daddr_t block,int count)1599f988b79SJean-Baptiste Boric v7fs_os_read_n(void *self, uint8_t *buf, daddr_t block, int count)
1609f988b79SJean-Baptiste Boric {
1619f988b79SJean-Baptiste Boric int i;
1629f988b79SJean-Baptiste Boric
1639f988b79SJean-Baptiste Boric for (i = 0; i < count; i++) {
1649f988b79SJean-Baptiste Boric if (!v7fs_os_read(self, buf, block))
1659f988b79SJean-Baptiste Boric return false;
1669f988b79SJean-Baptiste Boric buf += DEV_BSIZE;
1679f988b79SJean-Baptiste Boric block++;
1689f988b79SJean-Baptiste Boric }
1699f988b79SJean-Baptiste Boric
1709f988b79SJean-Baptiste Boric return true;
1719f988b79SJean-Baptiste Boric }
1729f988b79SJean-Baptiste Boric
1739f988b79SJean-Baptiste Boric static bool
v7fs_os_read(void * self,uint8_t * buf,daddr_t block)1749f988b79SJean-Baptiste Boric v7fs_os_read(void *self, uint8_t *buf, daddr_t block)
1759f988b79SJean-Baptiste Boric {
1769f988b79SJean-Baptiste Boric struct local_io *bio = (struct local_io *)self;
1779f988b79SJean-Baptiste Boric struct buf *bp = NULL;
1789f988b79SJean-Baptiste Boric
179*0a6a1f1dSLionel Sambuc if (bread(bio->vp, block, DEV_BSIZE, 0, &bp) != 0)
1809f988b79SJean-Baptiste Boric goto error_exit;
1819f988b79SJean-Baptiste Boric memcpy(buf, bp->b_data, DEV_BSIZE);
1829f988b79SJean-Baptiste Boric brelse(bp, 0);
1839f988b79SJean-Baptiste Boric
1849f988b79SJean-Baptiste Boric return true;
1859f988b79SJean-Baptiste Boric error_exit:
1869f988b79SJean-Baptiste Boric DPRINTF("block %ld read failed.\n", (long)block);
1879f988b79SJean-Baptiste Boric
1889f988b79SJean-Baptiste Boric if (bp != NULL)
1899f988b79SJean-Baptiste Boric brelse(bp, 0);
1909f988b79SJean-Baptiste Boric return false;
1919f988b79SJean-Baptiste Boric }
1929f988b79SJean-Baptiste Boric
1939f988b79SJean-Baptiste Boric static bool
v7fs_os_write_n(void * self,uint8_t * buf,daddr_t block,int count)1949f988b79SJean-Baptiste Boric v7fs_os_write_n(void *self, uint8_t *buf, daddr_t block, int count)
1959f988b79SJean-Baptiste Boric {
1969f988b79SJean-Baptiste Boric int i;
1979f988b79SJean-Baptiste Boric
1989f988b79SJean-Baptiste Boric for (i = 0; i < count; i++) {
1999f988b79SJean-Baptiste Boric if (!v7fs_os_write(self, buf, block))
2009f988b79SJean-Baptiste Boric return false;
2019f988b79SJean-Baptiste Boric buf += DEV_BSIZE;
2029f988b79SJean-Baptiste Boric block++;
2039f988b79SJean-Baptiste Boric }
2049f988b79SJean-Baptiste Boric
2059f988b79SJean-Baptiste Boric return true;
2069f988b79SJean-Baptiste Boric }
2079f988b79SJean-Baptiste Boric
2089f988b79SJean-Baptiste Boric static bool
v7fs_os_write(void * self,uint8_t * buf,daddr_t block)2099f988b79SJean-Baptiste Boric v7fs_os_write(void *self, uint8_t *buf, daddr_t block)
2109f988b79SJean-Baptiste Boric {
2119f988b79SJean-Baptiste Boric struct local_io *bio = (struct local_io *)self;
2129f988b79SJean-Baptiste Boric struct buf *bp;
2139f988b79SJean-Baptiste Boric
2149f988b79SJean-Baptiste Boric if ((bp = getblk(bio->vp, block, DEV_BSIZE, 0, 0)) == 0) {
2159f988b79SJean-Baptiste Boric DPRINTF("getblk failed. block=%ld\n", (long)block);
2169f988b79SJean-Baptiste Boric return false;
2179f988b79SJean-Baptiste Boric }
2189f988b79SJean-Baptiste Boric
2199f988b79SJean-Baptiste Boric memcpy(bp->b_data, buf, DEV_BSIZE);
2209f988b79SJean-Baptiste Boric
2219f988b79SJean-Baptiste Boric if (bwrite(bp) != 0) {
2229f988b79SJean-Baptiste Boric DPRINTF("bwrite failed. block=%ld\n", (long)block);
2239f988b79SJean-Baptiste Boric return false;
2249f988b79SJean-Baptiste Boric }
2259f988b79SJean-Baptiste Boric
2269f988b79SJean-Baptiste Boric return true;
2279f988b79SJean-Baptiste Boric }
2289f988b79SJean-Baptiste Boric
2299f988b79SJean-Baptiste Boric static void
v7fs_os_lock(void * self)2309f988b79SJean-Baptiste Boric v7fs_os_lock(void *self)
2319f988b79SJean-Baptiste Boric {
2329f988b79SJean-Baptiste Boric
2339f988b79SJean-Baptiste Boric mutex_enter((kmutex_t *)self);
2349f988b79SJean-Baptiste Boric }
2359f988b79SJean-Baptiste Boric
2369f988b79SJean-Baptiste Boric static void
v7fs_os_unlock(void * self)2379f988b79SJean-Baptiste Boric v7fs_os_unlock(void *self)
2389f988b79SJean-Baptiste Boric {
2399f988b79SJean-Baptiste Boric
2409f988b79SJean-Baptiste Boric mutex_exit((kmutex_t *)self);
2419f988b79SJean-Baptiste Boric }
242