Line data Source code
1 : /* $OpenBSD: ext2fs_alloc.c,v 1.36 2016/06/03 18:00:10 natano Exp $ */
2 : /* $NetBSD: ext2fs_alloc.c,v 1.10 2001/07/05 08:38:27 toshii Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1997 Manuel Bouyer.
6 : * Copyright (c) 1982, 1986, 1989, 1993
7 : * The Regents of the University of California. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer.
14 : * 2. Redistributions in binary form must reproduce the above copyright
15 : * notice, this list of conditions and the following disclaimer in the
16 : * documentation and/or other materials provided with the distribution.
17 : * 3. Neither the name of the University nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : *
33 : * @(#)ffs_alloc.c 8.11 (Berkeley) 10/27/94
34 : * Modified for ext2fs by Manuel Bouyer.
35 : */
36 :
37 : #include <sys/param.h>
38 : #include <sys/systm.h>
39 : #include <sys/buf.h>
40 : #include <sys/vnode.h>
41 : #include <sys/mount.h>
42 : #include <sys/syslog.h>
43 :
44 : #include <ufs/ufs/quota.h>
45 : #include <ufs/ufs/inode.h>
46 : #include <ufs/ufs/ufsmount.h>
47 : #include <ufs/ufs/ufs_extern.h>
48 :
49 : #include <ufs/ext2fs/ext2fs.h>
50 : #include <ufs/ext2fs/ext2fs_extern.h>
51 :
52 : u_long ext2gennumber;
53 :
54 : static u_int32_t ext2fs_alloccg(struct inode *, int, u_int32_t, int);
55 : static int ext2fs_dirpref(struct m_ext2fs *);
56 : static void ext2fs_fserr(struct m_ext2fs *, uid_t, char *);
57 : static u_int32_t ext2fs_hashalloc(struct inode *, int, u_int32_t, int,
58 : u_int32_t (*)(struct inode *, int, u_int32_t, int));
59 : static ufsino_t ext2fs_nodealloccg(struct inode *, int, ufsino_t, int);
60 : static u_int32_t ext2fs_mapsearch(struct m_ext2fs *, char *, u_int32_t);
61 :
62 : /*
63 : * Allocate a block in the file system.
64 : *
65 : * A preference may be optionally specified. If a preference is given
66 : * the following hierarchy is used to allocate a block:
67 : * 1) allocate the requested block.
68 : * 2) allocate a rotationally optimal block in the same cylinder.
69 : * 3) allocate a block in the same cylinder group.
70 : * 4) quadratically rehash into other cylinder groups, until an
71 : * available block is located.
72 : * If no block preference is given the following hierarchy is used
73 : * to allocate a block:
74 : * 1) allocate a block in the cylinder group that contains the
75 : * inode for the file.
76 : * 2) quadratically rehash into other cylinder groups, until an
77 : * available block is located.
78 : */
79 : int
80 0 : ext2fs_alloc(struct inode *ip, u_int32_t lbn, u_int32_t bpref,
81 : struct ucred *cred, u_int32_t *bnp)
82 : {
83 : struct m_ext2fs *fs;
84 : u_int32_t bno;
85 : int cg;
86 :
87 0 : *bnp = 0;
88 0 : fs = ip->i_e2fs;
89 : #ifdef DIAGNOSTIC
90 0 : if (cred == NOCRED)
91 0 : panic("ext2fs_alloc: missing credential");
92 : #endif /* DIAGNOSTIC */
93 0 : if (fs->e2fs.e2fs_fbcount == 0)
94 : goto nospace;
95 0 : if (cred->cr_uid != 0 && freespace(fs) <= 0)
96 : goto nospace;
97 0 : if (bpref >= fs->e2fs.e2fs_bcount)
98 0 : bpref = 0;
99 0 : if (bpref == 0)
100 0 : cg = ino_to_cg(fs, ip->i_number);
101 : else
102 0 : cg = dtog(fs, bpref);
103 0 : bno = ext2fs_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2fs_alloccg);
104 0 : if (bno > 0) {
105 0 : ip->i_e2fs_nblock += btodb(fs->e2fs_bsize);
106 0 : ip->i_flag |= IN_CHANGE | IN_UPDATE;
107 0 : *bnp = bno;
108 0 : return (0);
109 : }
110 : nospace:
111 0 : ext2fs_fserr(fs, cred->cr_uid, "file system full");
112 0 : uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt);
113 0 : return (ENOSPC);
114 0 : }
115 :
116 : /*
117 : * Allocate an inode in the file system.
118 : *
119 : * If allocating a directory, use ext2fs_dirpref to select the inode.
120 : * If allocating in a directory, the following hierarchy is followed:
121 : * 1) allocate the preferred inode.
122 : * 2) allocate an inode in the same cylinder group.
123 : * 3) quadratically rehash into other cylinder groups, until an
124 : * available inode is located.
125 : * If no inode preference is given the following hierarchy is used
126 : * to allocate an inode:
127 : * 1) allocate an inode in cylinder group 0.
128 : * 2) quadratically rehash into other cylinder groups, until an
129 : * available inode is located.
130 : */
131 : int
132 0 : ext2fs_inode_alloc(struct inode *pip, mode_t mode, struct ucred *cred,
133 : struct vnode **vpp)
134 : {
135 : struct vnode *pvp;
136 : struct m_ext2fs *fs;
137 : struct inode *ip;
138 : ufsino_t ino, ipref;
139 : int cg, error;
140 :
141 0 : *vpp = NULL;
142 0 : pvp = ITOV(pip);
143 0 : fs = pip->i_e2fs;
144 0 : if (fs->e2fs.e2fs_ficount == 0)
145 : goto noinodes;
146 :
147 0 : if ((mode & IFMT) == IFDIR)
148 0 : cg = ext2fs_dirpref(fs);
149 : else
150 0 : cg = ino_to_cg(fs, pip->i_number);
151 0 : ipref = cg * fs->e2fs.e2fs_ipg + 1;
152 0 : ino = ext2fs_hashalloc(pip, cg, ipref, mode, ext2fs_nodealloccg);
153 0 : if (ino == 0)
154 : goto noinodes;
155 0 : error = VFS_VGET(pvp->v_mount, ino, vpp);
156 0 : if (error) {
157 0 : ext2fs_inode_free(pip, ino, mode);
158 0 : return (error);
159 : }
160 0 : ip = VTOI(*vpp);
161 0 : if (ip->i_e2fs_mode && ip->i_e2fs_nlink != 0) {
162 0 : printf("mode = 0%o, nlinks %u, inum = %u, fs = %s\n",
163 0 : ip->i_e2fs_mode, ip->i_e2fs_nlink, ip->i_number,
164 0 : fs->e2fs_fsmnt);
165 0 : panic("ext2fs_valloc: dup alloc");
166 : }
167 :
168 0 : memset(ip->i_e2din, 0, sizeof(struct ext2fs_dinode));
169 :
170 : /*
171 : * Set up a new generation number for this inode.
172 : */
173 0 : if (++ext2gennumber < (u_long)time_second)
174 0 : ext2gennumber = time_second;
175 0 : ip->i_e2fs_gen = ext2gennumber;
176 0 : return (0);
177 : noinodes:
178 0 : ext2fs_fserr(fs, cred->cr_uid, "out of inodes");
179 0 : uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt);
180 0 : return (ENOSPC);
181 0 : }
182 :
183 : /*
184 : * Find a cylinder to place a directory.
185 : *
186 : * The policy implemented by this algorithm is to select from
187 : * among those cylinder groups with above the average number of
188 : * free inodes, the one with the smallest number of directories.
189 : */
190 : static int
191 0 : ext2fs_dirpref(struct m_ext2fs *fs)
192 : {
193 : int cg, maxspace, mincg, avgifree;
194 :
195 0 : avgifree = fs->e2fs.e2fs_ficount / fs->e2fs_ncg;
196 : maxspace = 0;
197 : mincg = -1;
198 0 : for (cg = 0; cg < fs->e2fs_ncg; cg++)
199 0 : if ( fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) {
200 0 : if (mincg == -1 || fs->e2fs_gd[cg].ext2bgd_nbfree > maxspace) {
201 : mincg = cg;
202 0 : maxspace = fs->e2fs_gd[cg].ext2bgd_nbfree;
203 0 : }
204 : }
205 0 : return mincg;
206 : }
207 :
208 : /*
209 : * Select the desired position for the next block in a file. The file is
210 : * logically divided into sections. The first section is composed of the
211 : * direct blocks. Each additional section contains fs_maxbpg blocks.
212 : *
213 : * If no blocks have been allocated in the first section, the policy is to
214 : * request a block in the same cylinder group as the inode that describes
215 : * the file. Otherwise, the policy is to try to allocate the blocks
216 : * contigously. The two fields of the ext2 inode extension (see
217 : * ufs/ufs/inode.h) help this.
218 : */
219 : daddr_t
220 0 : ext2fs_blkpref(struct inode *ip, u_int32_t lbn, int baps, u_int32_t *bap)
221 : {
222 : struct m_ext2fs *fs;
223 : int cg, i;
224 :
225 0 : fs = ip->i_e2fs;
226 : /*
227 : * if we are doing contigous lbn allocation, try to alloc blocks
228 : * contigously on disk
229 : */
230 :
231 0 : if ( ip->i_e2fs_last_blk && lbn == ip->i_e2fs_last_lblk + 1) {
232 0 : return ip->i_e2fs_last_blk + 1;
233 : }
234 :
235 : /*
236 : * bap, if provided, gives us a list of blocks to which we want to
237 : * stay close
238 : */
239 :
240 0 : if (bap) {
241 0 : for (i = baps; i >= 0 ; i--) {
242 0 : if (bap[i]) {
243 0 : return letoh32(bap[i]) + 1;
244 : }
245 : }
246 : }
247 :
248 : /* fall back to the first block of the cylinder containing the inode */
249 :
250 0 : cg = ino_to_cg(fs, ip->i_number);
251 0 : return fs->e2fs.e2fs_bpg * cg + fs->e2fs.e2fs_first_dblock + 1;
252 0 : }
253 :
254 : /*
255 : * Implement the cylinder overflow algorithm.
256 : *
257 : * The policy implemented by this algorithm is:
258 : * 1) allocate the block in its requested cylinder group.
259 : * 2) quadratically rehash on the cylinder group number.
260 : * 3) brute force search for a free block.
261 : */
262 : static u_int32_t
263 0 : ext2fs_hashalloc(struct inode *ip, int cg, u_int32_t pref, int size,
264 : u_int32_t (*allocator)(struct inode *, int, u_int32_t, int))
265 : {
266 : struct m_ext2fs *fs;
267 : long result;
268 : int i, icg = cg;
269 :
270 0 : fs = ip->i_e2fs;
271 : /*
272 : * 1: preferred cylinder group
273 : */
274 0 : result = (*allocator)(ip, cg, pref, size);
275 0 : if (result)
276 0 : return (result);
277 : /*
278 : * 2: quadratic rehash
279 : */
280 0 : for (i = 1; i < fs->e2fs_ncg; i *= 2) {
281 0 : cg += i;
282 0 : if (cg >= fs->e2fs_ncg)
283 0 : cg -= fs->e2fs_ncg;
284 0 : result = (*allocator)(ip, cg, 0, size);
285 0 : if (result)
286 0 : return (result);
287 : }
288 : /*
289 : * 3: brute force search
290 : * Note that we start at i == 2, since 0 was checked initially,
291 : * and 1 is always checked in the quadratic rehash.
292 : */
293 0 : cg = (icg + 2) % fs->e2fs_ncg;
294 0 : for (i = 2; i < fs->e2fs_ncg; i++) {
295 0 : result = (*allocator)(ip, cg, 0, size);
296 0 : if (result)
297 0 : return (result);
298 0 : cg++;
299 0 : if (cg == fs->e2fs_ncg)
300 : cg = 0;
301 : }
302 0 : return (0);
303 0 : }
304 :
305 : /*
306 : * Determine whether a block can be allocated.
307 : *
308 : * Check to see if a block of the appropriate size is available,
309 : * and if it is, allocate it.
310 : */
311 : static u_int32_t
312 0 : ext2fs_alloccg(struct inode *ip, int cg, u_int32_t bpref, int size)
313 : {
314 : struct m_ext2fs *fs;
315 : char *bbp;
316 0 : struct buf *bp;
317 : u_int32_t bno;
318 : int error, start, end, loc;
319 :
320 0 : fs = ip->i_e2fs;
321 0 : if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
322 0 : return (0);
323 0 : error = bread(ip->i_devvp, fsbtodb(fs,
324 0 : fs->e2fs_gd[cg].ext2bgd_b_bitmap), (int)fs->e2fs_bsize, &bp);
325 0 : if (error || fs->e2fs_gd[cg].ext2bgd_nbfree == 0) {
326 0 : brelse(bp);
327 0 : return (0);
328 : }
329 0 : bbp = (char *)bp->b_data;
330 :
331 0 : if (dtog(fs, bpref) != cg)
332 0 : bpref = 0;
333 0 : if (bpref != 0) {
334 0 : bpref = dtogd(fs, bpref);
335 : /*
336 : * if the requested block is available, use it
337 : */
338 0 : if (isclr(bbp, bpref)) {
339 : bno = bpref;
340 0 : goto gotit;
341 : }
342 : }
343 : /*
344 : * no blocks in the requested cylinder, so take next
345 : * available one in this cylinder group.
346 : * first try to get 8 contigous blocks, then fall back to a single
347 : * block.
348 : */
349 0 : if (bpref)
350 0 : start = dtogd(fs, bpref) / NBBY;
351 : else
352 : start = 0;
353 0 : end = howmany(fs->e2fs.e2fs_fpg, NBBY) - start;
354 0 : for (loc = start; loc < end; loc++) {
355 0 : if (bbp[loc] == 0) {
356 0 : bno = loc * NBBY;
357 0 : goto gotit;
358 : }
359 : }
360 0 : for (loc = 0; loc < start; loc++) {
361 0 : if (bbp[loc] == 0) {
362 0 : bno = loc * NBBY;
363 0 : goto gotit;
364 : }
365 : }
366 :
367 0 : bno = ext2fs_mapsearch(fs, bbp, bpref);
368 : gotit:
369 : #ifdef DIAGNOSTIC
370 0 : if (isset(bbp, bno)) {
371 0 : panic("%s: dup alloc: cg=%d bno=%u fs=%s\n",
372 0 : __func__, cg, bno, fs->e2fs_fsmnt);
373 : }
374 : #endif
375 0 : setbit(bbp, bno);
376 0 : fs->e2fs.e2fs_fbcount--;
377 0 : fs->e2fs_gd[cg].ext2bgd_nbfree--;
378 0 : fs->e2fs_fmod = 1;
379 0 : bdwrite(bp);
380 0 : return (cg * fs->e2fs.e2fs_fpg + fs->e2fs.e2fs_first_dblock + bno);
381 0 : }
382 :
383 : /*
384 : * Determine whether an inode can be allocated.
385 : *
386 : * Check to see if an inode is available, and if it is,
387 : * allocate it using the following policy:
388 : * 1) allocate the requested inode.
389 : * 2) allocate the next available inode after the requested
390 : * inode in the specified cylinder group.
391 : */
392 : static ufsino_t
393 0 : ext2fs_nodealloccg(struct inode *ip, int cg, ufsino_t ipref, int mode)
394 : {
395 : struct m_ext2fs *fs;
396 : char *ibp;
397 0 : struct buf *bp;
398 : int error, start, len, loc, map, i;
399 :
400 0 : ipref--; /* to avoid a lot of (ipref -1) */
401 0 : fs = ip->i_e2fs;
402 0 : if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
403 0 : return (0);
404 0 : error = bread(ip->i_devvp, fsbtodb(fs,
405 0 : fs->e2fs_gd[cg].ext2bgd_i_bitmap), (int)fs->e2fs_bsize, &bp);
406 0 : if (error) {
407 0 : brelse(bp);
408 0 : return (0);
409 : }
410 0 : ibp = (char *)bp->b_data;
411 0 : if (ipref) {
412 0 : ipref %= fs->e2fs.e2fs_ipg;
413 0 : if (isclr(ibp, ipref))
414 : goto gotit;
415 : }
416 0 : start = ipref / NBBY;
417 0 : len = howmany(fs->e2fs.e2fs_ipg - ipref, NBBY);
418 0 : loc = skpc(0xff, len, &ibp[start]);
419 0 : if (loc == 0) {
420 0 : len = start + 1;
421 : start = 0;
422 0 : loc = skpc(0xff, len, &ibp[0]);
423 0 : if (loc == 0) {
424 0 : printf("cg = %d, ipref = %u, fs = %s\n",
425 0 : cg, ipref, fs->e2fs_fsmnt);
426 0 : panic("ext2fs_nodealloccg: map corrupted");
427 : /* NOTREACHED */
428 : }
429 : }
430 0 : i = start + len - loc;
431 0 : map = ibp[i];
432 0 : ipref = i * NBBY;
433 0 : for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
434 0 : if ((map & i) == 0) {
435 : goto gotit;
436 : }
437 : }
438 0 : printf("fs = %s\n", fs->e2fs_fsmnt);
439 0 : panic("ext2fs_nodealloccg: block not in map");
440 : /* NOTREACHED */
441 : gotit:
442 0 : setbit(ibp, ipref);
443 0 : fs->e2fs.e2fs_ficount--;
444 0 : fs->e2fs_gd[cg].ext2bgd_nifree--;
445 0 : fs->e2fs_fmod = 1;
446 0 : if ((mode & IFMT) == IFDIR) {
447 0 : fs->e2fs_gd[cg].ext2bgd_ndirs++;
448 0 : }
449 0 : bdwrite(bp);
450 0 : return (cg * fs->e2fs.e2fs_ipg + ipref + 1);
451 0 : }
452 :
453 : /*
454 : * Free a block.
455 : *
456 : * The specified block is placed back in the
457 : * free map.
458 : */
459 : void
460 0 : ext2fs_blkfree(struct inode *ip, u_int32_t bno)
461 : {
462 : struct m_ext2fs *fs;
463 : char *bbp;
464 0 : struct buf *bp;
465 : int error, cg;
466 :
467 0 : fs = ip->i_e2fs;
468 0 : cg = dtog(fs, bno);
469 0 : if (bno >= fs->e2fs.e2fs_bcount) {
470 0 : printf("bad block %u, ino %u\n", bno, ip->i_number);
471 0 : ext2fs_fserr(fs, ip->i_e2fs_uid, "bad block");
472 0 : return;
473 : }
474 0 : error = bread(ip->i_devvp,
475 0 : fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
476 0 : (int)fs->e2fs_bsize, &bp);
477 0 : if (error) {
478 0 : brelse(bp);
479 0 : return;
480 : }
481 0 : bbp = (char *)bp->b_data;
482 0 : bno = dtogd(fs, bno);
483 0 : if (isclr(bbp, bno))
484 0 : panic("%s: freeing free block: dev = 0x%x, block = %u, fs = %s\n",
485 0 : __func__, ip->i_dev, bno, fs->e2fs_fsmnt);
486 :
487 0 : clrbit(bbp, bno);
488 0 : fs->e2fs.e2fs_fbcount++;
489 0 : fs->e2fs_gd[cg].ext2bgd_nbfree++;
490 :
491 0 : fs->e2fs_fmod = 1;
492 0 : bdwrite(bp);
493 0 : }
494 :
495 : /*
496 : * Free an inode.
497 : *
498 : * The specified inode is placed back in the free map.
499 : */
500 : void
501 0 : ext2fs_inode_free(struct inode *pip, ufsino_t ino, mode_t mode)
502 : {
503 : struct m_ext2fs *fs;
504 : char *ibp;
505 0 : struct buf *bp;
506 : int error, cg;
507 :
508 0 : fs = pip->i_e2fs;
509 0 : if (ino > fs->e2fs.e2fs_icount || ino < EXT2_FIRSTINO)
510 0 : panic("ifree: range: dev = 0x%x, ino = %u, fs = %s",
511 0 : pip->i_dev, ino, fs->e2fs_fsmnt);
512 0 : cg = ino_to_cg(fs, ino);
513 0 : error = bread(pip->i_devvp,
514 0 : fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
515 0 : (int)fs->e2fs_bsize, &bp);
516 0 : if (error) {
517 0 : brelse(bp);
518 0 : return;
519 : }
520 0 : ibp = (char *)bp->b_data;
521 0 : ino = (ino - 1) % fs->e2fs.e2fs_ipg;
522 0 : if (isclr(ibp, ino)) {
523 0 : printf("dev = 0x%x, ino = %d, fs = %s\n",
524 0 : pip->i_dev, ino, fs->e2fs_fsmnt);
525 0 : if (fs->e2fs_ronly == 0)
526 0 : panic("ifree: freeing free inode");
527 : }
528 0 : clrbit(ibp, ino);
529 0 : fs->e2fs.e2fs_ficount++;
530 0 : fs->e2fs_gd[cg].ext2bgd_nifree++;
531 0 : if ((mode & IFMT) == IFDIR) {
532 0 : fs->e2fs_gd[cg].ext2bgd_ndirs--;
533 0 : }
534 0 : fs->e2fs_fmod = 1;
535 0 : bdwrite(bp);
536 0 : }
537 :
538 : /*
539 : * Find a block in the specified cylinder group.
540 : *
541 : * It is a panic if a request is made to find a block if none are
542 : * available.
543 : */
544 :
545 : static u_int32_t
546 0 : ext2fs_mapsearch(struct m_ext2fs *fs, char *bbp, u_int32_t bpref)
547 : {
548 : u_int32_t bno;
549 : int start, len, loc, i, map;
550 :
551 : /*
552 : * find the fragment by searching through the free block
553 : * map for an appropriate bit pattern
554 : */
555 0 : if (bpref)
556 0 : start = dtogd(fs, bpref) / NBBY;
557 : else
558 : start = 0;
559 0 : len = howmany(fs->e2fs.e2fs_fpg, NBBY) - start;
560 0 : loc = skpc(0xff, len, &bbp[start]);
561 0 : if (loc == 0) {
562 0 : len = start + 1;
563 : start = 0;
564 0 : loc = skpc(0xff, len, &bbp[start]);
565 0 : if (loc == 0) {
566 0 : printf("start = %d, len = %d, fs = %s\n",
567 0 : start, len, fs->e2fs_fsmnt);
568 0 : panic("ext2fs_alloccg: map corrupted");
569 : /* NOTREACHED */
570 : }
571 : }
572 0 : i = start + len - loc;
573 0 : map = bbp[i];
574 0 : bno = i * NBBY;
575 0 : for (i = 1; i < (1 << NBBY); i <<= 1, bno++) {
576 0 : if ((map & i) == 0)
577 0 : return (bno);
578 : }
579 0 : printf("fs = %s\n", fs->e2fs_fsmnt);
580 0 : panic("ext2fs_mapsearch: block not in map");
581 : /* NOTREACHED */
582 : }
583 :
584 : /*
585 : * Fserr prints the name of a file system with an error diagnostic.
586 : *
587 : * The form of the error message is:
588 : * fs: error message
589 : */
590 : static void
591 0 : ext2fs_fserr(struct m_ext2fs *fs, uid_t uid, char *cp)
592 : {
593 0 : log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp);
594 0 : }
|