/* Initializes the free map. */
void
free_map_init (void) 
{
  free_map = bitmap_create (disk_size (filesys_disk));
  if (free_map == NULL)
    PANIC ("bitmap creation failed--disk is too large");
  bitmap_mark (free_map, FREE_MAP_SECTOR);
  bitmap_mark (free_map, ROOT_DIR_SECTOR);
}
Exemplo n.º 2
0
/* Initializes the free map. */
void
free_map_init (void) 
{
  free_map = bitmap_create (block_size (fs_device));
  if (free_map == NULL)
    PANIC ("bitmap creation failed--file system device is too large");
  bitmap_mark (free_map, FREE_MAP_SECTOR);
  bitmap_mark (free_map, ROOT_DIR_SECTOR);
}
Exemplo n.º 3
0
static int testfs_checkfs(struct super_block *sb, struct bitmap *i_freemap,
		struct bitmap *b_freemap, int inode_nr) {
	struct inode *in = testfs_get_inode(sb, inode_nr);
	int size;
	int size_roundup = ROUNDUP(testfs_inode_get_size(in), BLOCK_SIZE);

	assert((testfs_inode_get_type(in) == I_FILE) || (testfs_inode_get_type(in) == I_DIR));

	/* inode processing */
	bitmap_mark(i_freemap, inode_nr);
	if (testfs_inode_get_type(in) == I_DIR) {
		int offset = 0;
		struct dirent *d;
		for (; (d = testfs_next_dirent(in, &offset)); free(d)) {
			if ((d->d_inode_nr < 0) || (strcmp(D_NAME(d), ".") == 0)
					|| (strcmp(D_NAME(d), "..") == 0))
				continue;
			testfs_checkfs(sb, i_freemap, b_freemap, d->d_inode_nr);
		}
	}
	/* block processing */
	size = testfs_check_inode(sb, b_freemap, in);
	assert(size == size_roundup);
	testfs_put_inode(in);
	return 0;
}
Exemplo n.º 4
0
/*
 * Add an inverse entry for the swapped out page associated with mapping from 
 * vaddr to chunk into the swaparea.
 */
int add_spage (u_int32_t vaddr, u_int32_t chunk, pid_t pid)
{
    int result = 0;
        
    //get the index of the chunk in the swap area
    int chunk_index = (chunk & PAGE_FRAME) / PAGE_SIZE;
    //make sure that the chunk address is valid
    assert( (swaparea[ chunk_index ].paddr & PAGE_FRAME) == chunk );
    if (pid == 0)
		panic("PID = 0 in add_spage!");
    /*
     * Insert a mapping (invert index) of the page addresses by vaddr into the
     * swap area mapping indexed by the chunk
     */
    int spl=splhigh();
    swaparea[ chunk_index ].vaddr = vaddr;
    swaparea[ chunk_index ].last_access_time_sec = 0;
    swaparea[ chunk_index ].last_access_time_nsec = 0;
    //swaparea[ chunk_index ].pid = curthread->pid;
    swaparea[ chunk_index ].pid = pid; // changed by tocurtis

    /*
     * mark (as non-empty) the bitmap describing the swap area chunk
     */
    if(!bitmap_isset(swap_memmap, chunk_index))
        bitmap_mark(swap_memmap, chunk_index);
    
    splx(spl);    

    return result;
}
Exemplo n.º 5
0
struct file *
file_open(char *name)
{
    int result;
    struct file *f = malloc(sizeof(struct file));
    if (f == NULL) {
        goto done;
    }
    f->f_fd = open(name, O_CREAT | O_RDWR, S_IRWXU);
    if (f->f_fd == -1) {
        goto cleanup_malloc;
    }
    f->f_size = io_size(f->f_fd);
    unsigned bitmapbytes = FILE_BITMAP_PAGES * PAGESIZE;
    if (f->f_size == 0) {
        // if we are creating the file for the first time, allocate the
        // first page for the bitmap, and mark the page as taken
        f->f_page_bitmap = bitmap_create(bitmapbytes * 8);
        if (f->f_page_bitmap == NULL) {
            goto cleanup_fd;
        }
        for (unsigned i = 0; i < FILE_BITMAP_PAGES; i++) {
            bitmap_mark(f->f_page_bitmap, i);
        }
        result = file_sync_bitmap(f);
        if (result) {
            bitmap_destroy(f->f_page_bitmap);
            goto cleanup_fd;
        }
        f->f_size += bitmapbytes;
    } else {
        // if we are initing from an already existing file, read the first
        // page and init the bitmap using that page
        unsigned char buf[bitmapbytes];
        bzero(buf, bitmapbytes);
        result = io_read(f->f_fd, buf, bitmapbytes);
        if (result) {
            goto cleanup_fd;
        }
        f->f_page_bitmap = bitmap_init(bitmapbytes * 8, buf);
        if (f->f_page_bitmap == NULL) {
            goto cleanup_fd;
        }
    }
    // seek back to beginning on opening
    result = lseek(f->f_fd, 0, SEEK_SET);
    f->f_last_alloc_page = FILE_BITMAP_PAGES - 1;
    if (result) {
        goto cleanup_fd;
    }
    goto done;

  cleanup_fd:
    assert(close(f->f_fd) == 0);
  cleanup_malloc:
    free(f);
    f = NULL;
  done:
    return f;
}
Exemplo n.º 6
0
int
file_alloc_page(struct file *f, page_t *retpage)
{
    page_t page;
    unsigned nbits = bitmap_nbits(f->f_page_bitmap);
    for (page = f->f_last_alloc_page + 1; page < nbits; page++) {
        if (!bitmap_isset(f->f_page_bitmap, page)) {
            bitmap_mark(f->f_page_bitmap, page);
            //assert(file_sync_bitmap(f) == 0);
            break;
        }
    }
    if (page == nbits) {
        // no more space in bitmap
        fprintf(stderr, "no more space in bitmap\n");
        return DBENOMEM;
    }
    // if we do get a valid page number, extend the file if necessary
    if (page * PAGESIZE >= f->f_size) {
        int result = ftruncate(f->f_fd, f->f_size + PAGESIZE);
        if (result == -1) {
            perror("ftruncate");
            return result;
        }
        f->f_size += PAGESIZE;
        f->f_last_alloc_page = page;
    }
    *retpage = page;
    return 0;
}
Exemplo n.º 7
0
static
void
check_sb(void)
{
	struct sfs_super sp;
	uint32_t i;
	int schanged=0;

	diskread(&sp, SFS_SB_LOCATION);
	swapsb(&sp);
	if (sp.sp_magic != SFS_MAGIC) {
		errx(EXIT_UNRECOV, "Not an sfs filesystem");
	}

	assert(nblocks==0);
	assert(bitblocks==0);
	nblocks = sp.sp_nblocks;
	bitblocks = SFS_BITBLOCKS(nblocks);
	assert(nblocks>0);
	assert(bitblocks>0);

	bitmap_init(bitblocks);
	for (i=nblocks; i<bitblocks*SFS_BLOCKBITS; i++) {
		bitmap_mark(i, B_PASTEND, 0);
	}

	if (checknullstring(sp.sp_volname, sizeof(sp.sp_volname))) {
		warnx("Volume name not null-terminated (fixed)");
		setbadness(EXIT_RECOV);
		schanged = 1;
	}
	if (checkbadstring(sp.sp_volname)) {
		warnx("Volume name contains illegal characters (fixed)");
		setbadness(EXIT_RECOV);
		schanged = 1;
	}

	if (schanged) {
		swapsb(&sp);
		diskwrite(&sp, SFS_SB_LOCATION);
	}

	bitmap_mark(SFS_SB_LOCATION, B_SUPERBLOCK, 0);
	for (i=0; i<bitblocks; i++) {
		bitmap_mark(SFS_MAP_LOCATION+i, B_BITBLOCK, i);
	}
}
Exemplo n.º 8
0
void bitmap_ts_mark(struct bitmap_ts* b, unsigned index) {
    assert(b != NULL);

    lock_acquire(b->lk);
    bitmap_mark(b->bm, index);
    cv_signal(b->cv, b->lk);
    lock_release(b->lk);
}
Exemplo n.º 9
0
/*
 * swap_bootstrap: Initializes swap information and finishes
 * bootstrapping the VM so that processes can use it.
 *
 * Synchronization: none (runs during boot before anyone else uses VM)
 */
void
swap_bootstrap(size_t pmemsize)
{
	int rv;
	struct stat st;
	char path[sizeof(swapfilename)];
	off_t minsize;

	strcpy(path, swapfilename);
	rv = vfs_open(path, O_RDWR, &swapstore);
	if (rv) {
		kprintf("swap: Error %d opening swapfile %s\n", rv, 
			swapfilename);
		kprintf("swap: Please create swapfile/swapdisk.\n");
		panic("swap: Unable to continue.\n");
	}

	minsize = pmemsize*10;

	VOP_STAT(swapstore, &st);
	if (st.st_size < minsize) {
		kprintf("swap: swapfile %s is only %lu bytes.\n", swapfilename,
			(unsigned long) st.st_size);
		kprintf("swap: with %lu bytes of physical memory it should "
			"be at least\n", (unsigned long) pmemsize);
		kprintf("      %lu bytes (%lu blocks).\n", 
			(unsigned long) minsize, 
			(unsigned long) minsize / 512);
		kprintf("swap: Please extend it.\n");
		panic("swap: Unable to continue.\n");
	}

	kprintf("swap: swapping to %s (%lu bytes; %lu pages)\n", swapfilename,
		(unsigned long) st.st_size, 
		(unsigned long) st.st_size / PAGE_SIZE);

	swap_total_pages = st.st_size / PAGE_SIZE;
	swap_free_pages = swap_total_pages;
	swap_reserved_pages = 0;

	swapmap = bitmap_create(st.st_size/PAGE_SIZE);
	DEBUG(DB_VM, "creating swap map with %d entries\n",
			st.st_size/PAGE_SIZE);
	if (swapmap == NULL) {
		panic("swap: No memory for swap bitmap\n");
	}

	swaplock = lock_create("swaplock");
	if (swaplock == NULL) {
		panic("swap: No memory for swap lock\n");
	}

	/* mark the first page of swap used so we can check for errors */
	bitmap_mark(swapmap, 0);
	swap_free_pages--;
}
Exemplo n.º 10
0
static
void
observe_filelink(uint32_t ino)
{
	int i;
	for (i=0; i<ninodes; i++) {
		if (inodes[i].ino==ino) {
			assert(inodes[i].linkcount>0);
			inodes[i].linkcount++;
			return;
		}
	}
	bitmap_mark(ino, B_INODE, ino);
	addmemory(ino, 1);
}
Exemplo n.º 11
0
void
swap_bootstrap() {
	char		sdevice[64];
	int		res;
	size_t		ram_size;
	size_t		swap_size;

	//get the ram size.
	ram_size = ROUNDUP( mainbus_ramsize(), PAGE_SIZE );

	//prepare to open the swap device.
	strcpy( sdevice, SWAP_DEVICE );

	//open.
	res = vfs_open( sdevice, O_RDWR, 0, &vn_sw );
	if( res )
		panic( "swap_bootstrap: could not open swapping partition." );
	
	//make sure it is of suficient size.
	if( !swap_device_suficient( ram_size, &swap_size ) )
		panic( "swap_bootstrap: the swap partition is not large enough." );
	
	//init the stats.
	swap_init_stats( swap_size );

	//create the bitmap to manage the swap partition.
	bm_sw = bitmap_create( ss_sw.ss_total );
	if( bm_sw == NULL ) 
		panic( "swap_bootstrap: could not create the swap bitmap." );

	lk_sw = lock_create( "lk_sw" );
	if( lk_sw == NULL )
		panic( "swap_bootstrap: could not create the swap lock." );
		//remove the first page.
	bitmap_mark( bm_sw, 0 );

	//update stats.
	--ss_sw.ss_free;
}
Exemplo n.º 12
0
/*
 * Add an inverse entry for the physical page associated with mapping from vaddr 
 * to paddr into the coremap. Inverse mapping means the page is indexed by page
 * number calculated using paddr.
 */
int add_ppage (u_int32_t vaddr, u_int32_t paddr, pid_t pid, u_int32_t status)
{
    int result = 0;
    
    int spl=splhigh();    
    paddr = paddr & PAGE_FRAME;
    
    //get the index of the page in the page table
    int page_index = (paddr - coremap_base) / PAGE_SIZE;
    //make sure that the paddr address is valid
    assert( (coremap[ page_index ].paddr & PAGE_FRAME) == paddr );
    
    /*
     * Add the mapping and set the attribute bits
     */
    coremap[ page_index ].vaddr = vaddr;
    //If it is a kernel address allocated by kernel then set kernel attribute flag
    if(vaddr > USERTOP)
        coremap[ page_index ].paddr = SET_VALID(paddr)|SET_DIRTY(paddr)|SET_KERNEL(paddr);
    else
        coremap[ page_index ].paddr = SET_VALID(paddr)|SET_DIRTY(paddr);
    
    /*Initialize _PTE fields for this entry*/
    coremap[ page_index ].last_access_time_sec = 0;
    coremap[ page_index ].last_access_time_nsec = 0;
    coremap[ page_index ].pid = pid;
    coremap[ page_index ].status = PAGE_DIRTY;
    
    /*
     * mark (unavailable) the page entry of coremap.
     */
    if(!bitmap_isset(core_memmap,page_index))
        bitmap_mark(core_memmap, page_index);    
    splx(spl);
        
    return result;
}
Exemplo n.º 13
0
static
int
check_dir(uint32_t ino, uint32_t parentino, const char *pathsofar)
{
	struct sfs_inode sfi;
	struct sfs_dir *direntries;
	int *sortvector;
	uint32_t dirsize, ndirentries, maxdirentries, subdircount, i;
	int ichanged=0, dchanged=0, dotseen=0, dotdotseen=0;

	diskread(&sfi, ino);
	swapinode(&sfi);

	if (remember_dir(ino, pathsofar)) {
		/* crosslinked dir */
		return 1;
	}

	bitmap_mark(ino, B_INODE, ino);
	count_dirs++;

	if (sfi.sfi_size % sizeof(struct sfs_dir) != 0) {
		setbadness(EXIT_RECOV);
		warnx("Directory /%s has illegal size %lu (fixed)",
		      pathsofar, (unsigned long) sfi.sfi_size);
		sfi.sfi_size = SFS_ROUNDUP(sfi.sfi_size,
					   sizeof(struct sfs_dir));
		ichanged = 1;
	}

	if (check_inode_blocks(ino, &sfi, 1)) {
		ichanged = 1;
	}

	ndirentries = sfi.sfi_size/sizeof(struct sfs_dir);
	maxdirentries = SFS_ROUNDUP(ndirentries,
				    SFS_BLOCKSIZE/sizeof(struct sfs_dir));
	dirsize = maxdirentries * sizeof(struct sfs_dir);
	direntries = domalloc(dirsize);
	sortvector = domalloc(ndirentries * sizeof(int));

	dirread(&sfi, direntries, ndirentries);
	for (i=ndirentries; i<maxdirentries; i++) {
		direntries[i].sfd_ino = SFS_NOINO;
		bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name));
	}

	for (i=0; i<ndirentries; i++) {
		if (check_dir_entry(pathsofar, i, &direntries[i])) {
			dchanged = 1;
		}
		sortvector[i] = i;
	}

	sortdir(sortvector, direntries, ndirentries);

	/* don't use ndirentries-1 here in case ndirentries == 0 */
	for (i=0; i+1<ndirentries; i++) {
		struct sfs_dir *d1 = &direntries[sortvector[i]];
		struct sfs_dir *d2 = &direntries[sortvector[i+1]];
		assert(d1 != d2);

		if (d1->sfd_ino == SFS_NOINO) {
			continue;
		}

		if (!strcmp(d1->sfd_name, d2->sfd_name)) {
			if (d1->sfd_ino == d2->sfd_ino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Duplicate entries for "
				      "%s (merged)",
				      pathsofar, d1->sfd_name);
				d1->sfd_ino = SFS_NOINO;
				d1->sfd_name[0] = 0;
			}
			else {
				snprintf(d1->sfd_name, sizeof(d1->sfd_name),
					 "FSCK.%lu.%lu",
					 (unsigned long) d1->sfd_ino,
					 (unsigned long) uniquecounter++);
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Duplicate names %s "
				      "(one renamed: %s)",
				      pathsofar, d2->sfd_name, d1->sfd_name);
			}
			dchanged = 1;
		}
	}

	for (i=0; i<ndirentries; i++) {
		if (!strcmp(direntries[i].sfd_name, ".")) {
			if (direntries[i].sfd_ino != ino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Incorrect `.' entry "
				      "(fixed)", pathsofar);
				direntries[i].sfd_ino = ino;
				dchanged = 1;
			}
			assert(dotseen==0); /* due to duplicate checking */
			dotseen = 1;
		}
		else if (!strcmp(direntries[i].sfd_name, "..")) {
			if (direntries[i].sfd_ino != parentino) {
				setbadness(EXIT_RECOV);
				warnx("Directory /%s: Incorrect `..' entry "
				      "(fixed)", pathsofar);
				direntries[i].sfd_ino = parentino;
				dchanged = 1;
			}
			assert(dotdotseen==0); /* due to duplicate checking */
			dotdotseen = 1;
		}
	}

	if (!dotseen) {
		if (dir_tryadd(direntries, ndirentries, ".", ino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `.' entry (added)",
			      pathsofar);
			dchanged = 1;
		}
		else if (dir_tryadd(direntries, maxdirentries, ".", ino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `.' entry (added)",
			      pathsofar);
			ndirentries++;
			dchanged = 1;
			sfi.sfi_size += sizeof(struct sfs_dir);
			ichanged = 1;
		}
		else {
			setbadness(EXIT_UNRECOV);
			warnx("Directory /%s: No `.' entry (NOT FIXED)",
			      pathsofar);
		}
	}

	if (!dotdotseen) {
		if (dir_tryadd(direntries, ndirentries, "..", parentino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `..' entry (added)",
			      pathsofar);
			dchanged = 1;
		}
		else if (dir_tryadd(direntries, maxdirentries, "..",
				    parentino)==0) {
			setbadness(EXIT_RECOV);
			warnx("Directory /%s: No `..' entry (added)",
			      pathsofar);
			ndirentries++;
			dchanged = 1;
			sfi.sfi_size += sizeof(struct sfs_dir);
			ichanged = 1;
		}
		else {
			setbadness(EXIT_UNRECOV);
			warnx("Directory /%s: No `..' entry (NOT FIXED)",
			      pathsofar);
		}
	}

	subdircount=0;
	for (i=0; i<ndirentries; i++) {
		if (!strcmp(direntries[i].sfd_name, ".")) {
			/* nothing */
		}
		else if (!strcmp(direntries[i].sfd_name, "..")) {
			/* nothing */
		}
		else if (direntries[i].sfd_ino == SFS_NOINO) {
			/* nothing */
		}
		else {
			char path[strlen(pathsofar)+SFS_NAMELEN+1];
			struct sfs_inode subsfi;

			diskread(&subsfi, direntries[i].sfd_ino);
			swapinode(&subsfi);
			snprintf(path, sizeof(path), "%s/%s",
				 pathsofar, direntries[i].sfd_name);

			switch (subsfi.sfi_type) {
			    case SFS_TYPE_FILE:
				if (check_inode_blocks(direntries[i].sfd_ino,
						       &subsfi, 0)) {
					swapinode(&subsfi);
					diskwrite(&subsfi,
						  direntries[i].sfd_ino);
				}
				observe_filelink(direntries[i].sfd_ino);
				break;
			    case SFS_TYPE_DIR:
				if (check_dir(direntries[i].sfd_ino,
					      ino,
					      path)) {
					setbadness(EXIT_RECOV);
					warnx("Directory /%s: Crosslink to "
					      "other directory (removed)",
					      path);
					direntries[i].sfd_ino = SFS_NOINO;
					direntries[i].sfd_name[0] = 0;
					dchanged = 1;
				}
				else {
					subdircount++;
				}
				break;
			    default:
				setbadness(EXIT_RECOV);
				warnx("Object /%s: Invalid inode type "
				      "(removed)", path);
				direntries[i].sfd_ino = SFS_NOINO;
				direntries[i].sfd_name[0] = 0;
				dchanged = 1;
				break;
			}
		}
	}

	if (sfi.sfi_linkcount != subdircount+2) {
		setbadness(EXIT_RECOV);
		warnx("Directory /%s: Link count %lu should be %lu (fixed)",
		      pathsofar, (unsigned long) sfi.sfi_linkcount,
		      (unsigned long) subdircount+2);
		sfi.sfi_linkcount = subdircount+2;
		ichanged = 1;
	}

	if (dchanged) {
		dirwrite(&sfi, direntries, ndirentries);
	}

	if (ichanged) {
		swapinode(&sfi);
		diskwrite(&sfi, ino);
	}

	free(direntries);
	free(sortvector);

	return 0;
}
Exemplo n.º 14
0
/* returns nonzero if inode modified */
static
int
check_inode_blocks(uint32_t ino, struct sfs_inode *sfi, int isdir)
{
	uint32_t size, block, nblocks, badcount;

	badcount = 0;

	size = SFS_ROUNDUP(sfi->sfi_size, SFS_BLOCKSIZE);
	nblocks = size/SFS_BLOCKSIZE;

	for (block=0; block<SFS_NDIRECT; block++) {
		if (block < nblocks) {
			if (sfi->sfi_direct[block] != 0) {
				bitmap_mark(sfi->sfi_direct[block],
					    isdir ? B_DIRDATA : B_DATA, ino);
			}
		}
		else {
			if (sfi->sfi_direct[block] != 0) {
				badcount++;
				bitmap_mark(sfi->sfi_direct[block],
					    B_TOFREE, 0);
			}
		}
	}

#ifdef SFS_NIDIRECT
	for (i=0; i<SFS_NIDIRECT; i++) {
		check_indirect_block(ino, &sfi->sfi_indirect[i],
				     &block, nblocks, &badcount, isdir, 1);
	}
#else
	check_indirect_block(ino, &sfi->sfi_indirect,
			     &block, nblocks, &badcount, isdir, 1);
#endif

#ifdef SFS_NDIDIRECT
	for (i=0; i<SFS_NDIDIRECT; i++) {
		check_indirect_block(ino, &sfi->sfi_dindirect[i],
				     &block, nblocks, &badcount, isdir, 2);
	}
#else
#ifdef HAS_DIDIRECT
	check_indirect_block(ino, &sfi->sfi_dindirect,
			     &block, nblocks, &badcount, isdir, 2);
#endif
#endif

#ifdef SFS_NTIDIRECT
	for (i=0; i<SFS_NTIDIRECT; i++) {
		check_indirect_block(ino, &sfi->sfi_tindirect[i],
				     &block, nblocks, &badcount, isdir, 3);
	}
#else
#ifdef HAS_TIDIRECT
	check_indirect_block(ino, &sfi->sfi_tindirect,
			     &block, nblocks, &badcount, isdir, 3);
#endif
#endif

	if (badcount > 0) {
		warnx("Inode %lu: %lu blocks after EOF (freed)",
		     (unsigned long) ino, (unsigned long) badcount);
		setbadness(EXIT_RECOV);
		return 1;
	}

	return 0;
}
Exemplo n.º 15
0
static
void
check_indirect_block(uint32_t ino, uint32_t *ientry, uint32_t *blockp,
		     uint32_t nblocks, uint32_t *badcountp,
		     int isdir, int indirection)
{
	uint32_t entries[SFS_DBPERIDB];
	uint32_t i, ct;

	if (*ientry !=0) {
		diskread(entries, *ientry);
		swapindir(entries);
		bitmap_mark(*ientry, B_IBLOCK, ino);
	}
	else {
		for (i=0; i<SFS_DBPERIDB; i++) {
			entries[i] = 0;
		}
	}

	if (indirection > 1) {
		for (i=0; i<SFS_DBPERIDB; i++) {
			check_indirect_block(ino, &entries[i],
					     blockp, nblocks,
					     badcountp,
					     isdir,
					     indirection-1);
		}
	}
	else {
		assert(indirection==1);

		for (i=0; i<SFS_DBPERIDB; i++) {
			if (*blockp < nblocks) {
				if (entries[i] != 0) {
					bitmap_mark(entries[i],
						    isdir ? B_DIRDATA : B_DATA,
						    ino);
				}
			}
			else {
				if (entries[i] != 0) {
					(*badcountp)++;
					bitmap_mark(entries[i],
						    isdir ? B_DIRDATA : B_DATA,
						    ino);
					entries[i] = 0;
				}
			}
			(*blockp)++;
		}
	}

	ct=0;
	for (i=ct=0; i<SFS_DBPERIDB; i++) {
		if (entries[i]!=0) ct++;
	}
	if (ct==0) {
		if (*ientry != 0) {
			(*badcountp)++;
			bitmap_mark(*ientry, B_TOFREE, 0);
			*ientry = 0;
		}
	}
	else {
		assert(*ientry != 0);
		if (*badcountp > 0) {
			swapindir(entries);
			diskwrite(entries, *ientry);
		}
	}
}