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$
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
46xfs_buf_t *
47xfs_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
68xfs_buf_t *
69xfs_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
79xfs_buf_t*
80xfs_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
96xfs_buf_t*
97xfs_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
112void
113xfs_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
126void
127xfs_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
141void
142xfs_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
148xfs_buftarg_t *
149xfs_buf_get_target(xfs_buf_t *bp)
150{
151	return (xfs_buftarg_t *)bp->b_caller1;
152}
153
154int
155XFS_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
177void
178xfs_buf_pin(xfs_buf_t *bp)
179{
180	bpin(bp);
181}
182
183void
184xfs_buf_unpin(xfs_buf_t *bp)
185{
186	bunpin(bp);
187}
188
189int
190xfs_buf_ispin(xfs_buf_t *bp)
191{
192	return bp->b_pin_count;
193}
194
195#if 0
196void
197xfs_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 */
207void
208xfs_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 */
255void
256xfs_wait_buftarg(
257		 xfs_buftarg_t *bp)
258{
259	printf("xfs_wait_buftarg(%p) NI\n", bp);
260}
261
262int
263xfs_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
273void
274xfs_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
282int
283xfs_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
295void
296xfs_relse_buftarg(
297	xfs_buftarg_t		*btp)
298{
299	printf("xfs_relse_buftargNI %p\n",btp);
300}
301#endif
302
303unsigned int
304xfs_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
312int
313xfs_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
322xfs_buftarg_t *
323xfs_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