static void sync_inode(int inode_index,INODE inode){ #ifdef DEBUG_FS printl("inode_index=%d(in sync_inode)\n",inode_index); #endif int inode_first_index=get_inode_first_index(super_block); int off=inode_index*INODE_SIZE; u8 fsbuf[SECTOR_SIZE]; inode_first_index+=off/SECTOR_SIZE; off=off%SECTOR_SIZE; rw_sector(INFO_FS_READ, ROOT_DEVICE, (inode_first_index)*SECTOR_SIZE, SECTOR_SIZE, TASK_FS, fsbuf); memcpy(fsbuf+off,&inode,INODE_SIZE); rw_sector(INFO_FS_WRITE, ROOT_DEVICE, (inode_first_index)*SECTOR_SIZE, SECTOR_SIZE, TASK_FS, fsbuf); }
static void free_imap_bit(int bits_index){ u8 fsbuf[SECTOR_SIZE]; int sector_index,sector_length,bits_off; sector_index=get_imap_first_index(super_block)+bits_index/BITS_PER_SECTOR; sector_length=1; bits_off=bits_index%BITS_PER_SECTOR; //读取smap数据 rw_sector(INFO_FS_READ, ROOT_DEVICE, sector_index*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); /* printl("sector_index=%d sector_length=%d fsbuf=%c (in free_imap_bit)\n",sector_index,sector_length,*(char*)fsbuf[bits_off/BITS_PER_BYTE]); */ fsbuf[bits_off/BITS_PER_BYTE] &=~(1<<bits_index%BITS_PER_BYTE); /* #ifdef DEBUG_FS */ /* printl("bits_off/BITS_PER_BYTE=%d bits_index%BITS_PER_BYTE=%d fsbuf=%c(in free_imap_bit)\n",bits_off/BITS_PER_BYTE,bits_index%BITS_PER_BYTE,*(char*)fsbuf[bits_off/BITS_PER_BYTE]); */ /* #endif */ rw_sector(INFO_FS_WRITE, ROOT_DEVICE, sector_index*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); }
/* first_sector_index:该文件的起始扇区编号(相对于data_block起始位置的偏移) sector_length:分配给该文件的扇区数 */ static BOOL new_inode(int inode_index,int file_type,int first_sector_index,int sector_length){ int new_inode_sector_index=get_inode_first_index(super_block)+(inode_index*INODE_SIZE)/SECTOR_SIZE; int off=(inode_index*INODE_SIZE)%SECTOR_SIZE; u8 fsbuf[SECTOR_SIZE]; /* printl("data_index=%d(in new_inode)\n",new_inode_sector_index); */ rw_sector(INFO_FS_READ, ROOT_DEVICE, (new_inode_sector_index)*SECTOR_SIZE, SECTOR_SIZE, TASK_FS, fsbuf); INODE *pinode=(INODE*)(fsbuf+off); pinode->i_mode=file_type; pinode->i_size=0; pinode->i_start_sector_index=first_sector_index; pinode->i_sectors_length=sector_length; /* printl("first_sector_index=%d sector_length=%d (in new_inode)\n",first_sector_index,sector_length); */ sync_sectors(new_inode_sector_index,1,fsbuf); return TRUE; }
//目前仅支持文件长度为1扇区固定大小,即data_sector_length=1 static int alloc_smap_bit(int dev,int data_sector_length){ assert(data_sector_length==1,"only for data_sector_length=1 currently!"); int smap_first_index=get_smap_first_index(super_block); int smap_length=get_smap_length(super_block); u8 fsbuf[SECTOR_SIZE]; int off, byte_index,bit_index; for(off=0;off<smap_length;off++){ memset(fsbuf,0,SECTOR_SIZE); int sector_index=(smap_first_index+off); rw_sector(INFO_FS_READ, ROOT_DEVICE, sector_index*SECTOR_SIZE, SECTOR_SIZE, TASK_FS, fsbuf); for(byte_index=0;byte_index<SECTOR_SIZE;byte_index++){ if(fsbuf[byte_index]!=0xFF) break; } for(bit_index=0;bit_index<BITS_PER_BYTE;bit_index++){ if((fsbuf[byte_index] & (1<<bit_index))==0){ fsbuf[byte_index]=fsbuf[byte_index] | (1<<bit_index); sync_sectors(sector_index,1,fsbuf); return (off*SECTOR_SIZE+byte_index)*BITS_PER_BYTE+bit_index; } } } return -1; }
static void sync_sectors(int sector_index,int sector_length,u8 *data){ /* printl("sector_index=%d(in sync_sectors)\n",sector_index); */ rw_sector(INFO_FS_WRITE, ROOT_DEVICE, (sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, data); }
static void get_super_block(int dev,SUPER_BLOCK *super_block){ u8 fsbuf[SECTOR_SIZE]; int super_block_first_index=BOOT_SECTORS_LENGTH; /* READ_SECTOR(ROOT_DEVICE,fsbuf,super_block_first_index); */ rw_sector(INFO_FS_READ, ROOT_DEVICE, (super_block_first_index)*SECTOR_SIZE, SUPER_BLOCK_SIZE, TASK_FS, fsbuf); memcpy(super_block,fsbuf,SUPER_BLOCK_SIZE); }
static BOOL remove_dir_entry(const char *dir_name,int inode_index){ INODE dir_inode; get_dir_inode_by_name(dir_name,&dir_inode); assert(dir_inode.i_mode==I_DIRECTORY,"must be directory"); DIR_ENTRY *dir_entry; int length=dir_inode.i_size; int sector_length=(length+SECTOR_SIZE-1)/SECTOR_SIZE; int dir_entry_count=(dir_inode.i_size)/DIR_ENTRY_SIZE; int dir_entry_index; u8 fsbuf[SECTOR_SIZE*2]; rw_sector(INFO_FS_READ, ROOT_DEVICE, (dir_inode.i_start_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); for(dir_entry_index=0;dir_entry_index<dir_entry_count;dir_entry_index++){ dir_entry=(DIR_ENTRY *)(fsbuf+dir_entry_index*DIR_ENTRY_SIZE); /* #ifdef DEBUG_FS */ /* printl("dir_entry->inode_index=%d ",dir_entry->inode_index); */ /* #endif */ if(dir_entry->inode_index==inode_index){/*目录项inode_index=0表示该目录项为空*/ dir_entry->inode_index=0; rw_sector(INFO_FS_WRITE, ROOT_DEVICE, (dir_inode.i_start_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); return TRUE; } } return FALSE; }
static BOOL new_dir_entry(const char *dir_name,int inode_index,const char *filename){ INODE dir_inode; int dir_inode_index; dir_inode_index=get_dir_inode_by_name(dir_name,&dir_inode); assert(dir_inode.i_mode==I_DIRECTORY,"must be directory"); DIR_ENTRY *dir_entry; int length=dir_inode.i_size; int sector_length=(length+SECTOR_SIZE-1)/SECTOR_SIZE; int dir_entry_count=(dir_inode.i_size)/DIR_ENTRY_SIZE; int dir_entry_index; u8 fsbuf[SECTOR_SIZE*2]; BOOL find=FALSE; rw_sector(INFO_FS_READ, ROOT_DEVICE, (dir_inode.i_start_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); for(dir_entry_index=0;dir_entry_index<dir_entry_count;dir_entry_index++){ dir_entry=(DIR_ENTRY *)(fsbuf+dir_entry_index*DIR_ENTRY_SIZE); /* #ifdef DEBUG_FS */ /* printl("dir_entry->inode_index=%d ",dir_entry->inode_index); */ /* #endif */ if(dir_entry->inode_index==0){/*目录项inode_index=0表示该目录项为空*/ find=TRUE; break; } } if((!find) && ((dir_inode.i_size+DIR_ENTRY_SIZE) <= (dir_inode.i_sectors_length*SECTOR_SIZE))){ dir_entry=(DIR_ENTRY *)(fsbuf+dir_entry_index*DIR_ENTRY_SIZE); dir_inode.i_size=dir_inode.i_size+DIR_ENTRY_SIZE; sync_inode(dir_inode_index,dir_inode); find=TRUE; } if(find){ dir_entry->inode_index=inode_index; strcpy(dir_entry->name,filename); sync_sectors(dir_inode.i_start_sector_index,sector_length,fsbuf);//更新硬盘数据 return TRUE; } return FALSE; }
/* 根据inode_index获得对应的inode */ static int get_inode_by_index(int inode_index,INODE *p_inode){ int inode_first_index=get_inode_first_index(super_block); int off=inode_index*INODE_SIZE; u8 fsbuf[SECTOR_SIZE]; inode_first_index+=off/SECTOR_SIZE; off=off%SECTOR_SIZE; rw_sector(INFO_FS_READ, ROOT_DEVICE, (inode_first_index)*SECTOR_SIZE, SECTOR_SIZE, TASK_FS, fsbuf); memcpy(p_inode,fsbuf+off,INODE_SIZE); return inode_index; }
//有问题:调用的rw_sector中读取数据长度必须为SECTOR_SIZE的整数倍 //该函数还发现一个问题:如果fsbuf为全局静态变量,由于开始读目录内容填充了fsbuf,然后在比较的时候又读取了硬盘,再次填充了fsbuf,导致之前的数据被覆盖。所以fsbuf还是设定成局部变量。 //切忌:尽量减少全局变量的使用。 static int get_inode_by_name(const char *dir_name,const char *file_name,int file_type,INODE *p_inode){ INODE dir_inode; DIR_ENTRY *dir_entry; int dir_entry_index; int dir_entry_count; u8 fsbuf[SECTOR_SIZE*2]; if(get_dir_inode_by_name(dir_name,&dir_inode)<0){ set_error_index(DIR_NOT_EXIST); return -1; } dir_entry_count=dir_inode.i_size/DIR_ENTRY_SIZE; rw_sector(INFO_FS_READ, ROOT_DEVICE, (dir_inode.i_start_sector_index)*SECTOR_SIZE, dir_inode.i_size, TASK_FS, fsbuf); for(dir_entry_index=0;dir_entry_index<dir_entry_count;dir_entry_index++){ dir_entry=(DIR_ENTRY *)(fsbuf+dir_entry_index*DIR_ENTRY_SIZE); /* #ifdef DEBUG_FS */ /* printl("dir_index=%d dir_name=%s filename=%s cmp=%d\n", */ /* dir_entry->inode_index, */ /* dir_entry->name, */ /* file_name, */ /* strcmp(dir_entry->name,file_name)==0); */ /* #endif */ //此处的dir_entry->inode_index=0:表示该文件建立后删除了 if(dir_entry->inode_index>0 && strcmp(dir_entry->name,file_name)==0){ if(get_inode_by_index(dir_entry->inode_index,p_inode)){ if((p_inode->i_mode & file_type) !=0){ /* printl("get inode by name data_sector_index=%d\n",p_inode->i_start_sector_index); */ return dir_entry->inode_index; } } } } set_error_index(FILE_NOT_EXIST); return -1; }
static void/* int */ do_read(MESSAGE *message){ char fsbuf[SECTOR_SIZE*DEFAULT_FILE_SECTOR_LENGTH]; char *buf; int start_position,sector_length,length,data_sector_index; PROCESS *process; struct s_file_descriptor* pfd; process=pid2process(message->source_pid); pfd=process->file_descriptor[message->fd]; if((pfd->fd_op_mode & O_RDONLY)==0 && (pfd->fd_op_mode & O_RDWR)==0){ set_error_index(FILE_CANNOT_READ); message->length=-1; return; } buf=message->res_pointer; start_position=pfd->fd_position; if(start_position > pfd->fd_inode->i_size){ set_error_index(END_OF_FILE); message->length=-1; return; } assert(start_position<=pfd->fd_inode->i_size,"file read over"); length=min(start_position+message->length,pfd->fd_inode->i_size); sector_length=(length+SECTOR_SIZE-1)/SECTOR_SIZE; data_sector_index=pfd->fd_inode->i_start_sector_index; /* printl("data_sector_index=%d sector_length=%d\n",data_sector_index,sector_length); */ rw_sector(INFO_FS_READ, ROOT_DEVICE, (data_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); strncpy(buf,fsbuf+start_position,length-start_position); pfd->fd_position=length; message->length=length-start_position; }
/* 返回目录下文件/目录的个数 */ static int get_filename_in_dir(const char* dir_name,char *files){ INODE dir_inode; DIR_ENTRY *dir_entry; int dir_entry_index; int dir_entry_count; int files_index,files_off; u8 fsbuf[SECTOR_SIZE*2]; if(get_dir_inode_by_name(dir_name,&dir_inode)<0){ set_error_index(DIR_NOT_EXIST); return -1; } dir_entry_count=dir_inode.i_size/DIR_ENTRY_SIZE; rw_sector(INFO_FS_READ, ROOT_DEVICE, (dir_inode.i_start_sector_index)*SECTOR_SIZE, dir_inode.i_size, TASK_FS, fsbuf); files_off=0; files_index=0; for(dir_entry_index=0;dir_entry_index<dir_entry_count;dir_entry_index++){ dir_entry=(DIR_ENTRY *)(fsbuf+dir_entry_index*DIR_ENTRY_SIZE); //此处的dir_entry->inode_index=0:表示该文件建立后删除了 if(dir_entry->inode_index>0){ strcpy(files+files_off,dir_entry->name); #ifdef DEBUG_FS printl("%d:%s\n",files_index,files+files_off); #endif files_off+=strlen(dir_entry->name)+1; files_index++; } } return files_index; }
/** * Read/Write file and return byte count read/written. * * Sector map is not needed to update, since the sectors for the file have been * allocated and the bits are set when the file was created. * * @return How many bytes have been read/written. *****************************************************************************/ PUBLIC int do_rdwt(MESSAGE * msg,struct TASK *pcaller) { MESSAGE fs_msg = *msg; int fd = msg->FD; /**< file descriptor. */ void * buf = fs_msg.BUF;/**< r/w buffer */ int len = fs_msg.CNT; /**< r/w bytes */ int src = fs_msg.source; /* caller proc nr. */ debug("pos of fd[%d] = %d, inode_number = %d",fd,pcaller->filp[fd]->fd_pos,pcaller->filp[fd]->fd_inode->i_num); //sprintf(str,"fd = %d, len = %d", fd, len); assert((pcaller->filp[fd] >= &f_desc_table[0]) && (pcaller->filp[fd] < &f_desc_table[NR_FILE_DESC])); //if (!(pcaller->filp[fd]->fd_mode & O_RDWR)) // return -1; int pos = pcaller->filp[fd]->fd_pos; struct inode * pin = pcaller->filp[fd]->fd_inode; debug("pin->i_size = %d",pin->i_size); //int imode = pin->i_mode & I_TYPE_MASK; debug("imode = %d", pin->i_mode); assert( (pin >= &inode_table[0] && pin < &inode_table[NR_INODE]) || pin->i_mode == I_CHAR_SPECIAL ); if (pin->i_mode == I_CHAR_SPECIAL) { assert((fs_msg.type == READ) || (fs_msg.type == WRITE)); struct CONSOLE *cons = pcaller->cons; if(cons == NULL) return 0; struct SHEET *sht = cons->sht; if(sht == NULL) return 0; if(fs_msg.type == READ){ char *charBuf = (char *)buf; int ch = read_from_keyboard(pcaller, 1); if( ch == -1){ charBuf[0] = 0; }else{ charBuf[0] = ch; charBuf[1] = 0; } }else{ char *msg = (char *)buf; msg[len] = 0; cons_putstr0(cons, msg); } return strlen(buf); } else { assert(pin->i_mode == I_REGULAR || pin->i_mode == I_DIRECTORY); assert((fs_msg.type == READ) || (fs_msg.type == WRITE)); int pos_end; if (fs_msg.type == READ){ if( pos == pin->i_size) return -1; pos_end = min(pos + len, pin->i_size); } else /* WRITE */ pos_end = min(pos + len, pin->i_nr_sects * SECTOR_SIZE); debug("pin->i_size = %d, pos_end = %d",pin->i_size, pos_end); int off = pos % SECTOR_SIZE; int rw_sect_min=pin->i_start_sect+(pos>>SECTOR_SIZE_SHIFT); int rw_sect_max=pin->i_start_sect+(pos_end>>SECTOR_SIZE_SHIFT); int chunk = min(rw_sect_max - rw_sect_min + 1, FSBUF_SIZE >> SECTOR_SIZE_SHIFT); int bytes_rw = 0; int bytes_left = len; int i; for (i = rw_sect_min; i <= rw_sect_max; i += chunk) { /* read/write this amount of bytes every time */ int bytes = min(bytes_left, chunk * SECTOR_SIZE - off); debug("bytes = %d",bytes); rw_sector(DEV_READ, pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, -1, fsbuf); if (fs_msg.type == READ) { phys_copy((void*)va2la(src, buf + bytes_rw), (void*)va2la(-1, fsbuf + off), bytes); } else { /* WRITE */ phys_copy((void*)va2la(-1, fsbuf + off), (void*)va2la(src, buf + bytes_rw), bytes); rw_sector(DEV_WRITE, pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, -1, fsbuf); } off = 0; bytes_rw += bytes; pcaller->filp[fd]->fd_pos += bytes; debug("pos of fd[%d] = %d",fd,pcaller->filp[fd]->fd_pos); bytes_left -= bytes; } if (pcaller->filp[fd]->fd_pos > pin->i_size) { /* update inode::size */ pin->i_size = pcaller->filp[fd]->fd_pos; /* write the updated i-node back to disk */ sync_inode(pin); } pcaller->filp[fd]->fd_pos += bytes_rw; return bytes_rw; } }
static void free_smap_bit(int bits_index,int bits_length){ assert(bits_length==1,"only for sector_length=1 currently!"); #ifdef DEBUG_FS printl("bits_index=%d bits_length=%d(int free_smap_bit)\n",bits_index,bits_length); #endif u8 fsbuf[SECTOR_SIZE]; int sector_index,sector_length,bits_off, bytes_index,bytes_start,bytes_end; sector_index=get_smap_first_index(super_block)+bits_index/BITS_PER_SECTOR; sector_length=(bits_index+bits_length+BITS_PER_SECTOR-1)/BITS_PER_SECTOR; bits_off=bits_index%BITS_PER_SECTOR; bytes_start=(bits_off+BITS_PER_BYTE-1)/BITS_PER_BYTE; bytes_end=(bits_off+bits_length)/BITS_PER_BYTE; #ifdef DEBUG_FS printl("bytes_start=%d bytes_end=%d (in fre_smap_bit)\n",bytes_start,bytes_end); #endif //读取smap数据 rw_sector(INFO_FS_READ, ROOT_DEVICE, sector_index*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); /*分为三步处理: bits: ------------------------------------------------- | | | | | | bits_index 8m ^ 8(m+1) 8n ^ 8(n+1) step: | 1| 2 | 3 | */ for(bits_index=bits_off;bits_index%BITS_PER_BYTE!=0 && bits_index<bits_off+bits_length;bits_index++){ #ifdef DEBUG_FS printl("bits_index=%d(step 1. in fre_smap_bit)",bits_index); #endif fsbuf[bits_index/BITS_PER_BYTE] &=~(1<<bits_index%BITS_PER_BYTE); } #ifdef DEBUG_FS printl("\n"); #endif for(bytes_index=bytes_start;bytes_index<bytes_end;bytes_index++){ #ifdef DEBUG_FS printl("bytes_index=%d(step 2. in fre_smap_bit)",bytes_index); #endif fsbuf[bytes_index]=0; } #ifdef DEBUG_FS printl("\n"); #endif if(bytes_start<bytes_end){/*需要step3操作的情况*/ for(bits_index=bytes_end*BITS_PER_BYTE;bits_index<bits_off+bits_length;bits_index++){ #ifdef DEBUG_FS printl("bits_index=%d(step 3. in fre_smap_bit)",bits_index); #endif fsbuf[bits_index/BITS_PER_BYTE] &=~(1<<bits_index%BITS_PER_BYTE); } } /* #ifdef DEBUG_FS */ printl("\n"); /* #endif */ //更新smap数据 rw_sector(INFO_FS_WRITE, ROOT_DEVICE, sector_index*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); }
static /* int */void do_write(MESSAGE *message){ u8 fsbuf[SECTOR_SIZE*DEFAULT_FILE_SECTOR_LENGTH]; const char *buf; int start_position,sector_length,length,data_sector_index; PROCESS *process; struct s_file_descriptor* pfd; process=pid2process(message->source_pid); if(message->fd==STDOUT && process->file_descriptor[message->fd]==NULL){ #ifdef DEBUG_FS printl("pid=%d (in do_write)\n",message->source_pid); #endif /*pfd->fd_inode->i_mode & I_CHAR_SPECIAL !=0*/ /* int device=pfd->fd_inode->i_start_sector_index; */ message->process_index=message->source_pid; send_receive(SEND,TASK_TTY/* dd_map[DRIVER(device)] */,message); /* message->type=INFO_SUSPEND_PROCESS; */ }else{ pfd=process->file_descriptor[message->fd]; if((pfd->fd_op_mode & O_WRONLY)==0 && (pfd->fd_op_mode & O_RDWR)==0){ set_error_index(FILE_CANNOT_WRITE); message->length=-1; return; } buf=message->arg_pointer; start_position=pfd->fd_position; if(start_position >= pfd->fd_inode->i_sectors_length*SECTOR_SIZE){ set_error_index(FILE_ALLOC_MEM_USEUP); message->length=-1; return; } length=min(start_position+message->length,pfd->fd_inode->i_sectors_length*SECTOR_SIZE); sector_length=(length+SECTOR_SIZE-1)/SECTOR_SIZE; data_sector_index=pfd->fd_inode->i_start_sector_index; #ifdef DEBUG_FS /* printl("1 %d %d length=%d\n",start_position,message->length,length); */ printl("sector_index=%d sector_length=%d(in do_write)\n",data_sector_index,sector_length); #endif rw_sector(INFO_FS_READ, ROOT_DEVICE, (data_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); memcpy(fsbuf+start_position,buf,length-start_position); /* printl("2 %d %d\n",data_sector_index,length); */ rw_sector(INFO_FS_WRITE, ROOT_DEVICE, (data_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); /* printl("3 inode.i_size=%d\n",pfd->fd_inode->i_size); */ pfd->fd_inode->i_size=length; /* printl("inode_index=%d\n",pfd->fd_inode->i_inode_index); */ sync_inode(pfd->fd_inode->i_inode_index,*(pfd->fd_inode)); pfd->fd_position=length; message->length=length-start_position; } }
/** * <Ring 1> This routine handles the DEV_LOG message. * * @param p Ptr to the MESSAGE. *****************************************************************************/ PUBLIC int disklog(char * logstr) { int device = root_inode->i_dev; struct super_block * sb = get_super_block(device); int nr_log_blk0_nr = sb->nr_sects - NR_SECTS_FOR_LOG; /* 0x9D41-0x800=0x9541 */ static int pos = 0; if (!pos) { /* first time invoking this routine */ #ifdef SET_LOG_SECT_SMAP_AT_STARTUP /* * set sector-map so that other files cannot use the log sectors */ int bits_per_sect = SECTOR_SIZE * 8; /* 4096 */ int smap_blk0_nr = 1 + 1 + sb->nr_imap_sects; /* 3 */ int sect_nr = smap_blk0_nr + nr_log_blk0_nr / bits_per_sect; /* 3+9=12 */ int byte_off = (nr_log_blk0_nr % bits_per_sect) / 8; /* 168 */ int bit_off = (nr_log_blk0_nr % bits_per_sect) % 8; /* 1 */ int sect_cnt = NR_SECTS_FOR_LOG / bits_per_sect + 2; /* 1 */ int bits_left= NR_SECTS_FOR_LOG; /* 2048 */ int i; for (i = 0; i < sect_cnt; i++) { RD_SECT(device, sect_nr + i); /* RD_SECT(?, 12) */ for (; byte_off < SECTOR_SIZE && bits_left > 0; byte_off++) { for (; bit_off < 8; bit_off++) { /* repeat till enough bits are set */ assert(((fsbuf[byte_off] >> bit_off) & 1) == 0); fsbuf[byte_off] |= (1 << bit_off); if (--bits_left == 0) break; } bit_off = 0; } byte_off = 0; bit_off = 0; WR_SECT(device, sect_nr + i); if (bits_left == 0) break; } assert(bits_left == 0); #endif /* SET_LOG_SECT_SMAP_AT_STARTUP */ pos = 0x40; #ifdef MEMSET_LOG_SECTS /* write padding stuff to log sectors */ int chunk = min(MAX_IO_BYTES, FSBUF_SIZE >> SECTOR_SIZE_SHIFT); assert(chunk == 256); int sects_left = NR_SECTS_FOR_LOG; for (i = nr_log_blk0_nr; i < nr_log_blk0_nr + NR_SECTS_FOR_LOG; i += chunk) { memset(fsbuf, 0x20, chunk*SECTOR_SIZE); rw_sector(DEV_WRITE, device, i * SECTOR_SIZE, chunk * SECTOR_SIZE, TASK_FS, fsbuf); sects_left -= chunk; } if (sects_left != 0) panic("sects_left should be 0, current: %d.", sects_left); #endif /* MEMSET_LOG_SECTS */ }
/** * Read/Write file and return byte count read/written. * * Sector map is not needed to update, since the sectors for the file have been * allocated and the bits are set when the file was created. * * @return How many bytes have been read/written. *****************************************************************************/ PUBLIC int do_rdwt() { int fd = fs_msg.FD; /**< file descriptor. */ void * buf = fs_msg.BUF;/**< r/w buffer */ int len = fs_msg.CNT; /**< r/w bytes */ int src = fs_msg.source; /* caller proc nr. */ assert((pcaller->filp[fd] >= &f_desc_table[0]) && (pcaller->filp[fd] < &f_desc_table[NR_FILE_DESC])); if (!(pcaller->filp[fd]->fd_mode & O_RDWR)) return -1; int pos = pcaller->filp[fd]->fd_pos; struct inode * pin = pcaller->filp[fd]->fd_inode; assert(pin >= &inode_table[0] && pin < &inode_table[NR_INODE]); int imode = pin->i_mode & I_TYPE_MASK; if (imode == I_CHAR_SPECIAL) { int t = fs_msg.type == READ ? DEV_READ : DEV_WRITE; fs_msg.type = t; int dev = pin->i_start_sect; assert(MAJOR(dev) == 4); fs_msg.DEVICE = MINOR(dev); fs_msg.BUF = buf; fs_msg.CNT = len; fs_msg.PROC_NR = src; assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER); send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &fs_msg); assert(fs_msg.CNT == len); return fs_msg.CNT; } else { assert(pin->i_mode == I_REGULAR || pin->i_mode == I_DIRECTORY); assert((fs_msg.type == READ) || (fs_msg.type == WRITE)); //讀寫不能超過檔案大小 int pos_end; if (fs_msg.type == READ) pos_end = min(pos + len, pin->i_size); else /* WRITE */ pos_end = min(pos + len, pin->i_nr_sects * SECTOR_SIZE); //secNum的offset int off = pos % SECTOR_SIZE; //哪一個sector int rw_sect_min=pin->i_start_sect+(pos>>SECTOR_SIZE_SHIFT); //結束在那個sector int rw_sect_max=pin->i_start_sect+(pos_end>>SECTOR_SIZE_SHIFT); //扇區讀寫使用chunk為單位,如果一次buf傳的完的話,就使用rw_sect_max - rw_sect_min + 1 int chunk = min(rw_sect_max - rw_sect_min + 1, FSBUF_SIZE >> SECTOR_SIZE_SHIFT); int bytes_rw = 0; int bytes_left = len; int i; for (i = rw_sect_min; i <= rw_sect_max; i += chunk) { /* read/write this amount of bytes every time */ int bytes = min(bytes_left, chunk * SECTOR_SIZE - off); rw_sector(DEV_READ, pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, TASK_FS, fsbuf); if (fs_msg.type == READ) { phys_copy((void*)va2la(src, buf + bytes_rw), (void*)va2la(TASK_FS, fsbuf + off), bytes); } else { /* WRITE */ phys_copy((void*)va2la(TASK_FS, fsbuf + off), (void*)va2la(src, buf + bytes_rw), bytes); rw_sector(DEV_WRITE, pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, TASK_FS, fsbuf); } off = 0; bytes_rw += bytes; pcaller->filp[fd]->fd_pos += bytes; bytes_left -= bytes; } if (pcaller->filp[fd]->fd_pos > pin->i_size) { /* update inode::size */ pin->i_size = pcaller->filp[fd]->fd_pos; /* write the updated i-node back to disk */ sync_inode(pin); } return bytes_rw; } }
PUBLIC int do_rdwt() { int fd = fs_msg.FD; void *buf = fs_msg.BUF; int len = fs_msg.CNT; int src = fs_msg.source; /* 保证 fd 指向的是合法文件描述符 */ assert((pcaller->filp[fd] >= &f_desc_table[0]) && (pcaller->filp[fd] < &f_desc_table[NR_FILE_DESC])); if (!(pcaller->filp[fd]->fd_mode & O_RDWR)) return -1; int pos = pcaller->filp[fd]->fd_pos; struct inode *pin = pcaller->filp[fd]->fd_inode; /* 保证 fd 指向的是合法 inode */ assert(pin >= &inode_table[0] && pin < &inode_table[NR_INODE]); int imode = pin->i_mode & I_TYPE_MASK; /* 如果是字符设备则交给该设备的驱动处理 */ if (imode == I_CHAR_SPECIAL) { int t = fs_msg.type == READ ? DEV_READ : DEV_WRITE; fs_msg.type = t; int dev = pin->i_start_sect; assert(MAJOR(dev) == 4); fs_msg.DEVICE = MINOR(dev); fs_msg.BUF = buf; fs_msg.CNT = len; fs_msg.PROC_NR = src; assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER); send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &fs_msg); assert(fs_msg.CNT == len); return fs_msg.CNT; } /* 普通文件或目录 */ else { assert(pin->i_mode == I_REGULAR || pin->i_mode == I_DIRECTORY); assert((fs_msg.type == READ) || (fs_msg.type == WRITE)); int pos_end; if (fs_msg.type == READ) pos_end = min(pos + len, pin->i_size); else pos_end = min(pos + len, pin->i_nr_sects * SECTOR_SIZE); int off = pos % SECTOR_SIZE; int rw_sect_min = pin->i_start_sect + (pos >> SECTOR_SIZE_SHIFT); int rw_sect_max = pin->i_start_sect + (pos_end >> SECTOR_SIZE_SHIFT); int chunk = min(rw_sect_max - rw_sect_min + 1, FSBUF_SIZE >> SECTOR_SIZE_SHIFT); int bytes_rw = 0; int bytes_left = len; for (int i = rw_sect_min; i <= rw_sect_max; i += chunk) { // 逐块 int bytes = min(bytes_left, chunk * SECTOR_SIZE - off); rw_sector( DEV_READ, pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, TASK_FS, fsbuf ); if (fs_msg.type == READ) { phys_copy( (void *)va2la(src, buf + bytes_rw), (void *)va2la(TASK_FS, fsbuf + off), bytes ); } else { phys_copy( (void *)va2la(TASK_FS, fsbuf + off), (void *)va2la(src, buf + bytes_rw), bytes ); rw_sector( DEV_WRITE, pin->i_dev, i * SECTOR_SIZE, chunk * SECTOR_SIZE, TASK_FS, fsbuf ); } off = 0; bytes_rw += bytes; pcaller->filp[fd]->fd_pos += bytes; bytes_left -= bytes; } if (pcaller->filp[fd]->fd_pos > pin->i_size) { pin->i_size = pcaller->filp[fd]->fd_pos; sync_inode(pin); } return bytes_rw; } return 0; }