2 * Copyright (c) 1980, 1986 The Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 #include <afsconfig.h>
19 #include <afs/param.h>
22 /* We need the old directory type headers (included below), so don't include
23 * the normal dirent.h, or it will conflict. */
25 # include <sys/inode.h>
26 # define LONGFILENAMES 1
27 # include <sys/sysmacros.h>
30 # ifdef HAVE_USR_OLD_USR_INCLUDE_NDIR_H
31 # include </usr/old/usr/include/ndir.h>
41 #define VICE /* control whether AFS changes are present */
43 #ifdef AFS_VFSINCL_ENV
45 #include <sys/vnode.h>
47 #include <sys/fs/ufs_inode.h>
48 #include <sys/fs/ufs_fs.h>
50 #include <sys/fs/ufs_fsdir.h>
53 #include <ufs/inode.h>
55 #include <ufs/fsdir.h>
59 #else /* AFS_VFSINCL_ENV */
60 #include <sys/inode.h>
65 #endif /* AFS_VFSINCL_ENV */
67 #include <afs/osi_inode.h>
72 #include <sys/mnttab.h>
73 #include <sys/mntent.h>
77 #endif /* AFS_SUN_ENV */
79 struct bufarea *pbp = 0;
83 struct inodesc *idesc;
86 long ret, n, ndb, offset;
88 UOFF_T indir_data_blks;
89 extern int pass1check();
95 idesc->id_fix = DONTKNOW;
96 idesc->id_entryno = 0;
97 idesc->id_filesize = dp->di_size;
98 if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR)
101 ndb = howmany(dino.di_size, (UOFF_T) sblock.fs_bsize);
103 for (; ap < &dino.di_db[NDADDR]; ap++) {
104 if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
106 numfrags(&sblock, fragroundup(&sblock, offset));
108 idesc->id_numfrags = sblock.fs_frag;
111 idesc->id_blkno = *ap;
112 if (idesc->id_type == ADDR)
113 ret = (*idesc->id_func) (idesc);
115 ret = dirscan(idesc);
119 idesc->id_numfrags = sblock.fs_frag;
120 #if defined(AFS_SUN5_ENV)
122 * indir_data_blks determine the no. of data blocks
123 * in the previous levels. ie., at level 3 it
124 * is the number of data blocks at level 2, 1, and 0.
126 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
129 indir_data_blks = NDADDR;
132 indir_data_blks = NDADDR + NINDIR(&sblock);
136 NDADDR + NINDIR(&sblock) +
137 (NINDIR(&sblock) * NINDIR(&sblock));
140 idesc->id_blkno = *ap;
143 (u_offset_t) howmany(dino.di_size,
144 (u_offset_t) sblock.fs_bsize) -
151 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
153 idesc->id_blkno = *ap;
154 ret = iblock(idesc, n, dino.di_size - sblock.fs_bsize * NDADDR);
163 iblock(idesc, ilevel, isize)
164 struct inodesc *idesc;
170 int i, n, (*func) ();
175 extern int dirscan(), pass1check();
177 if (idesc->id_type == ADDR) {
178 func = idesc->id_func;
179 if (((n = (*func) (idesc)) & KEEPON) == 0)
183 if (chkrange(idesc->id_blkno, idesc->id_numfrags))
185 bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
187 #if defined(AFS_SUN5_ENV)
188 for (sizepb = 1, i = 0; i < ilevel; i++) {
189 sizepb *= (u_offset_t) NINDIR(&sblock);
193 * nif indicates the next "free" pointer (as an array index) in this
194 * indirect block, based on counting the blocks remaining in the
195 * file after subtracting all previously processed blocks.
196 * This figure is based on the size field of the inode.
198 * Note that in normal operation, nif may initially calculated to
199 * be larger than the number of pointers in this block; if that is
200 * the case, nif is limited to the max number of pointers per
203 * Also note that if an inode is inconsistant (has more blocks
204 * allocated to it than the size field would indicate), the sweep
205 * through any indirect blocks directly pointed at by the inode
206 * continues. Since the block offset of any data blocks referenced
207 * by these indirect blocks is greater than the size of the file,
208 * the index nif may be computed as a negative value.
209 * In this case, we reset nif to indicate that all pointers in
210 * this retrieval block should be zeroed and the resulting
211 * unreferenced data and/or retrieval blocks be recovered
212 * through garbage collection later.
214 nif = (offset_t) howmany(isize, sizepb);
215 if (nif > NINDIR(&sblock))
216 nif = NINDIR(&sblock);
220 for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
221 sizepb *= (UOFF_T) NINDIR(&sblock);
222 nif = isize / sizepb + 1;
223 if (nif > NINDIR(&sblock))
224 nif = NINDIR(&sblock);
226 if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
227 aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
228 for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
231 (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%d",
233 if (dofix(idesc, buf)) {
238 flush(fswritefd, bp);
240 aplim = &bp->b_un.b_indir[nif];
241 for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) {
243 idesc->id_blkno = *ap;
245 #if defined(AFS_SUN5_ENV)
246 n = iblock(idesc, ilevel, isize);
248 * each iteration decrease "remaining block
249 * count" by however many blocks were accessible
250 * by a pointer at this indirect block level.
254 n = iblock(idesc, ilevel, isize - i * sizepb);
259 bp->b_flags &= ~B_INUSE;
264 bp->b_flags &= ~B_INUSE;
269 * Check that a block in a legal block number.
270 * Return 0 if in range, 1 if out of range.
278 if ((unsigned)(blk + cnt) > maxfsblock)
280 c = dtog(&sblock, blk);
281 if (blk < cgdmin(&sblock, c)) {
282 if ((blk + cnt) > cgsblock(&sblock, c)) {
284 printf("blk %d < cgdmin %d;", blk, cgdmin(&sblock, c));
285 printf(" blk + cnt %d > cgsbase %d\n", blk + cnt,
286 cgsblock(&sblock, c));
291 if ((blk + cnt) > cgbase(&sblock, c + 1)) {
293 printf("blk %d >= cgdmin %d;", blk, cgdmin(&sblock, c));
294 printf(" blk + cnt %d > sblock.fs_fpg %d\n", blk + cnt,
309 if (inumber < ROOTINO || inumber > maxino)
310 errexit("bad inode number %d to ginode\n", inumber);
311 if (mlk_startinum == 0 || inumber < mlk_startinum
312 || inumber >= mlk_startinum + INOPB(&sblock)) {
313 iblk = itod(&sblock, inumber);
315 pbp->b_flags &= ~B_INUSE;
316 pbp = getdatablk(iblk, sblock.fs_bsize);
317 mlk_startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
319 return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
325 struct inoinfo **inpp;
329 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
333 inphead = inpsort = NULL;
343 clri(idesc, type, flag)
344 struct inodesc *idesc;
349 #if defined(ACLS) && defined(AFS_HPUX_ENV)
350 struct inodesc cidesc;
353 dp = ginode(idesc->id_number);
355 pwarn("%s %s", type, (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
356 pinode(idesc->id_number);
357 #if defined(ACLS) && defined(AFS_HPUX_ENV)
358 } else if (flag == 2) {
359 pwarn("%s %s", type, "CONTINUATION INODE ");
360 printf(" I=%u ", idesc->id_number);
363 if (preen || reply("CLEAR") == 1) {
365 printf(" (CLEARED)\n");
366 #if defined(ACLS) && defined(AFS_HPUX_ENV)
373 * If there is a CI associated with this inode, we must
376 if (statemap[idesc->id_number] & HASCINODE) {
377 if (!(dp->di_contin < ROOTINO || dp->di_contin > maxino))
378 cidesc.id_number = dp->di_contin;
379 clri(&cidesc, "UNREF", 2);
384 (void)ckinode(dp, idesc);
390 statemap[idesc->id_number] = USTATE;
396 struct inodesc *idesc;
398 struct direct *dirp = idesc->id_dirp;
400 if (dirp->d_ino != idesc->id_parent)
402 memcpy(idesc->id_name, dirp->d_name, (int)dirp->d_namlen + 1);
403 return (STOP | FOUND);
407 struct inodesc *idesc;
409 struct direct *dirp = idesc->id_dirp;
411 if (dirp->d_ino == 0)
413 if (strcmp(dirp->d_name, idesc->id_name) == 0 && dirp->d_ino >= ROOTINO
414 && dirp->d_ino <= maxino) {
415 idesc->id_parent = dirp->d_ino;
416 return (STOP | FOUND);
430 printf(" I=%u ", ino);
431 if (ino < ROOTINO || ino > maxino)
435 #if defined(AFS_HPUX110_ENV)
441 pwarn("Could not getinode(%d) in pinode.", ino);
444 uid = _GET_D_UID(dp);
445 if (getpw(uid, uidbuf) == 0) {
446 for (p = uidbuf; *p != ':'; p++);
448 printf("%s ", uidbuf);
453 #else /* AFS_HPUX110_ENV */
454 #if defined(AFS_HPUX102_ENV)
455 if ((pw = getpwuid(_GET_D_UID(dp))) != 0)
456 printf("%s ", pw->pw_name);
458 printf("%d ", _GET_D_UID(dp));
459 #else /* AFS_HPUX102_ENV */
460 if ((pw = getpwuid((int)dp->di_uid)) != 0)
461 printf("%s ", pw->pw_name);
463 printf("%d ", dp->di_uid);
464 #endif /* else AFS_HPUX102_ENV */
465 #endif /* else AFS_HPUX110_ENV */
466 printf("MODE=%o\n", dp->di_mode);
468 printf("%s: ", devname);
469 #if defined(AFS_SUN5_ENV)
470 printf("SIZE=%" AFS_INT64_FMT " ", dp->di_size);
472 printf("SIZE=%ld ", dp->di_size);
476 printf("MTIME=%12.12s %4.4s ", p + 4, p + 20);
479 blkerror(ino, type, blk)
485 pfatal("%ld %s I=%u", blk, type, ino);
487 switch (statemap[ino]) {
493 #if defined(ACLS) && defined(AFS_HPUX_ENV)
495 * Keep the continuation inode info
497 if (statemap[ino] & HASCINODE)
498 statemap[ino] = FCLEAR | HASCINODE;
500 statemap[ino] = FCLEAR;
502 statemap[ino] = FCLEAR;
507 #if defined(ACLS) && defined(AFS_HPUX_ENV)
509 * Keep the continuation inode info
511 if (statemap[ino] & HASCINODE)
512 statemap[ino] = DCLEAR | HASCINODE;
514 statemap[ino] = DCLEAR;
516 statemap[ino] = DCLEAR;
525 errexit("BAD STATE %d TO BLKERR", statemap[ino]);
531 * allocate an unused inode
534 allocino(request, type)
543 else if (statemap[request] != USTATE)
545 for (ino = request; ino < maxino; ino++)
546 if (statemap[ino] == USTATE)
550 switch (type & IFMT) {
552 statemap[ino] = DSTATE;
556 statemap[ino] = FSTATE;
562 dp->di_db[0] = allocblk((long)1);
563 if (dp->di_db[0] == 0) {
564 statemap[ino] = USTATE;
569 dp->di_mtime = dp->di_ctime = dp->di_atime;
570 dp->di_size = sblock.fs_fsize;
571 dp->di_blocks = btodb(sblock.fs_fsize);
579 * deallocate an inode
584 struct inodesc idesc;
585 extern int pass4check();
588 memset(&idesc, 0, sizeof(struct inodesc));
589 idesc.id_type = ADDR;
590 idesc.id_func = pass4check;
591 idesc.id_number = ino;
593 (void)ckinode(dp, &idesc);
600 statemap[ino] = USTATE;