138494Sobrien/*
2174294Sobrien * Copyright (c) 2001,2005 Russell Cattelan
338494Sobrien * All rights reserved.
438494Sobrien *
538494Sobrien * Redistribution and use in source and binary forms, with or without
638494Sobrien * modification, are permitted provided that the following conditions
738494Sobrien * are met:
838494Sobrien * 1. Redistributions of source code must retain the above copyright
938494Sobrien *    notice, this list of conditions and the following disclaimer.
1038494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1138494Sobrien *    notice, this list of conditions and the following disclaimer in the
1238494Sobrien *    documentation and/or other materials provided with the distribution.
1338494Sobrien *
1438494Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2042629Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438494Sobrien * SUCH DAMAGE.
2538494Sobrien *
2638494Sobrien * $FreeBSD$
2738494Sobrien */
2838494Sobrien
2938494Sobrien#include "xfs.h"
3038494Sobrien#include "xfs_types.h"
3138494Sobrien#include "xfs_inum.h"
3238494Sobrien#include "xfs_log.h"
3338494Sobrien#include "xfs_trans.h"
3438494Sobrien#include "xfs_sb.h"
3538494Sobrien#include "xfs_ag.h"
3638494Sobrien#include "xfs_dir.h"
3738494Sobrien#include "xfs_dir2.h"
3838494Sobrien#include "xfs_dmapi.h"
3938494Sobrien#include "xfs_mount.h"
40174294Sobrien#include "xfs_clnt.h"
4138494Sobrien#include "xfs_mountops.h"
4238494Sobrien
4338494Sobrien#include <geom/geom.h>
4438494Sobrien#include <geom/geom_vfs.h>
4538494Sobrien
4638494Sobrienxfs_buf_t *
4738494Sobrienxfs_buf_read_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
4838494Sobrien{
4938494Sobrien	struct buf *bp;
5038494Sobrien	KASSERT((target != NULL), ("got NULL buftarg_t"));
5138494Sobrien
5238494Sobrien	if (bread(target->specvp, blkno, BBTOB(len), NOCRED, &bp)) {
5338494Sobrien		printf("bread failed specvp %p blkno %qd BBTOB(len) %ld\n",
5438494Sobrien		       target->specvp, blkno, (long)BBTOB(len));
5538494Sobrien		bp = NULL;
5638494Sobrien	}
5738494Sobrien
5838494Sobrien	/* not really sure what B_MANAGED really does for us
5938494Sobrien	 * maybe we should drop this and just stick with a locked buf
6038494Sobrien	 */
6138494Sobrien
6238494Sobrien	if (flags & B_MANAGED)
6338494Sobrien		bp->b_flags |= B_MANAGED;
6438494Sobrien	xfs_buf_set_target(bp, target);
6538494Sobrien	return (bp);
66174294Sobrien}
6738494Sobrien
6838494Sobrienxfs_buf_t *
6938494Sobrienxfs_buf_get_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
7038494Sobrien{
7138494Sobrien	struct buf *bp = NULL;
7238494Sobrien	KASSERT((target != NULL), ("got NULL buftarg_t"));
7338494Sobrien	bp = getblk(target->specvp, blkno, BBTOB(len), 0, 0, 0);
7438494Sobrien	if (bp != NULL)
7538494Sobrien		xfs_buf_set_target(bp, target);
7638494Sobrien	return (bp);
7738494Sobrien}
7838494Sobrien
7938494Sobrienxfs_buf_t*
8038494Sobrienxfs_buf_get_empty(size_t size,  xfs_buftarg_t *target)
8138494Sobrien{
8238494Sobrien	struct buf *bp;
8338494Sobrien
8438494Sobrien	bp = geteblk(0, 0);
8538494Sobrien	if (bp != NULL) {
8638494Sobrien		bp->b_bufsize = size;
8738494Sobrien		bp->b_bcount = size;
8838494Sobrien
8938494Sobrien		BUF_ASSERT_HELD(bp);
9038494Sobrien
9138494Sobrien		xfs_buf_set_target(bp, target);
9238494Sobrien	}
9338494Sobrien	return (bp);
94174294Sobrien}
9538494Sobrien
9638494Sobrienxfs_buf_t*
9738494Sobrienxfs_buf_get_noaddr(size_t len, xfs_buftarg_t *target)
9838494Sobrien{
9938494Sobrien	struct buf *bp;
100174294Sobrien	if (len >= MAXPHYS)
10138494Sobrien		return (NULL);
10238494Sobrien
10338494Sobrien	bp = geteblk(len, 0);
10438494Sobrien	if (bp != NULL) {
10538494Sobrien		BUF_ASSERT_HELD(bp);
10638494Sobrien
107174294Sobrien		xfs_buf_set_target(bp, target);
108174294Sobrien	}
109174294Sobrien	return (bp);
110174294Sobrien}
111174294Sobrien
112174294Sobrienvoid
113174294Sobrienxfs_buf_free(xfs_buf_t *bp)
11438494Sobrien{
11538494Sobrien	bp->b_flags |= B_INVAL;
11638494Sobrien	BUF_KERNPROC(bp);			 /* ugly hack #1 */
11738494Sobrien	if (bp->b_kvasize == 0) {
11838494Sobrien		bp->b_saveaddr = bp->b_kvabase;  /* ugly hack #2 */
11938494Sobrien		bp->b_data = bp->b_saveaddr;
12038494Sobrien		bp->b_bcount  = 0;
12138494Sobrien		bp->b_bufsize = 0;
12238494Sobrien	}
12338494Sobrien	brelse(bp);
12438494Sobrien}
12538494Sobrien
12638494Sobrienvoid
12738494Sobrienxfs_buf_readahead(
128174294Sobrien		  xfs_buftarg_t		*target,
129174294Sobrien		  xfs_daddr_t		ioff,
130174294Sobrien		  size_t		isize,
131174294Sobrien		  xfs_buf_flags_t	flags)
13238494Sobrien{
13338494Sobrien	daddr_t rablkno;
13438494Sobrien	int rabsize;
13538494Sobrien
13638494Sobrien	rablkno = ioff;
137174294Sobrien	rabsize = BBTOB(isize);
138174294Sobrien	breada(target->specvp, &rablkno, &rabsize, 1, NOCRED);
139174294Sobrien}
140174294Sobrien
141174294Sobrienvoid
14238494Sobrienxfs_buf_set_target(xfs_buf_t *bp, xfs_buftarg_t *targ)
14338494Sobrien{
14438494Sobrien	bp->b_bufobj = &targ->specvp->v_bufobj;
14538494Sobrien	bp->b_caller1 = targ;
146174294Sobrien}
14738494Sobrien
14838494Sobrienxfs_buftarg_t *
149174294Sobrienxfs_buf_get_target(xfs_buf_t *bp)
15038494Sobrien{
15138494Sobrien	return (xfs_buftarg_t *)bp->b_caller1;
15238494Sobrien}
15338494Sobrien
15438494Sobrienint
15538494SobrienXFS_bwrite(xfs_buf_t *bp)
15638494Sobrien{
15738494Sobrien	int error;
15838494Sobrien	if (bp->b_vp == NULL) {
15951292Sobrien		error = xfs_buf_iorequest(bp);
16038494Sobrien
16138494Sobrien		if ((bp->b_flags & B_ASYNC) == 0) {
16238494Sobrien			error = bufwait(bp);
16338494Sobrien#if 0
16438494Sobrien			if (BUF_LOCKRECURSED(bp))
16538494Sobrien				BUF_UNLOCK(bp);
16638494Sobrien			else
16738494Sobrien				brelse(bp);
16838494Sobrien#endif
16938494Sobrien			brelse(bp);
17038494Sobrien		}
17138494Sobrien		return (error);
17238494Sobrien	}
17338494Sobrien	error = bwrite(bp);
174174294Sobrien	return (error);
17538494Sobrien}
17638494Sobrien
177174294Sobrienvoid
17838494Sobrienxfs_buf_pin(xfs_buf_t *bp)
17938494Sobrien{
180174294Sobrien	bpin(bp);
181174294Sobrien}
182174294Sobrien
183174294Sobrienvoid
18438494Sobrienxfs_buf_unpin(xfs_buf_t *bp)
185174294Sobrien{
18638494Sobrien	bunpin(bp);
18738494Sobrien}
18838494Sobrien
18938494Sobrienint
19038494Sobrienxfs_buf_ispin(xfs_buf_t *bp)
19138494Sobrien{
19238494Sobrien	return bp->b_pin_count;
19338494Sobrien}
194174294Sobrien
195174294Sobrien#if 0
196174294Sobrienvoid
197174294Sobrienxfs_buf_wait_unpin(
198174294Sobrien	xfs_buf_t *bp)
199174294Sobrien{
200174294Sobrien	bunpin_wait(bp);
201174294Sobrien}
202174294Sobrien#endif
203174294Sobrien
204174294Sobrien/*
20538494Sobrien *	Move data into or out of a buffer.
206174294Sobrien */
207174294Sobrienvoid
20838494Sobrienxfs_buf_iomove(
209174294Sobrien	xfs_buf_t		*bp,	/* buffer to process		*/
210174294Sobrien	size_t			boff,	/* starting buffer offset	*/
211174294Sobrien	size_t			bsize,	/* length to copy		*/
212174294Sobrien	caddr_t			data,	/* data address			*/
213174294Sobrien	xfs_buf_rw_t		mode)	/* read/write/zero flag		*/
21438494Sobrien{
21538494Sobrien
21638494Sobrien  printf("xfs_buf_iomove NI\n");
217174294Sobrien#ifdef RMC
218174294Sobrien	size_t			bend, cpoff, csize;
219174294Sobrien	struct page		*page;
220174294Sobrien
221174294Sobrien	bend = boff + bsize;
222174294Sobrien	while (boff < bend) {
223174294Sobrien		page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];
224174294Sobrien		cpoff = xfs_buf_poff(boff + bp->b_offset);
225174294Sobrien		csize = min_t(size_t,
22638494Sobrien			      PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff);
227174294Sobrien
228174294Sobrien		ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
229174294Sobrien
230174294Sobrien		switch (mode) {
231174294Sobrien		case XBRW_ZERO:
232174294Sobrien			memset(page_address(page) + cpoff, 0, csize);
233174294Sobrien			break;
234174294Sobrien		case XBRW_READ:
235174294Sobrien			memcpy(data, page_address(page) + cpoff, csize);
236174294Sobrien			break;
237174294Sobrien		case XBRW_WRITE:
238174294Sobrien			memcpy(page_address(page) + cpoff, data, csize);
239174294Sobrien		}
240174294Sobrien
241174294Sobrien		boff += csize;
242174294Sobrien		data += csize;
243174294Sobrien	}
244174294Sobrien#endif
245174294Sobrien}
246174294Sobrien
247174294Sobrien/*
248174294Sobrien *	Handling of buffer targets (buftargs).
249174294Sobrien */
250174294Sobrien
251174294Sobrien/*
252174294Sobrien *	Wait for any bufs with callbacks that have been submitted but
253174294Sobrien *	have not yet returned... walk the hash list for the target.
254174294Sobrien */
255174294Sobrienvoid
256174294Sobrienxfs_wait_buftarg(
257174294Sobrien		 xfs_buftarg_t *bp)
258174294Sobrien{
259174294Sobrien	printf("xfs_wait_buftarg(%p) NI\n", bp);
260174294Sobrien}
261174294Sobrien
262174294Sobrienint
263174294Sobrienxfs_flush_buftarg(
264174294Sobrien	xfs_buftarg_t		*btp,
265174294Sobrien	int wait)
266174294Sobrien{
267174294Sobrien	int error = 0;
268174294Sobrien
269174294Sobrien	error = vinvalbuf(btp->specvp, V_SAVE | V_NORMAL, 0, 0);
270174294Sobrien	return error;
271174294Sobrien}
272174294Sobrien
273174294Sobrienvoid
274174294Sobrienxfs_free_buftarg(
275174294Sobrien	xfs_buftarg_t		*btp,
276174294Sobrien	int			external)
277174294Sobrien{
278174294Sobrien	xfs_flush_buftarg(btp, /* wait */ 0);
279174294Sobrien	kmem_free(btp, sizeof(*btp));
280174294Sobrien}
281174294Sobrien
282174294Sobrienint
28338494Sobrienxfs_readonly_buftarg(
284174294Sobrien	xfs_buftarg_t		*btp)
285174294Sobrien{
286174294Sobrien	struct g_consumer *cp;
28738494Sobrien
288174294Sobrien	KASSERT(btp->specvp->v_bufobj.bo_ops == &xfs_bo_ops,
28938494Sobrien	   ("Bogus xfs_buftarg_t pointer"));
290174294Sobrien	cp = btp->specvp->v_bufobj.bo_private;
291174294Sobrien	return (cp->acw == 0);
292174294Sobrien}
293174294Sobrien
294174294Sobrien#if 0
295174294Sobrienvoid
296174294Sobrienxfs_relse_buftarg(
297174294Sobrien	xfs_buftarg_t		*btp)
29838494Sobrien{
29938494Sobrien	printf("xfs_relse_buftargNI %p\n",btp);
30038494Sobrien}
30138494Sobrien#endif
30238494Sobrien
30338494Sobrienunsigned int
30438494Sobrienxfs_getsize_buftarg(
30538494Sobrien	xfs_buftarg_t		*btp)
30638494Sobrien{
307174294Sobrien	struct g_consumer       *cp;
308174294Sobrien	cp = btp->specvp->v_bufobj.bo_private;
309174294Sobrien	return (cp->provider->sectorsize);
310174294Sobrien}
311174294Sobrien
312174294Sobrienint
31338494Sobrienxfs_setsize_buftarg(
31438494Sobrien	xfs_buftarg_t		*btp,
31538494Sobrien	unsigned int		blocksize,
31638494Sobrien	unsigned int		sectorsize)
31738494Sobrien{
31838494Sobrien	printf("xfs_setsize_buftarg NI %p\n",btp);
31938494Sobrien	return 0;
320174294Sobrien}
32138494Sobrien
322174294Sobrienxfs_buftarg_t *
32338494Sobrienxfs_alloc_buftarg(
32438494Sobrien		  struct vnode	*bdev,
32538494Sobrien		  int		external)
32638494Sobrien{
32738494Sobrien	xfs_buftarg_t		*btp;
32838494Sobrien
32938494Sobrien	btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
33038494Sobrien
33138494Sobrien	btp->dev    = bdev->v_rdev;
33238494Sobrien	btp->specvp = bdev;
33338494Sobrien	return btp;
33438494Sobrien}
33538494Sobrien