Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
/**
 * 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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
/**************************************************************************************************
 * 					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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
Archivo: open.c Proyecto: Zach41/OS
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;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
/**************************************************************************************************
 * 					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);
}
Ejemplo n.º 13
0
Archivo: open.c Proyecto: Zach41/OS
/* 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);
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
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;
	}
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
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;
}
Ejemplo n.º 18
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,
};
Ejemplo n.º 19
0
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;
    }
}
Ejemplo n.º 20
0
/*****************************************************************************
 *                                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&#91;NR_OPEN&#93;</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&#91;NR_OPEN&#93;</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&#91;NR_OPEN&#93;</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&#91;NR_OPEN&#93;</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;
}
Ejemplo n.º 21
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(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;
	}
}
Ejemplo n.º 22
0
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;
}