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