/* Possible return values and states of snap_src and snap_dest. 0: NULL, NULL - first new snapshot 1: snap_src, NULL - normal snapshot 2: snap_src, snap_dest - waiting for handover 2: snap_src, NULL - handed over, waiting for old to be deleted 1: NULL, snap_dest - source got destroyed without handover  */
static int __find_snapshots_sharing_cow(struct dm_snapshot *snap, struct dm_snapshot **snap_src, struct dm_snapshot **snap_dest, struct dm_snapshot **snap_merge)
/* Possible return values and states of snap_src and snap_dest. 0: NULL, NULL - first new snapshot 1: snap_src, NULL - normal snapshot 2: snap_src, snap_dest - waiting for handover 2: snap_src, NULL - handed over, waiting for old to be deleted 1: NULL, snap_dest - source got destroyed without handover  */
static int __find_snapshots_sharing_cow(struct dm_snapshot *snap, struct dm_snapshot **snap_src, struct dm_snapshot **snap_dest, struct dm_snapshot **snap_merge)
{
	struct dm_snapshot *s;
	struct origin *o;
	int count = 0;
	int active;
	o = __lookup_origin(snap->origin->bdev);
	if (!o)
		goto out;
	list_for_each_entry(s, &o->snapshots, list) {
		if (dm_target_is_snapshot_merge(s->ti) && snap_merge)
			*snap_merge = s;
		if (!bdev_equal(s->cow->bdev, snap->cow->bdev))
			continue;
		down_read(&s->lock);
		active = s->active;
		up_read(&s->lock);
		if (active) {
			if (snap_src)
				*snap_src = s;
		} else if (snap_dest)
			*snap_dest = s;
		count++;
	}
out:
	return count;
}