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