LFS version 2; minor cleanups, nothing important
[unix-history] / usr / src / sys / ufs / lfs / lfs_balloc.c
CommitLineData
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 *
175a033b 7 * @(#)lfs_balloc.c 7.22 (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.
fce00cda
KB
30 *
31 * LFS has a different version of bmap from FFS because of a naming conflict.
32 * In FFS, meta blocks are given real disk addresses at allocation time, and
33 * are linked into the device vnode, using a logical block number which is
34 * the same as the physical block number. This can't be done by LFS because
35 * blocks aren't given disk addresses until they're written, so there's no
36 * way to distinguish the meta-data blocks for one file from any other file.
37 * This means that meta-data blocks have to be on the vnode for the file so
38 * they can be found, and have to have "names" different from the standard
39 * data blocks. To do this, we divide the name space into positive and
40 * negative block numbers, and give the meta-data blocks negative logical
175a033b
KB
41 * numbers. Indirect blocks are addressed by the negative address of the
42 * first data block to which they point. Double indirect blocks are addressed
43 * by one less than the address of the first indirect block to which they
44 * point. Triple indirect blocks are addressed by one less than the address
45 * of the first double indirect block to which they point.
52212483 46 */
e3b6a940 47int
8ad16d99
KM
48lfs_bmap(vp, bn, vpp, bnp)
49 struct vnode *vp;
7188ac27 50 register daddr_t bn;
8ad16d99
KM
51 struct vnode **vpp;
52 daddr_t *bnp;
52212483 53{
8ad16d99 54 register struct inode *ip;
9fc995cf 55 register struct lfs *fs;
7188ac27
KM
56 register daddr_t nb;
57 struct buf *bp;
fce00cda 58 struct vnode *devvp;
175a033b
KB
59 daddr_t *bap, daddr, metalbn;
60 long realbn;
61 int error, j, off, sh;
7188ac27 62
8ad16d99
KM
63 /*
64 * Check for underlying vnode requests and ensure that logical
65 * to physical mapping is requested.
66 */
67 ip = VTOI(vp);
68 if (vpp != NULL)
69 *vpp = ip->i_devvp;
70 if (bnp == NULL)
71 return (0);
d5075120 72
fce00cda
KB
73#ifdef VERBOSE
74printf("lfs_bmap: block number %d, inode %d\n", bn, ip->i_number);
75#endif
175a033b
KB
76 realbn = bn;
77 if ((long)bn < 0)
78 bn = -(long)bn;
79
f6437c6d 80 /* The first NDADDR blocks are direct blocks. */
7188ac27
KM
81 if (bn < NDADDR) {
82 nb = ip->i_db[bn];
175a033b 83 if (nb == 0) {
e3b6a940 84 *bnp = UNASSIGNED;
175a033b
KB
85 return (0);
86 }
87 *bnp = nb;
7188ac27
KM
88 return (0);
89 }
f6437c6d 90
fce00cda 91 /*
fce00cda
KB
92 * Determine the number of levels of indirection. After this loop
93 * is done, sh indicates the number of data blocks possible at the
175a033b
KB
94 * given level of indirection, and NIADDR - j is the number of levels
95 * of indirection needed to locate the requested block.
fce00cda 96 */
175a033b 97 bn -= NDADDR;
fce00cda 98 fs = ip->i_lfs;
7188ac27 99 sh = 1;
7188ac27
KM
100 for (j = NIADDR; j > 0; j--) {
101 sh *= NINDIR(fs);
102 if (bn < sh)
103 break;
104 bn -= sh;
105 }
106 if (j == 0)
107 return (EFBIG);
d5075120 108
175a033b
KB
109 /* Calculate the address of the first meta-block. */
110 if (realbn >= 0)
111 metalbn = -(realbn - bn + NIADDR - j);
112 else
113 metalbn = -(-realbn - bn + NIADDR - j);
114
fce00cda
KB
115 /*
116 * Fetch through the indirect blocks. At each iteration, off is the
117 * offset into the bap array which is an array of disk addresses at
118 * the current level of indirection.
119 */
fce00cda 120 bp = NULL;
d5075120 121 devvp = VFSTOUFS(vp->v_mount)->um_devvp;
175a033b 122 for (off = NIADDR - j, bap = ip->i_ib; j <= NIADDR; j++) {
fce00cda
KB
123 /*
124 * In LFS, it's possible to have a block appended to a file
125 * for which the meta-blocks have not yet been allocated.
126 * This is a win if the file never gets written or if the
127 * file's growing.
128 */
129 if ((daddr = bap[off]) == 0) {
e3b6a940 130 daddr = UNASSIGNED;
d5075120
KB
131 break;
132 }
175a033b
KB
133
134 /* If searching for a meta-data block, quit when found. */
135 if (metalbn == realbn)
136 break;
137
fce00cda
KB
138 /*
139 * Read in the appropriate indirect block. LFS can't do a
140 * bread because bread knows that FFS will hand it the device
141 * vnode, not the file vnode, so the b_dev and b_blkno would
142 * be wrong.
143 *
144 * XXX
145 * This REALLY needs to be fixed, at the very least it needs
146 * to be rethought when the buffer cache goes away.
147 */
d5075120 148 if (bp)
7188ac27 149 brelse(bp);
175a033b 150 bp = getblk(vp, metalbn, fs->lfs_bsize);
d5075120 151 if (bp->b_flags & (B_DONE | B_DELWRI)) {
175a033b 152 trace(TR_BREADHIT, pack(vp, size), metalbn);
d5075120 153 } else {
175a033b 154 trace(TR_BREADMISS, pack(vp, size), metalbn);
fce00cda 155 bp->b_blkno = daddr;
175a033b 156 bp->b_flags |= B_READ;
d5075120 157 bp->b_dev = devvp->v_rdev;
275ca4f0 158 (devvp->v_op->vop_strategy)(bp);
d5075120
KB
159 curproc->p_stats->p_ru.ru_inblock++; /* XXX */
160 if (error = biowait(bp)) {
161 brelse(bp);
162 return (error);
163 }
7188ac27 164 }
175a033b 165
7188ac27
KM
166 bap = bp->b_un.b_daddr;
167 sh /= NINDIR(fs);
d5075120 168 off = (bn / sh) % NINDIR(fs);
175a033b 169 metalbn -= -1 + off * sh;
7188ac27 170 }
d5075120
KB
171 if (bp)
172 brelse(bp);
173
174 *bnp = daddr;
7188ac27 175 return (0);
52212483 176}