123396Smckusick /* 251494Sbostic * Copyright (c) 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*51561Smckusick * @(#)lfs_balloc.c 7.20 (Berkeley) 11/05/91 823396Smckusick */ 97443Sroot 1051486Sbostic #include <sys/param.h> 1151486Sbostic #include <sys/buf.h> 1251486Sbostic #include <sys/proc.h> 1351486Sbostic #include <sys/vnode.h> 1451486Sbostic #include <sys/mount.h> 1551486Sbostic #include <sys/resourcevar.h> 1651486Sbostic #include <sys/specdev.h> 1751486Sbostic #include <sys/trace.h> 187443Sroot 1951494Sbostic #include <ufs/ufs/quota.h> 2051494Sbostic #include <ufs/ufs/inode.h> 2151494Sbostic #include <ufs/ufs/ufsmount.h> 2247571Skarels 2351494Sbostic #include <ufs/lfs/lfs.h> 2451494Sbostic #include <ufs/lfs/lfs_extern.h> 2551486Sbostic 267443Sroot /* 2751486Sbostic * Bmap converts a the logical block number of a file to its physical block 2851486Sbostic * number on the disk. The conversion is done by using the logical block 2951486Sbostic * number to index into the array of block pointers described by the dinode. 307443Sroot */ 3151348Sroot int 32*51561Smckusick lfs_bmap(vp, bn, vpp, bnp) 33*51561Smckusick struct vnode *vp; 3437736Smckusick register daddr_t bn; 35*51561Smckusick struct vnode **vpp; 36*51561Smckusick daddr_t *bnp; 377443Sroot { 38*51561Smckusick register struct inode *ip; 3951494Sbostic register struct lfs *fs; 4037736Smckusick register daddr_t nb; 41*51561Smckusick struct vnode *devvp; 4237736Smckusick struct buf *bp; 4351183Sbostic daddr_t *bap, daddr; 4451183Sbostic daddr_t lbn_ind; 4551348Sroot int j, off, sh; 4637736Smckusick int error; 4737736Smckusick 48*51561Smckusick /* 49*51561Smckusick * Check for underlying vnode requests and ensure that logical 50*51561Smckusick * to physical mapping is requested. 51*51561Smckusick */ 52*51561Smckusick ip = VTOI(vp); 53*51561Smckusick if (vpp != NULL) 54*51561Smckusick *vpp = ip->i_devvp; 55*51561Smckusick if (bnp == NULL) 56*51561Smckusick return (0); 5751155Sbostic printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number); 5851486Sbostic fs = ip->i_lfs; 5937736Smckusick 6037736Smckusick /* 6151486Sbostic * We access all blocks in the cache, even indirect blocks by means 6251486Sbostic * of a logical address. Indirect blocks (single, double, triple) all 6351486Sbostic * have negative block numbers. The first NDADDR blocks are direct 6451486Sbostic * blocks, the first NIADDR negative blocks are the indirect block 6551486Sbostic * pointers. The single, double and triple indirect blocks in the 6651486Sbostic * inode * are addressed: -1, -2 and -3 respectively. 6751486Sbostic * 6851486Sbostic * XXX 6951486Sbostic * We don't handle triple indirect at all. 7051486Sbostic * 7151486Sbostic * XXX 7251486Sbostic * This panic shouldn't be here??? 7351183Sbostic */ 7451486Sbostic if (bn < 0) 7551486Sbostic panic("lfs_bmap: negative indirect block number %d", bn); 7651183Sbostic 7751486Sbostic /* The first NDADDR blocks are direct blocks. */ 7837736Smckusick if (bn < NDADDR) { 7937736Smckusick nb = ip->i_db[bn]; 8037736Smckusick if (nb == 0) { 8151348Sroot *bnp = UNASSIGNED; 8237736Smckusick return (0); 8337736Smckusick } 8451155Sbostic *bnp = nb; 8537736Smckusick return (0); 8637736Smckusick } 8751486Sbostic 8851486Sbostic /* Determine the number of levels of indirection. */ 8937736Smckusick sh = 1; 9037736Smckusick bn -= NDADDR; 9151183Sbostic lbn_ind = 0; 9237736Smckusick for (j = NIADDR; j > 0; j--) { 9351183Sbostic lbn_ind--; 9437736Smckusick sh *= NINDIR(fs); 9537736Smckusick if (bn < sh) 9637736Smckusick break; 9737736Smckusick bn -= sh; 9837736Smckusick } 9937736Smckusick if (j == 0) 10037736Smckusick return (EFBIG); 10151183Sbostic 10251486Sbostic /* Fetch through the indirect blocks. */ 10351183Sbostic vp = ITOV(ip); 10451183Sbostic devvp = VFSTOUFS(vp->v_mount)->um_devvp; 10551183Sbostic for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) { 10651183Sbostic if((daddr = bap[off]) == 0) { 10751348Sroot daddr = UNASSIGNED; 10851183Sbostic break; 10951183Sbostic } 11051183Sbostic if (bp) 11137736Smckusick brelse(bp); 11251183Sbostic bp = getblk(vp, lbn_ind, fs->lfs_bsize); 11351183Sbostic if (bp->b_flags & (B_DONE | B_DELWRI)) { 11451183Sbostic trace(TR_BREADHIT, pack(vp, size), lbn_ind); 11551183Sbostic } else { 11651183Sbostic trace(TR_BREADMISS, pack(vp, size), lbn_ind); 11751183Sbostic bp->b_blkno = daddr; 11851183Sbostic bp->b_flags |= B_READ; 11951183Sbostic bp->b_dev = devvp->v_rdev; 12051215Sbostic (devvp->v_op->vop_strategy)(bp); 12151183Sbostic curproc->p_stats->p_ru.ru_inblock++; /* XXX */ 12251183Sbostic if (error = biowait(bp)) { 12351183Sbostic brelse(bp); 12451183Sbostic return (error); 12551183Sbostic } 12637736Smckusick } 12737736Smckusick bap = bp->b_un.b_daddr; 12837736Smckusick sh /= NINDIR(fs); 12951183Sbostic off = (bn / sh) % NINDIR(fs); 13051183Sbostic lbn_ind = -(NIADDR + 1 + off); 13151183Sbostic } 13251183Sbostic if (bp) 13339679Smckusick brelse(bp); 13451183Sbostic 13551183Sbostic *bnp = daddr; 13637736Smckusick return (0); 13737736Smckusick } 138