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*51183Sbostic * @(#)lfs_balloc.c 7.15 (Berkeley) 09/25/91 823396Smckusick */ 97443Sroot 1017099Sbloom #include "param.h" 1117099Sbloom #include "systm.h" 1217099Sbloom #include "buf.h" 13*51183Sbostic #include "time.h" 14*51183Sbostic #include "resource.h" 15*51183Sbostic #include "resourcevar.h" 1617099Sbloom #include "proc.h" 1737736Smckusick #include "file.h" 1837736Smckusick #include "vnode.h" 19*51183Sbostic #include "mount.h" 20*51183Sbostic #include "specdev.h" 217443Sroot 2251155Sbostic #include "../ufs/quota.h" 2351155Sbostic #include "../ufs/inode.h" 24*51183Sbostic #include "../ufs/ufsmount.h" 25*51183Sbostic #include "trace.h" 2651155Sbostic #include "lfs.h" 2751155Sbostic #include "lfs_extern.h" 2847571Skarels 297443Sroot /* 3049450Smckusick * Bmap converts a the logical block number of a file 3149450Smckusick * to its physical block number on the disk. The conversion 3249450Smckusick * is done by using the logical block number to index into 3349450Smckusick * the array of block pointers described by the dinode. 347443Sroot */ 3551155Sbostic lfs_bmap(ip, bn, bnp) 367443Sroot register struct inode *ip; 3737736Smckusick register daddr_t bn; 3837736Smckusick daddr_t *bnp; 397443Sroot { 4051155Sbostic register LFS *fs; /* LFS */ 4137736Smckusick register daddr_t nb; 42*51183Sbostic struct vnode *devvp, *vp; 4337736Smckusick struct buf *bp; 44*51183Sbostic daddr_t *bap, daddr; 45*51183Sbostic daddr_t lbn_ind; 46*51183Sbostic int i, j, off, sh; 4737736Smckusick int error; 4837736Smckusick 4951155Sbostic printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number); 5051155Sbostic fs = ip->i_lfs; /* LFS */ 5137736Smckusick 5237736Smckusick /* 53*51183Sbostic * We access all blocks in the cache, even indirect blocks by means of 54*51183Sbostic * a logical address. Indirect blocks (single, double, triple) all have 55*51183Sbostic * negative block numbers. The first NDADDR blocks are direct blocks, 56*51183Sbostic * the first NIADDR negative blocks are the indirect block pointers. 57*51183Sbostic * The single, double and triple indirect blocks in the inode 58*51183Sbostic * are addressed: -1, -2 and -3 respectively. 59*51183Sbostic * XXX we don't handle triple indirect at all. 60*51183Sbostic */ 61*51183Sbostic if (bn < 0) { 62*51183Sbostic /* Shouldn't be here -- we don't think */ 63*51183Sbostic printf("lfs_bmap: NEGATIVE indirect block number %d\n", bn); 64*51183Sbostic panic("negative indirect block number"); 65*51183Sbostic } 66*51183Sbostic 67*51183Sbostic /* 6837736Smckusick * The first NDADDR blocks are direct blocks 6937736Smckusick */ 7037736Smckusick if (bn < NDADDR) { 7137736Smckusick nb = ip->i_db[bn]; 7237736Smckusick if (nb == 0) { 7337736Smckusick *bnp = (daddr_t)-1; 7437736Smckusick return (0); 7537736Smckusick } 7651155Sbostic *bnp = nb; 7737736Smckusick return (0); 7837736Smckusick } 7937736Smckusick /* 8039679Smckusick * Determine the number of levels of indirection. 8137736Smckusick */ 8237736Smckusick sh = 1; 8337736Smckusick bn -= NDADDR; 84*51183Sbostic lbn_ind = 0; 8537736Smckusick for (j = NIADDR; j > 0; j--) { 86*51183Sbostic lbn_ind--; 8737736Smckusick sh *= NINDIR(fs); 8837736Smckusick if (bn < sh) 8937736Smckusick break; 9037736Smckusick bn -= sh; 9137736Smckusick } 9237736Smckusick if (j == 0) 9337736Smckusick return (EFBIG); 9437736Smckusick /* 9539679Smckusick * Fetch through the indirect blocks. 9637736Smckusick */ 97*51183Sbostic 98*51183Sbostic vp = ITOV(ip); 99*51183Sbostic devvp = VFSTOUFS(vp->v_mount)->um_devvp; 100*51183Sbostic for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) { 101*51183Sbostic if((daddr = bap[off]) == 0) { 102*51183Sbostic daddr = (daddr_t)-1; 103*51183Sbostic break; 104*51183Sbostic } 105*51183Sbostic if (bp) 10637736Smckusick brelse(bp); 107*51183Sbostic bp = getblk(vp, lbn_ind, fs->lfs_bsize); 108*51183Sbostic if (bp->b_flags & (B_DONE | B_DELWRI)) { 109*51183Sbostic trace(TR_BREADHIT, pack(vp, size), lbn_ind); 110*51183Sbostic } else { 111*51183Sbostic trace(TR_BREADMISS, pack(vp, size), lbn_ind); 112*51183Sbostic bp->b_blkno = daddr; 113*51183Sbostic bp->b_flags |= B_READ; 114*51183Sbostic bp->b_dev = devvp->v_rdev; 115*51183Sbostic (*(devvp->v_op->vop_strategy))(bp); 116*51183Sbostic curproc->p_stats->p_ru.ru_inblock++; /* XXX */ 117*51183Sbostic if (error = biowait(bp)) { 118*51183Sbostic brelse(bp); 119*51183Sbostic return (error); 120*51183Sbostic } 12137736Smckusick } 12237736Smckusick bap = bp->b_un.b_daddr; 12337736Smckusick sh /= NINDIR(fs); 124*51183Sbostic off = (bn / sh) % NINDIR(fs); 125*51183Sbostic lbn_ind = -(NIADDR + 1 + off); 126*51183Sbostic } 127*51183Sbostic if (bp) 12839679Smckusick brelse(bp); 129*51183Sbostic 130*51183Sbostic *bnp = daddr; 13137736Smckusick return (0); 13237736Smckusick } 133