Commit | Line | Data |
---|---|---|
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 | 35 | lfs_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 | 49 | printf("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 | } |