/* * If we're not journaling and this is a just-created file, we have to * sync our parent directory (if it was freshly created) since * otherwise it will only be written by writeback, leaving a huge * window during which a crash may lose the file. This may apply for * the parent directory's parent as well, and so on recursively, if * they are also freshly created. */ static int ext4_sync_parent(struct inode *inode) { struct writeback_control wbc; struct dentry *dentry = NULL; struct inode *next; int ret = 0; if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) return 0; inode = igrab(inode); while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); dentry = d_find_any_alias(inode); if (!dentry) break; next = igrab(dentry->d_parent->d_inode); dput(dentry); if (!next) break; iput(inode); inode = next; ret = sync_mapping_buffers(inode->i_mapping); if (ret) break; memset(&wbc, 0, sizeof(wbc)); wbc.sync_mode = WB_SYNC_ALL; wbc.nr_to_write = 0; /* only write out the inode */ ret = sync_inode(inode, &wbc); if (ret) break; } iput(inode); return ret; }
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int ret = 0; J_ASSERT(ext3_journal_current_handle() == 0); /* * data=writeback: * The caller's filemap_fdatawrite()/wait will sync the data. * sync_inode() will sync the metadata * * data=ordered: * The caller's filemap_fdatawrite() will write the data and * sync_inode() will write the inode if it is dirty. Then the caller's * filemap_fdatawait() will wait on the pages. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext3_force_commit will write the file data into the journal and * will wait on that. * filemap_fdatawait() will encounter a ton of newly-dirtied pages * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ if (ext3_should_journal_data(inode)) { ret = ext3_force_commit(inode->i_sb); goto out; } if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) goto flush; /* * The VFS has written the file data. If the inode is unaltered * then we need not start a commit. */ if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 0, /* sys_fsync did this */ }; ret = sync_inode(inode, &wbc); goto out; } flush: /* * In case we didn't commit a transaction, we have to flush * disk caches manually so that data really is on persistent * storage */ if (test_opt(inode->i_sb, BARRIER)) blkdev_issue_flush(inode->i_sb->s_bdev, NULL); out: return ret; }
int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; int ret = 0; J_ASSERT(ext4_journal_current_handle() == NULL); trace_mark(ext4_sync_file, "dev %s datasync %d ino %ld parent %ld", inode->i_sb->s_id, datasync, inode->i_ino, dentry->d_parent->d_inode->i_ino); /* * data=writeback: * The caller's filemap_fdatawrite()/wait will sync the data. * sync_inode() will sync the metadata * * data=ordered: * The caller's filemap_fdatawrite() will write the data and * sync_inode() will write the inode if it is dirty. Then the caller's * filemap_fdatawait() will wait on the pages. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext4_force_commit will write the file data into the journal and * will wait on that. * filemap_fdatawait() will encounter a ton of newly-dirtied pages * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ if (ext4_should_journal_data(inode)) { ret = ext4_force_commit(inode->i_sb); goto out; } if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) goto out; /* * The VFS has written the file data. If the inode is unaltered * then we need not start a commit. */ if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 0, /* sys_fsync did this */ }; ret = sync_inode(inode, &wbc); if (journal && (journal->j_flags & JBD2_BARRIER)) blkdev_issue_flush(inode->i_sb->s_bdev, NULL); } out: return ret; }
static int aufs_commit_metadata(struct inode *inode) { int err; aufs_bindex_t bindex; struct super_block *sb; struct inode *h_inode; int (*f)(struct inode *inode); sb = inode->i_sb; si_read_lock(sb, AuLock_FLUSH); ii_write_lock_child(inode); bindex = au_ibstart(inode); AuDebugOn(bindex < 0); h_inode = au_h_iptr(inode, bindex); f = h_inode->i_sb->s_export_op->commit_metadata; if (f) err = f(h_inode); else { struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 0 /* metadata only */ }; err = sync_inode(h_inode, &wbc); } au_cpup_attr_timesizes(inode); ii_write_unlock(inode); si_read_unlock(sb); return err; } /* ---------------------------------------------------------------------- */ static struct export_operations aufs_export_op = { .fh_to_dentry = aufs_fh_to_dentry, /* .fh_to_parent = aufs_fh_to_parent, */ .encode_fh = aufs_encode_fh, .commit_metadata = aufs_commit_metadata }; void au_export_init(struct super_block *sb) { struct au_sbinfo *sbinfo; __u32 u; sb->s_export_op = &aufs_export_op; sbinfo = au_sbi(sb); sbinfo->si_xigen = NULL; get_random_bytes(&u, sizeof(u)); BUILD_BUG_ON(sizeof(u) != sizeof(int)); atomic_set(&sbinfo->si_xigen_next, u); }
/** * Write a new entry into the directory. * * @param dir_inode I-node of the directory. * @param inode_nr I-node nr of the new file. * @param filename Filename of the new file. *****************************************************************************/ PRIVATE void new_dir_entry(struct inode * dir_inode, int inode_nr, char * filename) { /* struct super_block * sb = get_super_block(dir_inode->i_dev); */ /* write the dir_entry */ int dir_blk0_nr = dir_inode->i_start_sect; /* printl("n_1st_sect:0x%x, dir_blk0_nr:0x%x\n", */ /* sb->n_1st_sect, dir_blk0_nr); */ int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; /** * including unused slots * (the file has been * deleted but the slot * is still there) */ int m = 0; struct dir_entry * pde; struct dir_entry * new_de = 0; int i, j; for (i = 0; i < nr_dir_blks; i++) { RD_SECT(dir_inode->i_dev, dir_blk0_nr + i); pde = (struct dir_entry *)fsbuf; for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) { if (++m > nr_dir_entries) break; if (pde->inode_nr == 0) { /* it's a free slot */ new_de = pde; break; } } if (m > nr_dir_entries ||/* all entries have been iterated or */ new_de) /* free slot is found */ break; } /* printm("FS::in create_file: nr_dir_blks:%d, i:%d\n", nr_dir_blks, i); */ if (!new_de) { /* reached the end of the dir */ new_de = pde; dir_inode->i_size += DIR_ENTRY_SIZE; } new_de->inode_nr = inode_nr; strcpy(new_de->name, filename); /* write dir block -- ROOT dir block */ WR_SECT(dir_inode->i_dev, dir_blk0_nr + i); /* update dir inode */ sync_inode(dir_inode); }
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; }
/************************************************************************************************** * new_inode ************************************************************************************************** * Generate a new inode and write it to disk. * * @param dev Home device of the inode. * @param nr_inode inode nr. * @param start_sect Start sector of the file pointed by the new inode. * * @return Pointer of the new inode. *************************************************************************************************/ PRIVATE struct inode* new_inode(int dev, int nr_inode, int start_sect){ struct inode* new_inode = get_inode(dev, nr_inode); new_inode->i_mode = I_REGULAR; new_inode->i_size = 0; new_inode->i_start_sect = start_sect; new_inode->i_nr_sects = NR_DEFAULT_FILE_SECTS; new_inode->i_dev = dev; new_inode->i_cnt = 1; new_inode->i_num = nr_inode; /* write it to the inode array */ sync_inode(new_inode); return new_inode; }
PRIVATE struct inode *new_inode(int dev, int inode_nr, int start_sect) { struct inode *new_inode = get_inode(dev, inode_nr); new_inode->i_mode = I_REGULAR; // 0x00008000 new_inode->i_size = 0; new_inode->i_start_sect = start_sect; new_inode->i_nr_sects = NR_DEFAULT_FILE_SECTS; new_inode->i_dev = dev; new_inode->i_cnt = 1; new_inode->i_num = inode_nr; sync_inode(new_inode); return new_inode; }
PRIVATE struct inode* new_inode(int dev, int inode_nr, int start_sect) { struct inode *p_node = get_inode(dev, inode_nr); p_node -> i_mode = I_REGULAR; p_node -> i_size = 0; p_node -> i_start_sect = start_sect; p_node -> i_nr_sects = NR_DEFAULT_FILE_SECTS; /* in memory items */ p_node -> i_dev = dev; p_node -> i_cnt = 1; p_node -> i_num = inode_nr; /* write to the inode array */ sync_inode(p_node); return p_node; }
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int ret = 0; J_ASSERT(ext3_journal_current_handle() == NULL); /* * data=writeback: * The caller's filemap_fdatawrite()/wait will sync the data. * sync_inode() will sync the metadata * * data=ordered: * The caller's filemap_fdatawrite() will write the data and * sync_inode() will write the inode if it is dirty. Then the caller's * filemap_fdatawait() will wait on the pages. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). * ext3_force_commit will write the file data into the journal and * will wait on that. * filemap_fdatawait() will encounter a ton of newly-dirtied pages * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ if (ext3_should_journal_data(inode)) { ret = ext3_force_commit(inode->i_sb); goto out; } /* * The VFS has written the file data. If the inode is unaltered * then we need not start a commit. */ if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 0, /* sys_fsync did this */ }; ret = sync_inode(inode, &wbc); } out: return ret; }
PRIVATE void new_dir_entry(struct inode *dir_inode, int inode_nr, char *filename) { /* write the dir_entry */ int dir_blk0_nr = dir_inode->i_start_sect; // 目录文件的起始扇区 int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; // 目录文件所占扇区数 int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; // 目录项数 int m = 0; struct dir_entry *pde; struct dir_entry *new_de = 0; int i; for (i = 0; i < nr_dir_blks; i++) { // 逐扇区 RD_SECT(dir_inode->i_dev, dir_blk0_nr + i); pde = (struct dir_entry *)fsbuf; for (int j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++) { // 逐目录项 if (++m > nr_dir_entries) break; if (pde->inode_nr == 0) { /* it's a free slot */ new_de = pde; break; } } if (m > nr_dir_entries || // all entries have been iterated or */ new_de) // free slot is found */ break; } if (!new_de) { /* reached the end of the dir */ new_de = pde; dir_inode->i_size += DIR_ENTRY_SIZE; } new_de->inode_nr = inode_nr; strcpy(new_de->name, filename); /* write dir block -- ROOT dir block */ WR_SECT(dir_inode->i_dev, dir_blk0_nr + i); /* update dir inode */ sync_inode(dir_inode); }
/************************************************************************************************** * new_dir_entry ************************************************************************************************** * Write a new entry into the directory. * * @param dir_inode Inode of the directory. * @param nr_inode Inode nr of the new file. * @param filename File name of the new file. *************************************************************************************************/ PRIVATE void new_dir_entry(struct inode* dir_inode, int nr_inode, char* filename){ /* Write the dir_entry */ int nr_dir_blk0 = dir_inode->i_start_sect; int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; /* including unused slots (the file has been deleted but the slot is still there) */ int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; int m = 0; int i, j; struct dir_entry* pde; struct dir_entry* new_de = 0; for(i=0; i<nr_dir_blks; i++){ RD_SECT(dir_inode->i_dev, nr_dir_blk0 + i); pde = (struct dir_entry*) fsbuf; for(j=0; j<SECTOR_SIZE / DIR_ENTRY_SIZE; j++, pde++){ if(++m > nr_dir_entries){ break; } if(pde->inode_nr == 0){ /* it's a free slot */ new_de = pde; break; } } if(m > nr_dir_entries || new_de){/* all entries have been iterated or */ break; /* free slot is found */ } } if(!new_de){ /* reached the end of the dir */ new_de = pde; dir_inode->i_size += DIR_ENTRY_SIZE; } new_de->inode_nr = nr_inode; strcpy(new_de->name, filename); /* Write dir block -- ROOT dir block */ WR_SECT(dir_inode->i_dev, nr_dir_blk0 + i); /* update dir inode */ sync_inode(dir_inode); }
/* dir_inode: root_node */ PRIVATE void new_dir_entry(struct inode* dir_inode, int inode_nr, char* filename) { int dir_blk0_nr = dir_inode -> i_start_sect; int nr_dir_blks = (dir_inode -> i_size + SECTOR_SIZE) / SECTOR_SIZE; int nr_dir_entries = dir_inode -> i_size / DIR_ENTRY_SIZE; int i, j; int m = 0; struct dir_entry* p_dir_entry; struct dir_entry* new_entry = 0; for(i=0; i<nr_dir_blks; i++) { RD_SECT(dir_inode -> i_dev, dir_blk0_nr + i); p_dir_entry = (struct dir_entry*)fsbuf; for (j = 0; j<SECTOR_SIZE / DIR_ENTRY_SIZE; j++, p_dir_entry++) { if (++m > nr_dir_entries) break; if (p_dir_entry -> inode_nr == 0) { /* 之前被删除的文件留下来的entry */ /* 如果文件删除了,dir_inode -> i_size不会改变 */ new_entry = p_dir_entry; break; } } if (m > nr_dir_entries || new_entry) break; } if (!new_entry) { new_entry = p_dir_entry; dir_inode -> i_size += DIR_ENTRY_SIZE; } new_entry -> inode_nr = inode_nr; strcpy(new_entry -> name, filename); WR_SECT(dir_inode -> i_dev, dir_blk0_nr+i); sync_inode(dir_inode); }
int sys_sync() { extern void sync_inode(); struct buffer *bh; sync_inode(); for (bh = buffer_table; bh < buffer_table + NR_BUFFER; bh++) { lock_buffer(bh); if (bh->b_flag & B_DIRTY){ /* * buffer shold be unlock in write_block. */ rw_block(WRITE_BUF, bh); irq_lock(); while(bh->b_lock.pid) sleep_on(&(bh->b_lock.wait)); irq_unlock(); } unlock_buffer(bh); } return 0; }
/** * 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; }
/** * Remove a file. * * @note We clear the i-node in inode_array[] although it is not really needed. * We don't clear the data bytes so the file is recoverable. * * @return On success, zero is returned. On error, -1 is returned. *****************************************************************************/ PUBLIC int do_unlink() { char pathname[MAX_PATH]; /* get parameters from the message */ int name_len = fs_msg.NAME_LEN; /* length of filename */ int src = fs_msg.source; /* caller proc nr. */ assert(name_len < MAX_PATH); phys_copy((void*)va2la(TASK_FS, pathname), (void*)va2la(src, fs_msg.PATHNAME), name_len); pathname[name_len] = 0; if (strcmp(pathname , "/") == 0) { printl("FS:do_unlink():: cannot unlink the root\n"); return -1; } int inode_nr = search_file(pathname); if (inode_nr == INVALID_INODE) { /* file not found */ printl("FS::do_unlink():: search_file() returns " "invalid inode: %s\n", pathname); return -1; } char filename[MAX_PATH]; struct inode * dir_inode; if (strip_path(filename, pathname, &dir_inode) != 0) return -1; struct inode * pin = get_inode(dir_inode->i_dev, inode_nr); if (pin->i_mode != I_REGULAR) { /* can only remove regular files */ printl("cannot remove file %s, because " "it is not a regular file.\n", pathname); return -1; } if (pin->i_cnt > 1) { /* the file was opened */ printl("cannot remove file %s, because pin->i_cnt is %d.\n", pathname, pin->i_cnt); return -1; } struct super_block * sb = get_super_block(pin->i_dev); /*************************/ /* free the bit in i-map */ /*************************/ int byte_idx = inode_nr / 8; int bit_idx = inode_nr % 8; assert(byte_idx < SECTOR_SIZE); /* we have only one i-map sector */ /* read sector 2 (skip bootsect and superblk): */ RD_SECT(pin->i_dev, 2); assert(fsbuf[byte_idx % SECTOR_SIZE] & (1 << bit_idx)); fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << bit_idx); WR_SECT(pin->i_dev, 2); /**************************/ /* free the bits in s-map */ /**************************/ /* * bit_idx: bit idx in the entire i-map * ... ____|____ * \ .-- byte_cnt: how many bytes between * \ | the first and last byte * +-+-+-+-+-+-+-+-+ V +-+-+-+-+-+-+-+-+ * ... | | | | | |*|*|*|...|*|*|*|*| | | | | * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 * ...__/ * byte_idx: byte idx in the entire i-map */ bit_idx = pin->i_start_sect - sb->n_1st_sect + 1; byte_idx = bit_idx / 8; int bits_left = pin->i_nr_sects; int byte_cnt = (bits_left - (8 - (bit_idx % 8))) / 8; /* current sector nr. */ int s = 2 /* 2: bootsect + superblk */ + sb->nr_imap_sects + byte_idx / SECTOR_SIZE; RD_SECT(pin->i_dev, s); int i; /* clear the first byte */ for (i = bit_idx % 8; (i < 8) && bits_left; i++,bits_left--) { //assert((fsbuf[byte_idx % SECTOR_SIZE] >> i & 1) == 1); fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << i); } /* clear bytes from the second byte to the second to last */ int k; i = (byte_idx % SECTOR_SIZE) + 1; /* the second byte */ for (k = 0; k < byte_cnt; k++,i++,bits_left-=8) { if (i == SECTOR_SIZE) { i = 0; WR_SECT(pin->i_dev, s); RD_SECT(pin->i_dev, ++s); } //assert(fsbuf[i] == 0xFF); fsbuf[i] = 0; } /* clear the last byte */ if (i == SECTOR_SIZE) { i = 0; WR_SECT(pin->i_dev, s); RD_SECT(pin->i_dev, ++s); } unsigned char mask = ~((unsigned char)(~0) << bits_left); //assert((fsbuf[i] & mask) == mask); fsbuf[i] &= (~0) << bits_left; WR_SECT(pin->i_dev, s); /***************************/ /* clear the i-node itself */ /***************************/ pin->i_mode = 0; pin->i_size = 0; pin->i_start_sect = 0; pin->i_nr_sects = 0; sync_inode(pin); /* release slot in inode_table[] */ put_inode(pin); /************************************************/ /* set the inode-nr to 0 in the directory entry */ /************************************************/ int dir_blk0_nr = dir_inode->i_start_sect; int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; /* including unused slots * (the file has been * deleted but the slot * is still there) */ int m = 0; struct dir_entry * pde = 0; int flg = 0; int dir_size = 0; for (i = 0; i < nr_dir_blks; i++) { RD_SECT(dir_inode->i_dev, dir_blk0_nr + i); pde = (struct dir_entry *)fsbuf; int j; for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) { if (++m > nr_dir_entries) break; if (pde->inode_nr == inode_nr) { /* pde->inode_nr = 0; */ memset(pde, 0, DIR_ENTRY_SIZE); WR_SECT(dir_inode->i_dev, dir_blk0_nr + i); flg = 1; break; } if (pde->inode_nr != INVALID_INODE) dir_size += DIR_ENTRY_SIZE; } if (m > nr_dir_entries || /* all entries have been iterated OR */ flg) /* file is found */ break; } assert(flg); if (m == nr_dir_entries) { /* the file is the last one in the dir */ dir_inode->i_size = dir_size; sync_inode(dir_inode); } return 0; }
static void v9fs_mmap_vm_close(struct vm_area_struct *vma) { struct inode *inode; struct writeback_control wbc = { .nr_to_write = LONG_MAX, .sync_mode = WB_SYNC_ALL, .range_start = vma->vm_pgoff * PAGE_SIZE, /* absolute end, byte at end included */ .range_end = vma->vm_pgoff * PAGE_SIZE + (vma->vm_end - vma->vm_start - 1), }; p9_debug(P9_DEBUG_VFS, "9p VMA close, %p, flushing", vma); inode = file_inode(vma->vm_file); if (!mapping_cap_writeback_dirty(inode->i_mapping)) wbc.nr_to_write = 0; might_sleep(); sync_inode(inode, &wbc); } static const struct vm_operations_struct v9fs_file_vm_ops = { .fault = filemap_fault, .map_pages = filemap_map_pages, .page_mkwrite = v9fs_vm_page_mkwrite, }; static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { .close = v9fs_mmap_vm_close, .fault = filemap_fault, .map_pages = filemap_map_pages, .page_mkwrite = v9fs_vm_page_mkwrite, }; const struct file_operations v9fs_cached_file_operations = { .llseek = generic_file_llseek, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, .mmap = v9fs_file_mmap, .fsync = v9fs_file_fsync, }; const struct file_operations v9fs_cached_file_operations_dotl = { .llseek = generic_file_llseek, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock_dotl, .flock = v9fs_file_flock_dotl, .mmap = v9fs_file_mmap, .fsync = v9fs_file_fsync_dotl, }; const struct file_operations v9fs_file_operations = { .llseek = generic_file_llseek, .read_iter = v9fs_file_read_iter, .write_iter = v9fs_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, .mmap = generic_file_readonly_mmap, .fsync = v9fs_file_fsync, }; const struct file_operations v9fs_file_operations_dotl = { .llseek = generic_file_llseek, .read_iter = v9fs_file_read_iter, .write_iter = v9fs_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock_dotl, .flock = v9fs_file_flock_dotl, .mmap = generic_file_readonly_mmap, .fsync = v9fs_file_fsync_dotl, }; const struct file_operations v9fs_mmap_file_operations = { .llseek = generic_file_llseek, .read_iter = v9fs_mmap_file_read_iter, .write_iter = v9fs_mmap_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, .mmap = v9fs_mmap_file_mmap, .fsync = v9fs_file_fsync, }; const struct file_operations v9fs_mmap_file_operations_dotl = { .llseek = generic_file_llseek, .read_iter = v9fs_mmap_file_read_iter, .write_iter = v9fs_mmap_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock_dotl, .flock = v9fs_file_flock_dotl, .mmap = v9fs_mmap_file_mmap, .fsync = v9fs_file_fsync_dotl, };
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; } }
/***************************************************************************** * do_open *************************************************************************//** * Open a file and return the file descriptor. * * \dot * digraph fd { * graph[rankdir=LR]; * node [shape=plaintext]; * * procs [label=<<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0"> * <TR> * <TD HEIGHT="40" WIDTH="110" ALIGN="right" BORDER="0"></TD> * <TD HEIGHT="40" WIDTH="110" ALIGN="center" VALIGN="bottom" BORDER="0">proc</TD> * </TR><TR> * <TD HEIGHT="10" WIDTH="110" ALIGN="right" BORDER="0"></TD> * <TD HEIGHT="10" WIDTH="110" ALIGN="center" VALIGN="bottom" BORDER="0"></TD> * </TR><TR> * <TD HEIGHT="40" WIDTH="110" ALIGN="right" BORDER="0">proc A </TD> * <TD HEIGHT="40" WIDTH="110" ALIGN="center" BORDER="1" PORT="p1">filp[NR_OPEN]</TD> * </TR><TR> * <TD HEIGHT="40" WIDTH="110" ALIGN="right" BORDER="0">proc B </TD> * <TD HEIGHT="40" WIDTH="110" ALIGN="center" BORDER="1" PORT="p2">filp[NR_OPEN]</TD> * </TR><TR> * <TD HEIGHT="40" WIDTH="110" ALIGN="right" BORDER="0"></TD> * <TD HEIGHT="40" WIDTH="110" ALIGN="center" BORDER="1">...</TD> * </TR><TR> * <TD HEIGHT="40" WIDTH="110" ALIGN="right" BORDER="0">proc Y </TD> * <TD HEIGHT="40" WIDTH="110" ALIGN="center" BORDER="1">filp[NR_OPEN]</TD> * </TR><TR> * <TD HEIGHT="40" WIDTH="110" ALIGN="right" BORDER="0">proc Z </TD> * <TD HEIGHT="40" WIDTH="110" ALIGN="center" BORDER="1">filp[NR_OPEN]</TD> * </TR> * </TABLE>>]; * * f_desc_table [label=<<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0"> * <TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" VALIGN="bottom" BORDER="0">f_desc_table</TD> * </TR><TR> * <TD HEIGHT="10" WIDTH="10" ALIGN="center" VALIGN="bottom" BORDER="0"></TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1" PORT="d1">file desc</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1" PORT="d2">file desc</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1">...</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1">file desc</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1">file desc</TD> * </TR> * </TABLE>>]; * * inode_table [label=<<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0"> * <TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" VALIGN="bottom" BORDER="0">inode_table</TD> * </TR><TR> * <TD HEIGHT="10" WIDTH="10" ALIGN="center" VALIGN="bottom" BORDER="0"></TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1" PORT="i1">inode</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1" PORT="i2">inode</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1">...</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1">inode</TD> * </TR><TR> * <TD HEIGHT="30" WIDTH="10" ALIGN="center" BORDER="1">inode</TD> * </TR> * </TABLE>>]; * * files [label=<<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0"> * <TR> * <TD HEIGHT="50" WIDTH="120" ALIGN="center" VALIGN="bottom" BORDER="0">files</TD> * </TR><TR> * <TD HEIGHT="10" WIDTH="120" ALIGN="center" VALIGN="bottom" BORDER="0"></TD> * </TR><TR> * <TD HEIGHT="90" WIDTH="120" ALIGN="center" BORDER="1" PORT="f1"></TD> * </TR><TR> * <TD HEIGHT="50" WIDTH="120" ALIGN="center" BORDER="1" PORT="f2"></TD> * </TR><TR> * <TD HEIGHT="150" WIDTH="120" ALIGN="center" BORDER="1">... ... ...</TD> * </TR><TR> * <TD HEIGHT="50" WIDTH="120" ALIGN="center" BORDER="1"></TD> * </TR><TR> * <TD HEIGHT="50" WIDTH="120" ALIGN="center" BORDER="1"></TD> * </TR> * </TABLE>>]; * * procs:p1 -> f_desc_table:d1; * procs:p2 -> f_desc_table:d2; * * f_desc_table:d1 -> inode_table:i1; * f_desc_table:d2 -> inode_table:i2; * * inode_table:i1 -> files:f1; * inode_table:i2 -> files:f2; *} * * \enddot * * @return File descriptor if successful, otherwise a negative error code. *****************************************************************************/ PUBLIC int do_open() { int fd = -1; /* return value */ char pathname[MAX_PATH]; /* get parameters from the message */ int flags = fs_msg.FLAGS; /* access mode */ int name_len = fs_msg.NAME_LEN; /* length of filename */ int src = fs_msg.source; /* caller proc nr. */ assert(name_len < MAX_PATH); phys_copy((void*)va2la(TASK_FS, pathname), (void*)va2la(src, fs_msg.PATHNAME), name_len); pathname[name_len] = 0; /* find a free slot in PROCESS::filp[] */ int i; for (i = 0; i < NR_FILES; i++) { if (pcaller->filp[i] == 0) { fd = i; break; } } if ((fd < 0) || (fd >= NR_FILES)) panic("filp[] is full (PID:%d)", proc2pid(pcaller)); /* find a free slot in f_desc_table[] */ for (i = 0; i < NR_FILE_DESC; i++) if (f_desc_table[i].fd_inode == 0) break; if (i >= NR_FILE_DESC) panic("f_desc_table[] is full (PID:%d)", proc2pid(pcaller)); int inode_nr = search_file(pathname); struct inode * pin = 0; if (inode_nr == INVALID_INODE) { /* file not exists */ if (flags & O_CREAT) { pin = create_file(pathname, flags); } else { printl("{FS} file not exists: %s\n", pathname); return -1; } } else if (flags & O_RDWR) { /* file exists */ if ((flags & O_CREAT) && (!(flags & O_TRUNC))) { assert(flags == (O_RDWR | O_CREAT)); printl("{FS} file exists: %s\n", pathname); return -1; } assert((flags == O_RDWR ) || (flags == (O_RDWR | O_TRUNC )) || (flags == (O_RDWR | O_TRUNC | O_CREAT))); char filename[MAX_PATH]; struct inode * dir_inode; if (strip_path(filename, pathname, &dir_inode) != 0) return -1; pin = get_inode(dir_inode->i_dev, inode_nr); } else { /* file exists, no O_RDWR flag */ printl("{FS} file exists: %s\n", pathname); return -1; } if (flags & O_TRUNC) { assert(pin); pin->i_size = 0; sync_inode(pin); } if (pin) { /* connects proc with file_descriptor */ pcaller->filp[fd] = &f_desc_table[i]; /* connects file_descriptor with inode */ f_desc_table[i].fd_inode = pin; f_desc_table[i].fd_mode = flags; f_desc_table[i].fd_cnt = 1; f_desc_table[i].fd_pos = 0; /* strcpy(f_desc_table[i].fd_filename, pathname); /\* DEL ME *\/ */ int imode = pin->i_mode & I_TYPE_MASK; if (imode == I_CHAR_SPECIAL) { MESSAGE driver_msg; driver_msg.type = DEV_OPEN; int dev = pin->i_start_sect; driver_msg.DEVICE = MINOR(dev); assert(MAJOR(dev) == 4); assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER); send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &driver_msg); } else if (imode == I_DIRECTORY) { assert(pin->i_num == ROOT_INODE); } else { assert(pin->i_mode == I_REGULAR); } } else { return -1; } return fd; }
/** * 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; } }
int xixfs_sync_inode(struct inode *inode) { struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 0, /* sys_fsync did this */ }; return sync_inode(inode, &wbc); } #endif int xixfs_sync_file( struct file *file, struct dentry *dentry, int datasync ) { struct inode *inode = dentry->d_inode; PXIXFS_LINUX_FCB pFCB = NULL; PXIXFS_LINUX_VCB pVCB = NULL; int err = 0; int ret = 0; XIXCORE_ASSERT(inode); pVCB = XIXFS_SB(inode->i_sb); XIXFS_ASSERT_VCB(pVCB); pFCB = XIXFS_I(inode); XIXFS_ASSERT_FCB(pFCB); DebugTrace(DEBUG_LEVEL_ERROR, (DEBUG_TARGET_FCB|DEBUG_TARGET_VFSAPIT), ("ENTER xixfs_sync_file (%s).\n", file->f_dentry->d_name.name)); if(pVCB->XixcoreVcb.IsVolumeWriteProtected){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("ERROR xixfs_sync_file : is read only .\n")); return -EPERM; } if(XIXCORE_TEST_FLAGS( pFCB->XixcoreFcb.FCBFlags, XIXCORE_FCB_CHANGE_DELETED )){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("ERROR DELETED FILE \n")); return -EPERM; } XIXCORE_ASSERT(pFCB->XixcoreFcb.FCBType == FCB_TYPE_FILE); if(pFCB->XixcoreFcb.HasLock == INODE_FILE_LOCK_HAS) { #if LINUX_VERSION_25_ABOVE ret = sync_mapping_buffers(inode->i_mapping); if (!(inode->i_state & I_DIRTY)) return ret; if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) return ret; xixfs_sync_inode(inode); #endif if(XIXCORE_TEST_FLAGS(pFCB->XixcoreFcb.FCBFlags,XIXCORE_FCB_MODIFIED_FILE)){ #if LINUX_VERSION_25_ABOVE err = xixfs_write_inode(inode, 1); #else xixfs_write_inode(inode, 1); #endif if(pFCB->XixcoreFcb.WriteStartOffset != -1){ printk(KERN_DEBUG "Set Update Information!!!\n"); xixfs_SendFileChangeRC( pVCB->XixcoreVcb.HostMac, pFCB->XixcoreFcb.LotNumber, pVCB->XixcoreVcb.VolumeId, i_size_read(inode), pFCB->XixcoreFcb.RealAllocationSize, pFCB->XixcoreFcb.WriteStartOffset ); pFCB->XixcoreFcb.WriteStartOffset = -1; } if (ret == 0) ret = err; return ret; } }else { return -EPERM; } return ret; } #if LINUX_VERSION_25_ABOVE #if LINUX_VERSION_2_6_19_REPLACE_INTERFACE ssize_t xixfs_file_splice_read( struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags ) { return generic_file_splice_read(in, ppos, pipe, len, flags); } ssize_t xixfs_file_splice_write( struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags ) { ssize_t RC = 0; int64 index = 0; struct address_space *mapping = out->f_mapping; struct inode *inode = mapping->host; PXIXFS_LINUX_FCB pFCB = NULL; PXIXFS_LINUX_VCB pVCB = NULL; XIXCORE_ASSERT(inode); pVCB = XIXFS_SB(inode->i_sb); XIXFS_ASSERT_VCB(pVCB); pFCB = XIXFS_I(inode); XIXFS_ASSERT_FCB(pFCB); DebugTrace(DEBUG_LEVEL_ERROR, (DEBUG_TARGET_FCB|DEBUG_TARGET_VFSAPIT), ("ENTER xixfs_file_splice_write (%s).\n", out->f_dentry->d_name.name)); if(pVCB->XixcoreVcb.IsVolumeWriteProtected){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("ERROR xixfs_file_splice_write : is read only .\n")); return -EPERM; } if(XIXCORE_TEST_FLAGS( pFCB->XixcoreFcb.FCBFlags, XIXCORE_FCB_CHANGE_DELETED )){ DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("ERROR DELETED FILE \n")); return -EPERM; } XIXCORE_ASSERT(pFCB->XixcoreFcb.FCBType == FCB_TYPE_FILE); if(pFCB->XixcoreFcb.HasLock == INODE_FILE_LOCK_HAS) { index =(int64) (*ppos); RC = generic_file_splice_write(pipe, out, ppos, len, flags); if(RC > 0 ) { if(pFCB->XixcoreFcb.WriteStartOffset == -1) { pFCB->XixcoreFcb.WriteStartOffset = index; XIXCORE_SET_FLAGS(pFCB->XixcoreFcb.FCBFlags, XIXCORE_FCB_MODIFIED_FILE_SIZE); } if(pFCB->XixcoreFcb.WriteStartOffset > index ){ pFCB->XixcoreFcb.WriteStartOffset = index; XIXCORE_SET_FLAGS(pFCB->XixcoreFcb.FCBFlags, XIXCORE_FCB_MODIFIED_FILE_SIZE); } } DebugTrace(DEBUG_LEVEL_ERROR, (DEBUG_TARGET_FCB|DEBUG_TARGET_VFSAPIT), ("EXIT xixfs_file_writev (%d).\n", RC)); return RC; } DebugTrace(DEBUG_LEVEL_ERROR, (DEBUG_TARGET_FCB|DEBUG_TARGET_VFSAPIT), ("EXIT xixfs_file_writev ERROR.\n")); return -EPERM; }