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*51215Sbostic * @(#)lfs_balloc.c 7.16 (Berkeley) 10/02/91 823396Smckusick */ 97443Sroot 10*51215Sbostic #ifdef LOGFS 1117099Sbloom #include "param.h" 1217099Sbloom #include "systm.h" 1317099Sbloom #include "buf.h" 1451183Sbostic #include "time.h" 1551183Sbostic #include "resource.h" 1651183Sbostic #include "resourcevar.h" 1717099Sbloom #include "proc.h" 1837736Smckusick #include "file.h" 1937736Smckusick #include "vnode.h" 2051183Sbostic #include "mount.h" 2151183Sbostic #include "specdev.h" 227443Sroot 2351155Sbostic #include "../ufs/quota.h" 2451155Sbostic #include "../ufs/inode.h" 2551183Sbostic #include "../ufs/ufsmount.h" 2651183Sbostic #include "trace.h" 2751155Sbostic #include "lfs.h" 2851155Sbostic #include "lfs_extern.h" 2947571Skarels 307443Sroot /* 3149450Smckusick * Bmap converts a the logical block number of a file 3249450Smckusick * to its physical block number on the disk. The conversion 3349450Smckusick * is done by using the logical block number to index into 3449450Smckusick * the array of block pointers described by the dinode. 357443Sroot */ 3651155Sbostic lfs_bmap(ip, bn, bnp) 377443Sroot register struct inode *ip; 3837736Smckusick register daddr_t bn; 3937736Smckusick daddr_t *bnp; 407443Sroot { 4151155Sbostic register LFS *fs; /* LFS */ 4237736Smckusick register daddr_t nb; 4351183Sbostic struct vnode *devvp, *vp; 4437736Smckusick struct buf *bp; 4551183Sbostic daddr_t *bap, daddr; 4651183Sbostic daddr_t lbn_ind; 4751183Sbostic int i, j, off, sh; 4837736Smckusick int error; 4937736Smckusick 5051155Sbostic printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number); 5151155Sbostic fs = ip->i_lfs; /* LFS */ 5237736Smckusick 5337736Smckusick /* 5451183Sbostic * We access all blocks in the cache, even indirect blocks by means of 5551183Sbostic * a logical address. Indirect blocks (single, double, triple) all have 5651183Sbostic * negative block numbers. The first NDADDR blocks are direct blocks, 5751183Sbostic * the first NIADDR negative blocks are the indirect block pointers. 5851183Sbostic * The single, double and triple indirect blocks in the inode 5951183Sbostic * are addressed: -1, -2 and -3 respectively. 6051183Sbostic * XXX we don't handle triple indirect at all. 6151183Sbostic */ 6251183Sbostic if (bn < 0) { 6351183Sbostic /* Shouldn't be here -- we don't think */ 6451183Sbostic printf("lfs_bmap: NEGATIVE indirect block number %d\n", bn); 6551183Sbostic panic("negative indirect block number"); 6651183Sbostic } 6751183Sbostic 6851183Sbostic /* 6937736Smckusick * The first NDADDR blocks are direct blocks 7037736Smckusick */ 7137736Smckusick if (bn < NDADDR) { 7237736Smckusick nb = ip->i_db[bn]; 7337736Smckusick if (nb == 0) { 7437736Smckusick *bnp = (daddr_t)-1; 7537736Smckusick return (0); 7637736Smckusick } 7751155Sbostic *bnp = nb; 7837736Smckusick return (0); 7937736Smckusick } 8037736Smckusick /* 8139679Smckusick * Determine the number of levels of indirection. 8237736Smckusick */ 8337736Smckusick sh = 1; 8437736Smckusick bn -= NDADDR; 8551183Sbostic lbn_ind = 0; 8637736Smckusick for (j = NIADDR; j > 0; j--) { 8751183Sbostic lbn_ind--; 8837736Smckusick sh *= NINDIR(fs); 8937736Smckusick if (bn < sh) 9037736Smckusick break; 9137736Smckusick bn -= sh; 9237736Smckusick } 9337736Smckusick if (j == 0) 9437736Smckusick return (EFBIG); 9537736Smckusick /* 9639679Smckusick * Fetch through the indirect blocks. 9737736Smckusick */ 9851183Sbostic 9951183Sbostic vp = ITOV(ip); 10051183Sbostic devvp = VFSTOUFS(vp->v_mount)->um_devvp; 10151183Sbostic for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) { 10251183Sbostic if((daddr = bap[off]) == 0) { 10351183Sbostic daddr = (daddr_t)-1; 10451183Sbostic break; 10551183Sbostic } 10651183Sbostic if (bp) 10737736Smckusick brelse(bp); 10851183Sbostic bp = getblk(vp, lbn_ind, fs->lfs_bsize); 10951183Sbostic if (bp->b_flags & (B_DONE | B_DELWRI)) { 11051183Sbostic trace(TR_BREADHIT, pack(vp, size), lbn_ind); 11151183Sbostic } else { 11251183Sbostic trace(TR_BREADMISS, pack(vp, size), lbn_ind); 11351183Sbostic bp->b_blkno = daddr; 11451183Sbostic bp->b_flags |= B_READ; 11551183Sbostic bp->b_dev = devvp->v_rdev; 116*51215Sbostic (devvp->v_op->vop_strategy)(bp); 11751183Sbostic curproc->p_stats->p_ru.ru_inblock++; /* XXX */ 11851183Sbostic if (error = biowait(bp)) { 11951183Sbostic brelse(bp); 12051183Sbostic return (error); 12151183Sbostic } 12237736Smckusick } 12337736Smckusick bap = bp->b_un.b_daddr; 12437736Smckusick sh /= NINDIR(fs); 12551183Sbostic off = (bn / sh) % NINDIR(fs); 12651183Sbostic lbn_ind = -(NIADDR + 1 + off); 12751183Sbostic } 12851183Sbostic if (bp) 12939679Smckusick brelse(bp); 13051183Sbostic 13151183Sbostic *bnp = daddr; 13237736Smckusick return (0); 13337736Smckusick } 134*51215Sbostic #endif /* LOGFS */ 135