static int gfs_zero_inode(struct gfs_inode_info *inode) { struct gfs_super_info *sb = (struct gfs_super_info *)inode->vfs_inode.i_sb->s_fs_info; int nblocks = sb->s_chunk_size, i; for( i = 0;i<nblocks; ++i ) { struct buffer_head *bh = get_inode_block(inode, i, 1); if(!bh) return -ENOMEM; memset(bh->b_data, 0, bh->b_size); put_inode_block(inode,1); } return 0; }
int create_file(char *path, int is_dir) { char *lpath = malloc(sizeof(char)*strlen(path)+1); char *last; char *ptr; int wd, free_inode_num, found, s; struct inode_block *cur_inode_block = NULL; struct inode *cur_inode = NULL; strcpy(lpath, path); if(strlen(lpath) == 1) { if(lpath[0] == '/') { return ERR_FILE_EXISTS; } else { return ERR_INVALID_PATH; } } ptr = strrchr(lpath, '/'); if(ptr == lpath+strlen(lpath)-1) { *ptr = '\0'; ptr = strrchr(lpath, '/'); } *ptr = '\0'; ptr++; last = malloc(sizeof(char)*strlen(ptr)+1); strcpy(last, ptr); wd = path_to_inode(lpath); DEBUG1 && printf("wd = %d \n", wd); if(wd < 0) { return ERR_INVALID_PATH; } //printf("wd inode = %d \n", wd); get_inode(&cur_inode_block, &cur_inode, wd); if(cur_inode_block == NULL || cur_inode == NULL) { DEBUG2 && printf("get inode failed\n"); return ERR_INTERNAL; } found = has_file(cur_inode, last); //printf("found = %d \n", found); DEBUG1 && printf("found = %d \n", found); if(found != -1) { //printf("file or dir already exists!\n"); //printf("wd = %d, last = %s \n ", wd, last); return ERR_FILE_EXISTS; } free_inode_num = get_free_inode(); //printf("free inode num = %d\n", free_inode_num); if(free_inode_num < 0) { return ERR_MAX_FILES; } get_inode( &cur_inode_block, &cur_inode , free_inode_num); if(cur_inode_block == NULL || cur_inode == NULL) { return ERR_INTERNAL; } cur_inode->is_dir = is_dir; put_inode_block(cur_inode_block, free_inode_num); //free_data_block_num = get_free_datablock(); //printf("free_data_block_num = %d\n", free_data_block_num); s = add_dir_to_inode(wd, last, free_inode_num); return s; }
int add_data_block(int inode_num) { struct datablock *dblock = malloc(sizeof(struct datablock)); struct indirection_block *iblock1; struct indirection_block *iblock2; struct inode_block *iblock; struct inode *inode; int block_num; int new_db_num = get_free_datablock(); DEBUG1 && printf("new db number: %d \n", new_db_num); if(new_db_num < 0) return -1; get_inode(&iblock, &inode, inode_num); block_num = inode->num_blocks; if(!inode) { DEBUG2 && printf("inode is null\n"); return -1; } if(block_num >= 0 && block_num < 10) { inode->file_blocks[block_num] = new_db_num; inode->num_blocks++; if(put_inode_block(iblock, inode_num)) { return -1; } free(iblock); return new_db_num; } else if(block_num == 10) { //make indirection block struct indirection_block *ib = malloc(sizeof(struct indirection_block)); ib->pointer[0] = new_db_num; int ind_block_num = get_free_datablock(); if(ind_block_num < 0) return -1; DEBUG1 && printf("adding indirection block: %d\n", ind_block_num); if(!write_block(file, ib, ind_block_num)) { DEBUG2 && printf("Error writing indirection block\n"); return -1; } inode->indirect1 = ind_block_num; inode->num_blocks++; if(put_inode_block(iblock, inode_num)) { return -1; } free(ib); free(iblock); return new_db_num; } else if(block_num > 10 && block_num < (10+128)) { struct indirection_block *ib = malloc(sizeof(struct indirection_block)); int ind_block_num = inode->indirect1; if(!read_block(file, ib, ind_block_num)) { DEBUG2 && printf("Error reading indirection block\n"); return -1; } ib->pointer[block_num - 10] = new_db_num; if(! write_block(file, ib, ind_block_num)) { DEBUG2 && printf("Error writing indirection block\n"); return -1; } inode->num_blocks++; if(put_inode_block(iblock, inode_num)) { return -1; } free(ib); free(iblock); return new_db_num; } else if(block_num == (10+128)) { struct indirection_block *ib1 = malloc(sizeof(struct indirection_block)); struct indirection_block *ib2 = malloc(sizeof(struct indirection_block)); int ind_block_num1 = get_free_datablock(); int ind_block_num2 = get_free_datablock(); if(ind_block_num1 < 0 || ind_block_num2 < 0) return -1; inode->indirect2 = ind_block_num1; inode->num_blocks++; ib1->pointer[0] = ind_block_num2; ib2->pointer[0] = new_db_num; if(!write_block(file, ib1, ind_block_num1)) { DEBUG2 && printf("Error writing indirection block\n"); return -1; } if(!write_block(file, ib2, ind_block_num2)) { DEBUG2 && printf("Error writing indirection block\n"); return -1; } if(put_inode_block(iblock, inode_num)) { return -1; } free(ib1); free(ib2); free(iblock); return new_db_num; } else if(block_num > (10+128) && block_num < (10+128+(128*128))) { struct indirection_block *ib1 = malloc(sizeof(struct indirection_block)); struct indirection_block *ib2 = malloc(sizeof(struct indirection_block)); int ind_block_num1 = inode->indirect2; if( !read_block(file, ib1, ind_block_num1)) { DEBUG2 && printf("error reading datablock\n"); return -1; } if(((block_num - (10+128)) % 128) == 0) { int new_ind_block = get_free_datablock(); ib1->pointer[(block_num - (10+128)) / 128] = new_ind_block; ib2->pointer[0] = new_db_num; inode->num_blocks++; if(!write_block(file, ib1, ind_block_num1)) { DEBUG2 && printf("error reading datablock\n"); return -1; } if(!write_block(file, ib2, new_ind_block)) { DEBUG2 && printf("error reading datablock\n"); return -1; } if(put_inode_block(iblock, inode_num)) { return -1; } return new_db_num; } else { int ind_block_num2 = ib1->pointer[(block_num - (10+128)) / 128]; if(!read_block(file, ib2, ind_block_num2)) { DEBUG2 && printf("error reading datablock\n"); return -1; } ib2->pointer[(block_num - (10+128)) % 128] = new_db_num; inode->num_blocks++; if( !write_block(file, ib2, ind_block_num2)) { DEBUG2 && printf("error reading datablock\n"); return -1; } if(put_inode_block(iblock, inode_num)) { return -1; } return new_db_num; } } else { DEBUG2 && printf("Error: cannot add another block, filesize max reached\n"); return -1; } return new_db_num; }
//find free inode, remove from free inode list, return inode number int get_free_inode(void) { struct superblock *sb = malloc(sizeof(struct superblock)); struct inode_block *iblock; struct inode *inode; int inode_num; int new_free; int i; if(! read_block(file, sb, 1)) { DEBUG2 && printf("Error reading superblock\n"); return -1; } if( (inode_num = sb->free_inode_list) == -1) { DEBUG2 && printf("Error no free inodes\n"); return -1; } if(get_inode(&iblock, &inode, inode_num)) { DEBUG2 && printf("ERROR: couldn't get inode \n "); return -1; } new_free = inode->next_free_inode; inode->next_free_inode = -2; inode->is_free=0; inode->num_blocks=0; inode->is_dir=0; for(i=0; i < 10 ; i++) { inode->file_blocks[i] = 0; } inode->indirect1 = 0; inode->indirect2 = 0; DEBUG1 && printf("new_free: %d \n", new_free); sb->free_inode_list = new_free; sb->files_allocated++; if(! write_block(file, sb, 1)) { DEBUG2 && printf("Error writing superblock\n"); return -1; } if(put_inode_block(iblock, inode_num)) { return -1; } free(sb); free(iblock); return inode_num; }
int delete_file(char *path) { char *lpath = malloc(sizeof(char)*strlen(path)+1); char *orig_path = malloc(sizeof(char)*strlen(path)+1); char *last; char *ptr; char null_array[12]; int wd, free_inode_num, found, s; int inode_num; struct inode_block *ib = NULL; struct inode *inode = NULL; struct inode_block *doomed_ib = NULL; struct inode *doomed_inode = NULL; struct directory *dir = NULL; struct datablock *datablock = NULL; struct directory *ldir = NULL; struct datablock *ldatablock = NULL; int doomed_inode_num; int i, j, k, foundit = 0; int cur_db_num, last_db_num; /* for(i=0;i<12;i++){ null_array[i] = '\0'; } */ strcpy(lpath, path); strcpy(orig_path, path); if(strlen(lpath) == 1) { if(lpath[0] == '/') { return ERR_FILE_EXISTS; //update this to correct val } else { return ERR_INVALID_PATH; } } ptr = strrchr(lpath, '/'); if(ptr == lpath+strlen(lpath)-1) { *ptr = '\0'; ptr = strrchr(lpath, '/'); } ptr++; last = malloc(sizeof(char)*strlen(ptr)+1); strcpy(last, ptr); *ptr = '\0'; wd = path_to_inode(lpath); DEBUG1 && printf("lpath = %s last = %s \n", lpath, last); //funct to remove all data blocks if((doomed_inode_num = path_to_inode(orig_path)) < 0) { DEBUG1 && printf("cannot delete, does not exist\n"); return ERR_FILE_NOT_FOUND; } if((get_inode(&doomed_ib, &doomed_inode, doomed_inode_num)) < 0) { DEBUG2 && printf("error get_inode\n"); return -1; } if(doomed_inode->is_dir != 0 && doomed_inode->num_blocks > 0) { DEBUG1 && printf("cannot delete a none empty directory"); return ERR_INVALID_PATH;//should be a different error } erase_inode(doomed_inode_num); //funct to remove from dir if((inode_num = path_to_inode(lpath)) < 0) { DEBUG2 && printf("error path_to_inode\n"); return -1; } if((get_inode(&ib, &inode, inode_num)) < 0) { DEBUG2 && printf("error get_inode\n"); return -1; } for(i=0; i<inode->num_blocks; i++) { cur_db_num = get_data_block(&datablock, inode, i); dir = (struct directory *)datablock; for(j=0; j<32; j++) { if(strcmp(last,dir->entries[j].filename) == 0 ) { DEBUG1 && printf("got it!\n"); //strcpy(dir->entries[j].filename, ""); //dir->entries[j].inode_number = 0; foundit = 1; //write_block(file, dir, cur_db_num); break; } } if(foundit) { break; } } if(!foundit) { return -1; } last_db_num = get_data_block(&ldatablock, inode, inode->num_blocks-1); ldir = (struct directory *)ldatablock; if(last_db_num == cur_db_num) { for(k=0; k<32; k++) { if(dir->entries[k].inode_number == 0) { //k++; break; } } // k-1 is the one we want, even if we went all the way to the end. strcpy(dir->entries[j].filename, dir->entries[k-1].filename); dir->entries[j].inode_number = dir->entries[k-1].inode_number; for(i=0; i<12; i++) { dir->entries[k-1].filename[i] = '\0'; } dir->entries[k-1].inode_number = 0; write_block(file, dir, cur_db_num); if(k-1 == 0) { //add last_db_num to free blocks if(make_free_datablock(last_db_num)) { DEBUG2 && printf("couldnt free datablock\n"); } //subtract a datablock from inode->num_blocks //WE NEED TO ADD STUFF TO SUBTRACT INDIRECTION BLOCKS inode->num_blocks--; DEBUG1 && printf("inode->num_blocks = %d \n", inode->num_blocks); //write the inode back put_inode_block(ib, inode_num); trim_indirection_blocks(inode_num); } } else { for(k=0; k<32; k++) { if(ldir->entries[k].inode_number == 0) { //k++; break; } } // k-1 is the one we want, even if we went all the way to the end. strcpy(dir->entries[j].filename, ldir->entries[k-1].filename); dir->entries[j].inode_number = ldir->entries[k-1].inode_number; for(i=0; i<12; i++) { ldir->entries[k-1].filename[i] = '\0'; } ldir->entries[k-1].inode_number = 0; write_block(file, dir, cur_db_num); write_block(file, ldir, last_db_num); if(k-1 == 0) { //add last_db_num to free blocks if(make_free_datablock(last_db_num)) { DEBUG1 && printf("couldnt free datablock\n"); } //subtract a datablock from inode->num_blocks //WE NEED TO ADD STUFF TO SUBTRACT INDIRECTION BLOCKS inode->num_blocks--; DEBUG1 && printf("inode->num_blocks = %d \n", inode->num_blocks); //write the inode back put_inode_block(ib, inode_num); trim_indirection_blocks(inode_num); } } return SUCCESS; }
int trim_indirection_blocks(int inode_num) { struct inode_block *ib = NULL; struct inode *inode = NULL; struct indirection_block *idb = malloc(sizeof(struct indirection_block)); int num_blocks; if((get_inode(&ib, &inode, inode_num)) < 0) { DEBUG2 && printf("error get_inode\n"); return -1; } num_blocks = inode->num_blocks; if(num_blocks < 10 && inode->indirect1 != 0) { //remove inode->indirect1 make_free_datablock(inode->indirect1); inode->indirect1 = 0; put_inode_block(ib, inode_num); return 1; } if(num_blocks < (10+128) && inode->indirect2 != 0) { //remove inode->indirect2 make_free_datablock(inode->indirect2); inode->indirect2 = 0; put_inode_block(ib, inode_num); return 1; } if(num_blocks >= (10+128) && num_blocks < (10+128+(128*128))) { if(((num_blocks - (10+128)) % 128) == 0) { //remove second level indirection block if(!read_block(file, idb, inode->indirect2)) { DEBUG2 && printf("Error reading indirection block\n"); return -1; } if( idb->pointer[(num_blocks - (10+128)) / 128] != 0) { make_free_datablock(idb->pointer[(num_blocks - (10+128)) / 128]); idb->pointer[(num_blocks - (10+128)) / 128] = 0; return 1; } //block to remove //ib1->pointer[(block_num - (10+128)) / 128] //int new_ind_block = get_free_datablock(); //ib1->pointer[(block_num - (10+128)) / 128] //ib2->pointer[0] = new_db_num; //inode->num_blocks++; } } return 0; }
int erase_inode(int inode_num) { struct inode_block *ib = NULL; struct inode *inode = NULL; struct directory *dir = NULL; struct datablock *datablock = NULL; struct indirection_block *idb = malloc(sizeof(struct indirection_block)); struct indirection_block *idb2 = malloc(sizeof(struct indirection_block)); struct superblock *sb = malloc(sizeof(struct superblock)); int cur_db_num, i; if((get_inode(&ib, &inode, inode_num)) < 0) { DEBUG2 && printf("error get_inode\n"); return -1; } while(inode->num_blocks > 0) { cur_db_num = get_data_block(&datablock, inode, inode->num_blocks-1); make_free_datablock(cur_db_num); inode->num_blocks--; } if(inode->indirect1 != 0) { make_free_datablock(inode->indirect1); inode->indirect1 = 0; } if(inode->indirect2 !=0) { if(!read_block(file, idb2, inode->indirect2)) { return ERR_INTERNAL; } for(i=0; i<128; i++) { if(idb2->pointer[i] != 0) { make_free_datablock(idb2->pointer[i]); } } make_free_datablock(inode->indirect2); inode->indirect2 = 0; } for(i=0; i<10; i++) { inode->file_blocks[i] = 0; } inode->is_dir = 0; inode->is_free = 1; if(!read_block(file, sb, 1)) { return ERR_INTERNAL; } inode->next_free_inode = sb->free_inode_list; sb->free_inode_list = inode_num; if(!write_block(file, sb, 1)) { return ERR_INTERNAL; } put_inode_block(ib, inode_num); }