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