summaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_actlog.c
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2011-07-05 20:59:26 +0200
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 16:57:51 +0100
commitd5d7ebd42250620a6da2a8f6943c024391433488 (patch)
tree1025faf28644b437a845f21606a1c2db83b54a3c /drivers/block/drbd/drbd_actlog.c
parentcdfda633d235028e9b27381dedb65416409e8729 (diff)
downloadop-kernel-dev-d5d7ebd42250620a6da2a8f6943c024391433488.zip
op-kernel-dev-d5d7ebd42250620a6da2a8f6943c024391433488.tar.gz
drbd: on attach, enforce clean meta data
Detection of unclean shutdown has moved into user space. The kernel code will, whenever it updates the meta data, mark it as "unclean", and will refuse to attach to such unclean meta data. "drbdadm up" now schedules "drbdmeta apply-al", which will apply the activity log to the bitmap, and/or reinitialize it, if necessary, as well as set a "clean" indicator flag. This moves a bit code out of kernel space. As a side effect, it also prevents some 8.3 module from accidentally ignoring the 8.4 style activity log, if someone should downgrade, whether on purpose, or accidentally because he changed kernel versions without providing an 8.4 for the new kernel, and the new kernel comes with in-tree 8.3. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_actlog.c')
-rw-r--r--drivers/block/drbd/drbd_actlog.c259
1 files changed, 0 insertions, 259 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 58b5b61..da8ffd5 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -462,265 +462,6 @@ w_al_write_transaction(struct drbd_work *w, int unused)
return 0;
}
-/* FIXME
- * reading of the activity log,
- * and potentially dirtying of the affected bitmap regions,
- * should be done from userland only.
- * DRBD would simply always attach with an empty activity log,
- * and refuse to attach to something that looks like a crashed primary.
- */
-
-/**
- * drbd_al_read_tr() - Read a single transaction from the on disk activity log
- * @mdev: DRBD device.
- * @bdev: Block device to read form.
- * @b: pointer to an al_transaction.
- * @index: On disk slot of the transaction to read.
- *
- * Returns -1 on IO error, 0 on checksum error and 1 upon success.
- */
-static int drbd_al_read_tr(struct drbd_conf *mdev,
- struct drbd_backing_dev *bdev,
- int index)
-{
- struct al_transaction_on_disk *b = page_address(mdev->md_io_page);
- sector_t sector;
- u32 crc;
-
- sector = bdev->md.md_offset
- + bdev->md.al_offset
- + index * (MD_BLOCK_SIZE>>9);
-
- /* Dont process error normally,
- * as this is done before disk is attached! */
- if (drbd_md_sync_page_io(mdev, bdev, sector, READ))
- return -1;
-
- if (!expect(b->magic == cpu_to_be32(DRBD_AL_MAGIC)))
- return 0;
-
- if (!expect(be16_to_cpu(b->n_updates) <= AL_UPDATES_PER_TRANSACTION))
- return 0;
-
- if (!expect(be16_to_cpu(b->context_size) <= DRBD_AL_EXTENTS_MAX))
- return 0;
-
- if (!expect(be16_to_cpu(b->context_start_slot_nr) < DRBD_AL_EXTENTS_MAX))
- return 0;
-
- crc = be32_to_cpu(b->crc32c);
- b->crc32c = 0;
- if (!expect(crc == crc32c(0, b, 4096)))
- return 0;
-
- return 1;
-}
-
-/**
- * drbd_al_read_log() - Restores the activity log from its on disk representation.
- * @mdev: DRBD device.
- * @bdev: Block device to read form.
- *
- * Returns 1 on success, returns 0 when reading the log failed due to IO errors.
- */
-int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
-{
- struct al_transaction_on_disk *b;
- int i;
- int rv;
- int mx;
- int active_extents = 0;
- int transactions = 0;
- int found_valid = 0;
- int found_initialized = 0;
- int from = 0;
- int to = 0;
- u32 from_tnr = 0;
- u32 to_tnr = 0;
- u32 cnr;
-
- /* Note that this is expected to be called with a newly created,
- * clean and all unused activity log of the "expected size".
- */
-
- /* lock out all other meta data io for now,
- * and make sure the page is mapped.
- */
- b = drbd_md_get_buffer(mdev);
- if (!b)
- return 0;
-
- /* Always use the full ringbuffer space for now.
- * possible optimization: read in all of it,
- * then scan the in-memory pages. */
-
- mx = (MD_AL_SECTORS*512/MD_BLOCK_SIZE);
-
- /* Find the valid transaction in the log */
- for (i = 0; i < mx; i++) {
- rv = drbd_al_read_tr(mdev, bdev, i);
- /* invalid data in that block */
- if (rv == 0)
- continue;
- if (be16_to_cpu(b->transaction_type) == AL_TR_INITIALIZED) {
- ++found_initialized;
- continue;
- }
-
- /* IO error */
- if (rv == -1) {
- drbd_md_put_buffer(mdev);
- return 0;
- }
-
- cnr = be32_to_cpu(b->tr_number);
- if (++found_valid == 1) {
- from = i;
- to = i;
- from_tnr = cnr;
- to_tnr = cnr;
- continue;
- }
-
- D_ASSERT(cnr != to_tnr);
- D_ASSERT(cnr != from_tnr);
- if ((int)cnr - (int)from_tnr < 0) {
- D_ASSERT(from_tnr - cnr + i - from == mx);
- from = i;
- from_tnr = cnr;
- }
- if ((int)cnr - (int)to_tnr > 0) {
- D_ASSERT(cnr - to_tnr == i - to);
- to = i;
- to_tnr = cnr;
- }
- }
-
- if (!found_valid) {
- if (found_initialized != mx)
- dev_warn(DEV, "No usable activity log found.\n");
- drbd_md_put_buffer(mdev);
- return 1;
- }
-
- /* Read the valid transactions.
- * dev_info(DEV, "Reading from %d to %d.\n",from,to); */
- i = from;
- while (1) {
- struct lc_element *e;
- unsigned j, n, slot, extent_nr;
-
- rv = drbd_al_read_tr(mdev, bdev, i);
- if (!expect(rv != 0))
- goto cancel;
- if (rv == -1) {
- drbd_md_put_buffer(mdev);
- return 0;
- }
-
- /* deal with different transaction types.
- * not yet implemented */
- if (!expect(b->transaction_type == 0))
- goto cancel;
-
- /* on the fly re-create/resize activity log?
- * will be a special transaction type flag. */
- if (!expect(be16_to_cpu(b->context_size) == mdev->act_log->nr_elements))
- goto cancel;
- if (!expect(be16_to_cpu(b->context_start_slot_nr) < mdev->act_log->nr_elements))
- goto cancel;
-
- /* We are the only user of the activity log right now,
- * don't actually need to take that lock. */
- spin_lock_irq(&mdev->al_lock);
-
- /* first, apply the context, ... */
- for (j = 0, slot = be16_to_cpu(b->context_start_slot_nr);
- j < AL_CONTEXT_PER_TRANSACTION &&
- slot < mdev->act_log->nr_elements; j++, slot++) {
- extent_nr = be32_to_cpu(b->context[j]);
- e = lc_element_by_index(mdev->act_log, slot);
- if (e->lc_number != extent_nr) {
- if (extent_nr != LC_FREE)
- active_extents++;
- else
- active_extents--;
- }
- lc_set(mdev->act_log, extent_nr, slot);
- }
-
- /* ... then apply the updates,
- * which override the context information.
- * drbd_al_read_tr already did the rangecheck
- * on n <= AL_UPDATES_PER_TRANSACTION */
- n = be16_to_cpu(b->n_updates);
- for (j = 0; j < n; j++) {
- slot = be16_to_cpu(b->update_slot_nr[j]);
- extent_nr = be32_to_cpu(b->update_extent_nr[j]);
- if (!expect(slot < mdev->act_log->nr_elements))
- break;
- e = lc_element_by_index(mdev->act_log, slot);
- if (e->lc_number != extent_nr) {
- if (extent_nr != LC_FREE)
- active_extents++;
- else
- active_extents--;
- }
- lc_set(mdev->act_log, extent_nr, slot);
- }
- spin_unlock_irq(&mdev->al_lock);
-
- transactions++;
-
-cancel:
- if (i == to)
- break;
- i++;
- if (i >= mx)
- i = 0;
- }
-
- mdev->al_tr_number = to_tnr+1;
- mdev->al_tr_pos = (to + 1) % (MD_AL_SECTORS*512/MD_BLOCK_SIZE);
-
- /* ok, we are done with it */
- drbd_md_put_buffer(mdev);
-
- dev_info(DEV, "Found %d transactions (%d active extents) in activity log.\n",
- transactions, active_extents);
-
- return 1;
-}
-
-/**
- * drbd_al_apply_to_bm() - Sets the bitmap to dirty(1) where covered by active AL extents
- * @mdev: DRBD device.
- */
-void drbd_al_apply_to_bm(struct drbd_conf *mdev)
-{
- unsigned int enr;
- unsigned long add = 0;
- char ppb[10];
- int i, tmp;
-
- wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
-
- for (i = 0; i < mdev->act_log->nr_elements; i++) {
- enr = lc_element_by_index(mdev->act_log, i)->lc_number;
- if (enr == LC_FREE)
- continue;
- tmp = drbd_bm_ALe_set_all(mdev, enr);
- dynamic_dev_dbg(DEV, "AL: set %d bits in extent %u\n", tmp, enr);
- add += tmp;
- }
-
- lc_unlock(mdev->act_log);
- wake_up(&mdev->al_wait);
-
- dev_info(DEV, "Marked additional %s as out-of-sync based on AL.\n",
- ppsize(ppb, Bit2KB(add)));
-}
-
static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext)
{
int rv;
OpenPOWER on IntegriCloud