static int clone_file_block(ext2_filsys fs,
			    blk64_t	*block_nr,
			    e2_blkcnt_t blockcnt,
			    blk64_t ref_block EXT2FS_ATTR((unused)),
			    int ref_offset EXT2FS_ATTR((unused)),
			    void *priv_data)
{
	struct dup_cluster *p = NULL;
	blk64_t	new_block;
	errcode_t	retval;
	struct clone_struct *cs = (struct clone_struct *) priv_data;
	dnode_t *n;
	e2fsck_t ctx;
	blk64_t c;
	int is_meta = 0;
	int should_write = 1;

	ctx = cs->ctx;
	deferred_dec_badcount(cs);

	if (*block_nr == 0)
		return 0;

	if (ext2fs_has_feature_shared_blocks(ctx->fs->super) &&
	    (ctx->options & E2F_OPT_UNSHARE_BLOCKS) &&
	    (ctx->options & E2F_OPT_NO))
		should_write = 0;

	c = EXT2FS_B2C(fs, blockcnt);
	if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr)))
		is_meta = 1;

	if (c == cs->dup_cluster && cs->alloc_block) {
		new_block = cs->alloc_block;
		goto got_block;
	}

	if (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);

		cs->dup_cluster = c;
		/*
		 * Let's try an implied cluster allocation.  If we get the same
		 * cluster back, then we need to find a new block; otherwise,
		 * we're merely fixing the problem of one logical cluster being
		 * mapped to multiple physical clusters.
		 */
		new_block = 0;
		retval = ext2fs_map_cluster_block(fs, cs->ino,
						  EXT2_INODE(cs->inode),
						  blockcnt, &new_block);
		if (retval == 0 && new_block != 0 &&
		    EXT2FS_B2C(ctx->fs, new_block) !=
		    EXT2FS_B2C(ctx->fs, *block_nr))
			goto cluster_alloc_ok;
		retval = ext2fs_new_block2(fs, 0, ctx->block_found_map,
					   &new_block);
		if (retval) {
			cs->errcode = retval;
			return BLOCK_ABORT;
		}
		if (ext2fs_has_feature_shared_blocks(fs->super)) {
			/*
			 * Update the block stats so we don't get a prompt to fix block
			 * counts in the final pass.
			 */
			ext2fs_block_alloc_stats2(fs, new_block, +1);
		}
cluster_alloc_ok:
		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);
			if (retval) {
				cs->errcode = retval;
				return BLOCK_ABORT;
			}
		}
#if 0
 		printf("Cloning block #%lld from %llu to %llu\n",
		       blockcnt, *block_nr, new_block);
#endif
		retval = io_channel_read_blk64(fs->io, *block_nr, 1, cs->buf);
		if (retval) {
			cs->errcode = retval;
			return BLOCK_ABORT;
		}
		if (should_write) {
			retval = io_channel_write_blk64(fs->io, new_block, 1, cs->buf);
			if (retval) {
				cs->errcode = retval;
				return BLOCK_ABORT;
			}
		}
		cs->save_dup_cluster = (is_meta ? NULL : p);
		cs->save_blocknr = *block_nr;
		*block_nr = new_block;
		ext2fs_mark_block_bitmap2(ctx->block_found_map, new_block);
		ext2fs_mark_block_bitmap2(fs->block_map, new_block);

		if (!should_write) {
			/* Don't try to change extent information; we want e2fsck to
			 * return success.
			 */
			return 0;
		}
		return BLOCK_CHANGED;
	}
	return 0;
}