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

📄 bitmap.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
				   -Hans */free_and_return:	for ( ; block_list_start != free_blocknrs; block_list_start++) {	  reiserfs_free_block (th, *block_list_start);	  *block_list_start = 0;	}	if (for_prealloc) 	    return NO_MORE_UNUSED_CONTIGUOUS_BLOCKS;	else	    return NO_DISK_SPACE;      }    }        /* i and j now contain the results of the search. i = bitmap block       number containing free block, j = offset in this block.  we       compute the blocknr which is our result, store it in       free_blocknrs, and increment the pointer so that on the next       loop we will insert into the next location in the array.  Also       in preparation for the next loop, search_start is changed so       that the next search will not rescan the same range but will       start where this search finished.  Note that while it is       possible that schedule has occurred and blocks have been freed       in that range, it is perhaps more important that the blocks       returned be near each other than that they be near their other       neighbors, and it also simplifies and speeds the code this way.  */    /* journal: we need to make sure the block we are giving out is not    ** a log block, horrible things would happen there.    */    new_block = (i * (s->s_blocksize << 3)) + j;     if (for_prealloc && (new_block - 1) != search_start) {      /* preallocated blocks must be contiguous, bail if we didnt find one.      ** this is not a bug.  We want to do the check here, before the      ** bitmap block is prepared, and before we set the bit and log the      ** bitmap.       **      ** If we do the check after this function returns, we have to       ** call reiserfs_free_block for new_block, which would be pure      ** overhead.      **      ** for_prealloc should only be set if the caller can deal with the      ** NO_MORE_UNUSED_CONTIGUOUS_BLOCKS return value.  This can be      ** returned before the disk is actually full      */      goto free_and_return ;    }    search_start = new_block ;    if (search_start >= reiserfs_get_journal_block(s) &&        search_start < (reiserfs_get_journal_block(s) + JOURNAL_BLOCK_COUNT)) {	reiserfs_warning("vs-4130: reiserfs_new_blocknrs: trying to allocate log block %lu\n",			 search_start) ;	search_start++ ;	amount_needed++ ;	continue ;    }           reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[i], 1) ;    RFALSE( buffer_locked (SB_AP_BITMAP (s)[i]) || 	    is_reusable (s, search_start, 0) == 0,	    "vs-4140: bitmap block is locked or bad block number found");    /* if this bit was already set, we've scheduled, and someone else    ** has allocated it.  loop around and try again    */    if (reiserfs_test_and_set_le_bit (j, SB_AP_BITMAP (s)[i]->b_data)) {	reiserfs_restore_prepared_buffer(s, SB_AP_BITMAP(s)[i]) ;	amount_needed++ ;	continue ;    }        journal_mark_dirty (th, s, SB_AP_BITMAP (s)[i]);     *free_blocknrs = search_start ;    free_blocknrs ++;  }  reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;  /* update free block count in super block */  PUT_SB_FREE_BLOCKS( s, SB_FREE_BLOCKS(s) - init_amount_needed );  journal_mark_dirty (th, s, SB_BUFFER_WITH_SB (s));  s->s_dirt = 1;  return CARRY_ON;}// this is called only by get_empty_nodesint reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th, unsigned long * free_blocknrs,			    unsigned long search_start, int amount_needed) {  return do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, amount_needed, 0/*priority*/, 0/*for_formatted*/, 0/*for_prealloc */) ;}// called by get_new_buffer and by reiserfs_get_block with amount_needed == 1int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle *th, unsigned long * free_blocknrs,			      unsigned long search_start) {  return do_reiserfs_new_blocknrs(th, free_blocknrs, search_start,                                   1/*amount_needed*/,				  0/*priority*/, 				  1/*for formatted*/,				  0/*for prealloc */) ;}#ifdef REISERFS_PREALLOCATE/* ** We pre-allocate 8 blocks.  Pre-allocation is used for files > 16 KB only.** This lowers fragmentation on large files by grabbing a contiguous set of** blocks at once.  It also limits the number of times the bitmap block is** logged by making X number of allocation changes in a single transaction.**** We are using a border to divide the disk into two parts.  The first part** is used for tree blocks, which have a very high turnover rate (they** are constantly allocated then freed)**** The second part of the disk is for the unformatted nodes of larger files.** Putting them away from the tree blocks lowers fragmentation, and makes** it easier to group files together.  There are a number of different** allocation schemes being tried right now, each is documented below.**** A great deal of the allocator's speed comes because reiserfs_get_block** sends us the block number of the last unformatted node in the file.  Once** a given block is allocated past the border, we don't collide with the** blocks near the search_start again.** */int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th, 				struct inode       * p_s_inode,				unsigned long      * free_blocknrs,				unsigned long        search_start){  int ret=0, blks_gotten=0;  unsigned long border = 0;  unsigned long bstart = 0;  unsigned long hash_in, hash_out;  unsigned long saved_search_start=search_start;  int allocated[PREALLOCATION_SIZE];  int blks;  if (!reiserfs_no_border(th->t_super)) {    /* we default to having the border at the 10% mark of the disk.  This    ** is an arbitrary decision and it needs tuning.  It also needs a limit    ** to prevent it from taking too much space on huge drives.    */    bstart = (SB_BLOCK_COUNT(th->t_super) / 10);   }  if (!reiserfs_no_unhashed_relocation(th->t_super)) {    /* this is a very simple first attempt at preventing too much grouping    ** around the border value.  Since k_dir_id is never larger than the    ** highest allocated oid, it is far from perfect, and files will tend    ** to be grouped towards the start of the border    */    border = le32_to_cpu(INODE_PKEY(p_s_inode)->k_dir_id) % (SB_BLOCK_COUNT(th->t_super) - bstart - 1) ;  } else if (!reiserfs_hashed_relocation(th->t_super)) {      hash_in = le32_to_cpu((INODE_PKEY(p_s_inode))->k_dir_id);				/* I wonder if the CPU cost of the                                   hash will obscure the layout                                   effect? Of course, whether that                                   effect is good or bad we don't                                   know.... :-) */            hash_out = keyed_hash(((char *) (&hash_in)), 4);      border = hash_out % (SB_BLOCK_COUNT(th->t_super) - bstart - 1) ;  }  border += bstart ;  allocated[0] = 0 ; /* important.  Allows a check later on to see if at                      * least one block was allocated.  This prevents false		      * no disk space returns		      */  if ( (p_s_inode->i_size < 4 * 4096) ||        !(S_ISREG(p_s_inode->i_mode)) )    {      if ( search_start < border 	   || (				/* allow us to test whether it is a                                   good idea to prevent files from                                   getting too far away from their                                   packing locality by some unexpected                                   means.  This might be poor code for                                   directories whose files total                                   larger than 1/10th of the disk, and                                   it might be good code for                                   suffering from old insertions when the disk                                   was almost full. */               /* changed from !reiserfs_test3(th->t_super), which doesn't               ** seem like a good idea.  Think about adding blocks to               ** a large file.  If you've allocated 10% of the disk               ** in contiguous blocks, you start over at the border value               ** for every new allocation.  This throws away all the               ** information sent in about the last block that was allocated               ** in the file.  Not a good general case at all.               ** -chris               */	       reiserfs_test4(th->t_super) && 	       (search_start > border + (SB_BLOCK_COUNT(th->t_super) / 10))	       )	   )	search_start=border;        ret = do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, 				     1/*amount_needed*/, 				     0/*use reserved blocks for root */,				     1/*for_formatted*/,				     0/*for prealloc */) ;        return ret;    }  /* take a block off the prealloc list and return it -Hans */  if (p_s_inode->u.reiserfs_i.i_prealloc_count > 0) {    p_s_inode->u.reiserfs_i.i_prealloc_count--;    *free_blocknrs = p_s_inode->u.reiserfs_i.i_prealloc_block++;    /* if no more preallocated blocks, remove inode from list */    if (! p_s_inode->u.reiserfs_i.i_prealloc_count) {      list_del(&p_s_inode->u.reiserfs_i.i_prealloc_list);    }        return ret;  }				/* else get a new preallocation for the file */  reiserfs_discard_prealloc (th, p_s_inode);  /* this uses the last preallocated block as the search_start.  discard  ** prealloc does not zero out this number.  */  if (search_start <= p_s_inode->u.reiserfs_i.i_prealloc_block) {    search_start = p_s_inode->u.reiserfs_i.i_prealloc_block;  }    /* doing the compare again forces search_start to be >= the border,  ** even if the file already had prealloction done.  This seems extra,  ** and should probably be removed  */  if ( search_start < border ) search_start=border;   /* If the disk free space is already below 10% we should   ** start looking for the free blocks from the beginning   ** of the partition, before the border line.  */  if ( SB_FREE_BLOCKS(th->t_super) <= (SB_BLOCK_COUNT(th->t_super) / 10) ) {    search_start=saved_search_start;  }  *free_blocknrs = 0;  blks = PREALLOCATION_SIZE-1;  for (blks_gotten=0; blks_gotten<PREALLOCATION_SIZE; blks_gotten++) {    ret = do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, 				   1/*amount_needed*/, 				   0/*for root reserved*/,				   1/*for_formatted*/,				   (blks_gotten > 0)/*must_be_contiguous*/) ;    /* if we didn't find a block this time, adjust blks to reflect    ** the actual number of blocks allocated    */     if (ret != CARRY_ON) {      blks = blks_gotten > 0 ? (blks_gotten - 1) : 0 ;      break ;    }    allocated[blks_gotten]= *free_blocknrs;#ifdef CONFIG_REISERFS_CHECK    if ( (blks_gotten>0) && (allocated[blks_gotten] - allocated[blks_gotten-1]) != 1 ) {      /* this should be caught by new_blocknrs now, checking code */      reiserfs_warning("yura-1, reiserfs_new_unf_blocknrs2: pre-allocated not contiguous set of blocks!\n") ;      reiserfs_free_block(th, allocated[blks_gotten]);      blks = blks_gotten-1;       break;    }#endif    if (blks_gotten==0) {      p_s_inode->u.reiserfs_i.i_prealloc_block = *free_blocknrs;    }    search_start = *free_blocknrs;     *free_blocknrs = 0;  }  p_s_inode->u.reiserfs_i.i_prealloc_count = blks;  *free_blocknrs = p_s_inode->u.reiserfs_i.i_prealloc_block;  p_s_inode->u.reiserfs_i.i_prealloc_block++;  /* if inode has preallocated blocks, link him to list */  if (p_s_inode->u.reiserfs_i.i_prealloc_count) {    list_add(&p_s_inode->u.reiserfs_i.i_prealloc_list,	     &SB_JOURNAL(th->t_super)->j_prealloc_list);  }   /* we did actually manage to get 1 block */  if (ret != CARRY_ON && allocated[0] > 0) {    return CARRY_ON ;  }  /* NO_MORE_UNUSED_CONTIGUOUS_BLOCKS should only mean something to  ** the preallocation code.  The rest of the filesystem asks for a block  ** and should either get it, or know the disk is full.  The code  ** above should never allow ret == NO_MORE_UNUSED_CONTIGUOUS_BLOCK,  ** as it doesn't send for_prealloc = 1 to do_reiserfs_new_blocknrs  ** unless it has already successfully allocated at least one block.  ** Just in case, we translate into a return value the rest of the  ** filesystem can understand.  **  ** It is an error to change this without making the  ** rest of the filesystem understand NO_MORE_UNUSED_CONTIGUOUS_BLOCKS  ** If you consider it a bug to return NO_DISK_SPACE here, fix the rest  ** of the fs first.  */  if (ret == NO_MORE_UNUSED_CONTIGUOUS_BLOCKS) {#ifdef CONFIG_REISERFS_CHECK    reiserfs_warning("reiser-2015: this shouldn't happen, may cause false out of disk space error");#endif     return NO_DISK_SPACE;   }  return ret;}//// a portion of this function, was derived from minix or ext2's// analog. You should be able to tell which portion by looking at the// ext2 code and comparing. static void __discard_prealloc (struct reiserfs_transaction_handle * th,				struct inode * inode){  unsigned long save = inode->u.reiserfs_i.i_prealloc_block ;  while (inode->u.reiserfs_i.i_prealloc_count > 0) {    reiserfs_free_prealloc_block(th,inode->u.reiserfs_i.i_prealloc_block);    inode->u.reiserfs_i.i_prealloc_block++;    inode->u.reiserfs_i.i_prealloc_count --;  }  inode->u.reiserfs_i.i_prealloc_block = save ;   list_del (&(inode->u.reiserfs_i.i_prealloc_list));}void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th, 				struct inode * inode){#ifdef CONFIG_REISERFS_CHECK  if (inode->u.reiserfs_i.i_prealloc_count < 0)     reiserfs_warning("zam-4001:" __FUNCTION__ ": inode has negative prealloc blocks count.\n");#endif      if (inode->u.reiserfs_i.i_prealloc_count > 0) {    __discard_prealloc(th, inode);  }      }void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th){  struct list_head * plist = &SB_JOURNAL(th->t_super)->j_prealloc_list;  struct inode * inode;    while (!list_empty(plist)) {    inode = list_entry(plist->next, struct inode, u.reiserfs_i.i_prealloc_list);#ifdef CONFIG_REISERFS_CHECK    if (!inode->u.reiserfs_i.i_prealloc_count) {      reiserfs_warning("zam-4001:" __FUNCTION__ ": inode is in prealloc list but has no preallocated blocks.\n");    }#endif        __discard_prealloc(th, inode);    }}#endif

⌨️ 快捷键说明

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