void seedRandom() { if (!already_initialized) { already_initialized = 1; __current_rand_index = zero_block(); srand(time(NULL)); block cur_seed = _mm_set_epi32(rand(), rand(), rand(), rand()); AES_set_encrypt_key((unsigned char *) &cur_seed, 128, &__rand_aes_key); } }
// Set *blk to the address in memory where the filebno'th // block of file 'f' would be mapped. // Allocate the block if it doesn't yet exist. // // Returns 0 on success, < 0 on error. Errors are: // -E_NO_DISK if a block needed to be allocated but the disk is full. // -E_INVAL if filebno is out of range. // // Hint: Use file_block_walk and alloc_block. int file_get_block(struct File *f, uint32_t filebno, char **blk) { // LAB 5: Your code here. //panic("file_get_block not implemented"); int r; uint32_t *pdiskbno; uint32_t blockno; if((r =file_block_walk(f,filebno, &pdiskbno, 1)) < 0) return r; if( *pdiskbno == 0){ if((*pdiskbno = alloc_block()) < 0) return -E_NO_DISK; zero_block(*pdiskbno); } *blk = (char *)diskaddr(*pdiskbno); return 0; }
// Find the disk block number slot for the 'filebno'th block in file 'f'. // Set '*ppdiskbno' to point to that slot. // The slot will be one of the f->f_direct[] entries, // or an entry in the indirect block. // When 'alloc' is set, this function will allocate an indirect block // if necessary. // // Returns: // 0 on success (but note that *ppdiskbno might equal 0). // -E_NOT_FOUND if the function needed to allocate an indirect block, but // alloc was 0. // -E_NO_DISK if there's no space on the disk for an indirect block. // -E_INVAL if filebno is out of range (it's >= NDIRECT + NINDIRECT). // // Analogy: This is like pgdir_walk for files. // Hint: Don't forget to clear any block you allocate. static int file_block_walk(struct File *f, uint32_t filebno, uint32_t **ppdiskbno, bool alloc) { // LAB 5: Your code here. //panic("file_block_walk not implemented"); uint32_t* indp; if(filebno >= NDIRECT + NINDIRECT) return -E_INVAL; if(filebno < NDIRECT){ *ppdiskbno = &f->f_direct[filebno]; return 0; } filebno -= NDIRECT; if(f->f_indirect == 0 ){ if(!alloc) return -E_NOT_FOUND; if((f->f_indirect = alloc_block()) <0){ f->f_indirect=0; return -E_NO_DISK; } //memset(diskaddr(f->f_indirect), 0, BLKSIZE); zero_block(f->f_indirect); } indp = (uint32_t*)diskaddr(f->f_indirect); *ppdiskbno = &indp[filebno]; flush_block((void *)indp); return 0; }
static int add_block(ospfs_inode_t *oi) { // current number of blocks in file uint32_t n = ospfs_size2nblocks(oi->oi_size); /* EXERCISE: Your code here */ //Max blocks already in use if(n >= OSPFS_MAXFILEBLKS){ return -ENOSPC; } uint32_t block = allocate_block(); if(block == 0){ return -ENOSPC; } zero_block(block); //Don't need indirect2 block if(indir2_index(n) == -1){ //Don't need indirect block if(indir_index(n) == -1){ oi->oi_direct[n] = block; //Need indirect block }else if(indir_index(n) == 0){ //Need to allocate new indirect block if(n == OSPFS_NDIRECT){ uint32_t indir = allocate_block(); if(indir == 0){ free_block(block); return -ENOSPC; } zero_block(indir); oi->oi_indirect = indir; } //Add in new block number into indirect block uint32_t *indir_ptr = ospfs_block(oi->oi_indirect); indir_ptr[direct_index(n)] = block; } //Need indirect2 block }else{ //Preset these values, so that if freed and unchanged nothing happens uint32_t indir = -1; uint32_t indir2 = -1; //Need to allocate new indirect2 block if(n == OSPFS_NDIRECT + OSPFS_NINDIRECT){ indir2 = allocate_block(); if(indir2 == 0){ free_block(block); return -ENOSPC; } zero_block(indir2); oi->oi_indirect2 = indir2; } uint32_t *indir2_ptr = ospfs_block(oi->oi_indirect2); //Need to allocate new indirect block if((n-OSPFS_NDIRECT-OSPFS_NINDIRECT) % OSPFS_NINDIRECT == 0){ uint32_t indir = allocate_block(); if(indir == 0){ free_block(block); free_block(indir2); return -ENOSPC; } zero_block(indir); indir2_ptr[indir_index(n)] = indir; }else{ indir = indir2_ptr[indir_index(n)]; } uint32_t *indir_ptr = ospfs_block(indir); indir_ptr[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT) % OSPFS_NINDIRECT] = block; } oi->oi_size = OSPFS_BLKSIZE * (n+1); return 0; }
/* * btt_read -- read a block from a btt namespace * * Returns 0 on success, otherwise -1/errno. */ int btt_read(struct btt *bttp, int lane, uint64_t lba, void *buf) { LOG(3, "bttp %p lane %u lba %zu", bttp, lane, lba); if (invalid_lba(bttp, lba)) return -1; /* if there's no layout written yet, all reads come back as zeros */ if (!bttp->laidout) return zero_block(bttp, buf); /* find which arena LBA lives in, and the offset to the map entry */ struct arena *arenap; uint32_t premap_lba; off_t map_entry_off; if (lba_to_arena_lba(bttp, lba, &arenap, &premap_lba) < 0) return -1; /* convert pre-map LBA into an offset into the map */ map_entry_off = arenap->mapoff + BTT_MAP_ENTRY_SIZE * premap_lba; /* * Read the current map entry to get the post-map LBA for the data * block read. */ uint32_t entry; if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, &entry, sizeof (entry), map_entry_off) < 0) return -1; entry = le32toh(entry); /* * Retries come back to the top of this loop (for a rare case where * the map is changed by another thread doing writes to the same LBA). */ while (1) { if (entry & BTT_MAP_ENTRY_ERROR) { LOG(1, "EIO due to map entry error flag"); errno = EIO; return -1; } if (entry & BTT_MAP_ENTRY_ZERO) return zero_block(bttp, buf); /* * Record the post-map LBA in the read tracking table during * the read. The write will check entries in the read tracking * table before allocating a block for a write, waiting for * outstanding reads on that block to complete. * * No need to mask off ERROR and ZERO bits since the above * checks make sure they are clear at this point. */ arenap->rtt[lane] = entry; __sync_synchronize(); /* * In case this thread was preempted between reading entry and * storing it in the rtt, check to see if the map changed. If * it changed, the block about to be read is at least free now * (in the flog, but that's okay since the data will still be * undisturbed) and potentially allocated and being used for * another write (data disturbed, so not okay to continue). */ uint32_t latest_entry; if ((*bttp->ns_cbp->nsread)(bttp->ns, lane, &latest_entry, sizeof (latest_entry), map_entry_off) < 0) { arenap->rtt[lane] = BTT_MAP_ENTRY_ERROR; return -1; } latest_entry = le32toh(latest_entry); if (entry == latest_entry) break; /* map stayed the same */ else entry = latest_entry; /* try again */ } /* * It is safe to read the block now, since the rtt protects the * block from getting re-allocated to something else by a write. */ off_t data_block_off = arenap->dataoff + entry * arenap->internal_lbasize; int readret = (*bttp->ns_cbp->nsread)(bttp->ns, lane, buf, bttp->lbasize, data_block_off); /* done with read, so clear out rtt entry */ arenap->rtt[lane] = BTT_MAP_ENTRY_ERROR; return readret; }
FUNCTION static CODE writeVmToFile ( Id vm, /* in: vm to write */ struct SFILE *f, /* in: SFILE to use */ TEXT *name) /* in: name of vm */ { CODE code; struct PARHDR ph; TEXT filespec[STRINGSIZ+1]; TEXT sizeString[STRINGSIZ+1]; TEXT dateString[STRINGSIZ+1]; LONG fileSize; struct POSCTX startPosition; /* position of file start */ #ifdef UNIX struct ar_hdr header; struct POSCTX headerPosition; struct POSCTX eofPosition; /* position of next file */ COUNT length; struct timeval time; /* build and write the archive header record */ s_blank ((TEXT *) &header, sizeof (struct ar_hdr) - 1); s_copy (name, filespec); s_append (".par", filespec); /* add .par suffix */ #ifdef AIX length = min(s_length (filespec), sizeof (header._ar_name.ar_name)); bytmov (filespec, header._ar_name.ar_name, length); #else length = min(s_length (filespec), sizeof (header.ar_name)); bytmov (filespec, header.ar_name, length); #endif gettimeofday (&time, NULL); sprintf (dateString, "%lu", time.tv_sec); bytmov (dateString, header.ar_date, s_length(dateString)); bytmov ("000 ", header.ar_uid, sizeof (header.ar_uid)); bytmov ("000 ", header.ar_gid, sizeof (header.ar_gid)); bytmov ("100644 ", header.ar_mode, sizeof (header.ar_mode)); #ifdef AIX header._ar_name.ar_fmag[0] = '\`'; header._ar_name.ar_fmag[1] = EOS; /* becomes \n when written */ #else header.ar_fmag[0] = '`'; header.ar_fmag[1] = EOS; /* becomes \n when written */ #endif f_write (f, (TEXT *)&header); /* write archive hdr recrd */ f_movpos (&(*f).posctx, &headerPosition); /* save position of the rec */ #endif zero_block ((GENPTR)&ph, sizeof (ph)); s_copy (P_SENTINEL, ph.sentinel); ph.recsize = sizeof (struct LARGE_PARBLK); s_copy ("TIME", ph.datetime); s_bcopy (name, ph.filename, sizeof (ph.filename)-1); code = f_bwrite (f, (GENPTR)&ph, sizeof (ph)); if (code != SUCCESS) return (0); /* stop the Co_ForEach */ f_movpos (&(*f).posctx, &startPosition); /* position of PARHDR record */ code = Vm_WriteVm ((struct VM_STRUCT *)vm, f); if (code == SUCCESS) { #ifdef UNIX f_curpos (f, &eofPosition); f_setpos (f, &headerPosition); /* go back and update header */ fileSize = eofPosition.pos - startPosition.pos; sprintf (sizeString, "%ld", fileSize); /* convert to ascii */ bytmov (sizeString, header.ar_size, s_length (sizeString)); f_write (f, (TEXT *)&header); f_setpos (f, &eofPosition); /* get ready for next file */ if (fileSize & 1) f_write (f, ""); /* get to dble byte bndry */ #endif return (0); /* keep Co_ForEach going */ } else return (0); /* stop the Co_ForEach */ }
static int file_block(struct filesys *fs, struct inode *node, int boffs, int allocate) { int res, idx, node_dirty = 0; blkid *barr; /* out of bounds */ if(boffs < 0 || boffs >= MAX_DIND) { return 0; } /* is it a direct block ? */ if(boffs < NDIRBLK) { if(!(res = node->blk[boffs]) && allocate) { res = node->blk[boffs] = alloc_block(fs); if(res) { zero_block(fs, res); /* also write back the modified inode */ put_inode(fs, node); } } return res; } barr = malloc(fs->sb->blksize); assert(barr); /* is it an indirect block ? */ if(boffs < MAX_IND) { int ind_dirty = 0; if(node->ind) { /* read the indirect block */ blk_read(fs->bdev, node->ind, 1, barr); } else { /* does not exist... try to allocate if requested */ if(!allocate || !(node->ind = alloc_block(fs))) { res = 0; goto end; } /* allocated a block clear the buffer, and invalidate everything */ memset(barr, 0, sizeof fs->sb->blksize); node_dirty = 1; ind_dirty = 1; } idx = boffs - NDIRBLK; if(!(res = barr[idx])) { if(allocate && (res = barr[idx] = alloc_block(fs))) { ind_dirty = 1; } } /* write back the indirect block if needed */ if(ind_dirty) { blk_write(fs->bdev, node->ind, 1, barr); } goto end; } /* TODO check/rewrite this */ #if 0 /* is it a double-indirect block ? */ if(boffs < MAX_DIND) { /* first read the dind block and find the index of the ind block */ if(!node->dind) { if(allocate) { /* allocate and zero-out the double indirect block */ res = node->dind = alloc_block(fs); if(res) { zero_block(fs, res); } } else { res = 0; goto end; } } blk_read(fd->bdev, node->dind, 1, barr); idx = (boffs - MAX_IND) / BLK_BLKID; /* then read the ind block and find the index of the block */ if(!barr[idx]) { res = 0; goto end; } blk_read(fd->bdev, barr[idx], 1, barr); res = barr[(boffs - MAX_IND) % BLK_BLKID]; } #endif end: if(node_dirty) { put_inode(fs, node); } free(barr); return res; }