⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
** On success, page_result is set to a locked, pinned page, and bh_result** is set to an up to date buffer for the last block in the file.  returns 0.**** tail conversion is not done, so bh_result might not be valid for writing** check buffer_mapped(bh_result) and bh_result->b_blocknr != 0 before** trying to write the block.**** on failure, nonzero is returned, page_result and bh_result are untouched.*/static int grab_tail_page(struct inode *p_s_inode, 			  struct page **page_result, 			  struct buffer_head **bh_result) {    /* we want the page with the last byte in the file,    ** not the page that will hold the next byte for appending    */    unsigned long index = (p_s_inode->i_size-1) >> PAGE_CACHE_SHIFT ;    unsigned long pos = 0 ;    unsigned long start = 0 ;    unsigned long blocksize = p_s_inode->i_sb->s_blocksize ;    unsigned long offset = (p_s_inode->i_size) & (PAGE_CACHE_SIZE - 1) ;    struct buffer_head *bh ;    struct buffer_head *head ;    struct page * page ;    int error ;        /* we know that we are only called with inode->i_size > 0.    ** we also know that a file tail can never be as big as a block    ** If i_size % blocksize == 0, our file is currently block aligned    ** and it won't need converting or zeroing after a truncate.    */    if ((offset & (blocksize - 1)) == 0) {        return -ENOENT ;    }    page = grab_cache_page(p_s_inode->i_mapping, index) ;    error = -ENOMEM ;    if (!page) {        goto out ;    }    /* start within the page of the last block in the file */    start = (offset / blocksize) * blocksize ;    error = block_prepare_write(page, start, offset, 				reiserfs_get_block_create_0) ;    if (error)	goto unlock ;    kunmap(page) ; /* mapped by block_prepare_write */    head = page->buffers ;          bh = head;    do {	if (pos >= start) {	    break ;	}	bh = bh->b_this_page ;	pos += blocksize ;    } while(bh != head) ;    if (!buffer_uptodate(bh)) {	/* note, this should never happen, prepare_write should	** be taking care of this for us.  If the buffer isn't up to date,	** I've screwed up the code to find the buffer, or the code to	** call prepare_write	*/	reiserfs_warning("clm-6000: error reading block %lu on dev %s\n",	                  bh->b_blocknr, kdevname(bh->b_dev)) ;	error = -EIO ;	goto unlock ;    }    *bh_result = bh ;    *page_result = page ;out:    return error ;unlock:    UnlockPage(page) ;    page_cache_release(page) ;    return error ;}/*** vfs version of truncate file.  Must NOT be called with** a transaction already started.**** some code taken from block_truncate_page*/void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {    struct reiserfs_transaction_handle th ;    int windex ;    /* we want the offset for the first byte after the end of the file */    unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1) ;    unsigned blocksize = p_s_inode->i_sb->s_blocksize ;    unsigned length ;    struct page *page = NULL ;    int error ;    struct buffer_head *bh = NULL ;    if (p_s_inode->i_size > 0) {        if ((error = grab_tail_page(p_s_inode, &page, &bh))) {	    // -ENOENT means we truncated past the end of the file, 	    // and get_block_create_0 could not find a block to read in,	    // which is ok.	    if (error != -ENOENT)	        reiserfs_warning("clm-6001: grab_tail_page failed %d\n", error);	    page = NULL ;	    bh = NULL ;	}    }    /* so, if page != NULL, we have a buffer head for the offset at     ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0,     ** then we have an unformatted node.  Otherwise, we have a direct item,     ** and no zeroing is required on disk.  We zero after the truncate,     ** because the truncate might pack the item anyway     ** (it will unmap bh if it packs).    */    /* it is enough to reserve space in transaction for 2 balancings:       one for "save" link adding and another for the first       cut_from_item. 1 is for update_sd */    journal_begin(&th, p_s_inode->i_sb,  JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;    reiserfs_update_inode_transaction(p_s_inode) ;    windex = push_journal_writer("reiserfs_vfs_truncate_file") ;    if (update_timestamps)           /* we are doing real truncate: if the system crashes before the last              transaction of truncating gets committed - on reboot the file              either appears truncated properly or not truncated at all */           add_save_link (&th, p_s_inode, 1);    reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;    pop_journal_writer(windex) ;    journal_end(&th, p_s_inode->i_sb,  JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;    if (update_timestamps)       remove_save_link (p_s_inode, 1/* truncate */);    if (page) {        length = offset & (blocksize - 1) ;	/* if we are not on a block boundary */	if (length) {	    length = blocksize - length ;	    memset((char *)kmap(page) + offset, 0, length) ;   	    flush_dcache_page(page) ;	    kunmap(page) ;	    if (buffer_mapped(bh) && bh->b_blocknr != 0) {	        mark_buffer_dirty(bh) ;	    }	}	UnlockPage(page) ;	page_cache_release(page) ;    }    return ;}static int map_block_for_writepage(struct inode *inode, 			       struct buffer_head *bh_result,                                unsigned long block) {    struct reiserfs_transaction_handle th ;    int fs_gen ;    struct item_head tmp_ih ;    struct item_head *ih ;    struct buffer_head *bh ;    __u32 *item ;    struct cpu_key key ;    INITIALIZE_PATH(path) ;    int pos_in_item ;    int jbegin_count = JOURNAL_PER_BALANCE_CNT ;    loff_t byte_offset = (block << inode->i_sb->s_blocksize_bits) + 1 ;    int retval ;    int use_get_block = 0 ;    int bytes_copied = 0 ;    int copy_size ;    kmap(bh_result->b_page) ;start_over:    lock_kernel() ;    journal_begin(&th, inode->i_sb, jbegin_count) ;    reiserfs_update_inode_transaction(inode) ;    make_cpu_key(&key, inode, byte_offset, TYPE_ANY, 3) ;research:    retval = search_for_position_by_key(inode->i_sb, &key, &path) ;    if (retval != POSITION_FOUND) {        use_get_block = 1;	goto out ;    }     bh = get_last_bh(&path) ;    ih = get_ih(&path) ;    item = get_item(&path) ;    pos_in_item = path.pos_in_item ;    /* we've found an unformatted node */    if (indirect_item_found(retval, ih)) {	if (bytes_copied > 0) {	    reiserfs_warning("clm-6002: bytes_copied %d\n", bytes_copied) ;	}        if (!get_block_num(item, pos_in_item)) {	    /* crap, we are writing to a hole */	    use_get_block = 1;	    goto out ;	}	set_block_dev_mapped(bh_result, get_block_num(item,pos_in_item),inode);        mark_buffer_uptodate(bh_result, 1);    } else if (is_direct_le_ih(ih)) {        char *p ;         p = page_address(bh_result->b_page) ;        p += (byte_offset -1) & (PAGE_CACHE_SIZE - 1) ;        copy_size = ih_item_len(ih) - pos_in_item;	fs_gen = get_generation(inode->i_sb) ;	copy_item_head(&tmp_ih, ih) ;	reiserfs_prepare_for_journal(inode->i_sb, bh, 1) ;	if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {	    reiserfs_restore_prepared_buffer(inode->i_sb, bh) ;	    goto research;	}	memcpy( B_I_PITEM(bh, ih) + pos_in_item, p + bytes_copied, copy_size) ;	journal_mark_dirty(&th, inode->i_sb, bh) ;	bytes_copied += copy_size ;	set_block_dev_mapped(bh_result, 0, inode);        mark_buffer_uptodate(bh_result, 1);	/* are there still bytes left? */        if (bytes_copied < bh_result->b_size && 	    (byte_offset + bytes_copied) < inode->i_size) {	    set_cpu_key_k_offset(&key, cpu_key_k_offset(&key) + copy_size) ;	    goto research ;	}    } else {        reiserfs_warning("clm-6003: bad item inode %lu, device %s\n", inode->i_ino, kdevname(inode->i_sb->s_dev)) ;        retval = -EIO ;	goto out ;    }    retval = 0 ;    out:    pathrelse(&path) ;    journal_end(&th, inode->i_sb, jbegin_count) ;    unlock_kernel() ;    /* this is where we fill in holes in the file. */    if (use_get_block) {	retval = reiserfs_get_block(inode, block, bh_result, 	                            GET_BLOCK_CREATE | GET_BLOCK_NO_ISEM) ;	if (!retval) {	    if (!buffer_mapped(bh_result) || bh_result->b_blocknr == 0) {	        /* get_block failed to find a mapped unformatted node. */		use_get_block = 0 ;		goto start_over ;	    }	}    }    kunmap(bh_result->b_page) ;    return retval ;}/* helper func to get a buffer head ready for writepage to send to** ll_rw_block*/static inline void submit_bh_for_writepage(struct buffer_head **bhp, int nr) {    struct buffer_head *bh ;    int i;    for(i = 0 ; i < nr ; i++) {        bh = bhp[i] ;	lock_buffer(bh) ;	set_buffer_async_io(bh) ;	/* submit_bh doesn't care if the buffer is dirty, but nobody	** later on in the call chain will be cleaning it.  So, we	** clean the buffer here, it still gets written either way.	*/	clear_bit(BH_Dirty, &bh->b_state) ;	set_bit(BH_Uptodate, &bh->b_state) ;	submit_bh(WRITE, bh) ;    }}static int reiserfs_write_full_page(struct page *page) {    struct inode *inode = page->mapping->host ;    unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT ;    unsigned last_offset = PAGE_CACHE_SIZE;    int error = 0;    unsigned long block ;    unsigned cur_offset = 0 ;    struct buffer_head *head, *bh ;    int partial = 0 ;    struct buffer_head *arr[PAGE_CACHE_SIZE/512] ;    int nr = 0 ;    if (!page->buffers) {        block_prepare_write(page, 0, 0, NULL) ;	kunmap(page) ;    }    /* last page in the file, zero out any contents past the    ** last byte in the file    */    if (page->index >= end_index) {        last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1) ;	/* no file contents in this page */	if (page->index >= end_index + 1 || !last_offset) {	    error =  -EIO ;	    goto fail ;	}	memset((char *)kmap(page)+last_offset, 0, PAGE_CACHE_SIZE-last_offset) ;	flush_dcache_page(page) ;	kunmap(page) ;    }    head = page->buffers ;    bh = head ;    block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits) ;    do {	/* if this offset in the page is outside the file */	if (cur_offset >= last_offset) {	    if (!buffer_uptodate(bh))	        partial = 1 ;	} else {	    /* fast path, buffer mapped to an unformatted node */	    if (buffer_mapped(bh) && bh->b_blocknr != 0) {		arr[nr++] = bh ;	    } else {		/* buffer not mapped yet, or points to a direct item.		** search and dirty or log		*/		if ((error = map_block_for_writepage(inode, bh, block))) {		    goto fail ;		}		/* map_block_for_writepage either found an unformatted node		** and mapped it for us, or it found a direct item		** and logged the changes.  		*/		if (buffer_mapped(bh) && bh->b_blocknr != 0) {		    arr[nr++] = bh ;		}	    }	}        bh = bh->b_this_page ;	cur_offset += bh->b_size ;	block++ ;    } while(bh != head) ;    /* if this page only had a direct item, it is very possible for    ** nr == 0 without there being any kind of error.    */    if (nr) {        submit_bh_for_writepage(arr, nr) ;    } else {        UnlockPage(page) ;    }    if (!partial)        SetPageUptodate(page) ;    return 0 ;fail:    if (nr) {        submit_bh_for_writepage(arr, nr) ;    } else {        UnlockPage(page) ;    }    ClearPageUptodate(page) ;    return error ;}//// this is exactly what 2.3.99-pre9's ext2_readpage is//static int reiserfs_readpage (struct file *f, struct page * page){    return block_read_full_page (page, reiserfs_get_block);}//// modified from ext2_writepage is//static int reiserfs_writepage (struct page * page){    struct inode *inode = page->mapping->host ;    reiserfs_wait_on_write_block(inode->i_sb) ;    return reiserfs_write_full_page(page) ;}//// from ext2_prepare_write, but modified//int reiserfs_prepare_write(struct file *f, struct page *page, 			   unsigned from, unsigned to) {    struct inode *inode = page->mapping->host ;    reiserfs_wait_on_write_block(inode->i_sb) ;    fix_tail_page_for_writing(page) ;    return block_prepare_write(page, from, to, reiserfs_get_block) ;}//// this is exactly what 2.3.99-pre9's ext2_bmap is//static int reiserfs_aop_bmap(struct address_space *as, long block) {  return generic_block_bmap(as, block, reiserfs_bmap) ;}static 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -