xref: /netbsd-src/sys/fs/v7fs/v7fs_io_kern.c (revision 1b9578b8c2c1f848eeb16dabbfd7d1f0d9fdefbd)
1 /*	$NetBSD: v7fs_io_kern.c,v 1.1 2011/06/27 11:52:25 uch 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.1 2011/06/27 11:52:25 uch 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.1 2011/06/27 11:52:25 uch 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/malloc.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 MALLOC_JUSTDEFINE(M_V7FS, "v7fs core", "v7fs internal structures");
73 
74 int
75 v7fs_io_init(struct v7fs_self **fs,
76     const struct v7fs_mount_device *mount_device, size_t block_size)
77 {
78 	struct vnode *vp = mount_device->device.vnode;
79 	struct v7fs_self *p;
80 	struct local_io *local;
81 	int error = 0;
82 
83 	/* Allocate myself */
84 	if (!(p = (struct v7fs_self *)malloc(sizeof(*p), M_TEMP, M_WAITOK |
85 	    M_ZERO)))
86 		return ENOMEM;
87 	memset(p, 0, sizeof(*p));
88 
89 	p->scratch_free = -1;
90 	p->scratch_remain = V7FS_SELF_NSCRATCH;
91 
92 	/* Endian */
93 	p->endian = mount_device->endian;
94 #ifdef V7FS_EI
95 	v7fs_endian_init(p);
96 #endif
97 	/* IO */
98 	if (!(local = (struct local_io *)malloc(sizeof(*local), M_TEMP,
99 	    M_WAITOK | M_ZERO))) {
100 		error = ENOMEM;
101 		goto errexit;
102 	}
103 	p->io.read = v7fs_os_read;
104 	p->io.read_n = v7fs_os_read_n;
105 	p->io.write = v7fs_os_write;
106 	p->io.write_n = v7fs_os_write_n;
107 	p->scratch_free = -1; /* free all scratch buffer */
108 
109 	p->io.cookie = local;
110 	local->vp = vp;
111 	local->cred = NOCRED;	/* upper layer check cred. */
112 
113 	/*LOCK */
114 	error = ENOMEM;
115 	if (!lock_init(&p->sb_lock))
116 		goto errexit;
117 	if (!lock_init(&p->ilist_lock))
118 		goto errexit;
119 	if (!lock_init(&p->mem_lock))
120 		goto errexit;
121 	error = 0;
122 
123 	*fs = p;
124 	return 0;
125 
126 errexit:
127 	if (p->io.cookie)
128 		free(p->io.cookie, M_TEMP);
129 	if (p->sb_lock.cookie)
130 		free(p->sb_lock.cookie, M_TEMP);
131 	if (p->ilist_lock.cookie)
132 		free(p->ilist_lock.cookie, M_TEMP);
133 	if (p->mem_lock.cookie)
134 		free(p->mem_lock.cookie, M_TEMP);
135 	free(p, M_TEMP);
136 
137 	return error;
138 }
139 
140 static bool
141 lock_init(struct lock_ops *ops)
142 {
143 	if (!(ops->cookie = (kmutex_t *)malloc(sizeof(kmutex_t), M_TEMP,
144 	    M_WAITOK | M_ZERO))) {
145 		return false;
146 	}
147 	mutex_init(ops->cookie, MUTEX_DEFAULT, IPL_NONE);
148 	ops->lock = v7fs_os_lock;
149 	ops->unlock = v7fs_os_unlock;
150 
151 	return true;
152 }
153 
154 void
155 v7fs_io_fini(struct v7fs_self *fs)
156 {
157 	mutex_destroy(fs->sb_lock.cookie);
158 	mutex_destroy(fs->ilist_lock.cookie);
159 	mutex_destroy(fs->mem_lock.cookie);
160 
161 	free(fs->io.cookie, M_TEMP);
162 	free(fs->sb_lock.cookie, M_TEMP);
163 	free(fs->ilist_lock.cookie, M_TEMP);
164 	free(fs, M_TEMP);
165 }
166 
167 static bool
168 v7fs_os_read_n(void *self, uint8_t *buf, daddr_t block, int count)
169 {
170 	int i;
171 
172 	for (i = 0; i < count; i++) {
173 		if (!v7fs_os_read(self, buf, block))
174 			return false;
175 		buf += DEV_BSIZE;
176 		block++;
177 	}
178 
179 	return true;
180 }
181 
182 static bool
183 v7fs_os_read(void *self, uint8_t *buf, daddr_t block)
184 {
185 	struct local_io *bio = (struct local_io *)self;
186 	struct buf *bp = NULL;
187 
188 	if (bread(bio->vp, block, DEV_BSIZE, bio->cred, 0, &bp) != 0)
189 		goto error_exit;
190 	memcpy(buf, bp->b_data, DEV_BSIZE);
191 	brelse(bp, 0);
192 
193 	return true;
194 error_exit:
195 	DPRINTF("block %ld read failed.\n", (long)block);
196 
197 	if (bp != NULL)
198 		brelse(bp, 0);
199 	return false;
200 }
201 
202 static bool
203 v7fs_os_write_n(void *self, uint8_t *buf, daddr_t block, int count)
204 {
205 	int i;
206 
207 	for (i = 0; i < count; i++) {
208 		if (!v7fs_os_write(self, buf, block))
209 			return false;
210 		buf += DEV_BSIZE;
211 		block++;
212 	}
213 
214 	return true;
215 }
216 
217 static bool
218 v7fs_os_write(void *self, uint8_t *buf, daddr_t block)
219 {
220 	struct local_io *bio = (struct local_io *)self;
221 	struct buf *bp;
222 
223 	if ((bp = getblk(bio->vp, block, DEV_BSIZE, 0, 0)) == 0) {
224 		DPRINTF("getblk failed. block=%ld\n", (long)block);
225 		return false;
226 	}
227 
228 	memcpy(bp->b_data, buf, DEV_BSIZE);
229 
230 	if (bwrite(bp) != 0) {
231 		DPRINTF("bwrite failed. block=%ld\n", (long)block);
232 		return false;
233 	}
234 
235 	return true;
236 }
237 
238 static void
239 v7fs_os_lock(void *self)
240 {
241 
242 	mutex_enter((kmutex_t *)self);
243 }
244 
245 static void
246 v7fs_os_unlock(void *self)
247 {
248 
249 	mutex_exit((kmutex_t *)self);
250 }
251