123396Smckusick /* 237736Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337736Smckusick * All rights reserved. 423396Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*51486Sbostic * @(#)lfs_balloc.c 7.18 (Berkeley) 11/01/91 823396Smckusick */ 97443Sroot 10*51486Sbostic #include <sys/param.h> 11*51486Sbostic #include <sys/buf.h> 12*51486Sbostic #include <sys/proc.h> 13*51486Sbostic #include <sys/vnode.h> 14*51486Sbostic #include <sys/mount.h> 15*51486Sbostic #include <sys/resourcevar.h> 16*51486Sbostic #include <sys/specdev.h> 17*51486Sbostic #include <sys/trace.h> 187443Sroot 19*51486Sbostic #include <ufs/quota.h> 20*51486Sbostic #include <ufs/inode.h> 21*51486Sbostic #include <ufs/ufsmount.h> 2247571Skarels 23*51486Sbostic #include <lfs/lfs.h> 24*51486Sbostic #include <lfs/lfs_extern.h> 25*51486Sbostic 267443Sroot /* 27*51486Sbostic * Bmap converts a the logical block number of a file to its physical block 28*51486Sbostic * number on the disk. The conversion is done by using the logical block 29*51486Sbostic * number to index into the array of block pointers described by the dinode. 307443Sroot */ 3151348Sroot int 3251155Sbostic lfs_bmap(ip, bn, bnp) 337443Sroot register struct inode *ip; 3437736Smckusick register daddr_t bn; 3537736Smckusick daddr_t *bnp; 367443Sroot { 37*51486Sbostic register LFS *fs; 3837736Smckusick register daddr_t nb; 3951183Sbostic struct vnode *devvp, *vp; 4037736Smckusick struct buf *bp; 4151183Sbostic daddr_t *bap, daddr; 4251183Sbostic daddr_t lbn_ind; 4351348Sroot int j, off, sh; 4437736Smckusick int error; 4537736Smckusick 4651155Sbostic printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number); 47*51486Sbostic fs = ip->i_lfs; 4837736Smckusick 4937736Smckusick /* 50*51486Sbostic * We access all blocks in the cache, even indirect blocks by means 51*51486Sbostic * of a logical address. Indirect blocks (single, double, triple) all 52*51486Sbostic * have negative block numbers. The first NDADDR blocks are direct 53*51486Sbostic * blocks, the first NIADDR negative blocks are the indirect block 54*51486Sbostic * pointers. The single, double and triple indirect blocks in the 55*51486Sbostic * inode * are addressed: -1, -2 and -3 respectively. 56*51486Sbostic * 57*51486Sbostic * XXX 58*51486Sbostic * We don't handle triple indirect at all. 59*51486Sbostic * 60*51486Sbostic * XXX 61*51486Sbostic * This panic shouldn't be here??? 6251183Sbostic */ 63*51486Sbostic if (bn < 0) 64*51486Sbostic panic("lfs_bmap: negative indirect block number %d", bn); 6551183Sbostic 66*51486Sbostic /* The first NDADDR blocks are direct blocks. */ 6737736Smckusick if (bn < NDADDR) { 6837736Smckusick nb = ip->i_db[bn]; 6937736Smckusick if (nb == 0) { 7051348Sroot *bnp = UNASSIGNED; 7137736Smckusick return (0); 7237736Smckusick } 7351155Sbostic *bnp = nb; 7437736Smckusick return (0); 7537736Smckusick } 76*51486Sbostic 77*51486Sbostic /* Determine the number of levels of indirection. */ 7837736Smckusick sh = 1; 7937736Smckusick bn -= NDADDR; 8051183Sbostic lbn_ind = 0; 8137736Smckusick for (j = NIADDR; j > 0; j--) { 8251183Sbostic lbn_ind--; 8337736Smckusick sh *= NINDIR(fs); 8437736Smckusick if (bn < sh) 8537736Smckusick break; 8637736Smckusick bn -= sh; 8737736Smckusick } 8837736Smckusick if (j == 0) 8937736Smckusick return (EFBIG); 9051183Sbostic 91*51486Sbostic /* Fetch through the indirect blocks. */ 9251183Sbostic vp = ITOV(ip); 9351183Sbostic devvp = VFSTOUFS(vp->v_mount)->um_devvp; 9451183Sbostic for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) { 9551183Sbostic if((daddr = bap[off]) == 0) { 9651348Sroot daddr = UNASSIGNED; 9751183Sbostic break; 9851183Sbostic } 9951183Sbostic if (bp) 10037736Smckusick brelse(bp); 10151183Sbostic bp = getblk(vp, lbn_ind, fs->lfs_bsize); 10251183Sbostic if (bp->b_flags & (B_DONE | B_DELWRI)) { 10351183Sbostic trace(TR_BREADHIT, pack(vp, size), lbn_ind); 10451183Sbostic } else { 10551183Sbostic trace(TR_BREADMISS, pack(vp, size), lbn_ind); 10651183Sbostic bp->b_blkno = daddr; 10751183Sbostic bp->b_flags |= B_READ; 10851183Sbostic bp->b_dev = devvp->v_rdev; 10951215Sbostic (devvp->v_op->vop_strategy)(bp); 11051183Sbostic curproc->p_stats->p_ru.ru_inblock++; /* XXX */ 11151183Sbostic if (error = biowait(bp)) { 11251183Sbostic brelse(bp); 11351183Sbostic return (error); 11451183Sbostic } 11537736Smckusick } 11637736Smckusick bap = bp->b_un.b_daddr; 11737736Smckusick sh /= NINDIR(fs); 11851183Sbostic off = (bn / sh) % NINDIR(fs); 11951183Sbostic lbn_ind = -(NIADDR + 1 + off); 12051183Sbostic } 12151183Sbostic if (bp) 12239679Smckusick brelse(bp); 12351183Sbostic 12451183Sbostic *bnp = daddr; 12537736Smckusick return (0); 12637736Smckusick } 127