remove back pointer to entry in tp_ref table; use tp_lref instead.
[unix-history] / usr / src / sys / ufs / lfs / lfs_balloc.c
CommitLineData
da7c5cc6 1/*
7188ac27
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
d5075120 7 * @(#)lfs_balloc.c 7.15 (Berkeley) %G%
da7c5cc6 8 */
52212483 9
94368568
JB
10#include "param.h"
11#include "systm.h"
94368568 12#include "buf.h"
d5075120
KB
13#include "time.h"
14#include "resource.h"
15#include "resourcevar.h"
94368568 16#include "proc.h"
7188ac27
KM
17#include "file.h"
18#include "vnode.h"
d5075120
KB
19#include "mount.h"
20#include "specdev.h"
c6f5111d 21
0b4d6502
KB
22#include "../ufs/quota.h"
23#include "../ufs/inode.h"
d5075120
KB
24#include "../ufs/ufsmount.h"
25#include "trace.h"
0b4d6502
KB
26#include "lfs.h"
27#include "lfs_extern.h"
52212483
BJ
28
29/*
a3257f3c
KM
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.
52212483 34 */
0b4d6502 35lfs_bmap(ip, bn, bnp)
52212483 36 register struct inode *ip;
7188ac27
KM
37 register daddr_t bn;
38 daddr_t *bnp;
52212483 39{
0b4d6502 40 register LFS *fs; /* LFS */
7188ac27 41 register daddr_t nb;
d5075120 42 struct vnode *devvp, *vp;
7188ac27 43 struct buf *bp;
d5075120
KB
44 daddr_t *bap, daddr;
45 daddr_t lbn_ind;
46 int i, j, off, sh;
7188ac27
KM
47 int error;
48
0b4d6502 49printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number);
0b4d6502 50 fs = ip->i_lfs; /* LFS */
7188ac27 51
d5075120
KB
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
7188ac27
KM
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 }
0b4d6502 76 *bnp = nb;
7188ac27
KM
77 return (0);
78 }
7188ac27 79 /*
9b392e39 80 * Determine the number of levels of indirection.
7188ac27
KM
81 */
82 sh = 1;
83 bn -= NDADDR;
d5075120 84 lbn_ind = 0;
7188ac27 85 for (j = NIADDR; j > 0; j--) {
d5075120 86 lbn_ind--;
7188ac27
KM
87 sh *= NINDIR(fs);
88 if (bn < sh)
89 break;
90 bn -= sh;
91 }
92 if (j == 0)
93 return (EFBIG);
7188ac27 94 /*
9b392e39 95 * Fetch through the indirect blocks.
7188ac27 96 */
d5075120
KB
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)
7188ac27 106 brelse(bp);
d5075120
KB
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 }
7188ac27
KM
121 }
122 bap = bp->b_un.b_daddr;
123 sh /= NINDIR(fs);
d5075120
KB
124 off = (bn / sh) % NINDIR(fs);
125 lbn_ind = -(NIADDR + 1 + off);
7188ac27 126 }
d5075120
KB
127 if (bp)
128 brelse(bp);
129
130 *bnp = daddr;
7188ac27 131 return (0);
52212483 132}