Example #1
0
/* Free any zones in NODE greater than or equal to END that are rooted
   in the block of indirection contained in the zone *P; OFFSET should
   be the zone position that *P corresponds to.  For each zone pointer
   in *P that should be freed, FREE_ZONE is called with a pointer to
   the entry for that zone, and the index of the entry within *P.  If
   every zone in *P is freed, then *P is set to 0, otherwise it is
   left alone.  */
static void
trunc_indirect_V1 (struct node *node, uint16_t end,
   uint16_t *p, uint16_t offset,
   void (*free_zone)(uint16_t *p,
     unsigned index),
   struct free_zone_run *fzr)
{
  if (*p)
    {
      unsigned index;
      int modified = 0, all_freed = 1;
      uint16_t *ind_bh = (uint16_t *) zptr ((zone_t) *p);
      unsigned first = end < offset ? 0 : end - offset;

      /* XXX only the first block in a zone does contain pointers */
      for (index = first; index < ADDR_PER_BLOCK; index++)
if (ind_bh[index])
  {
    (*free_zone)(ind_bh + index, index);
    if (ind_bh[index])
      all_freed = 0;/* Some descendent hasn't been freed.  */
    else
      modified = 1;
  }

      if (first == 0 && all_freed)
{
  pager_flush_some (diskfs_disk_pager, zoffs ((zone_t) *p),
    zone_size, 1);
  free_zone_run_free_ptr (fzr, (zone_t *) p);
}
      else if (modified)
record_indir_poke (node, (char *) ind_bh);
    }
}
Example #2
0
/* Free any blocks in NODE greater than or equal to END that are rooted in
   the indirect block *P; OFFSET should be the block position that *P
   corresponds to.  For each block pointer in *P that should be freed,
   FREE_BLOCK is called with a pointer to the entry for that block, and the
   index of the entry within *P.  If every block in *P is freed, then *P is
   set to 0, otherwise it is left alone.  */
static void
trunc_indirect (struct node *node, block_t end,
		block_t *p, block_t offset,
		void (*free_block)(block_t *p, unsigned index),
		struct free_block_run *fbr)
{
  if (*p)
    {
      unsigned index;
      int modified = 0, all_freed = 1;
      block_t *ind_bh = (block_t *) disk_cache_block_ref (*p);
      unsigned first = end < offset ? 0 : end - offset;

      for (index = first; index < addr_per_block; index++)
	if (ind_bh[index])
	  {
	    (*free_block)(ind_bh + index, index);
	    if (ind_bh[index])
	      all_freed = 0;	/* Some descendent hasn't been freed.  */
	    else
	      modified = 1;
	  }

      if (first == 0 && all_freed)
	{
	  pager_flush_some (diskfs_disk_pager,
			    bptr_index (ind_bh) << log2_block_size,
			    block_size, 1);
	  free_block_run_free_ptr (fbr, p);
	  disk_cache_block_deref (ind_bh);
	}
      else if (modified)
	record_indir_poke (node, ind_bh);
      else
	disk_cache_block_deref (ind_bh);
    }
}