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