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

📄 stree.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 5 页
字号:
       to balance, or we fix_nodes without schedule occuring */    while ( 1 ) {	/* Determine the balance mode, position of the first byte to	   be cut, and size to be cut.  In case of the indirect item	   free unformatted nodes which are pointed to by the cut	   pointers. */      	c_mode = prepare_for_delete_or_cut(th, p_s_inode, p_s_path, p_s_item_key, &n_removed, 					   &n_cut_size, n_new_file_size);	if ( c_mode == M_CONVERT )  {	    /* convert last unformatted node to direct item or leave               tail in the unformatted node */	    RFALSE( n_ret_value != CARRY_ON, "PAP-5570: can not convert twice");	    n_ret_value = maybe_indirect_to_direct (th, p_s_inode, page, p_s_path, p_s_item_key,						    n_new_file_size, &c_mode);	    if ( c_mode == M_SKIP_BALANCING )		/* tail has been left in the unformatted node */		return n_ret_value;	    n_is_inode_locked = 1;	  	    /* removing of last unformatted node will change value we               have to return to truncate. Save it */	    retval2 = n_ret_value;	    /*retval2 = p_s_sb->s_blocksize - (n_new_file_size & (p_s_sb->s_blocksize - 1));*/	  	    /* So, we have performed the first part of the conversion:	       inserting the new direct item.  Now we are removing the	       last unformatted node pointer. Set key to search for	       it. */      	    set_cpu_key_k_type (p_s_item_key, TYPE_INDIRECT);	    p_s_item_key->key_length = 4;	    n_new_file_size -= (n_new_file_size & (p_s_sb->s_blocksize - 1));	    set_cpu_key_k_offset (p_s_item_key, n_new_file_size + 1);	    if ( search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND ){		print_block (PATH_PLAST_BUFFER (p_s_path), 3, PATH_LAST_POSITION (p_s_path) - 1, PATH_LAST_POSITION (p_s_path) + 1);		reiserfs_panic(p_s_sb, "PAP-5580: reiserfs_cut_from_item: item to convert does not exist (%k)", p_s_item_key);	    }	    continue;	}	if (n_cut_size == 0) {	    pathrelse (p_s_path);	    return 0;	}	s_cut_balance.insert_size[0] = n_cut_size;		n_ret_value = fix_nodes(c_mode, &s_cut_balance, NULL, 0);      	if ( n_ret_value != REPEAT_SEARCH )	    break;		n_ret_value = search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path);	if (n_ret_value == POSITION_FOUND)	    continue;	reiserfs_warning ("PAP-5610: reiserfs_cut_from_item: item %K not found\n", p_s_item_key);	unfix_nodes (&s_cut_balance);	return (n_ret_value == IO_ERROR) ? -EIO : -ENOENT;    } /* while */      // check fix_nodes results (IO_ERROR or NO_DISK_SPACE)    if ( n_ret_value != CARRY_ON ) {	if ( n_is_inode_locked ) {	    // FIXME: this seems to be not needed: we are always able	    // to cut item	    indirect_to_direct_roll_back (th, p_s_inode, p_s_path);	}	if (n_ret_value == NO_DISK_SPACE)	    reiserfs_warning ("NO_DISK_SPACE");	unfix_nodes (&s_cut_balance);	return -EIO;    }    /* go ahead and perform balancing */        RFALSE( c_mode == M_PASTE || c_mode == M_INSERT, "illegal mode");    /* Calculate number of bytes that need to be cut from the item. */    if (retval2 == -1)	n_ret_value = calc_deleted_bytes_number(&s_cut_balance, c_mode);    else	n_ret_value = retval2;        if ( c_mode == M_DELETE ) {	struct item_head * p_le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);		if ( is_direct_le_ih (p_le_ih) && (le_ih_k_offset (p_le_ih) & (p_s_sb->s_blocksize - 1)) == 1 ) {	    /* we delete first part of tail which was stored in direct               item(s) */	    // FIXME: this is to keep 3.5 happy	    p_s_inode->u.reiserfs_i.i_first_direct_byte = U32_MAX;	    p_s_inode->i_blocks -= p_s_sb->s_blocksize / 512;	}    }#ifdef CONFIG_REISERFS_CHECK    if (n_is_inode_locked) {	struct item_head * le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);	/* we are going to complete indirect2direct conversion. Make           sure, that we exactly remove last unformatted node pointer           of the item */	if (!is_indirect_le_ih (le_ih))	    reiserfs_panic (p_s_sb, "vs-5652: reiserfs_cut_from_item: "			    "item must be indirect %h", le_ih);	if (c_mode == M_DELETE && ih_item_len(le_ih) != UNFM_P_SIZE)	    reiserfs_panic (p_s_sb, "vs-5653: reiserfs_cut_from_item: "			    "completing indirect2direct conversion indirect item %h "			    "being deleted must be of 4 byte long", le_ih);	if (c_mode == M_CUT && s_cut_balance.insert_size[0] != -UNFM_P_SIZE) {	    reiserfs_panic (p_s_sb, "vs-5654: reiserfs_cut_from_item: "			    "can not complete indirect2direct conversion of %h (CUT, insert_size==%d)",			    le_ih, s_cut_balance.insert_size[0]);	}	/* it would be useful to make sure, that right neighboring           item is direct item of this file */    }#endif        do_balance(&s_cut_balance, NULL, NULL, c_mode);    if ( n_is_inode_locked ) {	/* we've done an indirect->direct conversion.  when the data block 	** was freed, it was removed from the list of blocks that must 	** be flushed before the transaction commits, so we don't need to 	** deal with it here.	*/	p_s_inode->u.reiserfs_i.i_flags &= ~i_pack_on_close_mask;    }    return n_ret_value;}static void truncate_directory (struct reiserfs_transaction_handle *th, struct inode * inode){    if (inode->i_nlink)	reiserfs_warning ("vs-5655: truncate_directory: link count != 0\n");    set_le_key_k_offset (KEY_FORMAT_3_5, INODE_PKEY (inode), DOT_OFFSET);    set_le_key_k_type (KEY_FORMAT_3_5, INODE_PKEY (inode), TYPE_DIRENTRY);    reiserfs_delete_solid_item (th, INODE_PKEY (inode));    set_le_key_k_offset (KEY_FORMAT_3_5, INODE_PKEY (inode), SD_OFFSET);    set_le_key_k_type (KEY_FORMAT_3_5, INODE_PKEY (inode), TYPE_STAT_DATA);    }/* Truncate file to the new size. Note, this must be called with a transaction   already started */void reiserfs_do_truncate (struct reiserfs_transaction_handle *th, 			   struct  inode * p_s_inode, /* ->i_size contains new                                                         size */			   struct page *page, /* up to date for last block */			   int update_timestamps  /* when it is called by						     file_release to convert						     the tail - no timestamps						     should be updated */    ) {    INITIALIZE_PATH (s_search_path);       /* Path to the current object item. */    struct item_head    * p_le_ih;         /* Pointer to an item header. */    struct cpu_key      s_item_key;     /* Key to search for a previous file item. */    loff_t         n_file_size,    /* Old file size. */	n_new_file_size;/* New file size. */    int                   n_deleted;      /* Number of deleted or truncated bytes. */    int retval;    if ( ! (S_ISREG(p_s_inode->i_mode) || S_ISDIR(p_s_inode->i_mode) || S_ISLNK(p_s_inode->i_mode)) )	return;    if (S_ISDIR(p_s_inode->i_mode)) {	// deletion of directory - no need to update timestamps	truncate_directory (th, p_s_inode);	return;    }    /* Get new file size. */    n_new_file_size = p_s_inode->i_size;    // FIXME: note, that key type is unimportant here    make_cpu_key (&s_item_key, p_s_inode, max_reiserfs_offset (p_s_inode), TYPE_DIRECT, 3);    retval = search_for_position_by_key(p_s_inode->i_sb, &s_item_key, &s_search_path);    if (retval == IO_ERROR) {	reiserfs_warning ("vs-5657: reiserfs_do_truncate: "			  "i/o failure occurred trying to truncate %K\n", &s_item_key);	return;    }    if (retval == POSITION_FOUND || retval == FILE_NOT_FOUND) {	pathrelse (&s_search_path);	reiserfs_warning ("PAP-5660: reiserfs_do_truncate: "			  "wrong result %d of search for %K\n", retval, &s_item_key);	return;    }    s_search_path.pos_in_item --;    /* Get real file size (total length of all file items) */    p_le_ih = PATH_PITEM_HEAD(&s_search_path);    if ( is_statdata_le_ih (p_le_ih) )	n_file_size = 0;    else {	loff_t offset = le_ih_k_offset (p_le_ih);	int bytes = op_bytes_number (p_le_ih,p_s_inode->i_sb->s_blocksize);	/* this may mismatch with real file size: if last direct item           had no padding zeros and last unformatted node had no free           space, this file would have this file size */	n_file_size = offset + bytes - 1;    }    if ( n_file_size == 0 || n_file_size < n_new_file_size ) {	goto update_and_out ;    }    /* Update key to search for the last file item. */    set_cpu_key_k_offset (&s_item_key, n_file_size);    do  {	/* Cut or delete file item. */	n_deleted = reiserfs_cut_from_item(th, &s_search_path, &s_item_key, p_s_inode,  page, n_new_file_size);	if (n_deleted < 0) {	    reiserfs_warning ("vs-5665: reiserfs_truncate_file: cut_from_item failed");	    reiserfs_check_path(&s_search_path) ;	    return;	}	RFALSE( n_deleted > n_file_size,		"PAP-5670: reiserfs_truncate_file returns too big number: deleted %d, file_size %lu, item_key %k",		n_deleted, n_file_size, &s_item_key);	/* Change key to search the last file item. */	n_file_size -= n_deleted;	set_cpu_key_k_offset (&s_item_key, n_file_size);	/* While there are bytes to truncate and previous file item is presented in the tree. */	/*	** This loop could take a really long time, and could log 	** many more blocks than a transaction can hold.  So, we do a polite	** journal end here, and if the transaction needs ending, we make	** sure the file is consistent before ending the current trans	** and starting a new one	*/        if (journal_transaction_should_end(th, th->t_blocks_allocated)) {	  int orig_len_alloc = th->t_blocks_allocated ;	  decrement_counters_in_path(&s_search_path) ;	  if (update_timestamps) {	      p_s_inode->i_mtime = p_s_inode->i_ctime = CURRENT_TIME;	  } 	  reiserfs_update_sd(th, p_s_inode) ;	  journal_end(th, p_s_inode->i_sb, orig_len_alloc) ;	  journal_begin(th, p_s_inode->i_sb, orig_len_alloc) ;	  reiserfs_update_inode_transaction(p_s_inode) ;	}    } while ( n_file_size > ROUND_UP (n_new_file_size) &&	      search_for_position_by_key(p_s_inode->i_sb, &s_item_key, &s_search_path) == POSITION_FOUND )  ;    RFALSE( n_file_size > ROUND_UP (n_new_file_size),	    "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d\n",	    n_new_file_size, n_file_size, s_item_key.on_disk_key.k_objectid);update_and_out:    if (update_timestamps) {	// this is truncate, not file closing	p_s_inode->i_mtime = p_s_inode->i_ctime = CURRENT_TIME;    }    reiserfs_update_sd (th, p_s_inode);    pathrelse(&s_search_path) ;}#ifdef CONFIG_REISERFS_CHECK// this makes sure, that we __append__, not overwrite or add holesstatic void check_research_for_paste (struct path * path, 				      const struct cpu_key * p_s_key){    struct item_head * found_ih = get_ih (path);        if (is_direct_le_ih (found_ih)) {	if (le_ih_k_offset (found_ih) + op_bytes_number (found_ih, get_last_bh (path)->b_size) !=	    cpu_key_k_offset (p_s_key) ||	    op_bytes_number (found_ih, get_last_bh (path)->b_size) != pos_in_item (path))	    reiserfs_panic (0, "PAP-5720: check_research_for_paste: "			    "found direct item %h or position (%d) does not match to key %K",			    found_ih, pos_in_item (path), p_s_key);    }    if (is_indirect_le_ih (found_ih)) {	if (le_ih_k_offset (found_ih) + op_bytes_number (found_ih, get_last_bh (path)->b_size) != cpu_key_k_offset (p_s_key) || 	    I_UNFM_NUM (found_ih) != pos_in_item (path) ||	    get_ih_free_space (found_ih) != 0)	    reiserfs_panic (0, "PAP-5730: check_research_for_paste: "			    "found indirect item (%h) or position (%d) does not match to key (%K)",			    found_ih, pos_in_item (path), p_s_key);    }}#endif /* config reiserfs check *//* Paste bytes to the existing item. Returns bytes number pasted into the item. */int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th, 			      struct path         * p_s_search_path,	/* Path to the pasted item.          */			      const struct cpu_key      * p_s_key,        	/* Key to search for the needed item.*/			      const char          * p_c_body,       	/* Pointer to the bytes to paste.    */			      int                   n_pasted_size)  	/* Size of pasted bytes.             */{    struct tree_balance s_paste_balance;    int                 retval;    init_tb_struct(th, &s_paste_balance, th->t_super, p_s_search_path, n_pasted_size);        while ( (retval = fix_nodes(M_PASTE, &s_paste_balance, NULL, p_c_body)) == REPEAT_SEARCH ) {	/* file system changed while we were in the fix_nodes */	retval = search_for_position_by_key (th->t_super, p_s_key, p_s_search_path);	if (retval == IO_ERROR) {	    retval = -EIO ;	    goto error_out ;	}	if (retval == POSITION_FOUND) {	    reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists", p_s_key);	    retval = -EEXIST ;	    goto error_out ;	}	#ifdef CONFIG_REISERFS_CHECK	check_research_for_paste (p_s_search_path, p_s_key);#endif    }    /* Perform balancing after all resources are collected by fix_nodes, and       accessing them will not risk triggering schedule. */    if ( retval == CARRY_ON ) {	do_balance(&s_paste_balance, NULL/*ih*/, p_c_body, M_PASTE);	return 0;    }    retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;error_out:    /* this also releases the path */    unfix_nodes(&s_paste_balance);    return retval ;}/* Insert new item into the buffer at the path. */int reiserfs_insert_item(struct reiserfs_transaction_handle *th, 			 struct path         * 	p_s_path,         /* Path to the inserteded item.         */			 const struct cpu_key      * key,			 struct item_head    * 	p_s_ih,           /* Pointer to the item header to insert.*/			 const char          * 	p_c_body)         /* Pointer to the bytes to insert.      */{    struct tree_balance s_ins_balance;    int                 retval;    init_tb_struct(th, &s_ins_balance, th->t_super, p_s_path, IH_SIZE + ih_item_len(p_s_ih));    /*    if (p_c_body == 0)      n_zeros_num = ih_item_len(p_s_ih);    */    //    le_key2cpu_key (&key, &(p_s_ih->ih_key));    while ( (retval = fix_nodes(M_INSERT, &s_ins_balance, p_s_ih, p_c_body)) == REPEAT_SEARCH) {	/* file system changed while we were in the fix_nodes */	retval = search_item (th->t_supe

⌨️ 快捷键说明

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