1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_balloc.c 7.16 (Berkeley) 10/02/91 8 */ 9 10 #ifdef LOGFS 11 #include "param.h" 12 #include "systm.h" 13 #include "buf.h" 14 #include "time.h" 15 #include "resource.h" 16 #include "resourcevar.h" 17 #include "proc.h" 18 #include "file.h" 19 #include "vnode.h" 20 #include "mount.h" 21 #include "specdev.h" 22 23 #include "../ufs/quota.h" 24 #include "../ufs/inode.h" 25 #include "../ufs/ufsmount.h" 26 #include "trace.h" 27 #include "lfs.h" 28 #include "lfs_extern.h" 29 30 /* 31 * Bmap converts a the logical block number of a file 32 * to its physical block number on the disk. The conversion 33 * is done by using the logical block number to index into 34 * the array of block pointers described by the dinode. 35 */ 36 lfs_bmap(ip, bn, bnp) 37 register struct inode *ip; 38 register daddr_t bn; 39 daddr_t *bnp; 40 { 41 register LFS *fs; /* LFS */ 42 register daddr_t nb; 43 struct vnode *devvp, *vp; 44 struct buf *bp; 45 daddr_t *bap, daddr; 46 daddr_t lbn_ind; 47 int i, j, off, sh; 48 int error; 49 50 printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number); 51 fs = ip->i_lfs; /* LFS */ 52 53 /* 54 * We access all blocks in the cache, even indirect blocks by means of 55 * a logical address. Indirect blocks (single, double, triple) all have 56 * negative block numbers. The first NDADDR blocks are direct blocks, 57 * the first NIADDR negative blocks are the indirect block pointers. 58 * The single, double and triple indirect blocks in the inode 59 * are addressed: -1, -2 and -3 respectively. 60 * XXX we don't handle triple indirect at all. 61 */ 62 if (bn < 0) { 63 /* Shouldn't be here -- we don't think */ 64 printf("lfs_bmap: NEGATIVE indirect block number %d\n", bn); 65 panic("negative indirect block number"); 66 } 67 68 /* 69 * The first NDADDR blocks are direct blocks 70 */ 71 if (bn < NDADDR) { 72 nb = ip->i_db[bn]; 73 if (nb == 0) { 74 *bnp = (daddr_t)-1; 75 return (0); 76 } 77 *bnp = nb; 78 return (0); 79 } 80 /* 81 * Determine the number of levels of indirection. 82 */ 83 sh = 1; 84 bn -= NDADDR; 85 lbn_ind = 0; 86 for (j = NIADDR; j > 0; j--) { 87 lbn_ind--; 88 sh *= NINDIR(fs); 89 if (bn < sh) 90 break; 91 bn -= sh; 92 } 93 if (j == 0) 94 return (EFBIG); 95 /* 96 * Fetch through the indirect blocks. 97 */ 98 99 vp = ITOV(ip); 100 devvp = VFSTOUFS(vp->v_mount)->um_devvp; 101 for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) { 102 if((daddr = bap[off]) == 0) { 103 daddr = (daddr_t)-1; 104 break; 105 } 106 if (bp) 107 brelse(bp); 108 bp = getblk(vp, lbn_ind, fs->lfs_bsize); 109 if (bp->b_flags & (B_DONE | B_DELWRI)) { 110 trace(TR_BREADHIT, pack(vp, size), lbn_ind); 111 } else { 112 trace(TR_BREADMISS, pack(vp, size), lbn_ind); 113 bp->b_blkno = daddr; 114 bp->b_flags |= B_READ; 115 bp->b_dev = devvp->v_rdev; 116 (devvp->v_op->vop_strategy)(bp); 117 curproc->p_stats->p_ru.ru_inblock++; /* XXX */ 118 if (error = biowait(bp)) { 119 brelse(bp); 120 return (error); 121 } 122 } 123 bap = bp->b_un.b_daddr; 124 sh /= NINDIR(fs); 125 off = (bn / sh) % NINDIR(fs); 126 lbn_ind = -(NIADDR + 1 + off); 127 } 128 if (bp) 129 brelse(bp); 130 131 *bnp = daddr; 132 return (0); 133 } 134 #endif /* LOGFS */ 135