Changeset View
Changeset View
Standalone View
Standalone View
sbin/fsck_ffs/dir.c
| Show First 20 Lines • Show All 673 Lines • ▼ Show 20 Lines | |||||
| static int | static int | ||||
| expanddir(struct inode *ip, char *name) | expanddir(struct inode *ip, char *name) | ||||
| { | { | ||||
| ufs2_daddr_t lastlbn, oldblk, newblk, indirblk; | ufs2_daddr_t lastlbn, oldblk, newblk, indirblk; | ||||
| size_t filesize, lastlbnsize; | size_t filesize, lastlbnsize; | ||||
| struct bufarea *bp, *nbp; | struct bufarea *bp, *nbp; | ||||
| struct inodesc idesc; | struct inodesc idesc; | ||||
| union dinode *dp; | union dinode *dp; | ||||
| int indiralloced; | long cg, indiralloced; | ||||
| char *cp; | char *cp; | ||||
| nbp = NULL; | nbp = NULL; | ||||
| indiralloced = newblk = indirblk = 0; | indiralloced = newblk = indirblk = 0; | ||||
| memset(&idesc, 0, sizeof(struct inodesc)); | |||||
| idesc.id_type = ADDR; | |||||
| pwarn("NO SPACE LEFT IN %s", name); | pwarn("NO SPACE LEFT IN %s", name); | ||||
| if (!preen && reply("EXPAND") == 0) | if (!preen && reply("EXPAND") == 0) | ||||
| return (0); | return (0); | ||||
| cg = ino_to_cg(&sblock, ip->i_number); | |||||
| dp = ip->i_dp; | dp = ip->i_dp; | ||||
| filesize = DIP(dp, di_size); | filesize = DIP(dp, di_size); | ||||
| lastlbn = lblkno(&sblock, filesize); | lastlbn = lblkno(&sblock, filesize); | ||||
| /* | /* | ||||
| * We only expand lost+found to a single indirect block. | * We only expand lost+found to a single indirect block. | ||||
| */ | */ | ||||
| if ((DIP(dp, di_mode) & IFMT) != IFDIR || filesize == 0 || | if ((DIP(dp, di_mode) & IFMT) != IFDIR || filesize == 0 || | ||||
| lastlbn >= UFS_NDADDR + NINDIR(&sblock)) | lastlbn >= UFS_NDADDR + NINDIR(&sblock)) | ||||
| goto bad; | goto bad; | ||||
| /* | /* | ||||
| * If last block is a fragment, expand it to a full size block. | * If last block is a fragment, expand it to a full size block. | ||||
| */ | */ | ||||
| lastlbnsize = sblksize(&sblock, filesize, lastlbn); | lastlbnsize = sblksize(&sblock, filesize, lastlbn); | ||||
| if (lastlbnsize > 0 && lastlbnsize < sblock.fs_bsize) { | if (lastlbnsize > 0 && lastlbnsize < sblock.fs_bsize) { | ||||
| oldblk = DIP(dp, di_db[lastlbn]); | oldblk = DIP(dp, di_db[lastlbn]); | ||||
| bp = getdirblk(oldblk, lastlbnsize); | bp = getdirblk(oldblk, lastlbnsize); | ||||
| if (bp->b_errs) | if (bp->b_errs) | ||||
| goto bad; | goto bad; | ||||
| if ((newblk = allocblk(sblock.fs_frag)) == 0) | newblk = allocblk(cg, sblock.fs_frag, std_checkblkavail); | ||||
| if (newblk == 0) | |||||
| goto bad; | goto bad; | ||||
| nbp = getdatablk(newblk, sblock.fs_bsize, BT_DIRDATA); | nbp = getdatablk(newblk, sblock.fs_bsize, BT_DIRDATA); | ||||
| if (nbp->b_errs) | if (nbp->b_errs) | ||||
| goto bad; | goto bad; | ||||
| DIP_SET(dp, di_db[lastlbn], newblk); | DIP_SET(dp, di_db[lastlbn], newblk); | ||||
| DIP_SET(dp, di_size, filesize + sblock.fs_bsize - lastlbnsize); | DIP_SET(dp, di_size, filesize + sblock.fs_bsize - lastlbnsize); | ||||
| DIP_SET(dp, di_blocks, DIP(dp, di_blocks) + | DIP_SET(dp, di_blocks, DIP(dp, di_blocks) + | ||||
| btodb(sblock.fs_bsize - lastlbnsize)); | btodb(sblock.fs_bsize - lastlbnsize)); | ||||
| inodirty(ip); | inodirty(ip); | ||||
| memmove(nbp->b_un.b_buf, bp->b_un.b_buf, lastlbnsize); | memmove(nbp->b_un.b_buf, bp->b_un.b_buf, lastlbnsize); | ||||
| memset(&nbp->b_un.b_buf[lastlbnsize], 0, | memset(&nbp->b_un.b_buf[lastlbnsize], 0, | ||||
| sblock.fs_bsize - lastlbnsize); | sblock.fs_bsize - lastlbnsize); | ||||
| for (cp = &nbp->b_un.b_buf[lastlbnsize]; | for (cp = &nbp->b_un.b_buf[lastlbnsize]; | ||||
| cp < &nbp->b_un.b_buf[sblock.fs_bsize]; | cp < &nbp->b_un.b_buf[sblock.fs_bsize]; | ||||
| cp += DIRBLKSIZ) | cp += DIRBLKSIZ) | ||||
| memmove(cp, &emptydir, sizeof emptydir); | memmove(cp, &emptydir, sizeof emptydir); | ||||
| dirty(nbp); | dirty(nbp); | ||||
| brelse(nbp); | brelse(nbp); | ||||
| binval(bp); | |||||
| idesc.id_blkno = oldblk; | idesc.id_blkno = oldblk; | ||||
| idesc.id_numfrags = numfrags(&sblock, lastlbnsize); | idesc.id_numfrags = numfrags(&sblock, lastlbnsize); | ||||
| (void)freeblock(&idesc); | (void)freeblock(&idesc); | ||||
| if (preen) | if (preen) | ||||
| printf(" (EXPANDED)\n"); | printf(" (EXPANDED)\n"); | ||||
| return (1); | return (1); | ||||
| } | } | ||||
| if ((newblk = allocblk(sblock.fs_frag)) == 0) | if ((newblk = allocblk(cg, sblock.fs_frag, std_checkblkavail)) == 0) | ||||
| goto bad; | goto bad; | ||||
| bp = getdirblk(newblk, sblock.fs_bsize); | bp = getdirblk(newblk, sblock.fs_bsize); | ||||
| if (bp->b_errs) | if (bp->b_errs) | ||||
| goto bad; | goto bad; | ||||
| memset(bp->b_un.b_buf, 0, sblock.fs_bsize); | memset(bp->b_un.b_buf, 0, sblock.fs_bsize); | ||||
| for (cp = bp->b_un.b_buf; | for (cp = bp->b_un.b_buf; | ||||
| cp < &bp->b_un.b_buf[sblock.fs_bsize]; | cp < &bp->b_un.b_buf[sblock.fs_bsize]; | ||||
| cp += DIRBLKSIZ) | cp += DIRBLKSIZ) | ||||
| memmove(cp, &emptydir, sizeof emptydir); | memmove(cp, &emptydir, sizeof emptydir); | ||||
| dirty(bp); | dirty(bp); | ||||
| if (lastlbn < UFS_NDADDR) { | if (lastlbn < UFS_NDADDR) { | ||||
| DIP_SET(dp, di_db[lastlbn], newblk); | DIP_SET(dp, di_db[lastlbn], newblk); | ||||
| } else { | } else { | ||||
| /* | /* | ||||
| * Allocate indirect block if needed. | * Allocate indirect block if needed. | ||||
| */ | */ | ||||
| if ((indirblk = DIP(dp, di_ib[0])) == 0) { | if ((indirblk = DIP(dp, di_ib[0])) == 0) { | ||||
| if ((indirblk = allocblk(sblock.fs_frag)) == 0) | indirblk = allocblk(cg, sblock.fs_frag, | ||||
| std_checkblkavail); | |||||
| if (indirblk == 0) { | |||||
| binval(bp); | |||||
| goto bad; | goto bad; | ||||
| } | |||||
| indiralloced = 1; | indiralloced = 1; | ||||
| } | } | ||||
| nbp = getdatablk(indirblk, sblock.fs_bsize, BT_LEVEL1); | nbp = getdatablk(indirblk, sblock.fs_bsize, BT_LEVEL1); | ||||
| if (nbp->b_errs) | if (nbp->b_errs) | ||||
| goto bad; | goto bad; | ||||
| if (indiralloced) { | if (indiralloced) { | ||||
| memset(nbp->b_un.b_buf, 0, sblock.fs_bsize); | memset(nbp->b_un.b_buf, 0, sblock.fs_bsize); | ||||
| DIP_SET(dp, di_ib[0], indirblk); | DIP_SET(dp, di_ib[0], indirblk); | ||||
| DIP_SET(dp, di_blocks, | DIP_SET(dp, di_blocks, | ||||
| DIP(dp, di_blocks) + btodb(sblock.fs_bsize)); | DIP(dp, di_blocks) + btodb(sblock.fs_bsize)); | ||||
| } | } | ||||
| IBLK_SET(nbp, lastlbn - UFS_NDADDR, newblk); | IBLK_SET(nbp, lastlbn - UFS_NDADDR, newblk); | ||||
| dirty(nbp); | dirty(nbp); | ||||
| brelse(nbp); | brelse(nbp); | ||||
| } | } | ||||
| DIP_SET(dp, di_size, filesize + sblock.fs_bsize); | DIP_SET(dp, di_size, filesize + sblock.fs_bsize); | ||||
| DIP_SET(dp, di_blocks, DIP(dp, di_blocks) + btodb(sblock.fs_bsize)); | DIP_SET(dp, di_blocks, DIP(dp, di_blocks) + btodb(sblock.fs_bsize)); | ||||
| inodirty(ip); | inodirty(ip); | ||||
| if (preen) | if (preen) | ||||
| printf(" (EXPANDED)\n"); | printf(" (EXPANDED)\n"); | ||||
| return (1); | return (1); | ||||
| bad: | bad: | ||||
| pfatal(" (EXPANSION FAILED)\n"); | pfatal(" (EXPANSION FAILED)\n"); | ||||
| if (nbp != NULL) | if (nbp != NULL) { | ||||
| binval(bp); | |||||
| brelse(nbp); | brelse(nbp); | ||||
| } | |||||
| if (newblk != 0) { | if (newblk != 0) { | ||||
| idesc.id_blkno = newblk; | idesc.id_blkno = newblk; | ||||
| idesc.id_numfrags = sblock.fs_frag; | idesc.id_numfrags = sblock.fs_frag; | ||||
| (void)freeblock(&idesc); | (void)freeblock(&idesc); | ||||
| } | } | ||||
| if (indiralloced) { | if (indiralloced) { | ||||
| idesc.id_blkno = indirblk; | idesc.id_blkno = indirblk; | ||||
| idesc.id_numfrags = sblock.fs_frag; | idesc.id_numfrags = sblock.fs_frag; | ||||
| ▲ Show 20 Lines • Show All 130 Lines • Show Last 20 Lines | |||||