inode.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,950 行 · 第 1/5 页

C
1,950
字号
// read direct itemint reiserfs_bmap (struct inode * inode, sector_t block,		   struct buffer_head * bh_result, int create){    if (!file_capable (inode, block))	return -EFBIG;    reiserfs_write_lock(inode->i_sb);    /* do not read the direct item */    _get_block_create_0 (inode, block, bh_result, 0) ;    reiserfs_write_unlock(inode->i_sb);    return 0;}/* special version of get_block that is only used by grab_tail_page right** now.  It is sent to block_prepare_write, and when you try to get a** block past the end of the file (or a block from a hole) it returns** -ENOENT instead of a valid buffer.  block_prepare_write expects to** be able to do i/o on the buffers returned, unless an error value** is also returned.** ** So, this allows block_prepare_write to be used for reading a single block** in a page.  Where it does not produce a valid page for holes, or past the** end of the file.  This turns out to be exactly what we need for reading** tails for conversion.**** The point of the wrapper is forcing a certain value for create, even** though the VFS layer is calling this function with create==1.  If you ** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block, ** don't use this function.*/static int reiserfs_get_block_create_0 (struct inode * inode, sector_t block,			struct buffer_head * bh_result, int create) {    return reiserfs_get_block(inode, block, bh_result, GET_BLOCK_NO_HOLE) ;}/* This is special helper for reiserfs_get_block in case we are executing   direct_IO request. */static int reiserfs_get_blocks_direct_io(struct inode *inode,					 sector_t iblock,					 unsigned long max_blocks,					 struct buffer_head *bh_result,					 int create){    int ret ;    bh_result->b_page = NULL;    /* We set the b_size before reiserfs_get_block call since it is       referenced in convert_tail_for_hole() that may be called from       reiserfs_get_block() */    bh_result->b_size = (1 << inode->i_blkbits);    ret = reiserfs_get_block(inode, iblock, bh_result,                             create | GET_BLOCK_NO_DANGLE) ;    /* don't allow direct io onto tail pages */    if (ret == 0 && buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {        /* make sure future calls to the direct io funcs for this offset        ** in the file fail by unmapping the buffer        */        clear_buffer_mapped(bh_result);        ret = -EINVAL ;    }    /* Possible unpacked tail. Flush the data before pages have       disappeared */    if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) {        lock_kernel();        reiserfs_commit_for_inode(inode);        REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;        unlock_kernel();    }    return ret ;}/*** helper function for when reiserfs_get_block is called for a hole** but the file tail is still in a direct item** bh_result is the buffer head for the hole** tail_offset is the offset of the start of the tail in the file**** This calls prepare_write, which will start a new transaction** you should not be in a transaction, or have any paths held when you** call this.*/static int convert_tail_for_hole(struct inode *inode,                                  struct buffer_head *bh_result,				 loff_t tail_offset) {    unsigned long index ;    unsigned long tail_end ;     unsigned long tail_start ;    struct page * tail_page ;    struct page * hole_page = bh_result->b_page ;    int retval = 0 ;    if ((tail_offset & (bh_result->b_size - 1)) != 1)         return -EIO ;    /* always try to read until the end of the block */    tail_start = tail_offset & (PAGE_CACHE_SIZE - 1) ;    tail_end = (tail_start | (bh_result->b_size - 1)) + 1 ;    index = tail_offset >> PAGE_CACHE_SHIFT ;    /* hole_page can be zero in case of direct_io, we are sure       that we cannot get here if we write with O_DIRECT into       tail page */    if (!hole_page || index != hole_page->index) {	tail_page = grab_cache_page(inode->i_mapping, index) ;	retval = -ENOMEM;	if (!tail_page) {	    goto out ;	}    } else {        tail_page = hole_page ;    }    /* we don't have to make sure the conversion did not happen while    ** we were locking the page because anyone that could convert    ** must first take i_sem.    **    ** We must fix the tail page for writing because it might have buffers    ** that are mapped, but have a block number of 0.  This indicates tail    ** data that has been read directly into the page, and block_prepare_write    ** won't trigger a get_block in this case.    */    fix_tail_page_for_writing(tail_page) ;    retval = reiserfs_prepare_write(NULL, tail_page, tail_start, tail_end);    if (retval)        goto unlock ;    /* tail conversion might change the data in the page */    flush_dcache_page(tail_page) ;    retval = reiserfs_commit_write(NULL, tail_page, tail_start, tail_end) ;unlock:    if (tail_page != hole_page) {        unlock_page(tail_page) ;	page_cache_release(tail_page) ;    }out:    return retval ;}static inline int _allocate_block(struct reiserfs_transaction_handle *th,			   long block,                           struct inode *inode, 			   b_blocknr_t *allocated_block_nr, 			   struct path * path,			   int flags) {  #ifdef REISERFS_PREALLOCATE    if (!(flags & GET_BLOCK_NO_ISEM)) {	return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, path, block);    }#endif    return reiserfs_new_unf_blocknrs (th, inode, allocated_block_nr, path, block);}int reiserfs_get_block (struct inode * inode, sector_t block,			struct buffer_head * bh_result, int create){    int repeat, retval;    b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is (unsigned) 32 bit int    INITIALIZE_PATH(path);    int pos_in_item;    struct cpu_key key;    struct buffer_head * bh, * unbh = NULL;    struct item_head * ih, tmp_ih;    __u32 * item;    int done;    int fs_gen;    struct reiserfs_transaction_handle *th = NULL;    /* space reserved in transaction batch:         . 3 balancings in direct->indirect conversion        . 1 block involved into reiserfs_update_sd()       XXX in practically impossible worst case direct2indirect()       can incur (much) more that 3 balancings. */    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1;    int version;    int dangle = 1;    loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;				/* bad.... */    reiserfs_write_lock(inode->i_sb);    version = get_inode_item_key_version (inode);    if (block < 0) {	reiserfs_write_unlock(inode->i_sb);	return -EIO;    }    if (!file_capable (inode, block)) {	reiserfs_write_unlock(inode->i_sb);	return -EFBIG;    }    /* if !create, we aren't changing the FS, so we don't need to    ** log anything, so we don't need to start a transaction    */    if (!(create & GET_BLOCK_CREATE)) {	int ret ;	/* find number of block-th logical block of the file */	ret = _get_block_create_0 (inode, block, bh_result, 	                           create | GET_BLOCK_READ_DIRECT) ;	reiserfs_write_unlock(inode->i_sb);	return ret;    }    /*     * if we're already in a transaction, make sure to close     * any new transactions we start in this func     */    if ((create & GET_BLOCK_NO_DANGLE) ||        reiserfs_transaction_running(inode->i_sb))        dangle = 0;    /* If file is of such a size, that it might have a tail and tails are enabled    ** we should mark it as possibly needing tail packing on close    */    if ( (have_large_tails (inode->i_sb) && inode->i_size < i_block_size (inode)*4) ||	 (have_small_tails (inode->i_sb) && inode->i_size < i_block_size(inode)) )	REISERFS_I(inode)->i_flags |= i_pack_on_close_mask ;    /* set the key of the first byte in the 'block'-th block of file */    make_cpu_key (&key, inode, new_offset,		  TYPE_ANY, 3/*key length*/);    if ((new_offset + inode->i_sb->s_blocksize - 1) > inode->i_size) {start_trans:	th = reiserfs_persistent_transaction(inode->i_sb, jbegin_count);	if (!th) {	    retval = -ENOMEM;	    goto failure;	}	reiserfs_update_inode_transaction(inode) ;    } research:    retval = search_for_position_by_key (inode->i_sb, &key, &path);    if (retval == IO_ERROR) {	retval = -EIO;	goto failure;    }	    bh = get_last_bh (&path);    ih = get_ih (&path);    item = get_item (&path);    pos_in_item = path.pos_in_item;    fs_gen = get_generation (inode->i_sb);    copy_item_head (&tmp_ih, ih);    if (allocation_needed (retval, allocated_block_nr, ih, item, pos_in_item)) {	/* we have to allocate block for the unformatted node */	if (!th) {	    pathrelse(&path) ;	    goto start_trans;	}	repeat = _allocate_block(th, block, inode, &allocated_block_nr, &path, create);	if (repeat == NO_DISK_SPACE || repeat == QUOTA_EXCEEDED) {	    /* restart the transaction to give the journal a chance to free	    ** some blocks.  releases the path, so we have to go back to	    ** research if we succeed on the second try	    */	    SB_JOURNAL(inode->i_sb)->j_next_async_flush = 1;	    restart_transaction(th, inode, &path) ;	    repeat = _allocate_block(th, block, inode, &allocated_block_nr, NULL, create);	    if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) {		goto research ;	    }	    if (repeat == QUOTA_EXCEEDED)		retval = -EDQUOT;	    else		retval = -ENOSPC;	    goto failure;	}	if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {	    goto research;	}    }    if (indirect_item_found (retval, ih)) {        b_blocknr_t unfm_ptr;	/* 'block'-th block is in the file already (there is	   corresponding cell in some indirect item). But it may be	   zero unformatted node pointer (hole) */        unfm_ptr = get_block_num (item, pos_in_item);	if (unfm_ptr == 0) {	    /* use allocated block to plug the hole */	    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;	    }	    set_buffer_new(bh_result);	    if (buffer_dirty(bh_result) && reiserfs_data_ordered(inode->i_sb))	    	reiserfs_add_ordered_list(inode, bh_result);	    put_block_num(item, pos_in_item, allocated_block_nr) ;            unfm_ptr = allocated_block_nr;	    journal_mark_dirty (th, inode->i_sb, bh);	    reiserfs_update_sd(th, inode) ;	}	set_block_dev_mapped(bh_result, unfm_ptr, inode);	pathrelse (&path);	if (!dangle && th)	    reiserfs_end_persistent_transaction(th);	reiserfs_write_unlock(inode->i_sb);	 	/* the item was found, so new blocks were not added to the file	** there is no need to make sure the inode is updated with this 	** transaction	*/	return 0;    }    if (!th) {	pathrelse(&path) ;	goto start_trans;    }    /* desired position is not found or is in the direct item. We have       to append file with holes up to 'block'-th block converting       direct items to indirect one if necessary */    done = 0;    do {	if (is_statdata_le_ih (ih)) {	    __u32 unp = 0;	    struct cpu_key tmp_key;	    /* indirect item has to be inserted */	    make_le_item_head (&tmp_ih, &key, version, 1, TYPE_INDIRECT, 			       UNFM_P_SIZE, 0/* free_space */);	    if (cpu_key_k_offset (&key) == 1) {		/* we are going to add 'block'-th block to the file. Use		   allocated block for that */		unp = cpu_to_le32 (allocated_block_nr);		set_block_dev_mapped (bh_result, allocated_block_nr, inode);		set_buffer_new(bh_result);		done = 1;	    }	    tmp_key = key; // ;)	    set_cpu_key_k_offset (&tmp_key, 1);	    PATH_LAST_POSITION(&path) ++;	    retval = reiserfs_insert_item (th, &path, &tmp_key, &tmp_ih, inode, (char *)&unp);	    if (retval) {		reiserfs_free_block (th, inode, allocated_block_nr, 1);		goto failure; // retval == -ENOSPC, -EDQUOT or -EIO or -EEXIST	    }	    //mark_tail_converted (inode);	} else if (is_direct_le_ih (ih)) {	    /* direct item has to be converted */	    loff_t tail_offset;	    tail_offset = ((le_ih_k_offset (ih) - 1) & ~(inode->i_sb->s_blocksize - 1)) + 1;	    if (tail_offset == cpu_key_k_offset (&key)) {		/* direct item we just found fits into block we have                   to map. Convert it into unformatted node: use                   bh_result for the conversion */		set_block_dev_mapped (bh_result, allocated_block_nr, inode);		unbh = bh_result;		done = 1;	    } else {		/* we have to padd file tail stored in direct item(s)		   up to block size and convert it to unformatted		   node. FIXME: this should also get into page cache */		pathrelse(&path) ;		/*		 * ugly, but we can only end the transaction if		 * we aren't nested		 */		if (th->t_refcount == 1) {		    reiserfs_end_persistent_transaction(th);		    th = NULL;		}		retval = convert_tail_for_hole(inode, bh_result, tail_offset) ;		if (retval) {		    if ( retval != -ENOSPC )			reiserfs_warning (inode->i_sb, "clm-6004: convert tail failed inode %lu, error %d", inode->i_ino, retval) ;		    if (allocated_block_nr) {			/* the bitmap, the super, and the stat data == 3 */			if (!th)

⌨️ 快捷键说明

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