/* 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); }
/* 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); }
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; }
/* * 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; }
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; }
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; }
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); } }
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); }
/* * 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--; }
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); }
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; }
/* * 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; }
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; }
/* 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; }
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); } } }