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 = loffset / DEV_BSIZE;
46 
47 	bp = getblk(vp, blkno, size, 0, 0, 0);
48 	assert(bp);
49 	assert(bp->b_data);
50 
51 	bp->b_loffset = loffset;
52 	bp->b_is_hammer2 = 1;
53 
54 	return (bp);
55 }
56 
57 int
58 breadx(struct m_vnode *vp, off_t loffset, int size, struct m_buf **bpp)
59 {
60 	struct m_buf *bp;
61 	ssize_t ret;
62 
63 	assert(bpp != NULL);
64 
65 	bp = getblkx(vp, loffset, size, 0, 0);
66 	if (bp->b_fs == NULL)
67 		errx(1, "buf %p for vp %p has no makefs_fsinfo", bp, vp);
68 
69 	assert(bp->b_blkno * DEV_BSIZE == bp->b_loffset);
70 	assert(bp->b_bcount == size);
71 	assert(bp->b_vp);
72 	assert(!bp->b_vp->v_logical);
73 	*bpp = bp;
74 
75 	if (lseek(bp->b_fs->fd, bp->b_loffset, SEEK_SET) == -1)
76 		err(1, "%s: lseek vp %p offset 0x%016jx",
77 			__func__, vp, (intmax_t)bp->b_loffset);
78 
79 	ret = read(bp->b_fs->fd, bp->b_data, bp->b_bcount);
80 	if (debug & DEBUG_BUF_BREAD)
81 		printf("%s: read vp %p offset 0x%016jx size 0x%jx -> 0x%jx\n",
82 			__func__, vp, (intmax_t)bp->b_loffset, bp->b_bcount, ret);
83 
84 	if (ret == -1) {
85 		err(1, "%s: read vp %p offset 0x%016jx size 0x%jx",
86 			__func__, vp, (intmax_t)bp->b_loffset, bp->b_bcount);
87 	} else if (ret != bp->b_bcount) {
88 		if (debug)
89 			printf("%s: read vp %p offset 0x%016jx size 0x%jx -> "
90 				"0x%jx != 0x%jx\n",
91 				__func__, vp, (intmax_t)bp->b_loffset, bp->b_bcount, ret,
92 				bp->b_bcount);
93 		return (EINVAL);
94 	}
95 
96 	return (0);
97 }
98 
99 int
100 bread_kvabio(struct m_vnode *vp, off_t loffset, int size, struct m_buf **bpp)
101 {
102 	return (breadx(vp, loffset, size, bpp));
103 }
104 
105 void
106 bqrelse(struct m_buf *bp)
107 {
108 	brelse(bp);
109 }
110 
111 int
112 bawrite(struct m_buf *bp)
113 {
114 	return (bwrite(bp));
115 }
116 
117 static int
118 uiomove(caddr_t cp, size_t n, struct uio *uio)
119 {
120 	struct iovec *iov;
121 	size_t cnt;
122 	size_t tot = 0;
123 	int error = 0;
124 
125 	KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
126 	    ("uiomove: mode"));
127 
128 	while (n > 0 && uio->uio_resid) {
129 		iov = uio->uio_iov;
130 		cnt = iov->iov_len;
131 		if (cnt == 0) {
132 			uio->uio_iov++;
133 			uio->uio_iovcnt--;
134 			continue;
135 		}
136 		if (cnt > n)
137 			cnt = n;
138 		tot += cnt;
139 
140 		switch (uio->uio_segflg) {
141 		case UIO_USERSPACE:
142 			/* emulate copyout/copyin */
143 			if (uio->uio_rw == UIO_READ)
144 				bcopy(cp, iov->iov_base, cnt);
145 			else
146 				bcopy(iov->iov_base, cp, cnt);
147 			break;
148 		case UIO_SYSSPACE:
149 			if (uio->uio_rw == UIO_READ)
150 				bcopy(cp, iov->iov_base, cnt);
151 			else
152 				bcopy(iov->iov_base, cp, cnt);
153 			break;
154 		case UIO_NOCOPY:
155 			assert(0); /* no UIO_NOCOPY in makefs */
156 			break;
157 		}
158 
159 		if (error)
160 			break;
161 		iov->iov_base = (char *)iov->iov_base + cnt;
162 		iov->iov_len -= cnt;
163 		uio->uio_resid -= cnt;
164 		uio->uio_offset += cnt;
165 		cp += cnt;
166 		n -= cnt;
167 	}
168 
169 	return (error);
170 }
171 
172 int
173 uiomovebp(struct m_buf *bp, caddr_t cp, size_t n, struct uio *uio)
174 {
175 	return (uiomove(cp, n, uio));
176 }
177