pass1.c revision 74556
18871Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1986, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3541477Sjulian#if 0 3623675Speterstatic const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; 3741477Sjulian#endif 3841477Sjulianstatic const char rcsid[] = 3950476Speter "$FreeBSD: head/sbin/fsck_ffs/pass1.c 74556 2001-03-21 09:48:03Z mckusick $"; 401558Srgrimes#endif /* not lint */ 411558Srgrimes 421558Srgrimes#include <sys/param.h> 4362668Smckusick#include <sys/stat.h> 4474556Smckusick#include <sys/sysctl.h> 4523675Speter 461558Srgrimes#include <ufs/ufs/dinode.h> 471558Srgrimes#include <ufs/ufs/dir.h> 481558Srgrimes#include <ufs/ffs/fs.h> 4923675Speter 5023675Speter#include <err.h> 511558Srgrimes#include <string.h> 5223675Speter 531558Srgrimes#include "fsck.h" 541558Srgrimes 5523675Speterstatic ufs_daddr_t badblk; 5623675Speterstatic ufs_daddr_t dupblk; 5741474Sjulianstatic ino_t lastino; /* last inode in use */ 581558Srgrimes 5923675Speterstatic void checkinode __P((ino_t inumber, struct inodesc *)); 607585Sbde 617585Sbdevoid 621558Srgrimespass1() 631558Srgrimes{ 6441474Sjulian u_int8_t *cp; 651558Srgrimes ino_t inumber; 6641474Sjulian int c, i, cgd, inosused; 6741474Sjulian struct inostat *info; 681558Srgrimes struct inodesc idesc; 691558Srgrimes 701558Srgrimes /* 711558Srgrimes * Set file system reserved blocks in used block map. 721558Srgrimes */ 731558Srgrimes for (c = 0; c < sblock.fs_ncg; c++) { 741558Srgrimes cgd = cgdmin(&sblock, c); 751558Srgrimes if (c == 0) { 761558Srgrimes i = cgbase(&sblock, c); 771558Srgrimes } else 781558Srgrimes i = cgsblock(&sblock, c); 791558Srgrimes for (; i < cgd; i++) 801558Srgrimes setbmap(i); 811558Srgrimes } 8269800Stomsoft i = sblock.fs_csaddr; 8369800Stomsoft cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize); 8469800Stomsoft for (; i < cgd; i++) 8569800Stomsoft setbmap(i); 8669800Stomsoft 871558Srgrimes /* 881558Srgrimes * Find all allocated blocks. 891558Srgrimes */ 9023675Speter memset(&idesc, 0, sizeof(struct inodesc)); 911558Srgrimes idesc.id_func = pass1check; 921558Srgrimes n_files = n_blks = 0; 931558Srgrimes for (c = 0; c < sblock.fs_ncg; c++) { 9441474Sjulian inumber = c * sblock.fs_ipg; 9541474Sjulian setinodebuf(inumber); 9641474Sjulian inosused = sblock.fs_ipg; 9770050Siedowse if (got_siginfo) { 9870050Siedowse printf("%s: phase 1: cyl group %d of %d (%d%%)\n", 9970050Siedowse cdevname, c, sblock.fs_ncg, 10070050Siedowse c * 100 / sblock.fs_ncg); 10170050Siedowse got_siginfo = 0; 10270050Siedowse } 10341474Sjulian /* 10441474Sjulian * If we are using soft updates, then we can trust the 10541474Sjulian * cylinder group inode allocation maps to tell us which 10641474Sjulian * inodes are allocated. We will scan the used inode map 10741474Sjulian * to find the inodes that are really in use, and then 10841474Sjulian * read only those inodes in from disk. 10941474Sjulian */ 11041474Sjulian if (preen && usedsoftdep) { 11141474Sjulian getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize); 11241474Sjulian if (!cg_chkmagic(&cgrp)) 11341474Sjulian pfatal("CG %d: BAD MAGIC NUMBER\n", c); 11441474Sjulian cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY]; 11541474Sjulian for ( ; inosused > 0; inosused -= NBBY, cp--) { 11641474Sjulian if (*cp == 0) 11741474Sjulian continue; 11841474Sjulian for (i = 1 << (NBBY - 1); i > 0; i >>= 1) { 11941474Sjulian if (*cp & i) 12041474Sjulian break; 12141474Sjulian inosused--; 12241474Sjulian } 12341474Sjulian break; 12441474Sjulian } 12541474Sjulian if (inosused < 0) 12641474Sjulian inosused = 0; 12741474Sjulian } 12841474Sjulian /* 12941474Sjulian * Allocate inoinfo structures for the allocated inodes. 13041474Sjulian */ 13141474Sjulian inostathead[c].il_numalloced = inosused; 13241474Sjulian if (inosused == 0) { 13341474Sjulian inostathead[c].il_stat = 0; 13441474Sjulian continue; 13541474Sjulian } 13641474Sjulian info = calloc((unsigned)inosused, sizeof(struct inostat)); 13741474Sjulian if (info == NULL) 13841474Sjulian pfatal("cannot alloc %u bytes for inoinfo\n", 13941474Sjulian (unsigned)(sizeof(struct inostat) * inosused)); 14041474Sjulian inostathead[c].il_stat = info; 14141474Sjulian /* 14241474Sjulian * Scan the allocated inodes. 14341474Sjulian */ 14441474Sjulian for (i = 0; i < inosused; i++, inumber++) { 14541474Sjulian if (inumber < ROOTINO) { 14641474Sjulian (void)getnextinode(inumber); 1471558Srgrimes continue; 14841474Sjulian } 1491558Srgrimes checkinode(inumber, &idesc); 1501558Srgrimes } 15141474Sjulian lastino += 1; 15241474Sjulian if (inosused < sblock.fs_ipg || inumber == lastino) 15341474Sjulian continue; 15441474Sjulian /* 15541474Sjulian * If we were not able to determine in advance which inodes 15641474Sjulian * were in use, then reduce the size of the inoinfo structure 15741474Sjulian * to the size necessary to describe the inodes that we 15841474Sjulian * really found. 15941474Sjulian */ 16041474Sjulian inosused = lastino - (c * sblock.fs_ipg); 16141474Sjulian if (inosused < 0) 16241474Sjulian inosused = 0; 16341474Sjulian inostathead[c].il_numalloced = inosused; 16441474Sjulian if (inosused == 0) { 16541474Sjulian free(inostathead[c].il_stat); 16641474Sjulian inostathead[c].il_stat = 0; 16741474Sjulian continue; 16841474Sjulian } 16941474Sjulian info = calloc((unsigned)inosused, sizeof(struct inostat)); 17041474Sjulian if (info == NULL) 17141474Sjulian pfatal("cannot alloc %u bytes for inoinfo\n", 17241474Sjulian (unsigned)(sizeof(struct inostat) * inosused)); 17341474Sjulian memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); 17441474Sjulian free(inostathead[c].il_stat); 17541474Sjulian inostathead[c].il_stat = info; 1761558Srgrimes } 1771558Srgrimes freeinodebuf(); 1781558Srgrimes} 1791558Srgrimes 18023675Speterstatic void 1811558Srgrimescheckinode(inumber, idesc) 1821558Srgrimes ino_t inumber; 1831558Srgrimes register struct inodesc *idesc; 1841558Srgrimes{ 1851558Srgrimes register struct dinode *dp; 1861558Srgrimes struct zlncnt *zlnp; 18771884Siedowse u_int64_t kernmaxfilesize; 18871884Siedowse ufs_daddr_t ndb, j; 1891558Srgrimes mode_t mode; 1902603Sdg char *symbuf; 1911558Srgrimes 1921558Srgrimes dp = getnextinode(inumber); 1931558Srgrimes mode = dp->di_mode & IFMT; 1941558Srgrimes if (mode == 0) { 19523675Speter if (memcmp(dp->di_db, zino.di_db, 19623675Speter NDADDR * sizeof(ufs_daddr_t)) || 19723675Speter memcmp(dp->di_ib, zino.di_ib, 19823675Speter NIADDR * sizeof(ufs_daddr_t)) || 1991558Srgrimes dp->di_mode || dp->di_size) { 2001558Srgrimes pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); 2011558Srgrimes if (reply("CLEAR") == 1) { 2021558Srgrimes dp = ginode(inumber); 2031558Srgrimes clearinode(dp); 2041558Srgrimes inodirty(); 2051558Srgrimes } 2061558Srgrimes } 20741474Sjulian inoinfo(inumber)->ino_state = USTATE; 2081558Srgrimes return; 2091558Srgrimes } 2101558Srgrimes lastino = inumber; 21171884Siedowse /* This should match the file size limit in ffs_mountfs(). */ 21271884Siedowse kernmaxfilesize = (u_int64_t)0x40000000 * sblock.fs_bsize - 1; 21371884Siedowse if (dp->di_size > kernmaxfilesize || 21471884Siedowse dp->di_size > sblock.fs_maxfilesize || 21523999Speter (mode == IFDIR && dp->di_size > MAXDIRSIZE)) { 2161558Srgrimes if (debug) 2171558Srgrimes printf("bad size %qu:", dp->di_size); 2181558Srgrimes goto unknown; 2191558Srgrimes } 2201558Srgrimes if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 2211558Srgrimes dp = ginode(inumber); 2221558Srgrimes dp->di_size = sblock.fs_fsize; 2231558Srgrimes dp->di_mode = IFREG|0600; 2241558Srgrimes inodirty(); 2251558Srgrimes } 22663003Smckusick if ((mode == IFBLK || mode == IFCHR || mode == IFIFO || 22763003Smckusick mode == IFSOCK) && dp->di_size != 0) { 22863003Smckusick if (debug) 22963003Smckusick printf("bad special-file size %qu:", dp->di_size); 23063003Smckusick goto unknown; 23163003Smckusick } 23272525Stegge if ((mode == IFBLK || mode == IFCHR) && (dev_t)dp->di_rdev == NODEV) { 23372525Stegge if (debug) 23472525Stegge printf("bad special-file rdev NODEV:"); 23572525Stegge goto unknown; 23672525Stegge } 2371558Srgrimes ndb = howmany(dp->di_size, sblock.fs_bsize); 2381558Srgrimes if (ndb < 0) { 2391558Srgrimes if (debug) 2401558Srgrimes printf("bad size %qu ndb %d:", 2411558Srgrimes dp->di_size, ndb); 2421558Srgrimes goto unknown; 2431558Srgrimes } 2441558Srgrimes if (mode == IFBLK || mode == IFCHR) 2451558Srgrimes ndb++; 2461558Srgrimes if (mode == IFLNK) { 2471558Srgrimes if (doinglevel2 && 2481558Srgrimes dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && 2491558Srgrimes dp->di_blocks != 0) { 2502603Sdg symbuf = alloca(secsize); 2511558Srgrimes if (bread(fsreadfd, symbuf, 2521558Srgrimes fsbtodb(&sblock, dp->di_db[0]), 2532603Sdg (long)secsize) != 0) 25423675Speter errx(EEXIT, "cannot read symlink"); 2551558Srgrimes if (debug) { 2561558Srgrimes symbuf[dp->di_size] = 0; 25737236Sbde printf("convert symlink %lu(%s) of size %ld\n", 25841474Sjulian (u_long)inumber, symbuf, (long)dp->di_size); 2591558Srgrimes } 2601558Srgrimes dp = ginode(inumber); 26123675Speter memmove(dp->di_shortlink, symbuf, (long)dp->di_size); 2621558Srgrimes dp->di_blocks = 0; 2631558Srgrimes inodirty(); 2641558Srgrimes } 2651558Srgrimes /* 2661558Srgrimes * Fake ndb value so direct/indirect block checks below 2671558Srgrimes * will detect any garbage after symlink string. 2681558Srgrimes */ 26974556Smckusick if (dp->di_size < (u_int64_t)sblock.fs_maxsymlinklen) { 27023675Speter ndb = howmany(dp->di_size, sizeof(ufs_daddr_t)); 2711558Srgrimes if (ndb > NDADDR) { 2721558Srgrimes j = ndb - NDADDR; 2731558Srgrimes for (ndb = 1; j > 1; j--) 2741558Srgrimes ndb *= NINDIR(&sblock); 2751558Srgrimes ndb += NDADDR; 2761558Srgrimes } 2771558Srgrimes } 2781558Srgrimes } 2791558Srgrimes for (j = ndb; j < NDADDR; j++) 2801558Srgrimes if (dp->di_db[j] != 0) { 2811558Srgrimes if (debug) 28237236Sbde printf("bad direct addr: %ld\n", 28337236Sbde (long)dp->di_db[j]); 2841558Srgrimes goto unknown; 2851558Srgrimes } 2861558Srgrimes for (j = 0, ndb -= NDADDR; ndb > 0; j++) 2871558Srgrimes ndb /= NINDIR(&sblock); 2881558Srgrimes for (; j < NIADDR; j++) 2891558Srgrimes if (dp->di_ib[j] != 0) { 2901558Srgrimes if (debug) 2911558Srgrimes printf("bad indirect addr: %ld\n", 29237236Sbde (long)dp->di_ib[j]); 2931558Srgrimes goto unknown; 2941558Srgrimes } 2951558Srgrimes if (ftypeok(dp) == 0) 2961558Srgrimes goto unknown; 2971558Srgrimes n_files++; 29841474Sjulian inoinfo(inumber)->ino_linkcnt = dp->di_nlink; 2991558Srgrimes if (dp->di_nlink <= 0) { 3001558Srgrimes zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 3011558Srgrimes if (zlnp == NULL) { 3021558Srgrimes pfatal("LINK COUNT TABLE OVERFLOW"); 30334266Sjulian if (reply("CONTINUE") == 0) { 30434266Sjulian ckfini(0); 30523675Speter exit(EEXIT); 30634266Sjulian } 3071558Srgrimes } else { 3081558Srgrimes zlnp->zlncnt = inumber; 3091558Srgrimes zlnp->next = zlnhead; 3101558Srgrimes zlnhead = zlnp; 3111558Srgrimes } 3121558Srgrimes } 3131558Srgrimes if (mode == IFDIR) { 3141558Srgrimes if (dp->di_size == 0) 31541474Sjulian inoinfo(inumber)->ino_state = DCLEAR; 3161558Srgrimes else 31741474Sjulian inoinfo(inumber)->ino_state = DSTATE; 3181558Srgrimes cacheino(dp, inumber); 31941474Sjulian countdirs++; 3201558Srgrimes } else 32141474Sjulian inoinfo(inumber)->ino_state = FSTATE; 32241474Sjulian inoinfo(inumber)->ino_type = IFTODT(mode); 3231558Srgrimes if (doinglevel2 && 3241558Srgrimes (dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) { 3251558Srgrimes dp = ginode(inumber); 3261558Srgrimes dp->di_uid = dp->di_ouid; 3271558Srgrimes dp->di_ouid = -1; 3281558Srgrimes dp->di_gid = dp->di_ogid; 3291558Srgrimes dp->di_ogid = -1; 3301558Srgrimes inodirty(); 3311558Srgrimes } 3321558Srgrimes badblk = dupblk = 0; 3331558Srgrimes idesc->id_number = inumber; 33462668Smckusick if (dp->di_flags & SF_SNAPSHOT) 33562668Smckusick idesc->id_type = SNAP; 33662668Smckusick else 33762668Smckusick idesc->id_type = ADDR; 3381558Srgrimes (void)ckinode(dp, idesc); 3391558Srgrimes idesc->id_entryno *= btodb(sblock.fs_fsize); 3401558Srgrimes if (dp->di_blocks != idesc->id_entryno) { 3411558Srgrimes pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", 3421558Srgrimes inumber, dp->di_blocks, idesc->id_entryno); 3431558Srgrimes if (preen) 3441558Srgrimes printf(" (CORRECTED)\n"); 3451558Srgrimes else if (reply("CORRECT") == 0) 3461558Srgrimes return; 34774556Smckusick if (bkgrdflag == 0) { 34874556Smckusick dp = ginode(inumber); 34974556Smckusick dp->di_blocks = idesc->id_entryno; 35074556Smckusick inodirty(); 35174556Smckusick } else { 35274556Smckusick cmd.value = idesc->id_number; 35374556Smckusick cmd.size = idesc->id_entryno - dp->di_blocks; 35474556Smckusick if (debug) 35574556Smckusick printf("adjblkcnt ino %d amount %d\n", 35674556Smckusick (long)cmd.value, cmd.size); 35774556Smckusick if (sysctl(adjblkcnt, MIBSIZE, 0, 0, 35874556Smckusick &cmd, sizeof cmd) == -1) 35974556Smckusick rwerror("ADJUST INODE BLOCK COUNT", cmd.value); 36074556Smckusick } 3611558Srgrimes } 3621558Srgrimes return; 3631558Srgrimesunknown: 3641558Srgrimes pfatal("UNKNOWN FILE TYPE I=%lu", inumber); 36541474Sjulian inoinfo(inumber)->ino_state = FCLEAR; 3661558Srgrimes if (reply("CLEAR") == 1) { 36741474Sjulian inoinfo(inumber)->ino_state = USTATE; 3681558Srgrimes dp = ginode(inumber); 3691558Srgrimes clearinode(dp); 3701558Srgrimes inodirty(); 3711558Srgrimes } 3721558Srgrimes} 3731558Srgrimes 3747585Sbdeint 3751558Srgrimespass1check(idesc) 3761558Srgrimes register struct inodesc *idesc; 3771558Srgrimes{ 3781558Srgrimes int res = KEEPON; 3791558Srgrimes int anyout, nfrags; 38023675Speter ufs_daddr_t blkno = idesc->id_blkno; 3811558Srgrimes register struct dups *dlp; 3821558Srgrimes struct dups *new; 3831558Srgrimes 38462668Smckusick if (idesc->id_type == SNAP) { 38562668Smckusick if (blkno == BLK_NOCOPY) 38662668Smckusick return (KEEPON); 38762668Smckusick if (idesc->id_number == cursnapshot) { 38862668Smckusick if (blkno == blkstofrags(&sblock, idesc->id_lbn)) 38962668Smckusick return (KEEPON); 39062668Smckusick if (blkno == BLK_SNAP) { 39162668Smckusick blkno = blkstofrags(&sblock, idesc->id_lbn); 39262668Smckusick idesc->id_entryno -= idesc->id_numfrags; 39362668Smckusick } 39462668Smckusick } else { 39562668Smckusick if (blkno == BLK_SNAP) 39662668Smckusick return (KEEPON); 39762668Smckusick } 39862668Smckusick } 3991558Srgrimes if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 4001558Srgrimes blkerror(idesc->id_number, "BAD", blkno); 4011558Srgrimes if (badblk++ >= MAXBAD) { 4021558Srgrimes pwarn("EXCESSIVE BAD BLKS I=%lu", 4031558Srgrimes idesc->id_number); 4041558Srgrimes if (preen) 4051558Srgrimes printf(" (SKIPPING)\n"); 40634266Sjulian else if (reply("CONTINUE") == 0) { 40734266Sjulian ckfini(0); 40823675Speter exit(EEXIT); 40934266Sjulian } 4101558Srgrimes return (STOP); 4111558Srgrimes } 4121558Srgrimes } 4131558Srgrimes for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 4141558Srgrimes if (anyout && chkrange(blkno, 1)) { 4151558Srgrimes res = SKIP; 4161558Srgrimes } else if (!testbmap(blkno)) { 4171558Srgrimes n_blks++; 4181558Srgrimes setbmap(blkno); 4191558Srgrimes } else { 4201558Srgrimes blkerror(idesc->id_number, "DUP", blkno); 4211558Srgrimes if (dupblk++ >= MAXDUP) { 4221558Srgrimes pwarn("EXCESSIVE DUP BLKS I=%lu", 4231558Srgrimes idesc->id_number); 4241558Srgrimes if (preen) 4251558Srgrimes printf(" (SKIPPING)\n"); 42634266Sjulian else if (reply("CONTINUE") == 0) { 42734266Sjulian ckfini(0); 42823675Speter exit(EEXIT); 42934266Sjulian } 4301558Srgrimes return (STOP); 4311558Srgrimes } 4321558Srgrimes new = (struct dups *)malloc(sizeof(struct dups)); 4331558Srgrimes if (new == NULL) { 4341558Srgrimes pfatal("DUP TABLE OVERFLOW."); 43534266Sjulian if (reply("CONTINUE") == 0) { 43634266Sjulian ckfini(0); 43723675Speter exit(EEXIT); 43834266Sjulian } 4391558Srgrimes return (STOP); 4401558Srgrimes } 4411558Srgrimes new->dup = blkno; 4421558Srgrimes if (muldup == 0) { 4431558Srgrimes duplist = muldup = new; 4441558Srgrimes new->next = 0; 4451558Srgrimes } else { 4461558Srgrimes new->next = muldup->next; 4471558Srgrimes muldup->next = new; 4481558Srgrimes } 4491558Srgrimes for (dlp = duplist; dlp != muldup; dlp = dlp->next) 4501558Srgrimes if (dlp->dup == blkno) 4511558Srgrimes break; 4521558Srgrimes if (dlp == muldup && dlp->dup != blkno) 4531558Srgrimes muldup = new; 4541558Srgrimes } 4551558Srgrimes /* 4561558Srgrimes * count the number of blocks found in id_entryno 4571558Srgrimes */ 4581558Srgrimes idesc->id_entryno++; 4591558Srgrimes } 4601558Srgrimes return (res); 4611558Srgrimes} 462