inode.c revision 1.64 1 /* $NetBSD: inode.c,v 1.64 2011/03/06 17:08:16 bouyer Exp $ */
2
3 /*
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95";
36 #else
37 __RCSID("$NetBSD: inode.c,v 1.64 2011/03/06 17:08:16 bouyer Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <sys/param.h>
42 #include <sys/time.h>
43 #include <sys/stat.h>
44
45 #include <ufs/ufs/dinode.h>
46 #include <ufs/ufs/dir.h>
47 #include <ufs/ffs/fs.h>
48 #include <ufs/ffs/ffs_extern.h>
49 #include <ufs/ufs/ufs_bswap.h>
50
51 #ifndef SMALL
52 #include <err.h>
53 #include <pwd.h>
54 #endif
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <time.h>
59
60 #include "fsck.h"
61 #include "fsutil.h"
62 #include "extern.h"
63
64 static ino_t startinum;
65
66 static int iblock(struct inodesc *, long, u_int64_t);
67 static void swap_dinode1(union dinode *, int);
68 static void swap_dinode2(union dinode *, int);
69
70 int
71 ckinode(union dinode *dp, struct inodesc *idesc)
72 {
73 int ret, offset, i;
74 union dinode dino;
75 u_int64_t sizepb;
76 int64_t remsize;
77 daddr_t ndb;
78 mode_t mode;
79 char pathbuf[MAXPATHLEN + 1];
80
81 if (idesc->id_fix != IGNORE)
82 idesc->id_fix = DONTKNOW;
83 idesc->id_entryno = 0;
84 idesc->id_filesize = iswap64(DIP(dp, size));
85 mode = iswap16(DIP(dp, mode)) & IFMT;
86 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
87 (idesc->id_filesize < sblock->fs_maxsymlinklen ||
88 (isappleufs && (idesc->id_filesize < APPLEUFS_MAXSYMLINKLEN)) ||
89 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0))))
90 return (KEEPON);
91 if (is_ufs2)
92 dino.dp2 = dp->dp2;
93 else
94 dino.dp1 = dp->dp1;
95 ndb = howmany(iswap64(DIP(&dino, size)), sblock->fs_bsize);
96 for (i = 0; i < NDADDR; i++) {
97 if (--ndb == 0 &&
98 (offset = blkoff(sblock, iswap64(DIP(&dino, size)))) != 0)
99 idesc->id_numfrags =
100 numfrags(sblock, fragroundup(sblock, offset));
101 else
102 idesc->id_numfrags = sblock->fs_frag;
103 if (DIP(&dino, db[i]) == 0) {
104 if (idesc->id_type == DATA && ndb >= 0) {
105 /* An empty block in a directory XXX */
106 markclean = 0;
107 getpathname(pathbuf, sizeof(pathbuf),
108 idesc->id_number, idesc->id_number);
109 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
110 pathbuf);
111 if (reply("ADJUST LENGTH") == 1) {
112 dp = ginode(idesc->id_number);
113 DIP_SET(dp, size, iswap64(i *
114 sblock->fs_bsize));
115 printf(
116 "YOU MUST RERUN FSCK AFTERWARDS\n");
117 rerun = 1;
118 inodirty();
119 }
120 }
121 continue;
122 }
123 if (is_ufs2)
124 idesc->id_blkno = iswap64(dino.dp2.di_db[i]);
125 else
126 idesc->id_blkno = iswap32(dino.dp1.di_db[i]);
127 if (idesc->id_type != DATA)
128 ret = (*idesc->id_func)(idesc);
129 else
130 ret = dirscan(idesc);
131 if (ret & STOP)
132 return (ret);
133 }
134 idesc->id_numfrags = sblock->fs_frag;
135 remsize = iswap64(DIP(&dino, size)) - sblock->fs_bsize * NDADDR;
136 sizepb = sblock->fs_bsize;
137 for (i = 0; i < NIADDR; i++) {
138 if (DIP(&dino, ib[i])) {
139 if (is_ufs2)
140 idesc->id_blkno = iswap64(dino.dp2.di_ib[i]);
141 else
142 idesc->id_blkno = iswap32(dino.dp1.di_ib[i]);
143 ret = iblock(idesc, i + 1, remsize);
144 if (ret & STOP)
145 return (ret);
146 } else {
147 if (idesc->id_type == DATA && remsize > 0) {
148 /* An empty block in a directory XXX */
149 markclean = 0;
150 getpathname(pathbuf, sizeof(pathbuf),
151 idesc->id_number, idesc->id_number);
152 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
153 pathbuf);
154 if (reply("ADJUST LENGTH") == 1) {
155 dp = ginode(idesc->id_number);
156 DIP_SET(dp, size,
157 iswap64(iswap64(DIP(dp, size))
158 - remsize));
159 remsize = 0;
160 printf(
161 "YOU MUST RERUN FSCK AFTERWARDS\n");
162 rerun = 1;
163 inodirty();
164 break;
165 }
166 }
167 }
168 sizepb *= NINDIR(sblock);
169 remsize -= sizepb;
170 }
171 return (KEEPON);
172 }
173
174 static int
175 iblock(struct inodesc *idesc, long ilevel, u_int64_t isize)
176 {
177 struct bufarea *bp;
178 int i, n, (*func) (struct inodesc *), nif;
179 u_int64_t sizepb;
180 char buf[BUFSIZ];
181 char pathbuf[MAXPATHLEN + 1];
182 union dinode *dp;
183
184 if (idesc->id_type != DATA) {
185 func = idesc->id_func;
186 if (((n = (*func)(idesc)) & KEEPON) == 0)
187 return (n);
188 } else
189 func = dirscan;
190 if (chkrange(idesc->id_blkno, idesc->id_numfrags))
191 return (SKIP);
192 bp = getdatablk(idesc->id_blkno, sblock->fs_bsize);
193 ilevel--;
194 for (sizepb = sblock->fs_bsize, i = 0; i < ilevel; i++)
195 sizepb *= NINDIR(sblock);
196 if (howmany(isize, sizepb) > (size_t)NINDIR(sblock))
197 nif = NINDIR(sblock);
198 else
199 nif = howmany(isize, sizepb);
200 if (do_blkswap) { /* swap byte order of the whole blk */
201 if (is_ufs2) {
202 for (i = 0; i < nif; i++)
203 bp->b_un.b_indir2[i] =
204 bswap64(bp->b_un.b_indir2[i]);
205 } else {
206 for (i = 0; i < nif; i++)
207 bp->b_un.b_indir1[i] =
208 bswap32(bp->b_un.b_indir1[i]);
209 }
210 dirty(bp);
211 flush(fswritefd, bp);
212 }
213 if (idesc->id_func == pass1check && nif < NINDIR(sblock)) {
214 for (i = nif; i < NINDIR(sblock); i++) {
215 if (IBLK(bp, i) == 0)
216 continue;
217 (void)snprintf(buf, sizeof(buf),
218 "PARTIALLY TRUNCATED INODE I=%llu",
219 (unsigned long long)idesc->id_number);
220 if (dofix(idesc, buf)) {
221 IBLK_SET(bp, i, 0);
222 dirty(bp);
223 } else
224 markclean = 0;
225 }
226 flush(fswritefd, bp);
227 }
228 for (i = 0; i < nif; i++) {
229 if (IBLK(bp, i)) {
230 if (is_ufs2)
231 idesc->id_blkno = iswap64(bp->b_un.b_indir2[i]);
232 else
233 idesc->id_blkno = iswap32(bp->b_un.b_indir1[i]);
234 if (ilevel == 0)
235 n = (*func)(idesc);
236 else
237 n = iblock(idesc, ilevel, isize);
238 if (n & STOP) {
239 bp->b_flags &= ~B_INUSE;
240 return (n);
241 }
242 } else {
243 if (idesc->id_type == DATA && isize > 0) {
244 /* An empty block in a directory XXX */
245 markclean = 0;
246 getpathname(pathbuf, sizeof(pathbuf),
247 idesc->id_number, idesc->id_number);
248 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
249 pathbuf);
250 if (reply("ADJUST LENGTH") == 1) {
251 dp = ginode(idesc->id_number);
252 DIP_SET(dp, size,
253 iswap64(iswap64(DIP(dp, size))
254 - isize));
255 isize = 0;
256 printf(
257 "YOU MUST RERUN FSCK AFTERWARDS\n");
258 rerun = 1;
259 inodirty();
260 bp->b_flags &= ~B_INUSE;
261 return(STOP);
262 }
263 }
264 }
265 isize -= sizepb;
266 }
267 bp->b_flags &= ~B_INUSE;
268 return (KEEPON);
269 }
270
271 /*
272 * Check that a block in a legal block number.
273 * Return 0 if in range, 1 if out of range.
274 */
275 int
276 chkrange(daddr_t blk, int cnt)
277 {
278 int c;
279
280 if (cnt <= 0 || blk <= 0 || blk > maxfsblock ||
281 cnt - 1 > maxfsblock - blk)
282 return (1);
283 if (cnt > sblock->fs_frag ||
284 fragnum(sblock, blk) + cnt > sblock->fs_frag) {
285 if (debug)
286 printf("bad size: blk %lld, offset %d, size %d\n",
287 (long long)blk, (int)fragnum(sblock, blk), cnt);
288 }
289 c = dtog(sblock, blk);
290 if (blk < cgdmin(sblock, c)) {
291 if ((blk + cnt) > cgsblock(sblock, c)) {
292 if (debug) {
293 printf("blk %lld < cgdmin %lld;",
294 (long long)blk,
295 (long long)cgdmin(sblock, c));
296 printf(" blk + cnt %lld > cgsbase %lld\n",
297 (long long)(blk + cnt),
298 (long long)cgsblock(sblock, c));
299 }
300 return (1);
301 }
302 } else {
303 if ((blk + cnt) > cgbase(sblock, c+1)) {
304 if (debug) {
305 printf("blk %lld >= cgdmin %lld;",
306 (long long)blk,
307 (long long)cgdmin(sblock, c));
308 printf(" blk + cnt %lld > sblock->fs_fpg %d\n",
309 (long long)(blk+cnt), sblock->fs_fpg);
310 }
311 return (1);
312 }
313 }
314 return (0);
315 }
316
317 /*
318 * General purpose interface for reading inodes.
319 */
320 union dinode *
321 ginode(ino_t inumber)
322 {
323 daddr_t iblk;
324 int blkoff;
325
326 if (inumber < ROOTINO || inumber > maxino)
327 errexit("bad inode number %llu to ginode",
328 (unsigned long long)inumber);
329 if (startinum == 0 ||
330 inumber < startinum || inumber >= startinum + INOPB(sblock)) {
331 iblk = ino_to_fsba(sblock, inumber);
332 if (pbp != 0)
333 pbp->b_flags &= ~B_INUSE;
334 pbp = getdatablk(iblk, sblock->fs_bsize);
335 startinum = (inumber / INOPB(sblock)) * INOPB(sblock);
336 }
337 if (is_ufs2) {
338 blkoff = (inumber % INOPB(sblock)) * DINODE2_SIZE;
339 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff));
340 }
341 blkoff = (inumber % INOPB(sblock)) * DINODE1_SIZE;
342 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff));
343 }
344
345 static void
346 swap_dinode1(union dinode *dp, int n)
347 {
348 int i, j;
349 struct ufs1_dinode *dp1;
350 int32_t maxsymlinklen = sblock->fs_maxsymlinklen;
351 if (isappleufs)
352 maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
353
354 dp1 = (struct ufs1_dinode *)&dp->dp1;
355 for (i = 0; i < n; i++, dp1++) {
356 ffs_dinode1_swap(dp1, dp1);
357 if (((iswap16(dp1->di_mode) & IFMT) != IFLNK) ||
358 doinglevel2 ||
359 (maxsymlinklen < 0) ||
360 (iswap64(dp1->di_size) > (uint64_t)maxsymlinklen)) {
361 for (j = 0; j < (NDADDR + NIADDR); j++)
362 dp1->di_db[j] = bswap32(dp1->di_db[j]);
363 }
364 }
365 }
366
367 static void
368 swap_dinode2(union dinode *dp, int n)
369 {
370 int i, j;
371 struct ufs2_dinode *dp2;
372
373 dp2 = (struct ufs2_dinode *)&dp->dp2;
374 for (i = 0; i < n; i++, dp2++) {
375 ffs_dinode2_swap(dp2, dp2);
376 if ((iswap16(dp2->di_mode) & IFMT) != IFLNK) {
377 for (j = 0; j < (NDADDR + NIADDR + NXADDR); j++)
378 dp2->di_extb[j] = bswap64(dp2->di_extb[j]);
379 }
380 }
381 }
382
383 /*
384 * Special purpose version of ginode used to optimize first pass
385 * over all the inodes in numerical order.
386 */
387 ino_t nextino, lastinum, lastvalidinum;
388 long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
389 union dinode *inodebuf;
390
391 union dinode *
392 getnextinode(ino_t inumber)
393 {
394 long size;
395 daddr_t dblk;
396 static union dinode *dp;
397 union dinode *ret;
398
399 if (inumber != nextino++ || inumber > lastvalidinum)
400 errexit("bad inode number %llu to nextinode",
401 (unsigned long long)inumber);
402
403 if (inumber >= lastinum) {
404 readcnt++;
405 dblk = fsbtodb(sblock, ino_to_fsba(sblock, lastinum));
406 if (readcnt % readpercg == 0) {
407 size = partialsize;
408 lastinum += partialcnt;
409 } else {
410 size = inobufsize;
411 lastinum += fullcnt;
412 }
413 (void)bread(fsreadfd, (caddr_t)inodebuf, dblk, size);
414 if (doswap) {
415 if (is_ufs2)
416 swap_dinode2(inodebuf, lastinum - inumber);
417 else
418 swap_dinode1(inodebuf, lastinum - inumber);
419 bwrite(fswritefd, (char *)inodebuf, dblk, size);
420 }
421 dp = (union dinode *)inodebuf;
422 }
423 ret = dp;
424 dp = (union dinode *)
425 ((char *)dp + (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE));
426 return ret;
427 }
428
429 void
430 setinodebuf(ino_t inum)
431 {
432
433 if (inum % sblock->fs_ipg != 0)
434 errexit("bad inode number %llu to setinodebuf",
435 (unsigned long long)inum);
436
437 lastvalidinum = inum + sblock->fs_ipg - 1;
438 startinum = 0;
439 nextino = inum;
440 lastinum = inum;
441 readcnt = 0;
442 if (inodebuf != NULL)
443 return;
444 inobufsize = blkroundup(sblock, INOBUFSIZE);
445 fullcnt = inobufsize / (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE);
446 readpercg = sblock->fs_ipg / fullcnt;
447 partialcnt = sblock->fs_ipg % fullcnt;
448 partialsize = partialcnt * (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE);
449 if (partialcnt != 0) {
450 readpercg++;
451 } else {
452 partialcnt = fullcnt;
453 partialsize = inobufsize;
454 }
455 if (inodebuf == NULL &&
456 (inodebuf = malloc((unsigned)inobufsize)) == NULL)
457 errexit("Cannot allocate space for inode buffer");
458 }
459
460 void
461 freeinodebuf(void)
462 {
463
464 if (inodebuf != NULL)
465 free((char *)inodebuf);
466 inodebuf = NULL;
467 }
468
469 /*
470 * Routines to maintain information about directory inodes.
471 * This is built during the first pass and used during the
472 * second and third passes.
473 *
474 * Enter inodes into the cache.
475 */
476 void
477 cacheino(union dinode *dp, ino_t inumber)
478 {
479 struct inoinfo *inp;
480 struct inoinfo **inpp, **ninpsort;
481 unsigned int i, blks, extra;
482 int64_t size;
483
484 size = iswap64(DIP(dp, size));
485 blks = howmany(size, sblock->fs_bsize);
486 if (blks > NDADDR)
487 blks = NDADDR + NIADDR;
488 if (blks > 0)
489 extra = (blks - 1) * sizeof (int64_t);
490 else
491 extra = 0;
492 inp = malloc(sizeof(*inp) + extra);
493 if (inp == NULL)
494 return;
495 inpp = &inphead[inumber % dirhash];
496 inp->i_nexthash = *inpp;
497 *inpp = inp;
498 inp->i_child = inp->i_sibling = 0;
499 if (inumber == ROOTINO)
500 inp->i_parent = ROOTINO;
501 else
502 inp->i_parent = (ino_t)0;
503 inp->i_dotdot = (ino_t)0;
504 inp->i_number = inumber;
505 inp->i_isize = size;
506 inp->i_numblks = blks;
507 for (i = 0; i < (blks < NDADDR ? blks : NDADDR); i++)
508 inp->i_blks[i] = DIP(dp, db[i]);
509 if (blks > NDADDR)
510 for (i = 0; i < NIADDR; i++)
511 inp->i_blks[NDADDR + i] = DIP(dp, ib[i]);
512 if (inplast == listmax) {
513 ninpsort = (struct inoinfo **)realloc((char *)inpsort,
514 (unsigned)(listmax + 100) * sizeof(struct inoinfo *));
515 if (inpsort == NULL)
516 errexit("cannot increase directory list");
517 inpsort = ninpsort;
518 listmax += 100;
519 }
520 inpsort[inplast++] = inp;
521 }
522
523 /*
524 * Look up an inode cache structure.
525 */
526 struct inoinfo *
527 getinoinfo(ino_t inumber)
528 {
529 struct inoinfo *inp;
530
531 for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) {
532 if (inp->i_number != inumber)
533 continue;
534 return (inp);
535 }
536 errexit("cannot find inode %llu", (unsigned long long)inumber);
537 return ((struct inoinfo *)0);
538 }
539
540 /*
541 * Clean up all the inode cache structure.
542 */
543 void
544 inocleanup(void)
545 {
546 struct inoinfo **inpp;
547
548 if (inphead == NULL)
549 return;
550 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
551 free((char *)(*inpp));
552 free((char *)inphead);
553 free((char *)inpsort);
554 inphead = inpsort = NULL;
555 }
556
557 void
558 inodirty(void)
559 {
560
561 dirty(pbp);
562 }
563
564 void
565 clri(struct inodesc *idesc, const char *type, int flag)
566 {
567 union dinode *dp;
568
569 dp = ginode(idesc->id_number);
570 if (flag == 1) {
571 pwarn("%s %s", type,
572 (iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? "DIR" : "FILE");
573 pinode(idesc->id_number);
574 }
575 if (preen || reply("CLEAR") == 1) {
576 if (preen)
577 printf(" (CLEARED)\n");
578 n_files--;
579 /*
580 * ckinode will call id_func (actually always pass4check)
581 * which will update the block count
582 */
583 if (idesc->id_type != SNAP)
584 update_uquot(idesc->id_number,
585 idesc->id_uid, idesc->id_gid, 0, -1);
586 (void)ckinode(dp, idesc);
587 clearinode(dp);
588 inoinfo(idesc->id_number)->ino_state = USTATE;
589 inodirty();
590 } else
591 markclean = 0;
592 }
593
594 int
595 findname(struct inodesc *idesc)
596 {
597 struct direct *dirp = idesc->id_dirp;
598 size_t len;
599 char *buf;
600
601 if (iswap32(dirp->d_ino) != idesc->id_parent || idesc->id_entryno < 2) {
602 idesc->id_entryno++;
603 return (KEEPON);
604 }
605 if ((len = dirp->d_namlen + 1) > MAXPATHLEN) {
606 /* XXX: We don't fix but we ignore */
607 len = MAXPATHLEN;
608 }
609 /* this is namebuf from utilities.c */
610 buf = __UNCONST(idesc->id_name);
611 (void)memcpy(buf, dirp->d_name, (size_t)dirp->d_namlen + 1);
612 return (STOP|FOUND);
613 }
614
615 int
616 findino(struct inodesc *idesc)
617 {
618 struct direct *dirp = idesc->id_dirp;
619
620 if (dirp->d_ino == 0)
621 return (KEEPON);
622 if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
623 iswap32(dirp->d_ino) >= ROOTINO && iswap32(dirp->d_ino) <= maxino) {
624 idesc->id_parent = iswap32(dirp->d_ino);
625 return (STOP|FOUND);
626 }
627 return (KEEPON);
628 }
629
630 int
631 clearentry(struct inodesc *idesc)
632 {
633 struct direct *dirp = idesc->id_dirp;
634
635 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
636 idesc->id_entryno++;
637 return (KEEPON);
638 }
639 dirp->d_ino = 0;
640 return (STOP|FOUND|ALTERED);
641 }
642
643 void
644 pinode(ino_t ino)
645 {
646 union dinode *dp;
647 struct passwd *pw;
648
649 printf(" I=%llu ", (unsigned long long)ino);
650 if (ino < ROOTINO || ino > maxino)
651 return;
652 dp = ginode(ino);
653 printf(" OWNER=");
654 #ifndef SMALL
655 if (Uflag && (pw = getpwuid((int)iswap32(DIP(dp, uid)))) != 0)
656 printf("%s ", pw->pw_name);
657 else
658 #endif
659 printf("%u ", (unsigned)iswap32(DIP(dp, uid)));
660 printf("MODE=%o\n", iswap16(DIP(dp, mode)));
661 if (preen)
662 printf("%s: ", cdevname());
663 printf("SIZE=%llu ", (unsigned long long)iswap64(DIP(dp, size)));
664 printf("MTIME=%s ", print_mtime(iswap32(DIP(dp, mtime))));
665 }
666
667 void
668 blkerror(ino_t ino, const char *type, daddr_t blk)
669 {
670 struct inostat *info;
671
672 pfatal("%lld %s I=%llu", (long long)blk, type, (unsigned long long)ino);
673 printf("\n");
674 info = inoinfo(ino);
675 switch (info->ino_state) {
676
677 case FSTATE:
678 info->ino_state = FCLEAR;
679 return;
680
681 case DSTATE:
682 info->ino_state = DCLEAR;
683 return;
684
685 case FCLEAR:
686 case DCLEAR:
687 return;
688
689 default:
690 errexit("BAD STATE %d TO BLKERR", info->ino_state);
691 /* NOTREACHED */
692 }
693 }
694
695 /*
696 * allocate an unused inode
697 */
698 ino_t
699 allocino(ino_t request, int type)
700 {
701 ino_t ino;
702 union dinode *dp;
703 struct ufs1_dinode *dp1;
704 struct ufs2_dinode *dp2;
705 time_t t;
706 struct cg *cgp = cgrp;
707 int cg;
708 struct inostat *info = NULL;
709 int nfrags;
710
711 if (request == 0)
712 request = ROOTINO;
713 else if (inoinfo(request)->ino_state != USTATE)
714 return (0);
715 for (ino = request; ino < maxino; ino++) {
716 info = inoinfo(ino);
717 if (info->ino_state == USTATE)
718 break;
719 }
720 if (ino == maxino)
721 return (0);
722 cg = ino_to_cg(sblock, ino);
723 /* If necessary, extend the inoinfo array. grow exponentially */
724 if ((ino % sblock->fs_ipg) >= (uint64_t)inostathead[cg].il_numalloced) {
725 unsigned long newalloced, i;
726 newalloced = MIN(sblock->fs_ipg,
727 MAX(2 * inostathead[cg].il_numalloced, 10));
728 info = calloc(newalloced, sizeof(struct inostat));
729 if (info == NULL) {
730 pwarn("cannot alloc %lu bytes to extend inoinfo\n",
731 sizeof(struct inostat) * newalloced);
732 return 0;
733 }
734 memmove(info, inostathead[cg].il_stat,
735 inostathead[cg].il_numalloced * sizeof(*info));
736 for (i = inostathead[cg].il_numalloced; i < newalloced; i++) {
737 info[i].ino_state = USTATE;
738 }
739 if (inostathead[cg].il_numalloced)
740 free(inostathead[cg].il_stat);
741 inostathead[cg].il_stat = info;
742 inostathead[cg].il_numalloced = newalloced;
743 info = inoinfo(ino);
744 }
745 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
746 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
747 if ((doswap && !needswap) || (!doswap && needswap))
748 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
749 if (!cg_chkmagic(cgp, 0))
750 pfatal("CG %d: ALLOCINO: BAD MAGIC NUMBER\n", cg);
751 if (doswap)
752 cgdirty();
753 setbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg);
754 cgp->cg_cs.cs_nifree--;
755 sblock->fs_cstotal.cs_nifree--;
756 sblock->fs_cs(fs, cg).cs_nifree--;
757 sbdirty();
758 switch (type & IFMT) {
759 case IFDIR:
760 info->ino_state = DSTATE;
761 cgp->cg_cs.cs_ndir++;
762 nfrags = 1;
763 break;
764 case IFREG:
765 info->ino_state = FSTATE;
766 nfrags = sblock->fs_frag;
767 break;
768 case IFLNK:
769 info->ino_state = FSTATE;
770 nfrags = 1;
771 break;
772 default:
773 return (0);
774 }
775 cgdirty();
776 dp = ginode(ino);
777 if (is_ufs2) {
778 dp2 = &dp->dp2;
779 dp2->di_db[0] = iswap64(allocblk(nfrags));
780 if (dp2->di_db[0] == 0) {
781 info->ino_state = USTATE;
782 return (0);
783 }
784 dp2->di_mode = iswap16(type);
785 dp2->di_flags = 0;
786 (void)time(&t);
787 dp2->di_atime = iswap64(t);
788 dp2->di_mtime = dp2->di_ctime = dp2->di_atime;
789 dp2->di_size = iswap64(lfragtosize(sblock, nfrags));
790 dp2->di_blocks = iswap64(btodb(lfragtosize(sblock, nfrags)));
791 } else {
792 dp1 = &dp->dp1;
793 dp1->di_db[0] = iswap32(allocblk(nfrags));
794 if (dp1->di_db[0] == 0) {
795 info->ino_state = USTATE;
796 return (0);
797 }
798 dp1->di_mode = iswap16(type);
799 dp1->di_flags = 0;
800 (void)time(&t);
801 dp1->di_atime = iswap32(t);
802 dp1->di_mtime = dp1->di_ctime = dp1->di_atime;
803 dp1->di_size = iswap64(lfragtosize(sblock, nfrags));
804 dp1->di_blocks = iswap32(btodb(lfragtosize(sblock, nfrags)));
805 }
806 n_files++;
807 inodirty();
808 if (newinofmt)
809 info->ino_type = IFTODT(type);
810 return (ino);
811 }
812
813 /*
814 * deallocate an inode
815 */
816 void
817 freeino(ino_t ino)
818 {
819 struct inodesc idesc;
820 union dinode *dp;
821 struct cg *cgp = cgrp;
822 int cg;
823
824 cg = ino_to_cg(sblock, ino);
825 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
826 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
827 if ((doswap && !needswap) || (!doswap && needswap))
828 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
829 if (!cg_chkmagic(cgp, 0)) {
830 pwarn("CG %d: FREEINO: BAD MAGIC NUMBER\n", cg);
831 cgp = NULL;
832 }
833
834 memset(&idesc, 0, sizeof(struct inodesc));
835 idesc.id_func = pass4check;
836 idesc.id_number = ino;
837 dp = ginode(ino);
838 idesc.id_uid = iswap32(DIP(dp, uid));
839 idesc.id_gid = iswap32(DIP(dp, gid));
840 if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT)
841 idesc.id_type = SNAP;
842 else
843 idesc.id_type = ADDR;
844 (void)ckinode(dp, &idesc);
845 clearinode(dp);
846 inodirty();
847 inoinfo(ino)->ino_state = USTATE;
848 if (idesc.id_type != SNAP)
849 update_uquot(idesc.id_number,
850 idesc.id_uid, idesc.id_gid, 0, -1);
851 n_files--;
852 if (cgp) {
853 clrbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg);
854 cgp->cg_cs.cs_nifree++;
855 sblock->fs_cstotal.cs_nifree++;
856 sblock->fs_cs(fs, cg).cs_nifree++;
857 sbdirty();
858 cgdirty();
859 }
860 }
861
862 /* read a data block from inode */
863 ssize_t
864 readblk(union dinode *dp, off_t offset, struct bufarea **bp)
865 {
866 daddr_t blkno = lblkno(sblock, offset);
867 daddr_t iblkno;
868 int type = IFMT & iswap16(DIP(dp, mode));
869 ssize_t filesize = iswap64(DIP(dp, size));
870 int ilevel;
871 daddr_t nblks;
872 const daddr_t naddrperblk = sblock->fs_bsize /
873 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t));
874 struct bufarea *ibp;
875
876 *bp = NULL;
877 offset &= ~(sblock->fs_bsize - 1);
878
879 if (type != IFREG)
880 return 0;
881 if (offset >= filesize)
882 return 0; /* short read */
883 if (blkno < NDADDR) {
884 blkno = is_ufs2 ? iswap64(dp->dp2.di_db[blkno]) :
885 iswap32(dp->dp1.di_db[blkno]);
886 if (blkno == 0)
887 return 0;
888 *bp = getdatablk(blkno, sblock->fs_bsize);
889 return (bp != NULL) ? sblock->fs_bsize : 0;
890 }
891 blkno -= NDADDR;
892 /* find indir level */
893 for (ilevel = 1, nblks = naddrperblk;
894 ilevel <= NIADDR;
895 ilevel++, nblks *= naddrperblk) {
896 if (blkno < nblks)
897 break;
898 else
899 blkno -= nblks;
900 }
901 if (ilevel > NIADDR)
902 errexit("bad ofsset %" PRIu64 " to readblk", offset);
903
904 /* get the first indirect block */
905 iblkno = is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
906 iswap32(dp->dp1.di_ib[ilevel - 1]);
907 if (iblkno == 0)
908 return 0;
909 ibp = getdatablk(iblkno, sblock->fs_bsize);
910 /* walk indirect blocks up to the data block */
911 for (; ilevel >0 ; ilevel--) {
912 nblks = nblks / naddrperblk;
913 if (is_ufs2)
914 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]);
915 else
916 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]);
917 if (iblkno == 0)
918 return 0;
919 blkno = blkno % nblks;
920 ibp->b_flags &= ~B_INUSE;
921 ibp = getdatablk(iblkno, sblock->fs_bsize);
922 }
923 *bp = ibp;
924 return sblock->fs_bsize;
925 }
926
927 static struct bufarea * getnewblk(daddr_t *);
928 static struct bufarea *
929 getnewblk(daddr_t *blkno)
930 {
931 struct bufarea *bp;
932 *blkno = allocblk(sblock->fs_frag);
933 if (*blkno == 0)
934 return NULL;
935 bp = getdatablk(*blkno, sblock->fs_bsize);
936 memset(bp->b_un.b_buf, 0, sblock->fs_bsize);
937 return bp;
938 }
939
940 /* expand given inode by one full fs block */
941 struct bufarea *
942 expandfile(union dinode *dp)
943 {
944 uint64_t filesize = iswap64(DIP(dp, size));
945 daddr_t newblk, blkno, iblkno, nblks;
946 daddr_t di_blocks;
947 int ilevel;
948 const daddr_t naddrperblk = sblock->fs_bsize /
949 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t));
950 struct bufarea *ibp, *bp = NULL;
951
952 di_blocks = is_ufs2 ? iswap64(dp->dp2.di_blocks) :
953 iswap32(dp->dp1.di_blocks);
954 /* compute location of new block */
955 blkno = lblkno(sblock, filesize);
956
957 if (blkno < NDADDR) {
958 /* easy way: allocate a direct block */
959 if ((bp = getnewblk(&newblk)) == NULL) {
960 return NULL;
961 }
962 di_blocks += btodb(sblock->fs_bsize);
963
964 if (is_ufs2) {
965 dp->dp2.di_db[blkno] = iswap64(newblk);
966 } else {
967 dp->dp1.di_db[blkno] = iswap32(newblk);
968 }
969 goto out;
970 }
971 blkno -= NDADDR;
972 /* find indir level */
973 for (ilevel = 1, nblks = naddrperblk;
974 ilevel <= NIADDR;
975 ilevel++, nblks *= naddrperblk) {
976 if (blkno < nblks)
977 break;
978 else
979 blkno -= nblks;
980 }
981 if (ilevel > NIADDR)
982 errexit("bad filesize %" PRIu64 " to expandfile", filesize);
983
984 /* get the first indirect block, allocating if needed */
985 if ((is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
986 iswap32(dp->dp1.di_ib[ilevel - 1])) == 0) {
987 if ((ibp = getnewblk(&newblk)) == NULL)
988 return 0;
989 di_blocks += btodb(sblock->fs_bsize);
990 if (is_ufs2)
991 dp->dp2.di_ib[ilevel - 1] = iswap64(newblk);
992 else
993 dp->dp1.di_ib[ilevel - 1] = iswap32(newblk);
994 } else {
995 ibp = getdatablk(is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
996 iswap32(dp->dp2.di_ib[ilevel - 1]), sblock->fs_bsize);
997 }
998 /* walk indirect blocks up to the data block */
999 for (; ilevel >0 ; ilevel--) {
1000 nblks = nblks / naddrperblk;
1001 if (is_ufs2)
1002 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]);
1003 else
1004 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]);
1005 if (iblkno == 0) {
1006 if ((bp = getnewblk(&newblk)) == NULL)
1007 return NULL;
1008 di_blocks += btodb(sblock->fs_bsize);
1009 if (is_ufs2)
1010 ibp->b_un.b_indir2[blkno / nblks] =
1011 iswap64(newblk);
1012 else
1013 ibp->b_un.b_indir1[blkno / nblks] =
1014 iswap32(newblk);
1015 dirty(ibp);
1016 ibp->b_flags &= ~B_INUSE;
1017 ibp = bp;
1018 } else {
1019 ibp->b_flags &= ~B_INUSE;
1020 ibp = getdatablk(iblkno, sblock->fs_bsize);
1021 bp = NULL;
1022 }
1023 blkno = blkno % nblks;
1024 }
1025 if (bp == NULL) {
1026 errexit("INTERNAL ERROR: "
1027 "expandfile() failed to allocate a new block\n");
1028 }
1029
1030 out:
1031 filesize += sblock->fs_bsize;
1032 if (is_ufs2) {
1033 dp->dp2.di_size = iswap64(filesize);
1034 dp->dp2.di_blocks = iswap64(di_blocks);
1035 } else {
1036 dp->dp1.di_size = iswap64(filesize);
1037 dp->dp1.di_blocks = iswap32(di_blocks);
1038 }
1039 inodirty();
1040 return bp;
1041 }
1042