BSD 4_4_Lite2 release
[unix-history] / usr / src / libexec / lfs_cleanerd / library.c
index dc4a7ff..32f7d37 100644 (file)
@@ -1,27 +1,56 @@
 /*-
 /*-
- * Copyright (c) 1992 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)library.c  5.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)library.c  8.3 (Berkeley) 5/24/95";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/mman.h>
 
 #include <ufs/ufs/dinode.h>
 #include <ufs/lfs/lfs.h>
 
 #include <fcntl.h>
 #include <stdio.h>
 
 #include <ufs/ufs/dinode.h>
 #include <ufs/lfs/lfs.h>
 
 #include <fcntl.h>
 #include <stdio.h>
-#include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+
 #include "clean.h"
 
 void    add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
 #include "clean.h"
 
 void    add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
@@ -30,70 +59,67 @@ void         add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
             daddr_t));
 int     bi_compare __P((const void *, const void *));
 int     bi_toss __P((const void *, const void *, const void *));
             daddr_t));
 int     bi_compare __P((const void *, const void *));
 int     bi_toss __P((const void *, const void *, const void *));
-void    get_ifile __P((FS_INFO *));
+void    get_ifile __P((FS_INFO *, int));
 int     get_superblock __P((FS_INFO *, struct lfs *));
 int     pseg_valid __P((FS_INFO *, SEGSUM *));
 
 /*
 int     get_superblock __P((FS_INFO *, struct lfs *));
 int     pseg_valid __P((FS_INFO *, SEGSUM *));
 
 /*
- * This function will get information on all mounted file systems
- * of a given type.
+ * This function will get information on a a filesystem which matches
+ * the name and type given.  If a "name" is in a filesystem of the given
+ * type, then buf is filled with that filesystem's info, and the
+ * a non-zero value is returned.
  */
 int
  */
 int
-fs_getmntinfo(buf, type)
+fs_getmntinfo(buf, name, type)
        struct  statfs  **buf;
        struct  statfs  **buf;
-       int     type;
+       char    *name;
+       char    *type;
 {
 {
-       struct statfs *tstatfsp;
-       struct statfs *sbp;
-       int count, i, tcount;
-
-       tcount = getmntinfo(&tstatfsp, MNT_NOWAIT);
-
-       if (tcount < 0) {
-               err(0, "getmntinfo failed");
-               return (-1);
+       /* allocate space for the filesystem info */
+       *buf = (struct statfs *)malloc(sizeof(struct statfs));
+       if (*buf == NULL)
+               return 0;
+
+       /* grab the filesystem info */
+       if (statfs(name, *buf) < 0) {
+               free(*buf);
+               return 0;
        }
 
        }
 
-       for (count = 0, i = 0; i < tcount ; ++i)
-               if (tstatfsp[i].f_type == type)
-                       ++count;
-
-       if (count) {
-               if (!(*buf = (struct statfs *)
-                       malloc(count * sizeof(struct statfs))))
-                       err(1, "fs_getmntinfo: out of space");
-               for (i = 0, sbp = *buf; i < tcount ; ++i) {
-                       if (tstatfsp[i].f_type == type) {
-                               *sbp = tstatfsp[i];
-                               ++sbp;
-                       }
-               }
+       /* check to see if it's the one we want */
+       if (strcmp((*buf)->f_fstypename, type) ||
+           strncmp(name, (*buf)->f_mntonname, MNAMELEN)) {
+               /* "this is not the filesystem you're looking for */
+               free(*buf);
+               return 0;
        }
        }
-       return (count);
+
+       return 1;
 }
 
 /*
  * Get all the information available on an LFS file system.
 }
 
 /*
  * Get all the information available on an LFS file system.
- * Returns an array of FS_INFO structures, NULL on error.
+ * Returns an pointer to an FS_INFO structure, NULL on error.
  */
 FS_INFO *
  */
 FS_INFO *
-get_fs_info (lstatfsp, count)
-       struct statfs *lstatfsp;        /* IN: array of statfs structs */
-       int count;                      /* IN: number of file systems */
+get_fs_info (lstatfsp, use_mmap)
+       struct statfs *lstatfsp;        /* IN: pointer to statfs struct */
+       int use_mmap;                   /* IN: mmap or read */
 {
 {
-       FS_INFO *fp, *fsp;
+       FS_INFO *fsp;
        int     i;
        
        int     i;
        
-       fsp = (FS_INFO *)malloc(count * sizeof(FS_INFO));
-
-       for (fp = fsp, i = 0; i < count; ++i, ++fp) {
-               fp->fi_statfsp = lstatfsp++;
-               if (get_superblock (fp, &fp->fi_lfs))
-                       err(1, "get_fs_info: get_superblock failed");
-               fp->fi_daddr_shift =
-                    fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb;
-               get_ifile (fp);
-       }
+       fsp = (FS_INFO *)malloc(sizeof(FS_INFO));
+       if (fsp == NULL)
+               return NULL;
+       bzero(fsp, sizeof(FS_INFO));
+
+       fsp->fi_statfsp = lstatfsp;
+       if (get_superblock (fsp, &fsp->fi_lfs))
+               err(1, "get_fs_info: get_superblock failed");
+       fsp->fi_daddr_shift =
+            fsp->fi_lfs.lfs_bshift - fsp->fi_lfs.lfs_fsbtodb;
+       get_ifile (fsp, use_mmap);
        return (fsp);
 }
 
        return (fsp);
 }
 
@@ -103,23 +129,15 @@ get_fs_info (lstatfsp, count)
  * refresh the file system information (statfs) info.
  */
 void
  * refresh the file system information (statfs) info.
  */
 void
-reread_fs_info(fsp, count)
-       FS_INFO *fsp;   /* IN: array of fs_infos to free */
-       int count;      /* IN: number of file systems */
+reread_fs_info(fsp, use_mmap)
+       FS_INFO *fsp;   /* IN: prointer fs_infos to reread */
+       int use_mmap;
 {
        int i;
        
 {
        int i;
        
-       for (i = 0; i < count; ++i, ++fsp) {
-               if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))
-                       err(0, "reread_fs_info: statfs failed");
-#ifdef MMAP_WORKS
-               if (munmap(fsp->fi_cip, fsp->fi_ifile_length) < 0)
-                       err(0, "reread_fs_info: munmap failed");
-#else
-               free (fsp->fi_cip);
-#endif /* MMAP_WORKS */
-               get_ifile (fsp);
-       }
+       if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))
+               err(1, "reread_fs_info: statfs failed");
+       get_ifile (fsp, use_mmap);
 }
 
 /* 
 }
 
 /* 
@@ -152,8 +170,10 @@ get_superblock (fsp, sbp)
  * fatal error on failure.
  */
 void
  * fatal error on failure.
  */
 void
-get_ifile (fsp)
+get_ifile (fsp, use_mmap)
        FS_INFO *fsp;
        FS_INFO *fsp;
+       int use_mmap;
+
 {
        struct stat file_stat;
        caddr_t ifp;
 {
        struct stat file_stat;
        caddr_t ifp;
@@ -172,30 +192,37 @@ get_ifile (fsp)
        if (fstat (fid, &file_stat))
                err(1, "get_ifile: fstat failed");
 
        if (fstat (fid, &file_stat))
                err(1, "get_ifile: fstat failed");
 
-       fsp->fi_ifile_length = file_stat.st_size;
+       if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) {
+               (void) close(fid);
+               return;
+       }
 
        /* get the ifile */
 
        /* get the ifile */
-#ifndef MMAP_WORKS
-       if (!(ifp = malloc ((size_t)fsp->fi_ifile_length)))
-               err (1, "get_ifile: malloc failed"); 
+       if (use_mmap) {
+               if (fsp->fi_cip)
+                       munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length);
+               ifp = mmap ((caddr_t)0, file_stat.st_size,
+                   PROT_READ|PROT_WRITE, 0, fid, (off_t)0);
+               if (ifp ==  (caddr_t)(-1))
+                       err(1, "get_ifile: mmap failed");
+       } else {
+               if (fsp->fi_cip)
+                       free(fsp->fi_cip);
+               if (!(ifp = malloc (file_stat.st_size)))
+                       err (1, "get_ifile: malloc failed"); 
 redo_read:
 redo_read:
-       count = read (fid, ifp, (size_t) fsp->fi_ifile_length);
-
-       if (count < 0)
-               err(1, "get_ifile: bad ifile read"); 
-       else if (count < (int)fsp->fi_ifile_length) {
-               err(0, "get_ifile");
-               if (lseek(fid, 0, SEEK_SET) < 0)
-                       err(1, "get_ifile: bad ifile lseek"); 
-               goto redo_read;
+               count = read (fid, ifp, (size_t) file_stat.st_size);
+
+               if (count < 0)
+                       err(1, "get_ifile: bad ifile read"); 
+               else if (count < file_stat.st_size) {
+                       err(0, "get_ifile");
+                       if (lseek(fid, 0, SEEK_SET) < 0)
+                               err(1, "get_ifile: bad ifile lseek"); 
+                       goto redo_read;
+               }
        }
        }
-#else  /* MMAP_WORKS */
-       ifp = mmap ((caddr_t)0, (size_t) fsp->fi_ifile_length, PROT_READ|PROT_WRITE,
-               MAP_FILE|MAP_SHARED, fid, (off_t)0);
-       if (ifp < 0)
-               err(1, "get_ifile: mmap failed");
-#endif /* MMAP_WORKS */
-
+       fsp->fi_ifile_length = file_stat.st_size;
        close (fid);
 
        fsp->fi_cip = (CLEANERINFO *)ifp;
        close (fid);
 
        fsp->fi_cip = (CLEANERINFO *)ifp;
@@ -233,10 +260,11 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
        BLOCK_INFO *bip;
        SEGSUM *sp;
        SEGUSE *sup;
        BLOCK_INFO *bip;
        SEGSUM *sp;
        SEGUSE *sup;
+       FINFO *fip;
        struct lfs *lfsp;
        caddr_t s, segend;
        daddr_t pseg_addr, seg_addr;
        struct lfs *lfsp;
        caddr_t s, segend;
        daddr_t pseg_addr, seg_addr;
-       int nelem, nblocks;
+       int i, nelem, nblocks, nsegs, sumsize;
        time_t timestamp;
 
        lfsp = &fsp->fi_lfs;
        time_t timestamp;
 
        lfsp = &fsp->fi_lfs;
@@ -253,23 +281,44 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
 #endif /* VERBOSE */
 
        *bcount = 0;
 #endif /* VERBOSE */
 
        *bcount = 0;
-       for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) {
+       for (nsegs = 0, timestamp = 0; nsegs < sup->su_nsums; nsegs++) {
                sp = (SEGSUM *)s;
                sp = (SEGSUM *)s;
+
+               nblocks = pseg_valid(fsp, sp);
+               if (nblocks <= 0) {
+                       printf("Warning: invalid segment summary at 0x%x\n",
+                           pseg_addr);
+                       break;
+               }
+
 #ifdef VERBOSE
                printf("\tpartial at: 0x%x\n", pseg_addr);
                print_SEGSUM(lfsp, sp);
                fflush(stdout);
 #endif /* VERBOSE */
 
 #ifdef VERBOSE
                printf("\tpartial at: 0x%x\n", pseg_addr);
                print_SEGSUM(lfsp, sp);
                fflush(stdout);
 #endif /* VERBOSE */
 
-               nblocks = pseg_valid(fsp, sp);
-               if (nblocks <= 0)
-                       break;
-
                /* Check if we have hit old data */
                if (timestamp > ((SEGSUM*)s)->ss_create)
                        break;
                timestamp = ((SEGSUM*)s)->ss_create;
 
                /* Check if we have hit old data */
                if (timestamp > ((SEGSUM*)s)->ss_create)
                        break;
                timestamp = ((SEGSUM*)s)->ss_create;
 
+#ifdef DIAGNOSTIC
+               /* Verfiy size of summary block */
+               sumsize = sizeof(SEGSUM) +
+                   (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
+               for (i = 0, fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) {
+                       sumsize += sizeof(FINFO) +
+                           (fip->fi_nblocks - 1) * sizeof(daddr_t);
+                       fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]);
+               }
+               if (sumsize > LFS_SUMMARY_SIZE) {
+                       fprintf(stderr,
+                           "Segment %d summary block too big: %d\n",
+                           seg, sumsize);
+                       exit(1);
+               }
+#endif
+
                if (*bcount + nblocks + sp->ss_ninos > nelem) {
                        nelem = *bcount + nblocks + sp->ss_ninos;
                        bip = realloc (bip, nelem * sizeof(BLOCK_INFO));
                if (*bcount + nblocks + sp->ss_ninos > nelem) {
                        nelem = *bcount + nblocks + sp->ss_ninos;
                        bip = realloc (bip, nelem * sizeof(BLOCK_INFO));
@@ -322,7 +371,9 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
        caddr_t bp;
        daddr_t *dp, *iaddrp;
        int db_per_block, i, j;
        caddr_t bp;
        daddr_t *dp, *iaddrp;
        int db_per_block, i, j;
+       int db_frag;
        u_long page_size;
        u_long page_size;
+long *lp;
 
 #ifdef VERBOSE
        printf("FILE INFOS\n");
 
 #ifdef VERBOSE
        printf("FILE INFOS\n");
@@ -353,8 +404,25 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
                        bip->bi_daddr = psegaddr;
                        bip->bi_segcreate = (time_t)(sp->ss_create);
                        bip->bi_bp = bp;
                        bip->bi_daddr = psegaddr;
                        bip->bi_segcreate = (time_t)(sp->ss_create);
                        bip->bi_bp = bp;
-                       psegaddr += db_per_block;
-                       bp += page_size;
+                       bip->bi_version = ifp->if_version;
+                       if (fip->fi_lastlength == page_size) {
+                               bip->bi_size = page_size;
+                               psegaddr += db_per_block;
+                               bp += page_size;
+                       } else {
+                               db_frag = fragstodb(&(fsp->fi_lfs), 
+                                   numfrags(&(fsp->fi_lfs),
+                                   fip->fi_lastlength));
+#ifdef VERBOSE
+                               printf("lastlength, frags: %d, %d, %d\n", 
+                                   fip->fi_lastlength, temp,
+                                   bytetoda(fsp, temp));
+                               fflush(stdout);
+#endif
+                               bip->bi_size = fip->fi_lastlength;
+                               bp += fip->fi_lastlength;
+                               psegaddr += db_frag;
+                       }
                        ++bip;
                        ++(*countp);
                }
                        ++bip;
                        ++(*countp);
                }
@@ -400,7 +468,7 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
                } else 
                        ++di;
                
                } else 
                        ++di;
                
-               inum = di->di_inum;
+               inum = di->di_inumber;
                bp->bi_lbn = LFS_UNUSED_LBN;
                bp->bi_inode = inum;
                bp->bi_daddr = *daddrp;
                bp->bi_lbn = LFS_UNUSED_LBN;
                bp->bi_inode = inum;
                bp->bi_daddr = *daddrp;
@@ -408,12 +476,14 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
                bp->bi_segcreate = sp->ss_create;
 
                if (inum == LFS_IFILE_INUM) {
                bp->bi_segcreate = sp->ss_create;
 
                if (inum == LFS_IFILE_INUM) {
+                       bp->bi_version = 1;     /* Ifile version should be 1 */
                        bp++;
                        ++(*countp);
                        PRINT_INODE(1, bp);
                } else {
                        ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum);
                        PRINT_INODE(ifp->if_daddr == *daddrp, bp);
                        bp++;
                        ++(*countp);
                        PRINT_INODE(1, bp);
                } else {
                        ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum);
                        PRINT_INODE(ifp->if_daddr == *daddrp, bp);
+                       bp->bi_version = ifp->if_version;
                        if (ifp->if_daddr == *daddrp) {
                                bp++;
                                ++(*countp);
                        if (ifp->if_daddr == *daddrp) {
                                bp++;
                                ++(*countp);
@@ -437,7 +507,11 @@ pseg_valid (fsp, ssp)
        int i, nblocks;
        u_long *datap;
 
        int i, nblocks;
        u_long *datap;
 
-       if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0)
+       if (ssp->ss_magic != SS_MAGIC)
+               return(0);
+
+       if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 ||
+           nblocks > fsp->fi_lfs.lfs_ssize - 1)
                return(0);
                
        /* check data/inode block(s) checksum too */
                return(0);
                
        /* check data/inode block(s) checksum too */
@@ -459,10 +533,11 @@ pseg_valid (fsp, ssp)
  * read a segment into a memory buffer
  */
 int
  * read a segment into a memory buffer
  */
 int
-mmap_segment (fsp, segment, segbuf)
+mmap_segment (fsp, segment, segbuf, use_mmap)
        FS_INFO *fsp;           /* file system information */
        int segment;            /* segment number */
        caddr_t *segbuf;        /* pointer to buffer area */
        FS_INFO *fsp;           /* file system information */
        int segment;            /* segment number */
        caddr_t *segbuf;        /* pointer to buffer area */
+       int use_mmap;           /* mmap instead of read */
 {
        struct lfs *lfsp;
        int fid;                /* fildes for file system device */
 {
        struct lfs *lfsp;
        int fid;                /* fildes for file system device */
@@ -486,53 +561,53 @@ mmap_segment (fsp, segment, segbuf)
                return (-1);
        }
 
                return (-1);
        }
 
-#ifdef MMAP_SEGMENT
-       *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
-           MAP_FILE, fid, seg_byte);
-       if (*(long *)segbuf < 0) {
-               err(0, "mmap_segment: mmap failed");
-               return (NULL);
-       }
-#else /* MMAP_SEGMENT */
+       if (use_mmap) {
+               *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
+                   0, fid, seg_byte);
+               if (*(long *)segbuf < 0) {
+                       err(0, "mmap_segment: mmap failed");
+                       return (NULL);
+               }
+       } else {
 #ifdef VERBOSE
 #ifdef VERBOSE
-       printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n",
-           seg_daddr, ssize, seg_byte);
+               printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n",
+                   seg_daddr, ssize, seg_byte);
 #endif
 #endif
-       /* malloc the space for the buffer */
-       *segbuf = malloc(ssize);
-       if (!*segbuf) {
-               err(0, "mmap_segment: malloc failed");
-               return(NULL);
-       }
+               /* malloc the space for the buffer */
+               *segbuf = malloc(ssize);
+               if (!*segbuf) {
+                       err(0, "mmap_segment: malloc failed");
+                       return(NULL);
+               }
 
 
-       /* read the segment data into the buffer */
-       if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
-               err (0, "mmap_segment: bad lseek");
-               free(*segbuf);
-               return (-1);
-       }
-       
-       if (read (fid, *segbuf, ssize) != ssize) {
-               err (0, "mmap_segment: bad read");
-               free(*segbuf);
-               return (-1);
+               /* read the segment data into the buffer */
+               if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
+                       err (0, "mmap_segment: bad lseek");
+                       free(*segbuf);
+                       return (-1);
+               }
+               
+               if (read (fid, *segbuf, ssize) != ssize) {
+                       err (0, "mmap_segment: bad read");
+                       free(*segbuf);
+                       return (-1);
+               }
        }
        }
-#endif /* MMAP_SEGMENT */
        close (fid);
 
        return (0);
 }
 
 void
        close (fid);
 
        return (0);
 }
 
 void
-munmap_segment (fsp, seg_buf)
+munmap_segment (fsp, seg_buf, use_mmap)
        FS_INFO *fsp;           /* file system information */
        caddr_t seg_buf;        /* pointer to buffer area */
        FS_INFO *fsp;           /* file system information */
        caddr_t seg_buf;        /* pointer to buffer area */
+       int use_mmap;           /* mmap instead of read/write */
 {
 {
-#ifdef MMAP_SEGMENT
-       munmap (seg_buf, seg_size(&fsp->fi_lfs));
-#else /* MMAP_SEGMENT */
-       free (seg_buf);
-#endif /* MMAP_SEGMENT */
+       if (use_mmap)
+               munmap (seg_buf, seg_size(&fsp->fi_lfs));
+       else
+               free (seg_buf);
 }
 
 
 }
 
 
@@ -568,8 +643,10 @@ bi_compare(a, b)
                        return(-1);
                else if (bb->bi_lbn == LFS_UNUSED_LBN)
                        return(1);
                        return(-1);
                else if (bb->bi_lbn == LFS_UNUSED_LBN)
                        return(1);
-               else if (ba->bi_lbn < 0)
+               else if (ba->bi_lbn < 0 && bb->bi_lbn >= 0)
                        return(1);
                        return(1);
+               else if (bb->bi_lbn < 0 && ba->bi_lbn >= 0)
+                       return(-1);
                else
                        return (diff);
        }
                else
                        return (diff);
        }
@@ -610,7 +687,7 @@ toss(p, nump, size, dotoss, client)
        for (i = *nump; --i > 0;) {
                p1 = p + size;
                if (dotoss(client, p, p1)) {
        for (i = *nump; --i > 0;) {
                p1 = p + size;
                if (dotoss(client, p, p1)) {
-                       bcopy(p1, p, i * size);
+                       memmove(p, p1, i * size);
                        --(*nump);
                } else 
                        p += size;
                        --(*nump);
                } else 
                        p += size;