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 + -
显示快捷键?