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