[dm-devel] [PATCH 10/14] dm-multisnap-mikulas-io
Mike Snitzer
snitzer at redhat.com
Tue Mar 2 00:23:54 UTC 2010
From: Mikulas Patocka <mpatocka at redhat.com>
Callbacks from dm-multisnap.c
These functions are called directly from exception-store-neutral code.
The find the chunk or perform chunk reallocations.
Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
---
drivers/md/dm-multisnap-io.c | 209 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 209 insertions(+), 0 deletions(-)
create mode 100644 drivers/md/dm-multisnap-io.c
diff --git a/drivers/md/dm-multisnap-io.c b/drivers/md/dm-multisnap-io.c
new file mode 100644
index 0000000..7620ebe
--- /dev/null
+++ b/drivers/md/dm-multisnap-io.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2009 Red Hat Czech, s.r.o.
+ *
+ * Mikulas Patocka <mpatocka at redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-multisnap-mikulas.h"
+
+/*
+ * This function will check if there is remapping for a given snapid/chunk.
+ * It returns 1 if remapping exists and is read-only (shared by other snapshots)
+ * and 2 if it exists and is read-write (not shared by anyone).
+ */
+int dm_multisnap_find_snapshot_chunk(struct dm_exception_store *s,
+ snapid_t snapid, chunk_t chunk,
+ int write, chunk_t *result)
+{
+ int r;
+ struct bt_key key;
+ mikulas_snapid_t from, to;
+ mikulas_snapid_t find_from, find_to;
+
+ from = dm_multisnap_find_next_subsnapshot(s, snapid);
+ to = snapid;
+
+ key.chunk = chunk;
+ key.snap_from = snapid;
+ key.snap_to = snapid;
+ r = dm_multisnap_find_in_btree(s, &key, result);
+ if (unlikely(r < 0))
+ return r;
+
+ if (!r) {
+ s->query_new_key.chunk = chunk;
+ s->query_new_key.snap_from = from;
+ s->query_new_key.snap_to = to;
+ s->query_active = 1;
+ return 0;
+ }
+
+ if (!write)
+ return 1;
+
+ /*
+ * We are writing to a snapshot --- check if anything outside <from-to>
+ * range exists, if it does, it needs to be copied.
+ */
+ if (key.snap_from < from) {
+ if (likely(dm_multisnap_find_next_snapid_range(s, key.snap_from,
+ &find_from, &find_to))) {
+ if (find_from < from) {
+ s->query_new_key.chunk = chunk;
+ s->query_new_key.snap_from = from;
+ s->query_new_key.snap_to = key.snap_to;
+ s->query_block_from = key.snap_from;
+ s->query_block_to = key.snap_to;
+ s->query_active = 2;
+ return 1;
+ }
+ if (unlikely(find_from > from))
+ BUG(); /* SNAPID not in our tree */
+ } else
+ BUG(); /* we're asking for a SNAPID not in our tree */
+ }
+ if (key.snap_to > to) {
+ if (likely(dm_multisnap_find_next_snapid_range(s, to + 1,
+ &find_from, &find_to))) {
+ if (find_from <= key.snap_to) {
+ s->query_new_key.chunk = chunk;
+ s->query_new_key.snap_from = key.snap_from;
+ s->query_new_key.snap_to = to;
+ s->query_block_from = key.snap_from;
+ s->query_block_to = key.snap_to;
+ s->query_active = 2;
+ return 1;
+ }
+ }
+ }
+ return 2;
+}
+
+/*
+ * Reset the query/remap state machine.
+ */
+void dm_multisnap_reset_query(struct dm_exception_store *s)
+{
+ s->query_active = 0;
+ s->query_snapid = 0;
+}
+
+/*
+ * Find the next snapid range to remap.
+ */
+int dm_multisnap_query_next_remap(struct dm_exception_store *s, chunk_t chunk)
+{
+ int r;
+ chunk_t sink;
+ mikulas_snapid_t from, to;
+
+ s->query_active = 0;
+
+ while (dm_multisnap_find_next_snapid_range(s, s->query_snapid, &from, &to)) {
+ struct bt_key key;
+next_btree_search:
+ if (dm_multisnap_has_error(s->dm))
+ return -1;
+ key.chunk = chunk;
+ key.snap_from = from;
+ key.snap_to = to;
+ r = dm_multisnap_find_in_btree(s, &key, &sink);
+ if (unlikely(r < 0))
+ return -1;
+
+ if (!r) {
+ s->query_new_key.chunk = chunk;
+ s->query_new_key.snap_from = from;
+ s->query_new_key.snap_to = to;
+ s->query_active = 1;
+ return 1;
+ }
+
+ if (key.snap_from > from) {
+ s->query_new_key.chunk = chunk;
+ s->query_new_key.snap_from = from;
+ s->query_new_key.snap_to = key.snap_from - 1;
+ s->query_active = 1;
+ return 1;
+ }
+
+ if (key.snap_to < to) {
+ from = key.snap_to + 1;
+ goto next_btree_search;
+ }
+
+ s->query_snapid = to + 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Perform the remap on the range returned by dm_multisnap_query_next_remap.
+ */
+void dm_multisnap_add_next_remap(struct dm_exception_store *s,
+ union chunk_descriptor *cd, chunk_t *new_chunk)
+{
+ int r;
+
+ BUG_ON(s->query_active != 1);
+ s->query_active = 0;
+
+ cd->range.from = s->query_new_key.snap_from;
+ cd->range.to = s->query_new_key.snap_to;
+
+ r = dm_multisnap_alloc_blocks(s, new_chunk, 1, 0);
+ if (unlikely(r < 0))
+ return;
+
+ dm_multisnap_status_lock(s->dm);
+ s->data_allocated++;
+ dm_multisnap_status_unlock(s->dm);
+
+ dm_multisnap_add_to_btree(s, &s->query_new_key, *new_chunk);
+ dm_multisnap_transition_mark(s);
+}
+
+/*
+ * Make the chunk writeable (i.e. unshare multiple snapshots).
+ */
+void dm_multisnap_make_chunk_writeable(struct dm_exception_store *s,
+ union chunk_descriptor *cd, chunk_t *new_chunk)
+{
+ int r;
+
+ BUG_ON(s->query_active != 2);
+ s->query_active = 0;
+
+ cd->range.from = s->query_block_from;
+ cd->range.to = s->query_block_to;
+
+ r = dm_multisnap_alloc_blocks(s, new_chunk, 1, 0);
+ if (unlikely(r < 0))
+ return;
+
+ dm_multisnap_status_lock(s->dm);
+ s->data_allocated++;
+ dm_multisnap_status_unlock(s->dm);
+
+ dm_multisnap_restrict_btree_entry(s, &s->query_new_key);
+ dm_multisnap_transition_mark(s);
+
+ if (unlikely(dm_multisnap_has_error(s->dm)))
+ return;
+
+ dm_multisnap_add_to_btree(s, &s->query_new_key, *new_chunk);
+ dm_multisnap_transition_mark(s);
+}
+
+/*
+ * Check if the snapshot belongs to the remap range specified by "cd".
+ */
+int dm_multisnap_check_conflict(struct dm_exception_store *s,
+ union chunk_descriptor *cd, snapid_t snapid)
+{
+ return snapid >= cd->range.from && snapid <= cd->range.to;
+}
+
--
1.6.5.2
More information about the dm-devel
mailing list