+ c = EXT2FS_B2C(fs, blockcnt);
+ if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr)))
+ is_meta = 1;
+
+ if (((blockcnt > 0) && c == cs->dup_cluster) ||
+ ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) {
+ n = dict_lookup(&clstr_dict,
+ INT_TO_VOIDPTR(EXT2FS_B2C(fs, *block_nr)));
+ if (!n) {
+ com_err("clone_file_block", 0,
+ _("internal error: can't find dup_blk for %llu\n"),
+ *block_nr);
+ return 0;
+ }
+
+ p = (struct dup_cluster *) dnode_get(n);
+ if (!is_meta)
+ decrement_badcount(ctx, *block_nr, p);
+
+ if (p->num_bad == 0 && !is_meta) {
+ /*
+ * Normally num_bad never gets to zero; but in
+ * the case of bigalloc file systems, we don't
+ * how many blocks might be in use by a
+ * particular inode. So we may end up
+ * relocating the cluster even though this
+ * inode is the last user of the cluster. In
+ * that case, since we've already moved some
+ * of the blocks of that cluster, we'll
+ * complete the relocation and free the
+ * original cluster here.
+ */
+ ext2fs_unmark_block_bitmap2(ctx->block_found_map,
+ *block_nr);
+ ext2fs_block_alloc_stats2(fs, *block_nr, -1);
+ }
+
+ if ((blockcnt > 0) && c == cs->dup_cluster) {
+ new_block = cs->alloc_block;
+ goto got_block;
+ }
+ cs->dup_cluster = c;
+
+ retval = ext2fs_new_block2(fs, 0, ctx->block_found_map,
+ &new_block);
+ if (retval) {
+ cs->errcode = retval;
+ return BLOCK_ABORT;
+ }
+ cs->alloc_block = new_block;
+
+ got_block:
+ new_block &= ~EXT2FS_CLUSTER_MASK(fs);
+ new_block += EXT2FS_CLUSTER_MASK(fs) & blockcnt;
+ if (cs->dir && (blockcnt >= 0)) {
+ retval = ext2fs_set_dir_block2(fs->dblist,
+ cs->dir, new_block, blockcnt);