示例#1
0
/* may free b */
static int merge_bb(struct backed_block_list *bbl,
    struct backed_block *a, struct backed_block *b)
{
  unsigned int block_len;

  /* Block doesn't exist (possible if one block is the last block) */
  if (!a || !b) {
    return -EINVAL;
  }

  assert(a->block < b->block);

  /* Blocks are of different types */
  if (a->type != b->type) {
    return -EINVAL;
  }

  /* Blocks are not adjacent */
  block_len = a->len / bbl->block_size; /* rounds down */
  if (a->block + block_len != b->block) {
    return -EINVAL;
  }

  switch (a->type) {
  case BACKED_BLOCK_DATA:
    /* Don't support merging data for now */
    return -EINVAL;
  case BACKED_BLOCK_FILL:
    if (a->fill.val != b->fill.val) {
      return -EINVAL;
    }
    break;
  case BACKED_BLOCK_FILE:
    /* Already make sure b->type is BACKED_BLOCK_FILE */
    if (strcmp(a->file.filename, b->file.filename) ||
        a->file.offset + a->len != b->file.offset) {
      return -EINVAL;
    }
    break;
  case BACKED_BLOCK_FD:
    if (a->fd.fd != b->fd.fd ||
        a->fd.offset + a->len != b->fd.offset) {
      return -EINVAL;
    }
    break;
  }

  /* Blocks are compatible and adjacent, with a before b.  Merge b into a,
   * and free b */
  a->len += b->len;
  a->next = b->next;

  backed_block_destroy(b);

  return 0;
}
void backed_block_list_destroy(struct backed_block_list *bbl)
{
	if (bbl->data_blocks) {
		struct backed_block *bb = bbl->data_blocks;
		while (bb) {
			struct backed_block *next = bb->next;
			backed_block_destroy(bb);
			bb = next;
		}
	}

	free(bbl);
}