stree.c

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

C
1,882
字号
	       entry and log buffer containing that indirect item. For this we	       need to prepare last path element for logging. If some	       unformatted node has b_count > 1 we must not free this	       unformatted node since it is in use. */	    reiserfs_prepare_for_journal(p_s_sb, p_s_bh, 1);	    // note: path could be changed, first line in for loop takes care	    // of it	    for (n_counter = *p_n_removed;		 n_counter < n_unfm_number; n_counter++, p_n_unfm_pointer-- ) {		cond_resched();		if (item_moved (&s_ih, p_s_path)) {		    need_research = 1 ;		    break;		}		RFALSE( p_n_unfm_pointer < (__u32 *)B_I_PITEM(p_s_bh, &s_ih) ||			p_n_unfm_pointer > (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1,			"vs-5265: pointer out of range");		/* Hole, nothing to remove. */		if ( ! get_block_num(p_n_unfm_pointer,0) )  {			(*p_n_removed)++;			continue;		}		(*p_n_removed)++;		tmp = get_block_num(p_n_unfm_pointer,0);		put_block_num(p_n_unfm_pointer, 0, 0);		journal_mark_dirty (th, p_s_sb, p_s_bh);		reiserfs_free_block(th, inode, tmp, 1);		if ( item_moved (&s_ih, p_s_path) )  {			need_research = 1;			break ;		}	    }	    /* a trick.  If the buffer has been logged, this	    ** will do nothing.  If we've broken the loop without	    ** logging it, it will restore the buffer	    **	    */	    reiserfs_restore_prepared_buffer(p_s_sb, p_s_bh);	    /* This loop can be optimized. */	} while ( (*p_n_removed < n_unfm_number || need_research) &&		  search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_FOUND );	RFALSE( *p_n_removed < n_unfm_number, 		"PAP-5310: indirect item is not found");	RFALSE( item_moved (&s_ih, p_s_path), 		"after while, comp failed, retry") ;	if (c_mode == M_CUT)	    pos_in_item (p_s_path) *= UNFM_P_SIZE;	return c_mode;    }}/* Calculate number of bytes which will be deleted or cut during balance */int calc_deleted_bytes_number(    struct  tree_balance  * p_s_tb,    char                    c_mode    ) {    int                     n_del_size;    struct  item_head     * p_le_ih = PATH_PITEM_HEAD(p_s_tb->tb_path);    if ( is_statdata_le_ih (p_le_ih) )	return 0;    n_del_size = ( c_mode == M_DELETE ) ? ih_item_len(p_le_ih) : -p_s_tb->insert_size[0];    if ( is_direntry_le_ih (p_le_ih) ) {	// return EMPTY_DIR_SIZE; /* We delete emty directoris only. */	// we can't use EMPTY_DIR_SIZE, as old format dirs have a different	// empty size.  ick. FIXME, is this right?	//	return n_del_size ;    }    if ( is_indirect_le_ih (p_le_ih) )	n_del_size = (n_del_size/UNFM_P_SIZE)*	  (PATH_PLAST_BUFFER(p_s_tb->tb_path)->b_size);// - get_ih_free_space (p_le_ih);    return n_del_size;}static void init_tb_struct(    struct reiserfs_transaction_handle *th,    struct tree_balance * p_s_tb,    struct super_block  * p_s_sb,    struct path         * p_s_path,    int                   n_size    ) {    memset (p_s_tb,'\0',sizeof(struct tree_balance));    p_s_tb->transaction_handle = th ;    p_s_tb->tb_sb = p_s_sb;    p_s_tb->tb_path = p_s_path;    PATH_OFFSET_PBUFFER(p_s_path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL;    PATH_OFFSET_POSITION(p_s_path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0;    p_s_tb->insert_size[0] = n_size;}void padd_item (char * item, int total_length, int length){    int i;    for (i = total_length; i > length; )	item [--i] = 0;}#ifdef REISERQUOTA_DEBUGchar key2type(struct key *ih){  if (is_direntry_le_key(2, ih))    return 'd';  if (is_direct_le_key(2, ih))    return 'D';  if (is_indirect_le_key(2, ih))    return 'i';  if (is_statdata_le_key(2, ih))    return 's';  return 'u';}char head2type(struct item_head *ih){  if (is_direntry_le_ih(ih))    return 'd';  if (is_direct_le_ih(ih))    return 'D';  if (is_indirect_le_ih(ih))    return 'i';  if (is_statdata_le_ih(ih))    return 's';  return 'u';}#endif/* Delete object item. */int reiserfs_delete_item (struct reiserfs_transaction_handle *th, 			  struct path * p_s_path, /* Path to the deleted item. */			  const struct cpu_key * p_s_item_key, /* Key to search for the deleted item.  */			  struct inode * p_s_inode,/* inode is here just to update i_blocks and quotas */			  struct buffer_head  * p_s_un_bh)    /* NULL or unformatted node pointer.    */{    struct super_block * p_s_sb = p_s_inode->i_sb;    struct tree_balance   s_del_balance;    struct item_head      s_ih;    struct item_head      *q_ih;    int			  quota_cut_bytes;    int                   n_ret_value,	n_del_size,	n_removed;#ifdef CONFIG_REISERFS_CHECK    char                  c_mode;    int			n_iter = 0;#endif    init_tb_struct(th, &s_del_balance, p_s_sb, p_s_path, 0/*size is unknown*/);    while ( 1 ) {	n_removed = 0;#ifdef CONFIG_REISERFS_CHECK	n_iter++;	c_mode =#endif	    prepare_for_delete_or_cut(th, p_s_inode, p_s_path, p_s_item_key, &n_removed, &n_del_size, max_reiserfs_offset (p_s_inode));	RFALSE( c_mode != M_DELETE, "PAP-5320: mode must be M_DELETE");	copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));	s_del_balance.insert_size[0] = n_del_size;	n_ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, NULL);	if ( n_ret_value != REPEAT_SEARCH )	    break;	PROC_INFO_INC( p_s_sb, delete_item_restarted );	// file system changed, repeat search	n_ret_value = search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path);	if (n_ret_value == IO_ERROR)	    break;	if (n_ret_value == FILE_NOT_FOUND) {	    reiserfs_warning (p_s_sb, "vs-5340: reiserfs_delete_item: "			      "no items of the file %K found", p_s_item_key);	    break;	}    } /* while (1) */    if ( n_ret_value != CARRY_ON ) {	unfix_nodes(&s_del_balance);	return 0;    }    // reiserfs_delete_item returns item length when success    n_ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE);    q_ih = get_ih(p_s_path) ;    quota_cut_bytes = ih_item_len(q_ih) ;    /* hack so the quota code doesn't have to guess if the file    ** has a tail.  On tail insert, we allocate quota for 1 unformatted node.    ** We test the offset because the tail might have been    ** split into multiple items, and we only want to decrement for    ** the unfm node once    */    if (!S_ISLNK (p_s_inode->i_mode) && is_direct_le_ih(q_ih)) {        if ((le_ih_k_offset(q_ih) & (p_s_sb->s_blocksize - 1)) == 1) {            quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE;        } else {	    quota_cut_bytes = 0 ;	}    }    if ( p_s_un_bh )  {	int off;        char *data ;	/* We are in direct2indirect conversion, so move tail contents           to the unformatted node */	/* note, we do the copy before preparing the buffer because we	** don't care about the contents of the unformatted node yet.	** the only thing we really care about is the direct item's data	** is in the unformatted node.	**	** Otherwise, we would have to call reiserfs_prepare_for_journal on	** the unformatted node, which might schedule, meaning we'd have to	** loop all the way back up to the start of the while loop.	**	** The unformatted node must be dirtied later on.  We can't be	** sure here if the entire tail has been deleted yet.        **        ** p_s_un_bh is from the page cache (all unformatted nodes are        ** from the page cache) and might be a highmem page.  So, we        ** can't use p_s_un_bh->b_data.	** -clm	*/        data = kmap_atomic(p_s_un_bh->b_page, KM_USER0);	off = ((le_ih_k_offset (&s_ih) - 1) & (PAGE_CACHE_SIZE - 1));	memcpy(data + off,	       B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value);	kunmap_atomic(data, KM_USER0);    }    /* Perform balancing after all resources have been collected at once. */     do_balance(&s_del_balance, NULL, NULL, M_DELETE);#ifdef REISERQUOTA_DEBUG    reiserfs_debug (p_s_sb, "reiserquota delete_item(): freeing %u, id=%u type=%c", quota_cut_bytes, p_s_inode->i_uid, head2type(&s_ih));#endif    DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);    /* Return deleted body length */    return n_ret_value;}/* Summary Of Mechanisms For Handling Collisions Between Processes: deletion of the body of the object is performed by iput(), with the result that if multiple processes are operating on a file, the deletion of the body of the file is deferred until the last process that has an open inode performs its iput(). writes and truncates are protected from collisions by use of semaphores. creates, linking, and mknod are protected from collisions with other processes by making the reiserfs_add_entry() the last step in the creation, and then rolling back all changes if there was a collision. - Hans*//* this deletes item which never gets split */void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,				 struct inode *inode,				 struct key * key){    struct tree_balance tb;    INITIALIZE_PATH (path);    int item_len = 0;    int tb_init = 0 ;    struct cpu_key cpu_key;    int retval;    int quota_cut_bytes = 0;        le_key2cpu_key (&cpu_key, key);        while (1) {	retval = search_item (th->t_super, &cpu_key, &path);	if (retval == IO_ERROR) {	    reiserfs_warning (th->t_super,			      "vs-5350: reiserfs_delete_solid_item: "			      "i/o failure occurred trying to delete %K",			      &cpu_key);	    break;	}	if (retval != ITEM_FOUND) {	    pathrelse (&path);	    // No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir	    if ( !( (unsigned long long) GET_HASH_VALUE (le_key_k_offset (le_key_version (key), key)) == 0 && \		 (unsigned long long) GET_GENERATION_NUMBER (le_key_k_offset (le_key_version (key), key)) == 1 ) )		reiserfs_warning (th->t_super, "vs-5355: reiserfs_delete_solid_item: %k not found", key);	    break;	}	if (!tb_init) {	    tb_init = 1 ;	    item_len = ih_item_len( PATH_PITEM_HEAD(&path) );	    init_tb_struct (th, &tb, th->t_super, &path, - (IH_SIZE + item_len));	}	quota_cut_bytes = ih_item_len(PATH_PITEM_HEAD(&path)) ;	retval = fix_nodes (M_DELETE, &tb, NULL, NULL);	if (retval == REPEAT_SEARCH) {	    PROC_INFO_INC( th -> t_super, delete_solid_item_restarted );	    continue;	}	if (retval == CARRY_ON) {	    do_balance (&tb, NULL, NULL, M_DELETE);	    if (inode) {	/* Should we count quota for item? (we don't count quotas for save-links) */#ifdef REISERQUOTA_DEBUG		reiserfs_debug (th->t_super, "reiserquota delete_solid_item(): freeing %u id=%u type=%c", quota_cut_bytes, inode->i_uid, key2type(key));#endif		DQUOT_FREE_SPACE_NODIRTY(inode, quota_cut_bytes);	    }	    break;	}	// IO_ERROR, NO_DISK_SPACE, etc	reiserfs_warning (th->t_super, "vs-5360: reiserfs_delete_solid_item: "			  "could not delete %K due to fix_nodes failure", &cpu_key);	unfix_nodes (&tb);	break;    }    reiserfs_check_path(&path) ;}void reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inode * inode){    inode->i_size = 0;    /* for directory this deletes item containing "." and ".." */    reiserfs_do_truncate (th, inode, NULL, 0/*no timestamp updates*/);    #if defined( USE_INODE_GENERATION_COUNTER )    if( !old_format_only ( th -> t_super ) )      {       __u32 *inode_generation;              inode_generation =          &REISERFS_SB(th -> t_super) -> s_rs -> s_inode_generation;       *inode_generation = cpu_to_le32( le32_to_cpu( *inode_generation ) + 1 );      }/* USE_INODE_GENERATION_COUNTER */#endif    reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));}static voidunmap_buffers(struct page *page, loff_t pos) {    struct buffer_head *bh ;    struct buffer_head *head ;    struct buffer_head *next ;    unsigned long tail_index ;    unsigned long cur_index ;    if (page) {	if (page_has_buffers(page)) {	    tail_index = pos & (PAGE_CACHE_SIZE - 1) ;

⌨️ 快捷键说明

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