1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2022 Tomohiro Kusumi <tkusumi@netbsd.org>
5  * Copyright (c) 2011-2022 The DragonFly Project.  All rights reserved.
6  *
7  * This code is derived from software contributed to The DragonFly Project
8  * by Matthew Dillon <dillon@dragonflybsd.org>
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  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  * 3. Neither the name of The DragonFly Project nor the names of its
21  *    contributors may be used to endorse or promote products derived
22  *    from this software without specific, prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
28  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include "hammer2.h"
39 #include "makefs.h"
40 
41 struct m_buf *
42 getblkx(struct m_vnode *vp, off_t loffset, int size, int blkflags, int slptimeo)
43 {
44 	struct m_buf *bp;
45 	makefs_daddr_t blkno;
46 
47 	if (vp->v_logical)
48 		blkno = -1;
49 	else
50 		blkno = loffset / DEV_BSIZE; /* fsopts->sectorsize */
51 
52 	bp = getblk(vp, blkno, size, 0, 0, 0);
53 	assert(bp);
54 	assert(bp->b_data);
55 
56 	bp->b_loffset = loffset;
57 
58 	return (bp);
59 }
60 
61 int
62 breadx(struct m_vnode *vp, off_t loffset, int size, struct m_buf **bpp)
63 {
64 	struct m_buf *bp;
65 	ssize_t ret;
66 
67 	assert(bpp != NULL);
68 
69 	bp = getblkx(vp, loffset, size, 0, 0);
70 	if (bp->b_fs == NULL)
71 		errx(1, "buf %p for vp %p has no makefs_fsinfo", bp, vp);
72 
73 	assert(bp->b_blkno * DEV_BSIZE == bp->b_loffset);
74 	assert(bp->b_bcount == size);
75 	assert(bp->b_vp);
76 	assert(!bp->b_vp->v_logical);
77 	*bpp = bp;
78 
79 	if (lseek(bp->b_fs->fd, bp->b_loffset, SEEK_SET) == -1)
80 		err(1, "%s: lseek vp %p offset 0x%016jx",
81 			__func__, vp, (intmax_t)bp->b_loffset);
82 
83 	ret = read(bp->b_fs->fd, bp->b_data, bp->b_bcount);
84 	if (debug & DEBUG_BUF_BREAD)
85 		printf("%s: read vp %p offset 0x%016jx size 0x%jx -> 0x%jx\n",
86 			__func__, vp, (intmax_t)bp->b_loffset,
87 			(intmax_t)bp->b_bcount, (intmax_t)ret);
88 
89 	if (ret == -1) {
90 		err(1, "%s: read vp %p offset 0x%016jx size 0x%jx",
91 			__func__, vp, (intmax_t)bp->b_loffset,
92 			(intmax_t)bp->b_bcount);
93 	} else if (ret != bp->b_bcount) {
94 		if (debug)
95 			printf("%s: read vp %p offset 0x%016jx size 0x%jx -> "
96 				"0x%jx != 0x%jx\n",
97 				__func__, vp, (intmax_t)bp->b_loffset,
98 				(intmax_t)bp->b_bcount, (intmax_t)ret,
99 				(intmax_t)bp->b_bcount);
100 		return (EINVAL);
101 	}
102 
103 	return (0);
104 }
105 
106 int
107 bread_kvabio(struct m_vnode *vp, off_t loffset, int size, struct m_buf **bpp)
108 {
109 	return (breadx(vp, loffset, size, bpp));
110 }
111 
112 void
113 bqrelse(struct m_buf *bp)
114 {
115 	brelse(bp);
116 }
117 
118 int
119 bawrite(struct m_buf *bp)
120 {
121 	return (bwrite(bp));
122 }
123 
124 int
125 uiomove(caddr_t cp, size_t n, struct uio *uio)
126 {
127 	struct iovec *iov;
128 	size_t cnt;
129 	int error = 0;
130 
131 	KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
132 	    ("uiomove: mode"));
133 
134 	while (n > 0 && uio->uio_resid) {
135 		iov = uio->uio_iov;
136 		cnt = iov->iov_len;
137 		if (cnt == 0) {
138 			uio->uio_iov++;
139 			uio->uio_iovcnt--;
140 			continue;
141 		}
142 		if (cnt > n)
143 			cnt = n;
144 
145 		switch (uio->uio_segflg) {
146 		case UIO_USERSPACE:
147 			/* emulate copyout/copyin */
148 			if (uio->uio_rw == UIO_READ)
149 				bcopy(cp, iov->iov_base, cnt);
150 			else
151 				bcopy(iov->iov_base, cp, cnt);
152 			break;
153 		case UIO_SYSSPACE:
154 			if (uio->uio_rw == UIO_READ)
155 				bcopy(cp, iov->iov_base, cnt);
156 			else
157 				bcopy(iov->iov_base, cp, cnt);
158 			break;
159 		case UIO_NOCOPY:
160 			assert(0); /* no UIO_NOCOPY in makefs */
161 			break;
162 		}
163 
164 		if (error)
165 			break;
166 		iov->iov_base = (char *)iov->iov_base + cnt;
167 		iov->iov_len -= cnt;
168 		uio->uio_resid -= cnt;
169 		uio->uio_offset += cnt;
170 		cp += cnt;
171 		n -= cnt;
172 	}
173 
174 	return (error);
175 }
176 
177 int
178 uiomovebp(struct m_buf *bp, caddr_t cp, size_t n, struct uio *uio)
179 {
180 	return (uiomove(cp, n, uio));
181 }
182