func: uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
  
      int *num)
  
  {
  
      BDRVQcowState *s = bs->opaque;
  
      int l1_index, l2_index;
  
      uint64_t l2_offset, *l2_table, cluster_offset;
  
      int l1_bits, c;
  
      int index_in_cluster, nb_available, nb_needed, nb_clusters;
  
  
  
      index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1);
  
      nb_needed = *num + index_in_cluster;
  
  
  
      l1_bits = s->l2_bits + s->cluster_bits;
  
  
  
      /* compute how many bytes there are between the offset and
  
       * the end of the l1 entry
  
       */
  
  
  
      nb_available = (1 << l1_bits) - (offset & ((1 << l1_bits) - 1));
  
  
  
      /* compute the number of available sectors */
  
  
  
      nb_available = (nb_available >> 9) + index_in_cluster;
  
  
  
      if (nb_needed > nb_available) {
  
          nb_needed = nb_available;
  
      }
  
  
  
      cluster_offset = 0;
  
  
  
      /* seek the the l2 offset in the l1 table */
  
  
  
      l1_index = offset >> l1_bits;
  
      if (l1_index >= s->l1_size)
  
          goto out;
  
  
  
      l2_offset = s->l1_table[l1_index];
  
  
  
      /* seek the l2 table of the given l2 offset */
  
  
  
      if (!l2_offset)
  
          goto out;
  
  
  
      /* load the l2 table in memory */
  
  
  
      l2_offset &= ~QCOW_OFLAG_COPIED;
  
      l2_table = l2_load(bs, l2_offset);
  
      if (l2_table == NULL)
  
          return 0;
  
  
  
      /* find the cluster offset for the given disk offset */
  
  
  
      l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
  
      cluster_offset = be64_to_cpu(l2_table[l2_index]);
  
      nb_clusters = size_to_clusters(s, nb_needed << 9);
  
  
  
      if (!cluster_offset) {
  
          /* how many empty clusters ? */
  
          c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
  
      } else {
  
          /* how many allocated clusters ? */
  
          c = count_contiguous_clusters(nb_clusters, s->cluster_size,
  
                  &l2_table[l2_index], 0, QCOW_OFLAG_COPIED);
  
      }
  
  
  
     nb_available = (c * s->cluster_sectors);
  
  out:
  
      if (nb_available > nb_needed)
  
          nb_available = nb_needed;
  
  
  
      *num = nb_available - index_in_cluster;
  
  
  
      return cluster_offset & ~QCOW_OFLAG_COPIED;
  
  }
  