This source file includes following definitions.
- ufs_bmap
- ufs_bmaparray
- ufs_getlbns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/buf.h>
43 #include <sys/proc.h>
44 #include <sys/vnode.h>
45 #include <sys/mount.h>
46 #include <sys/resourcevar.h>
47
48 #include <miscfs/specfs/specdev.h>
49
50 #include <ufs/ufs/quota.h>
51 #include <ufs/ufs/inode.h>
52 #include <ufs/ufs/ufsmount.h>
53 #include <ufs/ufs/ufs_extern.h>
54
55
56
57
58
59
60 int
61 ufs_bmap(void *v)
62 {
63 struct vop_bmap_args *ap = v;
64
65
66
67
68
69 if (ap->a_vpp != NULL)
70 *ap->a_vpp = VTOI(ap->a_vp)->i_devvp;
71 if (ap->a_bnp == NULL)
72 return (0);
73
74 return (ufs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL, NULL,
75 ap->a_runp));
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 int
92 ufs_bmaparray(struct vnode *vp, daddr_t bn, daddr64_t *bnp, struct indir *ap,
93 int *nump, int *runp)
94 {
95 struct inode *ip;
96 struct buf *bp;
97 struct ufsmount *ump;
98 struct mount *mp;
99 struct vnode *devvp;
100 struct indir a[NIADDR+1], *xap;
101 daddr64_t daddr;
102 long metalbn;
103 int error, maxrun = 0, num;
104
105 ip = VTOI(vp);
106 mp = vp->v_mount;
107 ump = VFSTOUFS(mp);
108 #ifdef DIAGNOSTIC
109 if ((ap != NULL && nump == NULL) || (ap == NULL && nump != NULL))
110 panic("ufs_bmaparray: invalid arguments");
111 #endif
112
113 if (runp) {
114
115
116
117
118
119
120 *runp = 0;
121 maxrun = MAXBSIZE / mp->mnt_stat.f_iosize - 1;
122 }
123
124 xap = ap == NULL ? a : ap;
125 if (!nump)
126 nump = #
127 if ((error = ufs_getlbns(vp, bn, xap, nump)) != 0)
128 return (error);
129
130 num = *nump;
131 if (num == 0) {
132 *bnp = blkptrtodb(ump, DIP(ip, db[bn]));
133 if (*bnp == 0)
134 *bnp = -1;
135 else if (runp)
136 for (++bn; bn < NDADDR && *runp < maxrun &&
137 is_sequential(ump, DIP(ip, db[bn - 1]),
138 DIP(ip, db[bn]));
139 ++bn, ++*runp);
140 return (0);
141 }
142
143
144
145 daddr = DIP(ip, ib[xap->in_off]);
146
147 devvp = VFSTOUFS(vp->v_mount)->um_devvp;
148 for (bp = NULL, ++xap; --num; ++xap) {
149
150
151
152
153
154
155 metalbn = xap->in_lbn;
156 if ((daddr == 0 && !incore(vp, metalbn)) || metalbn == bn)
157 break;
158
159
160
161
162 if (bp)
163 brelse(bp);
164
165 xap->in_exists = 1;
166 bp = getblk(vp, metalbn, mp->mnt_stat.f_iosize, 0, 0);
167 if (bp->b_flags & (B_DONE | B_DELWRI)) {
168 ;
169 }
170 #ifdef DIAGNOSTIC
171 else if (!daddr)
172 panic("ufs_bmaparray: indirect block not in cache");
173 #endif
174 else {
175 bp->b_blkno = blkptrtodb(ump, daddr);
176 bp->b_flags |= B_READ;
177 VOP_STRATEGY(bp);
178 curproc->p_stats->p_ru.ru_inblock++;
179 if ((error = biowait(bp)) != 0) {
180 brelse(bp);
181 return (error);
182 }
183 }
184
185 #ifdef FFS2
186 if (ip->i_ump->um_fstype == UM_UFS2) {
187 daddr = ((daddr64_t *)bp->b_data)[xap->in_off];
188 if (num == 1 && daddr && runp)
189 for (bn = xap->in_off + 1;
190 bn < MNINDIR(ump) && *runp < maxrun &&
191 is_sequential(ump,
192 ((daddr64_t *)bp->b_data)[bn - 1],
193 ((daddr64_t *)bp->b_data)[bn]);
194 ++bn, ++*runp);
195
196 continue;
197 }
198
199 #endif
200
201 daddr = ((daddr_t *)bp->b_data)[xap->in_off];
202 if (num == 1 && daddr && runp)
203 for (bn = xap->in_off + 1;
204 bn < MNINDIR(ump) && *runp < maxrun &&
205 is_sequential(ump,
206 ((daddr_t *)bp->b_data)[bn - 1],
207 ((daddr_t *)bp->b_data)[bn]);
208 ++bn, ++*runp);
209 }
210 if (bp)
211 brelse(bp);
212
213 daddr = blkptrtodb(ump, daddr);
214 *bnp = daddr == 0 ? -1 : daddr;
215 return (0);
216 }
217
218
219
220
221
222
223
224
225
226
227 int
228 ufs_getlbns(struct vnode *vp, daddr_t bn, struct indir *ap, int *nump)
229 {
230 long metalbn, realbn;
231 struct ufsmount *ump;
232 int64_t blockcnt;
233 int i, numlevels, off;
234
235 ump = VFSTOUFS(vp->v_mount);
236 if (nump)
237 *nump = 0;
238 numlevels = 0;
239 realbn = bn;
240 if ((long)bn < 0)
241 bn = -(long)bn;
242
243 #ifdef DIAGNOSTIC
244 if (realbn < 0 && realbn > -NDADDR) {
245 panic ("ufs_getlbns: Invalid indirect block %d specified",
246 realbn);
247 }
248 #endif
249
250
251 if (bn < NDADDR)
252 return (0);
253
254
255
256
257
258
259
260 for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
261 if (i == 0)
262 return (EFBIG);
263 blockcnt *= MNINDIR(ump);
264 if (bn < blockcnt)
265 break;
266 }
267
268
269 if (realbn >= 0)
270 metalbn = -(realbn - bn + NIADDR - i);
271 else
272 metalbn = -(-realbn - bn + NIADDR - i);
273
274
275
276
277
278
279
280 ap->in_lbn = metalbn;
281 ap->in_off = off = NIADDR - i;
282 ap->in_exists = 0;
283 ap++;
284 for (++numlevels; i <= NIADDR; i++) {
285
286 if (metalbn == realbn)
287 break;
288
289 blockcnt /= MNINDIR(ump);
290 off = (bn / blockcnt) % MNINDIR(ump);
291
292 ++numlevels;
293 ap->in_lbn = metalbn;
294 ap->in_off = off;
295 ap->in_exists = 0;
296 ++ap;
297
298 metalbn -= -1 + off * blockcnt;
299 }
300 #ifdef DIAGNOSTIC
301 if (realbn < 0 && metalbn != realbn) {
302 panic("ufs_getlbns: indirect block %d not found", realbn);
303 }
304 #endif
305 if (nump)
306 *nump = numlevels;
307 return (0);
308 }