From 7196790b998cb21cff064cea965dc5aa953036a1 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Thu, 3 Oct 2024 17:54:07 +0200 Subject: [PATCH] librbd/crypto/LoadRequest: clone format for migration source image Migration source and migration target images naturally have the same encryption format, but the user shouldn't have to need to specify it for the image that they can't even immediately see -- migration source image gets moved to the RBD trash to avoid mistaken usage while migration is in progress. Fixes: https://tracker.ceph.com/issues/63184 Signed-off-by: Ilya Dryomov (cherry picked from commit 7b2085daad168d3d0e6357cd34979f91ecdc8486) --- qa/workunits/rbd/luks-encryption.sh | 91 +++++++++++++++++++++++++++-- src/librbd/crypto/LoadRequest.cc | 12 +++- 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/qa/workunits/rbd/luks-encryption.sh b/qa/workunits/rbd/luks-encryption.sh index 97cb5a0fe87..b6305cb46c6 100755 --- a/qa/workunits/rbd/luks-encryption.sh +++ b/qa/workunits/rbd/luks-encryption.sh @@ -2,7 +2,7 @@ set -ex CEPH_ID=${CEPH_ID:-admin} -TMP_FILES="/tmp/passphrase /tmp/passphrase2 /tmp/testdata1 /tmp/testdata2 /tmp/cmpdata /tmp/rawexport /tmp/export.qcow2" +TMP_FILES="/tmp/passphrase /tmp/passphrase1 /tmp/passphrase2 /tmp/testdata1 /tmp/testdata2 /tmp/cmpdata /tmp/rawexport /tmp/export.qcow2" _sudo() { @@ -278,8 +278,7 @@ function test_migration_clone() { rbd migration prepare testimg1 testimg2 # test reading - # FIXME: https://tracker.ceph.com/issues/63184 - LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase) + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase) cmp $LIBRBD_DEV /tmp/cmpdata # trigger copyup for an unwritten area @@ -297,8 +296,7 @@ function test_migration_clone() { _sudo rbd device unmap -t nbd $LIBRBD_DEV # test reading on a fresh mapping - # FIXME: https://tracker.ceph.com/issues/63184 - LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase) + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase) cmp $LIBRBD_DEV /tmp/cmpdata _sudo rbd device unmap -t nbd $LIBRBD_DEV @@ -320,6 +318,85 @@ function test_migration_clone() { rbd rm testimg } +function test_migration_open_clone_chain() { + rbd create --size 32M testimg + rbd encryption format testimg luks1 /tmp/passphrase + rbd snap create testimg@snap + rbd snap protect testimg@snap + + rbd clone testimg@snap testimg1 + rbd encryption format testimg1 luks2 /tmp/passphrase1 + rbd snap create testimg1@snap + rbd snap protect testimg1@snap + + rbd clone testimg1@snap testimg2 + rbd encryption format testimg2 luks1 /tmp/passphrase2 + + # 1. X <-- X <-- X + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + + # 2. X <-- X <-- migrating + rbd migration prepare testimg2 testimg2 + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + rbd migration abort testimg2 + + # 3. X <-- migrating <-- X + rbd migration prepare testimg1 testimg1 + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + rbd migration abort testimg1 + + # 4. migrating <-- X <-- X + rbd migration prepare testimg testimg + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + rbd migration abort testimg + + # 5. migrating <-- migrating <-- X + rbd migration prepare testimg testimg + rbd migration prepare testimg1 testimg1 + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + rbd migration abort testimg1 + rbd migration abort testimg + + # 6. migrating <-- X <-- migrating + rbd migration prepare testimg testimg + rbd migration prepare testimg2 testimg2 + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + rbd migration abort testimg2 + rbd migration abort testimg + + # 7. X <-- migrating <-- migrating + rbd migration prepare testimg1 testimg1 + rbd migration prepare testimg2 testimg2 + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + rbd migration abort testimg2 + rbd migration abort testimg1 + + # 8. migrating <-- migrating <-- migrating + rbd migration prepare testimg testimg + rbd migration prepare testimg1 testimg1 + rbd migration prepare testimg2 testimg2 + LIBRBD_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd -o encryption-passphrase-file=/tmp/passphrase2,encryption-passphrase-file=/tmp/passphrase1,encryption-passphrase-file=/tmp/passphrase) + _sudo rbd device unmap -t nbd $LIBRBD_DEV + + rbd migration abort testimg2 + rbd rm testimg2 + rbd migration abort testimg1 + rbd snap unprotect testimg1@snap + rbd snap rm testimg1@snap + rbd rm testimg1 + rbd migration abort testimg + rbd snap unprotect testimg@snap + rbd snap rm testimg@snap + rbd rm testimg +} + function get_nbd_device_paths { rbd device list -t nbd | tail -n +2 | egrep "\s+rbd\s+testimg" | awk '{print $5;}' } @@ -343,6 +420,7 @@ function clean_up { rbd snap unprotect testimg1@snap || true rbd snap remove testimg1@snap || true rbd remove testimg1 || true + rbd migration abort testimg || true rbd snap remove testimg@snap2 || true rbd snap remove testimg@snap1 || true rbd snap unprotect testimg@snap || true @@ -371,6 +449,7 @@ dd if=/dev/urandom of=/tmp/testdata2 bs=4M count=4 # create passphrase files printf "pass\0word\n" > /tmp/passphrase +printf " passwo\nrd 1,1" > /tmp/passphrase1 printf "\t password2 " > /tmp/passphrase2 # create an image @@ -401,4 +480,6 @@ test_migration_clone luks1 rbd create --size 48M testimg test_migration_clone luks2 +test_migration_open_clone_chain + echo OK diff --git a/src/librbd/crypto/LoadRequest.cc b/src/librbd/crypto/LoadRequest.cc index a751605e0d5..66beed59130 100644 --- a/src/librbd/crypto/LoadRequest.cc +++ b/src/librbd/crypto/LoadRequest.cc @@ -130,12 +130,22 @@ void LoadRequest::handle_load(int r) { << dendl; m_format_idx++; + if (!m_current_image_ctx->migration_info.empty()) { + // prepend the format to use for the migration source image + // it's done implicitly here because this image is moved to the + // trash when migration is prepared + ceph_assert(m_current_image_ctx->parent != nullptr); + ldout(m_image_ctx->cct, 20) << "under migration, cloning format" << dendl; + m_formats.insert(m_formats.begin() + m_format_idx, + m_formats[m_format_idx - 1]->clone()); + } + m_current_image_ctx = m_current_image_ctx->parent; if (m_current_image_ctx != nullptr) { // move on to loading parent if (m_format_idx >= m_formats.size()) { // try to load next ancestor using the same format - ldout(m_image_ctx->cct, 20) << "cloning format" << dendl; + ldout(m_image_ctx->cct, 20) << "out of formats, cloning format" << dendl; m_formats.push_back(m_formats[m_formats.size() - 1]->clone()); m_is_current_format_assumed = true; } -- 2.39.5