1 /*
2  * Copyright (c) 2001,2005 Russell Cattelan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: stable/9/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c 189878 2009-03-16 15:39:46Z kib $
27  */
28 
29 #include "xfs.h"
30 #include "xfs_types.h"
31 #include "xfs_inum.h"
32 #include "xfs_log.h"
33 #include "xfs_trans.h"
34 #include "xfs_sb.h"
35 #include "xfs_ag.h"
36 #include "xfs_dir.h"
37 #include "xfs_dir2.h"
38 #include "xfs_dmapi.h"
39 #include "xfs_mount.h"
40 #include "xfs_clnt.h"
41 #include "xfs_mountops.h"
42 
43 #include <geom/geom.h>
44 #include <geom/geom_vfs.h>
45 
46 xfs_buf_t *
xfs_buf_read_flags(xfs_buftarg_t * target,xfs_daddr_t blkno,size_t len,int flags)47 xfs_buf_read_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
48 {
49 	struct buf *bp;
50 	KASSERT((target != NULL), ("got NULL buftarg_t"));
51 
52 	if (bread(target->specvp, blkno, BBTOB(len), NOCRED, &bp)) {
53 		printf("bread failed specvp %p blkno %qd BBTOB(len) %ld\n",
54 		       target->specvp, blkno, (long)BBTOB(len));
55 		bp = NULL;
56 	}
57 
58 	/* not really sure what B_MANAGED really does for us
59 	 * maybe we should drop this and just stick with a locked buf
60 	 */
61 
62 	if (flags & B_MANAGED)
63 		bp->b_flags |= B_MANAGED;
64 	xfs_buf_set_target(bp, target);
65 	return (bp);
66 }
67 
68 xfs_buf_t *
xfs_buf_get_flags(xfs_buftarg_t * target,xfs_daddr_t blkno,size_t len,int flags)69 xfs_buf_get_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
70 {
71 	struct buf *bp = NULL;
72 	KASSERT((target != NULL), ("got NULL buftarg_t"));
73 	bp = getblk(target->specvp, blkno, BBTOB(len), 0, 0, 0);
74 	if (bp != NULL)
75 		xfs_buf_set_target(bp, target);
76 	return (bp);
77 }
78 
79 xfs_buf_t*
xfs_buf_get_empty(size_t size,xfs_buftarg_t * target)80 xfs_buf_get_empty(size_t size,  xfs_buftarg_t *target)
81 {
82 	struct buf *bp;
83 
84 	bp = geteblk(0, 0);
85 	if (bp != NULL) {
86 		bp->b_bufsize = size;
87 		bp->b_bcount = size;
88 
89 		BUF_ASSERT_HELD(bp);
90 
91 		xfs_buf_set_target(bp, target);
92 	}
93 	return (bp);
94 }
95 
96 xfs_buf_t*
xfs_buf_get_noaddr(size_t len,xfs_buftarg_t * target)97 xfs_buf_get_noaddr(size_t len, xfs_buftarg_t *target)
98 {
99 	struct buf *bp;
100 	if (len >= MAXPHYS)
101 		return (NULL);
102 
103 	bp = geteblk(len, 0);
104 	if (bp != NULL) {
105 		BUF_ASSERT_HELD(bp);
106 
107 		xfs_buf_set_target(bp, target);
108 	}
109 	return (bp);
110 }
111 
112 void
xfs_buf_free(xfs_buf_t * bp)113 xfs_buf_free(xfs_buf_t *bp)
114 {
115 	bp->b_flags |= B_INVAL;
116 	BUF_KERNPROC(bp);			 /* ugly hack #1 */
117 	if (bp->b_kvasize == 0) {
118 		bp->b_saveaddr = bp->b_kvabase;  /* ugly hack #2 */
119 		bp->b_data = bp->b_saveaddr;
120 		bp->b_bcount  = 0;
121 		bp->b_bufsize = 0;
122 	}
123 	brelse(bp);
124 }
125 
126 void
xfs_buf_readahead(xfs_buftarg_t * target,xfs_daddr_t ioff,size_t isize,xfs_buf_flags_t flags)127 xfs_buf_readahead(
128 		  xfs_buftarg_t		*target,
129 		  xfs_daddr_t		ioff,
130 		  size_t		isize,
131 		  xfs_buf_flags_t	flags)
132 {
133 	daddr_t rablkno;
134 	int rabsize;
135 
136 	rablkno = ioff;
137 	rabsize = BBTOB(isize);
138 	breada(target->specvp, &rablkno, &rabsize, 1, NOCRED);
139 }
140 
141 void
xfs_buf_set_target(xfs_buf_t * bp,xfs_buftarg_t * targ)142 xfs_buf_set_target(xfs_buf_t *bp, xfs_buftarg_t *targ)
143 {
144 	bp->b_bufobj = &targ->specvp->v_bufobj;
145 	bp->b_caller1 = targ;
146 }
147 
148 xfs_buftarg_t *
xfs_buf_get_target(xfs_buf_t * bp)149 xfs_buf_get_target(xfs_buf_t *bp)
150 {
151 	return (xfs_buftarg_t *)bp->b_caller1;
152 }
153 
154 int
XFS_bwrite(xfs_buf_t * bp)155 XFS_bwrite(xfs_buf_t *bp)
156 {
157 	int error;
158 	if (bp->b_vp == NULL) {
159 		error = xfs_buf_iorequest(bp);
160 
161 		if ((bp->b_flags & B_ASYNC) == 0) {
162 			error = bufwait(bp);
163 #if 0
164 			if (BUF_LOCKRECURSED(bp))
165 				BUF_UNLOCK(bp);
166 			else
167 				brelse(bp);
168 #endif
169 			brelse(bp);
170 		}
171 		return (error);
172 	}
173 	error = bwrite(bp);
174 	return (error);
175 }
176 
177 void
xfs_buf_pin(xfs_buf_t * bp)178 xfs_buf_pin(xfs_buf_t *bp)
179 {
180 	bpin(bp);
181 }
182 
183 void
xfs_buf_unpin(xfs_buf_t * bp)184 xfs_buf_unpin(xfs_buf_t *bp)
185 {
186 	bunpin(bp);
187 }
188 
189 int
xfs_buf_ispin(xfs_buf_t * bp)190 xfs_buf_ispin(xfs_buf_t *bp)
191 {
192 	return bp->b_pin_count;
193 }
194 
195 #if 0
196 void
197 xfs_buf_wait_unpin(
198 	xfs_buf_t *bp)
199 {
200 	bunpin_wait(bp);
201 }
202 #endif
203 
204 /*
205  *	Move data into or out of a buffer.
206  */
207 void
xfs_buf_iomove(xfs_buf_t * bp,size_t boff,size_t bsize,caddr_t data,xfs_buf_rw_t mode)208 xfs_buf_iomove(
209 	xfs_buf_t		*bp,	/* buffer to process		*/
210 	size_t			boff,	/* starting buffer offset	*/
211 	size_t			bsize,	/* length to copy		*/
212 	caddr_t			data,	/* data address			*/
213 	xfs_buf_rw_t		mode)	/* read/write/zero flag		*/
214 {
215 
216   printf("xfs_buf_iomove NI\n");
217 #ifdef RMC
218 	size_t			bend, cpoff, csize;
219 	struct page		*page;
220 
221 	bend = boff + bsize;
222 	while (boff < bend) {
223 		page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];
224 		cpoff = xfs_buf_poff(boff + bp->b_offset);
225 		csize = min_t(size_t,
226 			      PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff);
227 
228 		ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
229 
230 		switch (mode) {
231 		case XBRW_ZERO:
232 			memset(page_address(page) + cpoff, 0, csize);
233 			break;
234 		case XBRW_READ:
235 			memcpy(data, page_address(page) + cpoff, csize);
236 			break;
237 		case XBRW_WRITE:
238 			memcpy(page_address(page) + cpoff, data, csize);
239 		}
240 
241 		boff += csize;
242 		data += csize;
243 	}
244 #endif
245 }
246 
247 /*
248  *	Handling of buffer targets (buftargs).
249  */
250 
251 /*
252  *	Wait for any bufs with callbacks that have been submitted but
253  *	have not yet returned... walk the hash list for the target.
254  */
255 void
xfs_wait_buftarg(xfs_buftarg_t * bp)256 xfs_wait_buftarg(
257 		 xfs_buftarg_t *bp)
258 {
259 	printf("xfs_wait_buftarg(%p) NI\n", bp);
260 }
261 
262 int
xfs_flush_buftarg(xfs_buftarg_t * btp,int wait)263 xfs_flush_buftarg(
264 	xfs_buftarg_t		*btp,
265 	int wait)
266 {
267 	int error = 0;
268 
269 	error = vinvalbuf(btp->specvp, V_SAVE | V_NORMAL, 0, 0);
270 	return error;
271 }
272 
273 void
xfs_free_buftarg(xfs_buftarg_t * btp,int external)274 xfs_free_buftarg(
275 	xfs_buftarg_t		*btp,
276 	int			external)
277 {
278 	xfs_flush_buftarg(btp, /* wait */ 0);
279 	kmem_free(btp, sizeof(*btp));
280 }
281 
282 int
xfs_readonly_buftarg(xfs_buftarg_t * btp)283 xfs_readonly_buftarg(
284 	xfs_buftarg_t		*btp)
285 {
286 	struct g_consumer *cp;
287 
288 	KASSERT(btp->specvp->v_bufobj.bo_ops == &xfs_bo_ops,
289 	   ("Bogus xfs_buftarg_t pointer"));
290 	cp = btp->specvp->v_bufobj.bo_private;
291 	return (cp->acw == 0);
292 }
293 
294 #if 0
295 void
296 xfs_relse_buftarg(
297 	xfs_buftarg_t		*btp)
298 {
299 	printf("xfs_relse_buftargNI %p\n",btp);
300 }
301 #endif
302 
303 unsigned int
xfs_getsize_buftarg(xfs_buftarg_t * btp)304 xfs_getsize_buftarg(
305 	xfs_buftarg_t		*btp)
306 {
307 	struct g_consumer       *cp;
308 	cp = btp->specvp->v_bufobj.bo_private;
309 	return (cp->provider->sectorsize);
310 }
311 
312 int
xfs_setsize_buftarg(xfs_buftarg_t * btp,unsigned int blocksize,unsigned int sectorsize)313 xfs_setsize_buftarg(
314 	xfs_buftarg_t		*btp,
315 	unsigned int		blocksize,
316 	unsigned int		sectorsize)
317 {
318 	printf("xfs_setsize_buftarg NI %p\n",btp);
319 	return 0;
320 }
321 
322 xfs_buftarg_t *
xfs_alloc_buftarg(struct vnode * bdev,int external)323 xfs_alloc_buftarg(
324 		  struct vnode	*bdev,
325 		  int		external)
326 {
327 	xfs_buftarg_t		*btp;
328 
329 	btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
330 
331 	btp->dev    = bdev->v_rdev;
332 	btp->specvp = bdev;
333 	return btp;
334 }
335