Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!wuarchive!cs.utexas.edu!uunet!pcrat!rick From: rick@pcrat.uucp (Rick Richardson) Newsgroups: comp.sources.d Subject: Re: v08i093: System V disk compactor Summary: Here's the fixes for 16 bit machines Keywords: packdisk, pcc patches, 80286 patches, performance improvment Message-ID: <1989Oct15.073237.2472@pcrat.uucp> Date: 15 Oct 89 07:32:37 GMT References: <69626@uunet.UU.NET> <1383@rebel.UUCP> <1989Oct14.130123.1067@pcrat.uucp> Reply-To: rick@pcrat.UUCP (Rick Richardson) Organization: PC Research, Inc., Tinton Falls, NJ Lines: 863 In article <1989Oct14.130123.1067@pcrat.uucp> rick@pcrat.UUCP (Rick Richardson) writes: >I would like to warn people that even after applying Georges patches, >which are good, there are still some other problems with packdisk. I fixed the stuff for 16 bit machines, Venix/286 filesystems, and made a performance enhancement. I present the entire package again here, with Georges and my changes, because the "patch" file was twice as big as just sending the whole shar. I believe that the changes are all compatible and integrated with the original package. I've run this on a 44 MB filesystem which was horribly fragmented (46% fragmented, average seek 139 cyls). The filesystem is now less than 2% fragmented with an average seek of 1.02 cyclinders. I'm done with "packdisk", and I doubt I'll need it again for several months. The performance improvement I made (added a reference count) was critical to the success of using packdisk on 16 bit hardware. Before the algorithm change, extrapolation led me to estimate that the process would take some 60 hours to complete. The original algorithm was compute bound, moving a block only every 2-4 seconds. Worse yet, the portion of the algorithm that was compute bound was approximately quadratic with the size of the partition being repacked. After the improvement, the program is nearly I/O bound, and runs some twenty times faster. I repacked the 44MB's in 3 hours flat on an 80286 running at 7.5 Mhz. Standard IBM AT disk controller (3:1), and a Micropolis 28 msec drive. Most people will want to compile with -DOLDC, and pay attention to the definiton of FsBSIZEdev at the beginning of packdisk.c 16 bit folks will need to add -DSMALL and -Ml (large model), and pay attention to the definition of MAXBLKS. Large model is used because you'll need plenty of memory for the block mapping and reference count arrays. This program has been needed for years, and I congratulate Andy Fyfe for getting the job done. -Rick Richardson PC Research, Inc. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # README # COPYRIGHT # Makefile # packdisk.c # This archive created: Sun Oct 15 03:08:41 1989 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'README' then echo shar: "will not over-write existing file 'README'" else sed 's/^X//' << \SHAR_EOF > 'README' XThis program rearranges the files and directories on a disk Xso that they appear contiguously. This is to counteract the Xfragmentation that occurs after a time under System V. After Xthe program finishes all the free space will be collected at Xthe end of the disk. X XThis program was written on an AT&T 3b1 (running unix version 3.5). XWhile the program was written with portability in mind, it is *not* Xguaranteed to run on *any* machine, not even the 3b1. It has, Xhowever, worked for me. X XYou should run fsck before running this program, and again after Xit's done, just to be sure! X XThe program is *slow*. However, the disk is updated after *every* Xblock is moved, so the file system should be in a consistent state Xif the program is halted for any reason (except for the free list, Xwhich is not rebuilt until the very end). X XI don't guarantee that this program won't destroy your disk. XMake sure you have a backup just in case!!! X XTo run the program, simply give the disk device as its only Xargument. The program will normally ensure that the given name Xis a character special device. If compiled with '-DDEBUG', this Xcheck is eliminated. This allows, for example, you to "dd" a Xfloppy to a disk file (say /tmp/disk) and then run the program Xwith '/tmp/disk' as its argument. When running on a real disk, Xthe disk in question *must* *not* be mounted!!! X XRemember: THIS PROGRAM IS POTENTIALLY VERY DANGEROUS. Use it Xat your own risk. X X Andrew Fyfe X andy@csvax.caltech.edu X X------------------------------------------------------------------- X * I took George Sipe's "-DOLDC" fixes, and added fixes X * for 16 bit machines "-DSMALL", a compatible fix for filesystems X * that store s_nfree as a short (no compile option needed), and X * the most important thing -- an algorithm speedup. Without X * the speedup, I estimated that the program would take 60 hours X * to run in my environment. It now takes 3 hours, and could be X * improved even more. Look for "RERSPEEDUP" below. The speedup X * invloves using a reference count to decide whether the block X * map needs to be scanned for indirect block references. When X * -DSMALL is defined, the filesystem size is limited to 128K X * 1024 byte blocks. These changes worked for me, and should X * be compatible with the original version. Still, USE AT YOUR X * OWN RISK! X * X * Rick Richardson X * 14 October 1989 X * uunet!pcrat!rick SHAR_EOF fi if test -f 'COPYRIGHT' then echo shar: "will not over-write existing file 'COPYRIGHT'" else sed 's/^X//' << \SHAR_EOF > 'COPYRIGHT' X/* X * Copyright (c) Andrew Fyfe, 1989 X * All rights reserved. X * Written by Andrew Fyfe. X * X * Permission is granted to anyone to use this software for any purpose on X * any computer system, and to alter it and redistribute it freely, subject X * to the following restrictions: X * X * 1. The author is not responsible for the consequences of use of this X * software, no matter how awful, even if they arise from flaws in it. X * X * 2. The origin of this software must not be misrepresented, either by X * explicit claim or by omission. Since few users ever read sources, X * credits must appear in the documentation. X * X * 3. Altered versions must be plainly marked as such, and must not be X * misrepresented as being the original software. Since few users X * ever read sources, credits must appear in the documentation. X * X * 4. This notice may not be removed or altered. X */ X X /* X * This notice is copied from that included with cnews, which was X * written (mostly) by Geoffrey Collyer and Henry Spencer. X */ SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X#CC = gcc -Wall XCC = cc XCFLAGS = -O # System V on 32 bit machine with function prototypes compiler XCFLAGS = -O -DOLDC # System V on 32 bit machine without function prototypes XCFLAGS = -Ml -DSMALL -DOLDC -O # Venix/286 XLINTFLAGS = -DSMALL -DOLDC # Venix/286 XLDFLAGS = # -shlib X Xpackdisk: packdisk.o X $(CC) $(CFLAGS) $(LDFLAGS) -o packdisk packdisk.o X Xlint: X lint $(LINTFLAGS) packdisk.c > lint.out X Xshar: X shar -p X README COPYRIGHT Makefile packdisk.c > packdisk.shar SHAR_EOF fi if test -f 'packdisk.c' then echo shar: "will not over-write existing file 'packdisk.c'" else sed 's/^X//' << \SHAR_EOF > 'packdisk.c' X/* X * X * This program takes a disk and makes all the files and directories, X * and the free list, contiguous. X * X * Andrew Fyfe X * 7 October 1989 X * X * andy@csvax.caltech.edu X */ X X/* X * I took George Sipe's "-DOLDC" fixes, and added fixes X * for 16 bit machines "-DSMALL", a compatible fix for filesystems X * that store s_nfree as a short (no compile option needed), and X * the most important thing -- an algorithm speedup. Without X * the speedup, I estimated that the program would take 60 hours X * to run in my environment. It now takes 3 hours, and could be X * improved even more. Look for "RERSPEEDUP" below. The speedup X * invloves using a reference count to decide whether the block X * map needs to be scanned for indirect block references. When X * -DSMALL is defined, the filesystem size is limited to 128K X * 1024 byte blocks. These changes worked for me, and should X * be compatible with the original version. Still, USE AT YOUR X * OWN RISK! X * X * Rick Richardson X * 14 October 1989 X * uunet!pcrat!rick X */ X X#ifndef OLDC X#include X#endif X#include X#include X#include X#include X#include X#include X X#ifndef OLDC X#define FsBSIZEdev FsBSIZE(dev) X#else X#define FsBSIZEdev 1024 /* BE SURE THIS IS OK FOR YOU */ X#endif X X#define NUM_ADDR 13 X#define FIRST_INDIR 10 /* 0-9 direct, 10 single, 11 double, 12 triple */ X#define NUM_INDIR (NUM_ADDR - FIRST_INDIR) X Xchar *cmd_name; Xint disk, dev; X Xstruct filsys filsys; X Xstruct dinode ino; /* current working inode, and its number */ Xino_t w_ino; X Xchar *inode_block; /* block containing last read/written inode */ Xdaddr_t w_ino_blk; /* and its number */ X Xchar *indir[NUM_INDIR]; /* current working indirect blocks */ Xdaddr_t w_indir[NUM_INDIR]; /* and their numbers */ X Xdaddr_t next_fill; /* next (sequential) block to fill */ X Xchar *inode_table; /* a cache of the entire inode section of the disk */ X X#ifdef SMALL X#define MAXINT 32767 /* Size of an integer */ X#define MAXBLKS (128L*1024) /* Max blocks in a filesystem */ X#define MAPSEG (4096) /* # blocks in each array */ X#define MN(BLN) (BLN/MAPSEG) /* Map number to use */ X#define BN(BLN) (BLN&(MAPSEG-1)) /* Block index in map */ X#define MB(BLN) (BLN/MAPSEG)][(BLN&(MAPSEG-1)) Xlong *map[MAXBLKS/MAPSEG]; X /* a map from block numbers to referencing inode/indir block */ Xint *ref[MAXBLKS/MAPSEG]; X /* reference count for block number (RERSPEEDUP) */ X#else X#define MAXINT 2147483647 /* Size of an integer */ Xlong *map; /* a map from block numbers to referencing inode/indir block */ Xint *ref; /* a map from block numbers to referencing inode/indir block */ X#endif X X#ifndef OLDC Xstatic void read_superblk(void); Xstatic void write_superblk(void); Xstatic void map_inode(ino_t inode); Xstatic void update_map(long map_entry, daddr_t block, int level); Xstatic void read_block(daddr_t block, void *buf); Xstatic void write_block(daddr_t block, void *buf); Xstatic void read_inode(ino_t inode, struct dinode *buf); Xstatic void write_inode(ino_t inode, struct dinode *buf); Xstatic void move_block(daddr_t from, daddr_t to); Xstatic void move_inode(ino_t inode); Xstatic void move_indirect(daddr_t block, int level); Xstatic void make_hole(void); Xstatic void rebuild_free_list(void); X Xextern void l3tol(long *, char *, int length); Xextern void ltol3(char *, long *, int length); X#else X#define move_indirect Move_Indirect /* make uniq */ Xextern char *calloc(); Xextern char *malloc(); Xextern char *memcpy(); Xextern char *memset(); Xextern long lseek(); Xextern void exit(); Xextern void perror(); X Xstatic void read_superblk(); Xstatic void write_superblk(); Xstatic void map_inode(); Xstatic void update_map(); Xstatic void read_block(); Xstatic void write_block(); Xstatic void read_inode(); Xstatic void write_inode(); Xstatic void move_block(); Xstatic void move_inode(); Xstatic void move_indirect(); Xstatic void make_hole(); Xstatic void rebuild_free_list(); X Xextern void l3tol(); Xextern void ltol3(); X#endif X Xint main(argc, argv) Xint argc; Xchar *argv[]; X{ X ino_t inode, total_inodes; X daddr_t block; X long isize; X int ilimit = -1; X int i; X#ifndef OLDC X char *ctime(long *); X#ifndef DEBUG X struct stat statb; X extern int stat(const char *, struct stat *); X#endif X#else X char *ctime(); X#ifndef DEBUG X struct stat statb; X extern int stat(); X#endif X#endif X X cmd_name = argv[0]; X X if (argc < 2) { X (void) fprintf(stderr, "%s: Usage: %s \n", X cmd_name, cmd_name); X exit(1); X } X X if (argc == 3) ilimit = atoi(argv[2]); X X#ifndef DEBUG X if (stat(argv[1], &statb) < 0) { X (void) fprintf(stderr, "%s: can't stat %s: ", cmd_name, argv[1]); X perror(""); X exit(1); X } X if ((statb.st_mode & S_IFMT) != S_IFCHR) { X (void) fprintf(stderr, "%s: %s is not a character device\n", X cmd_name, argv[1]); X exit(1); X } X#endif X X disk = open(argv[1], 2, 0); X if (disk < 0) { X (void) fprintf(stderr, "%s: can't open %s: ", cmd_name, argv[1]); X perror(""); X exit(1); X } X X read_superblk(); X X total_inodes = (filsys.s_isize - FsITOD(dev, ROOTINO)) * FsINOPB(dev); X (void) fprintf(stderr, "File system: name: \"%.6s\", pack: \"%.6s\"\n", X filsys.s_fname, filsys.s_fpack); X (void) fprintf(stderr, "\tlast modified on %s", ctime(&filsys.s_time)); X (void) fprintf(stderr, X "\ttotal inodes = %d, data blocks = %ld, total = %ld blocks\n", X total_inodes, filsys.s_fsize - filsys.s_isize, filsys.s_fsize); X (void) fprintf(stderr, "\tfree blocks = %ld, free inodes = %d\n", X filsys.s_tfree, filsys.s_tinode); X X for (i = 0; i < NUM_INDIR; ++i) { X w_indir[i] = 0; X indir[i] = (char *) malloc((unsigned) FsBSIZE(dev)); X if (indir[i] == 0) { X (void) fprintf(stderr, "%s: can't malloc indir buffer space: ", X cmd_name); X perror(""); X exit(1); X } X } X w_ino = 0; X X# ifdef SMALL X for (isize = filsys.s_fsize, i = 0; isize > 0; ++i) X { X map[i] = (long *) calloc((unsigned) MAPSEG, sizeof(long)); X ref[i] = (int *) calloc((unsigned) MAPSEG, sizeof(int)); X isize -= MAPSEG; X if (map[i] == 0 || ref[i] == 0) { X (void) fprintf(stderr, "%s: can't calloc map: ", cmd_name); X perror(""); X exit(1); X } X } X# else X map = (long *) calloc((unsigned) filsys.s_fsize, sizeof(*map)); X ref = (int *) calloc((unsigned) filsys.s_fsize, sizeof(*ref)); X if (map == 0 || ref == 0) { X (void) fprintf(stderr, "%s: can't calloc map: ", cmd_name); X perror(""); X exit(1); X } X# endif X X isize = (long) filsys.s_isize * FsBSIZE(dev); X if (isize > MAXINT) X inode_table = NULL; X else X inode_table = (char *) malloc((unsigned) isize); X if (inode_table == 0) { X (void) fprintf(stderr, "%s: can't malloc space for inode table\n", X cmd_name); X (void) fprintf(stderr, "%s: that's OK, I will just run slower\n", X cmd_name); X w_ino_blk = 0; X inode_block = (char *) malloc((unsigned) FsBSIZE(dev)); X if (inode_block == 0) { X (void) fprintf(stderr, "%s: can't malloc inode buffer space: %u", X cmd_name, FsBSIZE(dev)); X perror(""); X exit(1); X } X } X else X for (block = FsITOD(dev, ROOTINO); block < filsys.s_isize; ++block) X read_block(block, &inode_table[block * FsBSIZE(dev)]); X X (void) fprintf(stderr, "mapping..."); X for (inode = ROOTINO; inode <= total_inodes; ++inode) X map_inode(inode); X (void) fprintf(stderr, "done\n"); X X next_fill = filsys.s_isize; X if (ilimit >= 0) X for (inode = ROOTINO; inode <= ilimit; ++inode) X move_inode(inode); X else X for (inode = ROOTINO; inode <= total_inodes; ++inode) X move_inode(inode); X X (void) fprintf(stderr, "\nrebuilding the free list\n"); X rebuild_free_list(); X X (void) fprintf(stderr, "*** Run fsck to check out the disk!!!\n"); X X (void) close(disk); X exit(0); X /* NOTREACHED */ X} X Xstatic void read_superblk() X{ X if (lseek(disk, (long) SUPERBOFF, 0) != (long) SUPERBOFF) { X (void) fprintf(stderr, "%s: can't seek to superblock: ", cmd_name); X perror(""); X exit(1); X } X if (read(disk, (char *) &filsys, sizeof(filsys)) != sizeof(filsys)) { X (void) fprintf(stderr, "%s: can't read superblock: ", cmd_name); X perror(""); X exit(1); X } X if (filsys.s_magic != FsMAGIC) { X (void) fprintf(stderr, "%s: invalid superblock magic number\n", X cmd_name); X exit(1); X } X dev = (filsys.s_type == Fs2b) ? Fs2BLK : 0; X} X Xstatic void write_superblk() X{ X if (lseek(disk, (long) SUPERBOFF, 0) == -1L) { X (void) fprintf(stderr, "%s: can't seek to superblock: ", cmd_name); X perror(""); X exit(1); X } X if (write(disk, (char *) &filsys, sizeof(filsys)) != sizeof(filsys)) { X (void) fprintf(stderr, "%s: can't write superblock: ", cmd_name); X perror(""); X exit(1); X } X} X Xstatic void map_inode(inode) Xino_t inode; X{ X int type, i; X long block[NUM_ADDR]; X X read_inode(inode, &ino); X if (ino.di_mode == 0) X return; X type = ino.di_mode & S_IFMT; X if (type == S_IFCHR || type == S_IFBLK) X return; X X l3tol(block, ino.di_addr, NUM_ADDR); X for (i = 0; i < NUM_ADDR; ++i) X if (block[i] != 0) X update_map((long) inode, block[i], X (i < FIRST_INDIR) ? 0 : (i - FIRST_INDIR + 1)); X} X Xstatic void update_map(map_entry, block, level) Xlong map_entry; Xdaddr_t block; Xint level; X{ X int i; X X if (map[MB(block)] != 0) { X (void) fprintf(stderr, "%s: duplicate block %d in %d and %d\n", X cmd_name, block, map[block], map_entry); X exit(1); X } X map[MB(block)] = map_entry; X X if (map_entry < 0) X ++ref[MB(-map_entry)]; /* RERSPEEDUP: maintain reference count */ X /* for indirect blocks */ X X if (level == 0) X return; X X --level; X read_block(block, indir[level]); X for (i = 0; i < FsNINDIR(dev); ++i) X if (((daddr_t *)indir[level])[i] != 0) X update_map(-block, ((daddr_t *)indir[level])[i], level); X} X Xstatic void read_block(block, buf) Xdaddr_t block; Xchar *buf; X{ X if (lseek(disk, (long) block * FsBSIZE(dev), 0) == -1L) { X (void) fprintf(stderr, "%s: can't seek block %ld, addr %ld: ", X cmd_name, block, (long) block * FsBSIZE(dev) ); X perror(""); X exit(1); X } X if (read(disk, buf, (unsigned) FsBSIZE(dev)) != FsBSIZE(dev)) { X (void) fprintf(stderr, "%s: can't read block %ld, addr %ld: ", X cmd_name, block, (long) block * FsBSIZE(dev) ); X perror(""); X exit(1); X } X} X Xstatic void write_block(block, buf) Xdaddr_t block; Xchar *buf; X{ X if (lseek(disk, (long) block * FsBSIZE(dev), 0) == -1L X || write(disk, buf, (unsigned) FsBSIZE(dev)) != FsBSIZE(dev)) { X (void) fprintf(stderr, "%s: can't write block %d: ", cmd_name, block); X perror(""); X exit(1); X } X} X Xstatic void read_inode(inode, the_ino) Xino_t inode; Xstruct dinode *the_ino; X{ X daddr_t block; X X block = FsITOD(dev, inode); X if (inode_table == 0) { X if (w_ino_blk != block) { X w_ino_blk = block; X read_block(block, inode_block); X } X *the_ino = ((struct dinode *)inode_block)[FsITOO(dev, inode)]; X } X else { X *the_ino = ((struct dinode *)&inode_table[block * FsBSIZE(dev)]) X [FsITOO(dev, inode)]; X } X} X Xstatic void write_inode(inode, the_ino) Xino_t inode; Xstruct dinode *the_ino; X{ X daddr_t block; X X block = FsITOD(dev, inode); X if (inode_table == 0) { X if (w_ino_blk != block) { X w_ino_blk = block; X read_block(block, inode_block); X } X ((struct dinode *)inode_block)[FsITOO(dev, inode)] = *the_ino; X write_block(block, inode_block); X } X else { X ((struct dinode *)&inode_table[block * FsBSIZE(dev)]) X [FsITOO(dev, inode)] = *the_ino; X write_block(block, &inode_table[block * FsBSIZE(dev)]); X } X} X Xstatic void move_block(from, to) Xdaddr_t from; Xdaddr_t to; X{ X char buffer[FsBSIZEdev]; X daddr_t block; X daddr_t negfrom = -from; X daddr_t negto = -to; X# ifdef SMALL X register int bn, seg; X long *mapp; X# endif X X if (map[MB(to)] != 0) X make_hole(); X X read_block(from, buffer); X write_block(to, buffer); X X map[MB(to)] = map[MB(from)]; X ref[MB(to)] = ref[MB(from)]; X map[MB(from)] = 0; X ref[MB(from)] = 0; X X if (ref[MB(to)]) X { X /* RERSPEEDUP X * The original algorithm did the "for" loop every time X * a block was moved, searching for indirect blocks which X * contain the "from" disk address. I added a reference X * count so we only do the search if there is at least one X * indirect block that has the address. This was a twenty X * fold improvement in speed, and changed the program from X * being compute bound to being I/O bound most of the time. X * In fact, you could abort the for loop early once you've X * found "ref[]" indirect blocks. I didn't, since the X * number of files with indirect blocks was only 10% of all X * of my files. The two second delay for the search proved X * convenient for hitting INTERRUPT in case I wanted to stop. X * X * I also tuned the loop a little for the braindamage of having X * to segment the map on a 16 bit machine. X */ X X (void) fprintf(stderr, "%c", 007); /* Beep */ X# ifdef SMALL X bn = BN(filsys.s_isize); seg = MN(filsys.s_isize); X mapp = &map[seg][bn]; X for (block = filsys.s_isize; block < filsys.s_fsize; ) X { X if (*mapp == negfrom) X *mapp = negto; X ++block; ++mapp; X if (++bn >= MAPSEG) X { X ++seg; bn = 0; mapp = map[seg]; X } X } X# else X for (block = filsys.s_isize; block < filsys.s_fsize; ++block) X if (map[MB(block)] == negfrom) X map[MB(block)] = negto; X# endif X } X} X Xstatic void move_inode(inode) Xino_t inode; X{ X int type, i; X long block[NUM_ADDR]; X X read_inode(inode, &ino); X w_ino = inode; X if (ino.di_mode == 0) X return; X type = ino.di_mode & S_IFMT; X if (type == S_IFCHR || type == S_IFBLK) X return; X X (void) fprintf(stderr, X "moving inode %d (size %ld) \r", X inode, ino.di_size); X X l3tol(block, ino.di_addr, NUM_ADDR); X for (i = 0; i < NUM_ADDR; ++i) { X if (block[i] == 0) X continue; X if (block[i] != next_fill) { X move_block(block[i], next_fill); X l3tol(block, ino.di_addr, NUM_ADDR); X block[i] = next_fill; X ltol3(ino.di_addr, block, NUM_ADDR); X write_inode(inode, &ino); X } X ++next_fill; X } X X for (i = FIRST_INDIR; i < NUM_ADDR; ++i) X move_indirect(block[i], i-FIRST_INDIR); X} X Xstatic void move_indirect(block, level) Xdaddr_t block; Xint level; X{ X int i; X X if (block == 0) X return; X X read_block(block, indir[level]); X w_indir[level] = block; X X for (i = 0; i < FsNINDIR(dev); ++i) { X if (((daddr_t *)indir[level])[i] == 0) X continue; X if (((daddr_t *)indir[level])[i] != next_fill) { X move_block(((daddr_t *)indir[level])[i], next_fill); X ((daddr_t *)indir[level])[i] = next_fill; X write_block(block, indir[level]); X } X ++next_fill; X } X X if (level == 0) X return; X X for (i = 0; i < FsNINDIR(dev); ++i) X move_indirect(((daddr_t *)indir[level])[i], level-1); X} X Xstatic void make_hole() X{ X char t_indir[FsBSIZEdev]; X daddr_t *p_indir; X struct dinode t_ino, *p_ino; X long block[NUM_ADDR]; X daddr_t back; X int i; X X back = filsys.s_fsize - 1; X while (next_fill < back && map[MB(back)] != 0) X --back; X X if (next_fill >= back) { X (void) fprintf(stderr, "%s: can't find a free block for %d\n", X cmd_name, next_fill); X exit(1); X } X X move_block(next_fill, back); X X if (map[MB(back)] < 0) { X block[0] = -map[MB(back)]; X for (i = 0; i < NUM_INDIR; ++i) X if (block[0] == w_indir[i]) X break; X if (i < NUM_INDIR) { X p_indir = (daddr_t *)indir[i]; X } X else { X p_indir = (daddr_t *)t_indir; X read_block(block[0], t_indir); X } X for (i = 0; i < FsNINDIR(dev); ++i) { X if (p_indir[i] == next_fill) { X p_indir[i] = back; X break; X } X } X if (i == FsNINDIR(dev)) { X (void) fprintf(stderr, X "%s: panic: can't find %d in indirect block %d\n", X cmd_name, next_fill, -map[MB(back)]); X exit(1); X } X write_block(block[0], (char *) p_indir); X } X else { X if (map[MB(back)] == w_ino) { X p_ino = &ino; X } X else { X p_ino = &t_ino; X read_inode((ino_t) map[MB(back)], &t_ino); X } X l3tol(block, p_ino->di_addr, NUM_ADDR); X for (i = 0; i < NUM_ADDR; ++i) { X if (block[i] == next_fill) { X block[i] = back; X ltol3(p_ino->di_addr, block, NUM_ADDR); X break; X } X } X if (i == NUM_ADDR) { X (void) fprintf(stderr, "%s: panic: can't find %d in inode %d\n", X cmd_name, next_fill, map[MB(back)]); X exit(1); X } X write_inode((ino_t) map[MB(back)], p_ino); X } X} X Xstatic void rebuild_free_list() X{ X long free_size, nfree; X daddr_t free[NICFREE], block; X char buf[FsBSIZEdev]; X X free_size = filsys.s_fsize - next_fill; X if (free_size != filsys.s_tfree) { X (void) fprintf(stderr, "%s: free list changed size from %ld to %ld\n", X cmd_name, filsys.s_tfree, free_size); X exit(1); X } X X nfree = 1; X (void) memset((char *) free, 0, sizeof(free)); X (void) memset(buf, 0, sizeof(buf)); X X for (block = filsys.s_fsize - 1; block >= next_fill; --block) { X if (nfree == NICFREE) { X if (sizeof(filsys.s_nfree) == sizeof(short)) X { /* Venix/286 has a short s_nfree member */ X ((short *)buf)[0] = nfree; X (void) memcpy((char *) (&((short *)buf)[1]), X (char *) free, sizeof(free)); X } X else X { /* The usual case for System V */ X ((daddr_t *)buf)[0] = nfree; X (void) memcpy((char *) (&((daddr_t *)buf)[1]), X (char *) free, sizeof(free)); X } X write_block(block, buf); X nfree = 0; X (void) memset((char *) free, 0, sizeof(free)); X } X free[nfree++] = block; X } X X filsys.s_nfree = nfree; X (void) memcpy((char *) filsys.s_free, (char *) free, sizeof(free)); X write_superblk(); X} SHAR_EOF fi exit 0 # End of shell archive -- Rick Richardson | Looking for FAX software for UNIX/386 ?????? mention PC Research,Inc.| WE'RE SHIPPING your uunet!pcrat!rick| Ask about FaxiX - UNIX Facsimile System (tm) FAX # (201) 389-8963 | Or JetRoff - troff postprocessor for the HP {Laser,Desk}Jet