1139825Simp/*-
21541Srgrimes * Copyright (c) 1989, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes * (c) UNIX System Laboratories, Inc.
51541Srgrimes * All or some portions of this file are derived from material licensed
61541Srgrimes * to the University of California by American Telephone and Telegraph
71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with
81541Srgrimes * the permission of UNIX System Laboratories, Inc.
91541Srgrimes *
101541Srgrimes * Redistribution and use in source and binary forms, with or without
111541Srgrimes * modification, are permitted provided that the following conditions
121541Srgrimes * are met:
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in the
171541Srgrimes *    documentation and/or other materials provided with the distribution.
181541Srgrimes * 4. Neither the name of the University nor the names of its contributors
191541Srgrimes *    may be used to endorse or promote products derived from this software
201541Srgrimes *    without specific prior written permission.
211541Srgrimes *
221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321541Srgrimes * SUCH DAMAGE.
331541Srgrimes *
3422521Sdyson *	@(#)ufs_bmap.c	8.7 (Berkeley) 3/21/95
351541Srgrimes */
361541Srgrimes
37116192Sobrien#include <sys/cdefs.h>
38116192Sobrien__FBSDID("$FreeBSD$");
39116192Sobrien
401541Srgrimes#include <sys/param.h>
417430Sbde#include <sys/systm.h>
4260041Sphk#include <sys/bio.h>
431541Srgrimes#include <sys/buf.h>
441541Srgrimes#include <sys/proc.h>
451541Srgrimes#include <sys/vnode.h>
461541Srgrimes#include <sys/mount.h>
471541Srgrimes#include <sys/resourcevar.h>
4862976Smckusick#include <sys/stat.h>
491541Srgrimes
5059241Srwatson#include <ufs/ufs/extattr.h>
511541Srgrimes#include <ufs/ufs/quota.h>
521541Srgrimes#include <ufs/ufs/inode.h>
531541Srgrimes#include <ufs/ufs/ufsmount.h>
541541Srgrimes#include <ufs/ufs/ufs_extern.h>
551541Srgrimes
561541Srgrimes/*
57151657Sdelphij * Bmap converts the logical block number of a file to its physical block
581541Srgrimes * number on the disk. The conversion is done by using the logical block
591541Srgrimes * number to index into the array of block pointers described by the dinode.
601541Srgrimes */
611541Srgrimesint
621541Srgrimesufs_bmap(ap)
631541Srgrimes	struct vop_bmap_args /* {
641541Srgrimes		struct vnode *a_vp;
6596572Sphk		daddr_t a_bn;
66137726Sphk		struct bufobj **a_bop;
6796572Sphk		daddr_t *a_bnp;
681541Srgrimes		int *a_runp;
6910551Sdyson		int *a_runb;
701541Srgrimes	} */ *ap;
711541Srgrimes{
7298542Smckusick	ufs2_daddr_t blkno;
7392363Smckusick	int error;
7492363Smckusick
751541Srgrimes	/*
761541Srgrimes	 * Check for underlying vnode requests and ensure that logical
771541Srgrimes	 * to physical mapping is requested.
781541Srgrimes	 */
79137726Sphk	if (ap->a_bop != NULL)
80137726Sphk		*ap->a_bop = &VTOI(ap->a_vp)->i_devvp->v_bufobj;
811541Srgrimes	if (ap->a_bnp == NULL)
821541Srgrimes		return (0);
831541Srgrimes
84100344Smckusick	error = ufs_bmaparray(ap->a_vp, ap->a_bn, &blkno, NULL,
8592363Smckusick	    ap->a_runp, ap->a_runb);
8692363Smckusick	*ap->a_bnp = blkno;
8792363Smckusick	return (error);
881541Srgrimes}
891541Srgrimes
901541Srgrimes/*
911541Srgrimes * Indirect blocks are now on the vnode for the file.  They are given negative
921541Srgrimes * logical block numbers.  Indirect blocks are addressed by the negative
931541Srgrimes * address of the first data block to which they point.  Double indirect blocks
941541Srgrimes * are addressed by one less than the address of the first indirect block to
951541Srgrimes * which they point.  Triple indirect blocks are addressed by one less than
961541Srgrimes * the address of the first double indirect block to which they point.
971541Srgrimes *
981541Srgrimes * ufs_bmaparray does the bmap conversion, and if requested returns the
991541Srgrimes * array of logical blocks which must be traversed to get to a block.
1001541Srgrimes * Each entry contains the offset into that block that gets you to the
1011541Srgrimes * next block and the disk address of the block (if it is assigned).
1021541Srgrimes */
1031541Srgrimes
1041541Srgrimesint
105100344Smckusickufs_bmaparray(vp, bn, bnp, nbp, runp, runb)
1061541Srgrimes	struct vnode *vp;
10798542Smckusick	ufs2_daddr_t bn;
10898542Smckusick	ufs2_daddr_t *bnp;
109100344Smckusick	struct buf *nbp;
1101541Srgrimes	int *runp;
11110551Sdyson	int *runb;
1121541Srgrimes{
11396506Sphk	struct inode *ip;
1141541Srgrimes	struct buf *bp;
1151541Srgrimes	struct ufsmount *ump;
1161541Srgrimes	struct mount *mp;
1171541Srgrimes	struct vnode *devvp;
11876128Sphk	struct indir a[NIADDR+1], *ap;
11998542Smckusick	ufs2_daddr_t daddr;
12098542Smckusick	ufs_lbn_t metalbn;
12162976Smckusick	int error, num, maxrun = 0;
12276128Sphk	int *nump;
1231541Srgrimes
12476128Sphk	ap = NULL;
1251541Srgrimes	ip = VTOI(vp);
1261541Srgrimes	mp = vp->v_mount;
1271541Srgrimes	ump = VFSTOUFS(mp);
12851483Sphk	devvp = ump->um_devvp;
1291541Srgrimes
1301541Srgrimes	if (runp) {
13162976Smckusick		maxrun = mp->mnt_iosize_max / mp->mnt_stat.f_iosize - 1;
13232724Sdyson		*runp = 0;
13332724Sdyson	}
13432724Sdyson
13532724Sdyson	if (runb) {
13632724Sdyson		*runb = 0;
13732724Sdyson	}
13832724Sdyson
13932724Sdyson
14076128Sphk	ap = a;
14176128Sphk	nump = &num;
14276128Sphk	error = ufs_getlbns(vp, bn, ap, nump);
1433427Sphk	if (error)
1441541Srgrimes		return (error);
1451541Srgrimes
1461541Srgrimes	num = *nump;
1471541Srgrimes	if (num == 0) {
148100344Smckusick		if (bn >= 0 && bn < NDADDR) {
149100344Smckusick			*bnp = blkptrtodb(ump, DIP(ip, i_db[bn]));
150100344Smckusick		} else if (bn < 0 && bn >= -NXADDR) {
151100344Smckusick			*bnp = blkptrtodb(ump, ip->i_din2->di_extb[-1 - bn]);
152100344Smckusick			if (*bnp == 0)
153100344Smckusick				*bnp = -1;
154100344Smckusick			if (nbp == NULL)
155100344Smckusick				panic("ufs_bmaparray: mapping ext data");
156100344Smckusick			nbp->b_xflags |= BX_ALTDATA;
157100344Smckusick			return (0);
158100344Smckusick		} else {
159100344Smckusick			panic("ufs_bmaparray: blkno out of range");
160100344Smckusick		}
16163788Smckusick		/*
16263788Smckusick		 * Since this is FFS independent code, we are out of
16363788Smckusick		 * scope for the definitions of BLK_NOCOPY and
16463788Smckusick		 * BLK_SNAP, but we do know that they will fall in
16563788Smckusick		 * the range 1..um_seqinc, so we use that test and
16663788Smckusick		 * return a request for a zeroed out buffer if attempts
16763788Smckusick		 * are made to read a BLK_NOCOPY or BLK_SNAP block.
16863788Smckusick		 */
16998542Smckusick		if ((ip->i_flags & SF_SNAPSHOT) && DIP(ip, i_db[bn]) > 0 &&
17098542Smckusick		    DIP(ip, i_db[bn]) < ump->um_seqinc) {
17163788Smckusick			*bnp = -1;
17263788Smckusick		} else if (*bnp == 0) {
17362976Smckusick			if (ip->i_flags & SF_SNAPSHOT)
17462976Smckusick				*bnp = blkptrtodb(ump, bn * ump->um_seqinc);
17562976Smckusick			else
17662976Smckusick				*bnp = -1;
17762976Smckusick		} else if (runp) {
17898542Smckusick			ufs2_daddr_t bnb = bn;
1791541Srgrimes			for (++bn; bn < NDADDR && *runp < maxrun &&
18098542Smckusick			    is_sequential(ump, DIP(ip, i_db[bn - 1]),
18198542Smckusick			    DIP(ip, i_db[bn]));
1821541Srgrimes			    ++bn, ++*runp);
18310551Sdyson			bn = bnb;
18410551Sdyson			if (runb && (bn > 0)) {
18510551Sdyson				for (--bn; (bn >= 0) && (*runb < maxrun) &&
18698542Smckusick					is_sequential(ump, DIP(ip, i_db[bn]),
18798542Smckusick						DIP(ip, i_db[bn+1]));
18810551Sdyson						--bn, ++*runb);
18910551Sdyson			}
19010551Sdyson		}
1911541Srgrimes		return (0);
1921541Srgrimes	}
1931541Srgrimes
1941541Srgrimes
1951541Srgrimes	/* Get disk address out of indirect block array */
19698542Smckusick	daddr = DIP(ip, i_ib[ap->in_off]);
1971541Srgrimes
19876128Sphk	for (bp = NULL, ++ap; --num; ++ap) {
1998876Srgrimes		/*
2001541Srgrimes		 * Exit the loop if there is no disk address assigned yet and
2011541Srgrimes		 * the indirect block isn't in the cache, or if we were
2021541Srgrimes		 * looking for an indirect block and we've found it.
2031541Srgrimes		 */
2041541Srgrimes
20576128Sphk		metalbn = ap->in_lbn;
206136767Sphk		if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn)
2071541Srgrimes			break;
2081541Srgrimes		/*
2091541Srgrimes		 * If we get here, we've either got the block in the cache
2101541Srgrimes		 * or we have a disk address for it, go fetch it.
2111541Srgrimes		 */
2121541Srgrimes		if (bp)
21313490Sdyson			bqrelse(bp);
2141541Srgrimes
215111856Sjeff		bp = getblk(vp, metalbn, mp->mnt_stat.f_iosize, 0, 0, 0);
2166875Sdg		if ((bp->b_flags & B_CACHE) == 0) {
217173464Sobrien#ifdef INVARIANTS
2186875Sdg			if (!daddr)
21923562Smpp				panic("ufs_bmaparray: indirect block not in cache");
2201541Srgrimes#endif
2211541Srgrimes			bp->b_blkno = blkptrtodb(ump, daddr);
22258345Sphk			bp->b_iocmd = BIO_READ;
22358934Sphk			bp->b_flags &= ~B_INVAL;
22458934Sphk			bp->b_ioflags &= ~BIO_ERROR;
2255455Sdg			vfs_busy_pages(bp, 0);
226121205Sphk			bp->b_iooffset = dbtob(bp->b_blkno);
227136927Sphk			bstrategy(bp);
228170174Sjeff			curthread->td_ru.ru_inblock++;
22959762Sphk			error = bufwait(bp);
2303427Sphk			if (error) {
2311541Srgrimes				brelse(bp);
2321541Srgrimes				return (error);
2331541Srgrimes			}
2341541Srgrimes		}
2351541Srgrimes
23698542Smckusick		if (ip->i_ump->um_fstype == UFS1) {
23798542Smckusick			daddr = ((ufs1_daddr_t *)bp->b_data)[ap->in_off];
23898542Smckusick			if (num == 1 && daddr && runp) {
23998542Smckusick				for (bn = ap->in_off + 1;
24098542Smckusick				    bn < MNINDIR(ump) && *runp < maxrun &&
24198542Smckusick				    is_sequential(ump,
24298542Smckusick				    ((ufs1_daddr_t *)bp->b_data)[bn - 1],
24398542Smckusick				    ((ufs1_daddr_t *)bp->b_data)[bn]);
24498542Smckusick				    ++bn, ++*runp);
24598542Smckusick				bn = ap->in_off;
24698542Smckusick				if (runb && bn) {
24798542Smckusick					for (--bn; bn >= 0 && *runb < maxrun &&
24898542Smckusick					    is_sequential(ump,
24998542Smckusick					    ((ufs1_daddr_t *)bp->b_data)[bn],
25098542Smckusick					    ((ufs1_daddr_t *)bp->b_data)[bn+1]);
25198542Smckusick					    --bn, ++*runb);
25298542Smckusick				}
25398542Smckusick			}
25498542Smckusick			continue;
25598542Smckusick		}
25698542Smckusick		daddr = ((ufs2_daddr_t *)bp->b_data)[ap->in_off];
25710551Sdyson		if (num == 1 && daddr && runp) {
25876128Sphk			for (bn = ap->in_off + 1;
2591541Srgrimes			    bn < MNINDIR(ump) && *runp < maxrun &&
26022521Sdyson			    is_sequential(ump,
26198542Smckusick			    ((ufs2_daddr_t *)bp->b_data)[bn - 1],
26298542Smckusick			    ((ufs2_daddr_t *)bp->b_data)[bn]);
2631541Srgrimes			    ++bn, ++*runp);
26476128Sphk			bn = ap->in_off;
26510551Sdyson			if (runb && bn) {
26698542Smckusick				for (--bn; bn >= 0 && *runb < maxrun &&
26798542Smckusick				    is_sequential(ump,
26898542Smckusick				    ((ufs2_daddr_t *)bp->b_data)[bn],
26998542Smckusick				    ((ufs2_daddr_t *)bp->b_data)[bn + 1]);
27098542Smckusick				    --bn, ++*runb);
27110551Sdyson			}
27210551Sdyson		}
2731541Srgrimes	}
2741541Srgrimes	if (bp)
27513490Sdyson		bqrelse(bp);
2761541Srgrimes
27763788Smckusick	/*
27863788Smckusick	 * Since this is FFS independent code, we are out of scope for the
27963788Smckusick	 * definitions of BLK_NOCOPY and BLK_SNAP, but we do know that they
28063788Smckusick	 * will fall in the range 1..um_seqinc, so we use that test and
28163788Smckusick	 * return a request for a zeroed out buffer if attempts are made
28263788Smckusick	 * to read a BLK_NOCOPY or BLK_SNAP block.
28363788Smckusick	 */
28463788Smckusick	if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc){
28563788Smckusick		*bnp = -1;
28663788Smckusick		return (0);
28763788Smckusick	}
28862976Smckusick	*bnp = blkptrtodb(ump, daddr);
28962976Smckusick	if (*bnp == 0) {
29062976Smckusick		if (ip->i_flags & SF_SNAPSHOT)
29162976Smckusick			*bnp = blkptrtodb(ump, bn * ump->um_seqinc);
29262976Smckusick		else
29362976Smckusick			*bnp = -1;
29462976Smckusick	}
2951541Srgrimes	return (0);
2961541Srgrimes}
2971541Srgrimes
2981541Srgrimes/*
2991541Srgrimes * Create an array of logical block number/offset pairs which represent the
3001541Srgrimes * path of indirect blocks required to access a data block.  The first "pair"
3011541Srgrimes * contains the logical block number of the appropriate single, double or
3021541Srgrimes * triple indirect block and the offset into the inode indirect block array.
3031541Srgrimes * Note, the logical block number of the inode single/double/triple indirect
3041541Srgrimes * block appears twice in the array, once with the offset into the i_ib and
3051541Srgrimes * once with the offset into the page itself.
3061541Srgrimes */
3071541Srgrimesint
3081541Srgrimesufs_getlbns(vp, bn, ap, nump)
3091541Srgrimes	struct vnode *vp;
31098542Smckusick	ufs2_daddr_t bn;
3111541Srgrimes	struct indir *ap;
3121541Srgrimes	int *nump;
3131541Srgrimes{
31498542Smckusick	ufs2_daddr_t blockcnt;
31598542Smckusick	ufs_lbn_t metalbn, realbn;
3161541Srgrimes	struct ufsmount *ump;
31731394Sbde	int i, numlevels, off;
3181541Srgrimes
3191541Srgrimes	ump = VFSTOUFS(vp->v_mount);
3201541Srgrimes	if (nump)
3211541Srgrimes		*nump = 0;
3221541Srgrimes	numlevels = 0;
3231541Srgrimes	realbn = bn;
32498542Smckusick	if (bn < 0)
32598542Smckusick		bn = -bn;
3261541Srgrimes
3271541Srgrimes	/* The first NDADDR blocks are direct blocks. */
3281541Srgrimes	if (bn < NDADDR)
3291541Srgrimes		return (0);
3301541Srgrimes
3318876Srgrimes	/*
3321541Srgrimes	 * Determine the number of levels of indirection.  After this loop
3331541Srgrimes	 * is done, blockcnt indicates the number of data blocks possible
33431394Sbde	 * at the previous level of indirection, and NIADDR - i is the number
3351541Srgrimes	 * of levels of indirection needed to locate the requested block.
3361541Srgrimes	 */
3371541Srgrimes	for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
3381541Srgrimes		if (i == 0)
3391541Srgrimes			return (EFBIG);
34098542Smckusick		blockcnt *= MNINDIR(ump);
34198542Smckusick		if (bn < blockcnt)
3421541Srgrimes			break;
3431541Srgrimes	}
3441541Srgrimes
3451541Srgrimes	/* Calculate the address of the first meta-block. */
3461541Srgrimes	if (realbn >= 0)
3471541Srgrimes		metalbn = -(realbn - bn + NIADDR - i);
3481541Srgrimes	else
3491541Srgrimes		metalbn = -(-realbn - bn + NIADDR - i);
3501541Srgrimes
3518876Srgrimes	/*
3521541Srgrimes	 * At each iteration, off is the offset into the bap array which is
3531541Srgrimes	 * an array of disk addresses at the current level of indirection.
3541541Srgrimes	 * The logical block number and the offset in that block are stored
3551541Srgrimes	 * into the argument array.
3561541Srgrimes	 */
3571541Srgrimes	ap->in_lbn = metalbn;
3581541Srgrimes	ap->in_off = off = NIADDR - i;
3591541Srgrimes	ap++;
3601541Srgrimes	for (++numlevels; i <= NIADDR; i++) {
3611541Srgrimes		/* If searching for a meta-data block, quit when found. */
3621541Srgrimes		if (metalbn == realbn)
3631541Srgrimes			break;
3641541Srgrimes
36598542Smckusick		blockcnt /= MNINDIR(ump);
3661541Srgrimes		off = (bn / blockcnt) % MNINDIR(ump);
3671541Srgrimes
3681541Srgrimes		++numlevels;
3691541Srgrimes		ap->in_lbn = metalbn;
3701541Srgrimes		ap->in_off = off;
3711541Srgrimes		++ap;
3721541Srgrimes
3731541Srgrimes		metalbn -= -1 + off * blockcnt;
3741541Srgrimes	}
3751541Srgrimes	if (nump)
3761541Srgrimes		*nump = numlevels;
3771541Srgrimes	return (0);
3781541Srgrimes}
379