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

📄 inode.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */#include <linux/config.h>#include <linux/sched.h>#include <linux/reiserfs_fs.h>#include <linux/locks.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/unaligned.h>/* args for the create parameter of reiserfs_get_block */#define GET_BLOCK_NO_CREATE 0 /* don't create new blocks or convert tails */#define GET_BLOCK_CREATE 1    /* add anything you need to find block */#define GET_BLOCK_NO_HOLE 2   /* return -ENOENT for file holes */#define GET_BLOCK_READ_DIRECT 4  /* read the tail if indirect item not found */#define GET_BLOCK_NO_ISEM     8 /* i_sem is not held, don't preallocate */static int reiserfs_get_block (struct inode * inode, long block,			       struct buffer_head * bh_result, int create);//// initially this function was derived from minix or ext2's analog and// evolved as the prototype did//void reiserfs_delete_inode (struct inode * inode){    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2;     int windex ;    struct reiserfs_transaction_handle th ;      lock_kernel() ;     /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */    if (INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */	down (&inode->i_sem); 	journal_begin(&th, inode->i_sb, jbegin_count) ;	reiserfs_update_inode_transaction(inode) ;	windex = push_journal_writer("delete_inode") ;	reiserfs_delete_object (&th, inode);	pop_journal_writer(windex) ;	journal_end(&th, inode->i_sb, jbegin_count) ;        up (&inode->i_sem);        /* all items of file are deleted, so we can remove "save" link */	remove_save_link (inode, 0/* not truncate */);    } else {	/* no object items are in the tree */	;    }    clear_inode (inode); /* note this must go after the journal_end to prevent deadlock */    inode->i_blocks = 0;    unlock_kernel() ;}static void _make_cpu_key (struct cpu_key * key, int version, __u32 dirid, __u32 objectid, 	       loff_t offset, int type, int length ){    key->version = version;    key->on_disk_key.k_dir_id = dirid;    key->on_disk_key.k_objectid = objectid;    set_cpu_key_k_offset (key, offset);    set_cpu_key_k_type (key, type);      key->key_length = length;}/* take base of inode_key (it comes from inode always) (dirid, objectid) and version from an inode, set   offset and type of key */void make_cpu_key (struct cpu_key * key, const struct inode * inode, loff_t offset,	      int type, int length ){  _make_cpu_key (key, get_inode_item_key_version (inode), le32_to_cpu (INODE_PKEY (inode)->k_dir_id),		 le32_to_cpu (INODE_PKEY (inode)->k_objectid), 		 offset, type, length);}//// when key is 0, do not set version and short key//inline void make_le_item_head (struct item_head * ih, const struct cpu_key * key,			       int version,			       loff_t offset, int type, int length, 			       int entry_count/*or ih_free_space*/){    if (key) {	ih->ih_key.k_dir_id = cpu_to_le32 (key->on_disk_key.k_dir_id);	ih->ih_key.k_objectid = cpu_to_le32 (key->on_disk_key.k_objectid);    }    put_ih_version( ih, version );    set_le_ih_k_offset (ih, offset);    set_le_ih_k_type (ih, type);    put_ih_item_len( ih, length );    /*    set_ih_free_space (ih, 0);*/    // for directory items it is entry count, for directs and stat    // datas - 0xffff, for indirects - 0    put_ih_entry_count( ih, entry_count );}static void add_to_flushlist(struct inode *inode, struct buffer_head *bh) {    struct inode *jinode = &(SB_JOURNAL(inode->i_sb)->j_dummy_inode) ;    buffer_insert_inode_queue(bh, jinode) ;}//// FIXME: we might cache recently accessed indirect item (or at least// first 15 pointers just like ext2 does// Ugh.  Not too eager for that....//  I cut the code until such time as I see a convincing argument (benchmark).// I don't want a bloated inode struct..., and I don't like code complexity..../* cutting the code is fine, since it really isn't in use yet and is easy** to add back in.  But, Vladimir has a really good idea here.  Think** about what happens for reading a file.  For each page,** The VFS layer calls reiserfs_readpage, who searches the tree to find** an indirect item.  This indirect item has X number of pointers, where** X is a big number if we've done the block allocation right.  But,** we only use one or two of these pointers during each call to readpage,** needlessly researching again later on.**** The size of the cache could be dynamic based on the size of the file.**** I'd also like to see us cache the location the stat data item, since** we are needlessly researching for that frequently.**** --chris*//* If this page has a file tail in it, and** it was read in by get_block_create_0, the page data is valid,** but tail is still sitting in a direct item, and we can't write to** it.  So, look through this page, and check all the mapped buffers** to make sure they have valid block numbers.  Any that don't need** to be unmapped, so that block_prepare_write will correctly call** reiserfs_get_block to convert the tail into an unformatted node*/static inline void fix_tail_page_for_writing(struct page *page) {    struct buffer_head *head, *next, *bh ;    if (page && page->buffers) {	head = page->buffers ;	bh = head ;	do {	    next = bh->b_this_page ;	    if (buffer_mapped(bh) && bh->b_blocknr == 0) {	        reiserfs_unmap_buffer(bh) ;	    }	    bh = next ;	} while (bh != head) ;    }}/* we need to allocate a block for new unformatted node.  Try to figure out   what point in bitmap reiserfs_new_blocknrs should start from. */static b_blocknr_t find_tag (struct buffer_head * bh, struct item_head * ih,			     __u32 * item, int pos_in_item){  __u32 block ;  if (!is_indirect_le_ih (ih))	 /* something more complicated could be here */	 return bh->b_blocknr;  /* for indirect item: go to left and look for the first non-hole entry in	  the indirect item */  if (pos_in_item == I_UNFM_NUM (ih))	 pos_in_item --;  while (pos_in_item >= 0) {	 block = get_block_num(item, pos_in_item) ;	 if (block)		return block ;	 pos_in_item --;  }  return bh->b_blocknr;}/* reiserfs_get_block does not need to allocate a block only if it has been   done already or non-hole position has been found in the indirect item */static inline int allocation_needed (int retval, b_blocknr_t allocated, 				     struct item_head * ih,				     __u32 * item, int pos_in_item){  if (allocated)	 return 0;  if (retval == POSITION_FOUND && is_indirect_le_ih (ih) &&       get_block_num(item, pos_in_item))	 return 0;  return 1;}static inline int indirect_item_found (int retval, struct item_head * ih){  return (retval == POSITION_FOUND) && is_indirect_le_ih (ih);}static inline void set_block_dev_mapped (struct buffer_head * bh, 					 b_blocknr_t block, struct inode * inode){  bh->b_dev = inode->i_dev;  bh->b_blocknr = block;  bh->b_state |= (1UL << BH_Mapped);}//// files which were created in the earlier version can not be longer,// than 2 gb//static int file_capable (struct inode * inode, long block){    if (get_inode_item_key_version (inode) != KEY_FORMAT_3_5 || // it is new file.	block < (1 << (31 - inode->i_sb->s_blocksize_bits))) // old file, but 'block' is inside of 2gb	return 1;    return 0;}/*static*/ void restart_transaction(struct reiserfs_transaction_handle *th,				struct inode *inode, struct path *path) {  struct super_block *s = th->t_super ;  int len = th->t_blocks_allocated ;  pathrelse(path) ;  reiserfs_update_sd(th, inode) ;  journal_end(th, s, len) ;  journal_begin(th, s, len) ;  reiserfs_update_inode_transaction(inode) ;}// it is called by get_block when create == 0. Returns block number// for 'block'-th logical block of file. When it hits direct item it// returns 0 (being called from bmap) or read direct item into piece// of page (bh_result)// Please improve the english/clarity in the comment above, as it is// hard to understand.static int _get_block_create_0 (struct inode * inode, long block,				 struct buffer_head * bh_result,				 int args){    INITIALIZE_PATH (path);    struct cpu_key key;    struct buffer_head * bh;    struct item_head * ih, tmp_ih;    int fs_gen ;    int blocknr;    char * p = NULL;    int chars;    int ret ;    int done = 0 ;    unsigned long offset ;    // prepare the key to look for the 'block'-th block of file    make_cpu_key (&key, inode,		  (loff_t)block * inode->i_sb->s_blocksize + 1, TYPE_ANY, 3);research:    if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND) {	pathrelse (&path);        if (p)            kunmap(bh_result->b_page) ;	// We do not return -ENOENT if there is a hole but page is uptodate, because it means	// That there is some MMAPED data associated with it that is yet to be written to disk.	if ((args & GET_BLOCK_NO_HOLE) && !Page_Uptodate(bh_result->b_page) ) {	    return -ENOENT ;	}        return 0 ;    }        //    bh = get_last_bh (&path);    ih = get_ih (&path);    if (is_indirect_le_ih (ih)) {	__u32 * ind_item = (__u32 *)B_I_PITEM (bh, ih);		/* FIXME: here we could cache indirect item or part of it in	   the inode to avoid search_by_key in case of subsequent	   access to file */	blocknr = get_block_num(ind_item, path.pos_in_item) ;	ret = 0 ;	if (blocknr) {	    bh_result->b_dev = inode->i_dev;	    bh_result->b_blocknr = blocknr;	    bh_result->b_state |= (1UL << BH_Mapped);	} else	    // We do not return -ENOENT if there is a hole but page is uptodate, because it means	    // That there is some MMAPED data associated with it that is yet to be written to disk.	    if ((args & GET_BLOCK_NO_HOLE) && !Page_Uptodate(bh_result->b_page) ) {		ret = -ENOENT ;	    }	pathrelse (&path);        if (p)            kunmap(bh_result->b_page) ;	return ret ;    }    // requested data are in direct item(s)    if (!(args & GET_BLOCK_READ_DIRECT)) {	// we are called by bmap. FIXME: we can not map block of file	// when it is stored in direct item(s)	pathrelse (&path);	        if (p)            kunmap(bh_result->b_page) ;	return -ENOENT;    }    /* if we've got a direct item, and the buffer was uptodate,    ** we don't want to pull data off disk again.  skip to the    ** end, where we map the buffer and return    */    if (buffer_uptodate(bh_result)) {        goto finished ;    } else 	/*	** grab_tail_page can trigger calls to reiserfs_get_block on up to date	** pages without any buffers.  If the page is up to date, we don't want	** read old data off disk.  Set the up to date bit on the buffer instead	** and jump to the end	*/	    if (Page_Uptodate(bh_result->b_page)) {		mark_buffer_uptodate(bh_result, 1);		goto finished ;    }    // read file tail into part of page    offset = (cpu_key_k_offset(&key) - 1) & (PAGE_CACHE_SIZE - 1) ;    fs_gen = get_generation(inode->i_sb) ;    copy_item_head (&tmp_ih, ih);    /* we only want to kmap if we are reading the tail into the page.    ** this is not the common case, so we don't kmap until we are    ** sure we need to.  But, this means the item might move if    ** kmap schedules    */    if (!p) {    p = (char *)kmap(bh_result->b_page) ;    if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {        goto research;    }    }    p += offset ;    memset (p, 0, inode->i_sb->s_blocksize);    do {	if (!is_direct_le_ih (ih)) {	    BUG ();        }	/* make sure we don't read more bytes than actually exist in	** the file.  This can happen in odd cases where i_size isn't	** correct, and when direct item padding results in a few 	** extra bytes at the end of the direct item	*/        if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)	    break ;	if ((le_ih_k_offset(ih) - 1 + ih_item_len(ih)) > inode->i_size) {	    chars = inode->i_size - (le_ih_k_offset(ih) - 1) - path.pos_in_item;	    done = 1 ;	} else {	    chars = ih_item_len(ih) - path.pos_in_item;	}	memcpy (p, B_I_PITEM (bh, ih) + path.pos_in_item, chars);	if (done) 	    break ;	p += chars;	if (PATH_LAST_POSITION (&path) != (B_NR_ITEMS (bh) - 1))	    // we done, if read direct item is not the last item of	    // node FIXME: we could try to check right delimiting key	    // to see whether direct item continues in the right	    // neighbor or rely on i_size	    break;	// update key to look for the next piece	set_cpu_key_k_offset (&key, cpu_key_k_offset (&key) + chars);	if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND)	    // we read something from tail, even if now we got IO_ERROR	    break;	bh = get_last_bh (&path);	ih = get_ih (&path);    } while (1);    flush_dcache_page(bh_result->b_page) ;    kunmap(bh_result->b_page) ;finished:    pathrelse (&path);    bh_result->b_blocknr = 0 ;    bh_result->b_dev = inode->i_dev;    mark_buffer_uptodate (bh_result, 1);    bh_result->b_state |= (1UL << BH_Mapped);    return 0;}

⌨️ 快捷键说明

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