xref: /dragonfly/sbin/fsck/inode.c (revision 7d2302ac)
1 /*
2  * Copyright (c) 1980, 1986, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#)inode.c	8.8 (Berkeley) 4/28/95
30  * $FreeBSD: src/sbin/fsck/inode.c,v 1.20 2000/02/28 20:02:41 mckusick Exp $
31  */
32 
33 #include <sys/param.h>
34 #include <sys/time.h>
35 
36 #include <vfs/ufs/dinode.h>
37 #include <vfs/ufs/dir.h>
38 #include <vfs/ufs/fs.h>
39 
40 #include <err.h>
41 #include <pwd.h>
42 #include <string.h>
43 
44 #include "fsck.h"
45 #include "memzone.h"
46 
47 static ufs1_ino_t startinum;
48 
49 static int iblock(struct inodesc *, long ilevel, quad_t isize);
50 
51 int
52 ckinode(struct ufs1_dinode *dp, struct inodesc *idesc)
53 {
54 	ufs_daddr_t *ap;
55 	int ret;
56 	long n, ndb, offset;
57 	struct ufs1_dinode dino;
58 	quad_t remsize, sizepb;
59 	mode_t mode;
60 	char pathbuf[MAXPATHLEN + 1];
61 
62 	if (idesc->id_fix != IGNORE)
63 		idesc->id_fix = DONTKNOW;
64 	idesc->id_entryno = 0;
65 	idesc->id_filesize = dp->di_size;
66 	mode = dp->di_mode & IFMT;
67 	if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
68 	    dp->di_size < (unsigned)sblock.fs_maxsymlinklen))
69 		return (KEEPON);
70 	dino = *dp;
71 	ndb = howmany(dino.di_size, sblock.fs_bsize);
72 	for (ap = &dino.di_db[0]; ap < &dino.di_db[UFS_NDADDR]; ap++) {
73 		if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
74 			idesc->id_numfrags =
75 				numfrags(&sblock, fragroundup(&sblock, offset));
76 		else
77 			idesc->id_numfrags = sblock.fs_frag;
78 		if (*ap == 0) {
79 			if (idesc->id_type == DATA && ndb >= 0) {
80 				/* An empty block in a directory XXX */
81 				getpathname(pathbuf, idesc->id_number,
82 						idesc->id_number);
83                         	pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
84 					pathbuf);
85                         	if (reply("ADJUST LENGTH") == 1) {
86 					dp = ginode(idesc->id_number);
87                                 	dp->di_size = (ap - &dino.di_db[0]) *
88 					    sblock.fs_bsize;
89 					printf(
90 					    "YOU MUST RERUN FSCK AFTERWARDS\n");
91 					rerun = 1;
92                                 	inodirty();
93 
94                         	}
95 			}
96 			continue;
97 		}
98 		idesc->id_blkno = *ap;
99 		if (idesc->id_type == ADDR)
100 			ret = (*idesc->id_func)(idesc);
101 		else
102 			ret = dirscan(idesc);
103 		if (ret & STOP)
104 			return (ret);
105 	}
106 	idesc->id_numfrags = sblock.fs_frag;
107 	remsize = dino.di_size - sblock.fs_bsize * UFS_NDADDR;
108 	sizepb = sblock.fs_bsize;
109 	for (ap = &dino.di_ib[0], n = 1; n <= UFS_NIADDR; ap++, n++) {
110 		if (*ap) {
111 			idesc->id_blkno = *ap;
112 			ret = iblock(idesc, n, remsize);
113 			if (ret & STOP)
114 				return (ret);
115 		} else {
116 			if (idesc->id_type == DATA && remsize > 0) {
117 				/* An empty block in a directory XXX */
118 				getpathname(pathbuf, idesc->id_number,
119 						idesc->id_number);
120                         	pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
121 					pathbuf);
122                         	if (reply("ADJUST LENGTH") == 1) {
123 					dp = ginode(idesc->id_number);
124                                 	dp->di_size -= remsize;
125 					remsize = 0;
126 					printf(
127 					    "YOU MUST RERUN FSCK AFTERWARDS\n");
128 					rerun = 1;
129                                 	inodirty();
130 					break;
131                         	}
132 			}
133 		}
134 		sizepb *= NINDIR(&sblock);
135 		remsize -= sizepb;
136 	}
137 	return (KEEPON);
138 }
139 
140 static int
141 iblock(struct inodesc *idesc, long ilevel, quad_t isize)
142 {
143 	ufs_daddr_t *ap;
144 	ufs_daddr_t *aplim;
145 	struct bufarea *bp;
146 	int i, n, (*func)(), nif;
147 	quad_t sizepb;
148 	char buf[BUFSIZ];
149 	char pathbuf[MAXPATHLEN + 1];
150 	struct ufs1_dinode *dp;
151 
152 	if (idesc->id_type == ADDR) {
153 		func = idesc->id_func;
154 		if (((n = (*func)(idesc)) & KEEPON) == 0)
155 			return (n);
156 	} else
157 		func = dirscan;
158 	if (chkrange(idesc->id_blkno, idesc->id_numfrags))
159 		return (SKIP);
160 	bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
161 	ilevel--;
162 	for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
163 		sizepb *= NINDIR(&sblock);
164 	nif = howmany(isize , sizepb);
165 	if (nif > NINDIR(&sblock))
166 		nif = NINDIR(&sblock);
167 	if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
168 		aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
169 		for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
170 			if (*ap == 0)
171 				continue;
172 			sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu",
173 			    (u_long)idesc->id_number);
174 			if (dofix(idesc, buf)) {
175 				*ap = 0;
176 				dirty(bp);
177 			}
178 		}
179 		flush(fswritefd, bp);
180 	}
181 	aplim = &bp->b_un.b_indir[nif];
182 	for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
183 		if (*ap) {
184 			idesc->id_blkno = *ap;
185 			if (ilevel == 0)
186 				n = (*func)(idesc);
187 			else
188 				n = iblock(idesc, ilevel, isize);
189 			if (n & STOP) {
190 				bp->b_flags &= ~B_INUSE;
191 				return (n);
192 			}
193 		} else {
194 			if (idesc->id_type == DATA && isize > 0) {
195 				/* An empty block in a directory XXX */
196 				getpathname(pathbuf, idesc->id_number,
197 						idesc->id_number);
198                         	pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
199 					pathbuf);
200                         	if (reply("ADJUST LENGTH") == 1) {
201 					dp = ginode(idesc->id_number);
202                                 	dp->di_size -= isize;
203 					isize = 0;
204 					printf(
205 					    "YOU MUST RERUN FSCK AFTERWARDS\n");
206 					rerun = 1;
207                                 	inodirty();
208 					bp->b_flags &= ~B_INUSE;
209 					return(STOP);
210                         	}
211 			}
212 		}
213 		isize -= sizepb;
214 	}
215 	bp->b_flags &= ~B_INUSE;
216 	return (KEEPON);
217 }
218 
219 /*
220  * Check that a block in a legal block number.
221  * Return 0 if in range, 1 if out of range.
222  */
223 int
224 chkrange(ufs_daddr_t blk, int cnt)
225 {
226 	int c;
227 
228 	if (cnt <= 0 || blk <= 0 || blk > maxfsblock ||
229 	    cnt - 1 > maxfsblock - blk)
230 		return (1);
231 	if (cnt > sblock.fs_frag ||
232 	    fragnum(&sblock, blk) + cnt > sblock.fs_frag) {
233 		if (debug)
234 			printf("bad size: blk %ld, offset %d, size %d\n",
235 				(long)blk, fragnum(&sblock, blk), cnt);
236 		return (1);
237 	}
238 	c = dtog(&sblock, blk);
239 	if (blk < cgdmin(&sblock, c)) {
240 		if ((blk + cnt) > cgsblock(&sblock, c)) {
241 			if (debug) {
242 				printf("blk %ld < cgdmin %ld;",
243 				    (long)blk, (long)cgdmin(&sblock, c));
244 				printf(" blk + cnt %ld > cgsbase %ld\n",
245 				    (long)(blk + cnt),
246 				    (long)cgsblock(&sblock, c));
247 			}
248 			return (1);
249 		}
250 	} else {
251 		if ((blk + cnt) > cgbase(&sblock, c+1)) {
252 			if (debug)  {
253 				printf("blk %ld >= cgdmin %ld;",
254 				    (long)blk, (long)cgdmin(&sblock, c));
255 				printf(" blk + cnt %ld > sblock.fs_fpg %ld\n",
256 				    (long)(blk + cnt), (long)sblock.fs_fpg);
257 			}
258 			return (1);
259 		}
260 	}
261 	return (0);
262 }
263 
264 /*
265  * General purpose interface for reading inodes.
266  */
267 struct ufs1_dinode *
268 ginode(ufs1_ino_t inumber)
269 {
270 	ufs_daddr_t iblk;
271 
272 	if (inumber < UFS_ROOTINO || inumber > maxino)
273 		errx(EEXIT, "bad inode number %d to ginode", inumber);
274 	if (startinum == 0 ||
275 	    inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
276 		iblk = ino_to_fsba(&sblock, inumber);
277 		if (pbp != 0)
278 			pbp->b_flags &= ~B_INUSE;
279 		pbp = getdatablk(iblk, sblock.fs_bsize);
280 		startinum = rounddown(inumber, INOPB(&sblock));
281 	}
282 	return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
283 }
284 
285 /*
286  * Special purpose version of ginode used to optimize first pass
287  * over all the inodes in numerical order.
288  */
289 ufs1_ino_t nextino, lastinum;
290 long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
291 struct ufs1_dinode *inodebuf;
292 
293 struct ufs1_dinode *
294 getnextinode(ufs1_ino_t inumber)
295 {
296 	long size;
297 	ufs_daddr_t dblk;
298 	static struct ufs1_dinode *dp;
299 
300 	if (inumber != nextino++ || inumber > maxino)
301 		errx(EEXIT, "bad inode number %d to nextinode", inumber);
302 	if (inumber >= lastinum) {
303 		readcnt++;
304 		dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum));
305 		if (readcnt % readpercg == 0) {
306 			size = partialsize;
307 			lastinum += partialcnt;
308 		} else {
309 			size = inobufsize;
310 			lastinum += fullcnt;
311 		}
312 		/*
313 		 * If bread returns an error, it will already have zeroed
314 		 * out the buffer, so we do not need to do so here.
315 		 */
316 		bread(fsreadfd, (char *)inodebuf, dblk, size);
317 		dp = inodebuf;
318 	}
319 	return (dp++);
320 }
321 
322 void
323 setinodebuf(ufs1_ino_t inum)
324 {
325 
326 	if (inum % sblock.fs_ipg != 0)
327 		errx(EEXIT, "bad inode number %d to setinodebuf", inum);
328 	startinum = 0;
329 	nextino = inum;
330 	lastinum = inum;
331 	readcnt = 0;
332 	if (inodebuf != NULL)
333 		return;
334 	inobufsize = blkroundup(&sblock, INOBUFSIZE);
335 	fullcnt = inobufsize / sizeof(struct ufs1_dinode);
336 	readpercg = sblock.fs_ipg / fullcnt;
337 	partialcnt = sblock.fs_ipg % fullcnt;
338 	partialsize = partialcnt * sizeof(struct ufs1_dinode);
339 	if (partialcnt != 0) {
340 		readpercg++;
341 	} else {
342 		partialcnt = fullcnt;
343 		partialsize = inobufsize;
344 	}
345 	if ((inodebuf = (struct ufs1_dinode *)malloc((unsigned)inobufsize)) == NULL)
346 		errx(EEXIT, "cannot allocate space for inode buffer");
347 }
348 
349 void
350 freeinodebuf(void)
351 {
352 
353 	if (inodebuf != NULL)
354 		free((char *)inodebuf);
355 	inodebuf = NULL;
356 }
357 
358 /*
359  * Routines to maintain information about directory inodes.
360  * This is built during the first pass and used during the
361  * second and third passes.
362  *
363  * Enter inodes into the cache.
364  */
365 static struct memzone inoinfo_zone;
366 
367 void
368 cacheino(struct ufs1_dinode *dp, ufs1_ino_t inumber)
369 {
370 	struct inoinfo *inp;
371 	struct inoinfo **inpp;
372 	int blks;
373 
374 	blks = howmany(dp->di_size, sblock.fs_bsize);
375 	if (blks > UFS_NDADDR)
376 		blks = UFS_NDADDR + UFS_NIADDR;
377 	inp = mzalloc(&inoinfo_zone,
378 		      sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t));
379 	if (inp == NULL)
380 		errx(EEXIT, "cannot increase directory list");
381 	inpp = &inphead[DIRHASH(inumber)];
382 	inp->i_nexthash = *inpp;
383 	*inpp = inp;
384 	inp->i_parent = inumber == UFS_ROOTINO ? UFS_ROOTINO : (ufs1_ino_t)0;
385 	inp->i_dotdot = (ufs1_ino_t)0;
386 	inp->i_number = inumber;
387 	inp->i_isize = dp->di_size;
388 	inp->i_numblks = blks * sizeof(ufs_daddr_t);
389 	memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks);
390 	if (inplast == listmax) {
391 		listmax += 100;
392 		inpsort = (struct inoinfo **)realloc((char *)inpsort,
393 		    (unsigned)listmax * sizeof(struct inoinfo *));
394 		if (inpsort == NULL)
395 			errx(EEXIT, "cannot increase directory list");
396 	}
397 	inpsort[inplast++] = inp;
398 }
399 
400 /*
401  * Look up an inode cache structure.
402  */
403 struct inoinfo *
404 getinoinfo(ufs1_ino_t inumber)
405 {
406 	struct inoinfo *inp;
407 
408 	for (inp = inphead[DIRHASH(inumber)]; inp; inp = inp->i_nexthash) {
409 		if (inp->i_number != inumber)
410 			continue;
411 		return (inp);
412 	}
413 	errx(EEXIT, "cannot find inode %d", inumber);
414 	return (NULL);
415 }
416 
417 /*
418  * Clean up all the inode cache structure.
419  */
420 void
421 inocleanup(void)
422 {
423 	if (inphead == NULL)
424 		return;
425 	mzpurge(&inoinfo_zone);
426 	free((char *)inphead);
427 	free((char *)inpsort);
428 	inphead = inpsort = NULL;
429 }
430 
431 void
432 inodirty(void)
433 {
434 
435 	dirty(pbp);
436 }
437 
438 void
439 clri(struct inodesc *idesc, char *type, int flag)
440 {
441 	struct ufs1_dinode *dp;
442 
443 	dp = ginode(idesc->id_number);
444 	if (flag == 1) {
445 		pwarn("%s %s", type,
446 		    (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
447 		pinode(idesc->id_number);
448 	}
449 	if (preen || reply("CLEAR") == 1) {
450 		if (preen)
451 			printf(" (CLEARED)\n");
452 		n_files--;
453 		ckinode(dp, idesc);
454 		clearinode(dp);
455 		inoinfo(idesc->id_number)->ino_state = USTATE;
456 		inodirty();
457 	}
458 }
459 
460 int
461 findname(struct inodesc *idesc)
462 {
463 	struct direct *dirp = idesc->id_dirp;
464 
465 	if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
466 		idesc->id_entryno++;
467 		return (KEEPON);
468 	}
469 	memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
470 	return (STOP|FOUND);
471 }
472 
473 int
474 findino(struct inodesc *idesc)
475 {
476 	struct direct *dirp = idesc->id_dirp;
477 
478 	if (dirp->d_ino == 0)
479 		return (KEEPON);
480 	if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
481 	    dirp->d_ino >= UFS_ROOTINO && dirp->d_ino <= maxino) {
482 		idesc->id_parent = dirp->d_ino;
483 		return (STOP|FOUND);
484 	}
485 	return (KEEPON);
486 }
487 
488 int
489 clearentry(struct inodesc *idesc)
490 {
491 	struct direct *dirp = idesc->id_dirp;
492 
493 	if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
494 		idesc->id_entryno++;
495 		return (KEEPON);
496 	}
497 	dirp->d_ino = 0;
498 	return (STOP|FOUND|ALTERED);
499 }
500 
501 void
502 pinode(ufs1_ino_t ino)
503 {
504 	struct ufs1_dinode *dp;
505 	char *p;
506 	struct passwd *pw;
507 	time_t t;
508 
509 	printf(" I=%lu ", (u_long)ino);
510 	if (ino < UFS_ROOTINO || ino > maxino)
511 		return;
512 	dp = ginode(ino);
513 	printf(" OWNER=");
514 	if ((pw = getpwuid((int)dp->di_uid)) != NULL)
515 		printf("%s ", pw->pw_name);
516 	else
517 		printf("%u ", (unsigned)dp->di_uid);
518 	printf("MODE=%o\n", dp->di_mode);
519 	if (preen)
520 		printf("%s: ", cdevname);
521 	printf("SIZE=%ju ", (uintmax_t)dp->di_size);
522 	t = dp->di_mtime;
523 	p = ctime(&t);
524 	printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
525 }
526 
527 void
528 blkerror(ufs1_ino_t ino, char *type, ufs_daddr_t blk)
529 {
530 
531 	pfatal("%d %s I=%u", blk, type, ino);
532 	printf("\n");
533 	switch (inoinfo(ino)->ino_state) {
534 
535 	case FSTATE:
536 		inoinfo(ino)->ino_state = FCLEAR;
537 		return;
538 
539 	case DSTATE:
540 		inoinfo(ino)->ino_state = DCLEAR;
541 		return;
542 
543 	case FCLEAR:
544 	case DCLEAR:
545 		return;
546 
547 	default:
548 		errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state);
549 		/* NOTREACHED */
550 	}
551 }
552 
553 /*
554  * allocate an unused inode
555  */
556 ufs1_ino_t
557 allocino(ufs1_ino_t request, int type)
558 {
559 	ufs1_ino_t ino;
560 	struct ufs1_dinode *dp;
561 	struct cg *cgp = &cgrp;
562 	int cg;
563 
564 	if (request == 0)
565 		request = UFS_ROOTINO;
566 	else if (inoinfo(request)->ino_state != USTATE)
567 		return (0);
568 	for (ino = request; ino < maxino; ino++)
569 		if (inoinfo(ino)->ino_state == USTATE)
570 			break;
571 	if (ino == maxino)
572 		return (0);
573 	cg = ino_to_cg(&sblock, ino);
574 	getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
575 	if (!cg_chkmagic(cgp))
576 		pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
577 	setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
578 	cgp->cg_cs.cs_nifree--;
579 	switch (type & IFMT) {
580 	case IFDIR:
581 		inoinfo(ino)->ino_state = DSTATE;
582 		cgp->cg_cs.cs_ndir++;
583 		break;
584 	case IFREG:
585 	case IFLNK:
586 		inoinfo(ino)->ino_state = FSTATE;
587 		break;
588 	default:
589 		return (0);
590 	}
591 	cgdirty();
592 	dp = ginode(ino);
593 	dp->di_db[0] = allocblk((long)1);
594 	if (dp->di_db[0] == 0) {
595 		inoinfo(ino)->ino_state = USTATE;
596 		return (0);
597 	}
598 	dp->di_mode = type;
599 	dp->di_flags = 0;
600 	dp->di_atime = time(NULL);
601 	dp->di_mtime = dp->di_ctime = dp->di_atime;
602 	dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0;
603 	dp->di_size = sblock.fs_fsize;
604 	dp->di_blocks = btodb(sblock.fs_fsize);
605 	n_files++;
606 	inodirty();
607 	if (newinofmt)
608 		inoinfo(ino)->ino_type = IFTODT(type);
609 	return (ino);
610 }
611 
612 /*
613  * deallocate an inode
614  */
615 void
616 freeino(ufs1_ino_t ino)
617 {
618 	struct inodesc idesc;
619 	struct ufs1_dinode *dp;
620 
621 	memset(&idesc, 0, sizeof(struct inodesc));
622 	idesc.id_type = ADDR;
623 	idesc.id_func = pass4check;
624 	idesc.id_number = ino;
625 	dp = ginode(ino);
626 	ckinode(dp, &idesc);
627 	clearinode(dp);
628 	inodirty();
629 	inoinfo(ino)->ino_state = USTATE;
630 	n_files--;
631 }
632