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>
23 #define VICE /* control whether AFS changes are present */
27 #include <sys/param.h>
30 #include <sys/mount.h>
31 #include <sys/vnode.h>
32 #include <ufs/inode.h>
39 #else /* AFS_OSF_ENV */
40 #ifdef AFS_VFSINCL_ENV
42 #include <sys/vnode.h>
44 #include <sys/fs/ufs_inode.h>
45 #include <sys/fs/ufs_fs.h>
47 #include <sys/fs/ufs_fsdir.h>
50 #include <ufs/inode.h>
52 #include <ufs/fsdir.h>
56 #else /* AFS_VFSINCL_ENV */
57 #include <sys/inode.h>
60 #define LONGFILENAMES 1
61 #include <sys/sysmacros.h>
69 #endif /* AFS_VFSINCL_ENV */
70 #endif /* AFS_OSF_ENV */
72 #include <afs/osi_inode.h>
78 #include <sys/mnttab.h>
79 #include <sys/mntent.h>
83 #endif /* AFS_SUN_ENV */
85 struct bufarea *pbp = 0;
89 register struct inodesc *idesc;
92 long ret, n, ndb, offset;
94 UOFF_T indir_data_blks;
95 extern int pass1check();
101 idesc->id_fix = DONTKNOW;
102 idesc->id_entryno = 0;
103 idesc->id_filesize = dp->di_size;
104 if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR)
107 if ((dp->di_flags & IC_FASTLINK) != 0) {
110 #endif /* AFS_OSF_ENV */
112 ndb = howmany(dino.di_size, (UOFF_T)sblock.fs_bsize);
116 * Check property lists on pass1
118 if (idesc->id_func == pass1check &&
119 dino.di_flags & IC_PROPLIST && *ap) {
120 ret = proplist_scan(dp, idesc);
124 #endif /* AFS_OSF_ENV */
125 for (; ap < &dino.di_db[NDADDR]; ap++) {
126 if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
128 numfrags(&sblock, fragroundup(&sblock, offset));
130 idesc->id_numfrags = sblock.fs_frag;
133 idesc->id_blkno = *ap;
134 if (idesc->id_type == ADDR)
135 ret = (*idesc->id_func)(idesc);
137 ret = dirscan(idesc);
141 idesc->id_numfrags = sblock.fs_frag;
142 #if defined(AFS_SUN56_ENV)
144 * indir_data_blks determine the no. of data blocks
145 * in the previous levels. ie., at level 3 it
146 * is the number of data blocks at level 2, 1, and 0.
148 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
151 indir_data_blks = NDADDR;
154 indir_data_blks = NDADDR + NINDIR(&sblock);
157 indir_data_blks = NDADDR + NINDIR(&sblock) +
158 (NINDIR(&sblock) * NINDIR(&sblock));
161 idesc->id_blkno = *ap;
162 ret = iblock(idesc, n,
163 (u_offset_t)howmany(dino.di_size,
164 (u_offset_t)sblock.fs_bsize) - indir_data_blks);
170 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
172 idesc->id_blkno = *ap;
173 ret = iblock(idesc, n,
174 dino.di_size - sblock.fs_bsize * NDADDR);
183 iblock(idesc, ilevel, isize)
184 struct inodesc *idesc;
185 register long ilevel;
188 register daddr_t *ap;
189 register daddr_t *aplim;
193 register struct bufarea *bp;
195 extern int dirscan(), pass1check();
197 if (idesc->id_type == ADDR) {
198 func = idesc->id_func;
199 if (((n = (*func)(idesc)) & KEEPON) == 0)
203 if (chkrange(idesc->id_blkno, idesc->id_numfrags))
205 bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
207 #if defined(AFS_SUN56_ENV)
208 for (sizepb = 1, i = 0; i < ilevel; i++) {
209 sizepb *= (u_offset_t)NINDIR(&sblock);
213 * nif indicates the next "free" pointer (as an array index) in this
214 * indirect block, based on counting the blocks remaining in the
215 * file after subtracting all previously processed blocks.
216 * This figure is based on the size field of the inode.
218 * Note that in normal operation, nif may initially calculated to
219 * be larger than the number of pointers in this block; if that is
220 * the case, nif is limited to the max number of pointers per
223 * Also note that if an inode is inconsistant (has more blocks
224 * allocated to it than the size field would indicate), the sweep
225 * through any indirect blocks directly pointed at by the inode
226 * continues. Since the block offset of any data blocks referenced
227 * by these indirect blocks is greater than the size of the file,
228 * the index nif may be computed as a negative value.
229 * In this case, we reset nif to indicate that all pointers in
230 * this retrieval block should be zeroed and the resulting
231 * unreferenced data and/or retrieval blocks be recovered
232 * through garbage collection later.
234 nif = (offset_t)howmany(isize, sizepb);
235 if (nif > NINDIR(&sblock))
236 nif = NINDIR(&sblock);
240 for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
241 sizepb *= (UOFF_T)NINDIR(&sblock);
242 nif = isize / sizepb + 1;
243 if (nif > NINDIR(&sblock))
244 nif = NINDIR(&sblock);
246 if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
247 aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
248 for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
251 (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%d",
253 if (dofix(idesc, buf)) {
258 flush(fswritefd, bp);
260 aplim = &bp->b_un.b_indir[nif];
261 for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) {
263 idesc->id_blkno = *ap;
265 #if defined(AFS_SUN56_ENV)
266 n = iblock(idesc, ilevel, isize);
268 * each iteration decrease "remaining block
269 * count" by however many blocks were accessible
270 * by a pointer at this indirect block level.
274 n = iblock(idesc, ilevel, isize - i * sizepb);
280 bp->b_flags &= ~B_INUSE;
285 bp->b_flags &= ~B_INUSE;
290 * Check that a block in a legal block number.
291 * Return 0 if in range, 1 if out of range.
299 if ((unsigned)(blk + cnt) > maxfsblock)
301 c = dtog(&sblock, blk);
302 if (blk < cgdmin(&sblock, c)) {
303 if ((blk + cnt) > cgsblock(&sblock, c)) {
305 printf("blk %d < cgdmin %d;",
306 blk, cgdmin(&sblock, c));
307 printf(" blk + cnt %d > cgsbase %d\n",
308 blk + cnt, cgsblock(&sblock, c));
313 if ((blk + cnt) > cgbase(&sblock, c+1)) {
315 printf("blk %d >= cgdmin %d;",
316 blk, cgdmin(&sblock, c));
317 printf(" blk + cnt %d > sblock.fs_fpg %d\n",
318 blk+cnt, sblock.fs_fpg);
332 if (inumber < ROOTINO || inumber > maxino)
333 errexit("bad inode number %d to ginode\n", inumber);
334 if (mlk_startinum == 0 ||
335 inumber < mlk_startinum || inumber >= mlk_startinum + INOPB(&sblock)) {
336 iblk = itod(&sblock, inumber);
338 pbp->b_flags &= ~B_INUSE;
339 pbp = getdatablk(iblk, sblock.fs_bsize);
340 mlk_startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
342 return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
348 register struct inoinfo **inpp;
352 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
353 free((char *)(*inpp));
354 free((char *)inphead);
355 free((char *)inpsort);
356 inphead = inpsort = NULL;
366 clri(idesc, type, flag)
367 register struct inodesc *idesc;
371 register struct dinode *dp;
372 #if defined(ACLS) && defined(AFS_HPUX_ENV)
373 struct inodesc cidesc;
376 dp = ginode(idesc->id_number);
379 (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
380 pinode(idesc->id_number);
381 #if defined(ACLS) && defined(AFS_HPUX_ENV)
382 } else if (flag == 2) {
383 pwarn("%s %s", type, "CONTINUATION INODE ");
384 printf(" I=%u ", idesc->id_number);
387 if (preen || reply("CLEAR") == 1) {
389 printf(" (CLEARED)\n");
390 #if defined(ACLS) && defined(AFS_HPUX_ENV)
397 * If there is a CI associated with this inode, we must
400 if (statemap[idesc->id_number] & HASCINODE) {
401 if (!(dp->di_contin < ROOTINO || dp->di_contin > maxino))
402 cidesc.id_number = dp->di_contin;
403 clri(&cidesc, "UNREF", 2);
408 (void)ckinode(dp, idesc);
414 statemap[idesc->id_number] = USTATE;
420 struct inodesc *idesc;
422 register struct direct *dirp = idesc->id_dirp;
424 if (dirp->d_ino != idesc->id_parent)
426 bcopy(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1);
431 struct inodesc *idesc;
433 register struct direct *dirp = idesc->id_dirp;
435 if (dirp->d_ino == 0)
437 if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
438 dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) {
439 idesc->id_parent = dirp->d_ino;
448 register struct dinode *dp;
453 printf(" I=%u ", ino);
454 if (ino < ROOTINO || ino > maxino)
458 #if defined(AFS_HPUX110_ENV)
464 pwarn("Could not getinode(%d) in pinode.", ino);
467 uid = _GET_D_UID(dp);
468 if (getpw(uid, uidbuf) == 0) {
469 for (p = uidbuf; *p != ':'; p++);
471 printf("%s ", uidbuf);
476 #else /* AFS_HPUX110_ENV */
477 #if defined(AFS_HPUX102_ENV)
478 if ((pw = getpwuid(_GET_D_UID(dp))) != 0)
479 printf("%s ", pw->pw_name);
481 printf("%d ", _GET_D_UID(dp));
482 #else /* AFS_HPUX102_ENV */
483 if ((pw = getpwuid((int)dp->di_uid)) != 0)
484 printf("%s ", pw->pw_name);
486 printf("%d ", dp->di_uid);
487 #endif /* else AFS_HPUX102_ENV */
488 #endif /* else AFS_HPUX110_ENV */
489 printf("MODE=%o\n", dp->di_mode);
491 printf("%s: ", devname);
492 #if defined(AFS_SUN56_ENV)
493 printf("SIZE=%lld ", dp->di_size);
495 printf("SIZE=%ld ", dp->di_size);
497 p = ctime(&dp->di_mtime);
498 printf("MTIME=%12.12s %4.4s ", p + 4, p + 20);
501 blkerror(ino, type, blk)
507 pfatal("%ld %s I=%u", blk, type, ino);
509 switch (statemap[ino]) {
515 #if defined(ACLS) && defined(AFS_HPUX_ENV)
517 * Keep the continuation inode info
519 if (statemap[ino] & HASCINODE)
520 statemap[ino] = FCLEAR|HASCINODE;
522 statemap[ino] = FCLEAR;
524 statemap[ino] = FCLEAR;
529 #if defined(ACLS) && defined(AFS_HPUX_ENV)
531 * Keep the continuation inode info
533 if (statemap[ino] & HASCINODE)
534 statemap[ino] = DCLEAR|HASCINODE;
536 statemap[ino] = DCLEAR;
538 statemap[ino] = DCLEAR;
547 errexit("BAD STATE %d TO BLKERR", statemap[ino]);
553 * allocate an unused inode
556 allocino(request, type)
561 register struct dinode *dp;
565 else if (statemap[request] != USTATE)
567 for (ino = request; ino < maxino; ino++)
568 if (statemap[ino] == USTATE)
572 switch (type & IFMT) {
574 statemap[ino] = DSTATE;
578 statemap[ino] = FSTATE;
584 dp->di_db[0] = allocblk((long)1);
585 if (dp->di_db[0] == 0) {
586 statemap[ino] = USTATE;
591 dp->di_mtime = dp->di_ctime = dp->di_atime;
592 dp->di_size = sblock.fs_fsize;
593 dp->di_blocks = btodb(sblock.fs_fsize);
601 * deallocate an inode
606 struct inodesc idesc;
607 extern int pass4check();
610 bzero((char *)&idesc, sizeof(struct inodesc));
611 idesc.id_type = ADDR;
612 idesc.id_func = pass4check;
613 idesc.id_number = ino;
615 (void)ckinode(dp, &idesc);
622 statemap[ino] = USTATE;