]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: Implemented create-bdev-label 62148/head
authorJaya Prakash <jayaprakash@ibm.com>
Wed, 5 Mar 2025 21:56:37 +0000 (21:56 +0000)
committerJaya Prakash <jayaprakash@ibm.com>
Wed, 11 Jun 2025 09:44:23 +0000 (09:44 +0000)
Introduces a helper function create_bdev_label() and a new command create-bdev-label
to write essential OSD metadata (e.g., fsid, whoami) directly into the device label
at offset 0, for use on devices where support_bdev_label == false.

Usage: ./bin/ceph-bluestore-tool --path dev/osd0 --dev dev/osd0/block create-bdev-label

If a label already exists, the function throws an error to avoid overwriting.

This lays the groundwork for eventually removing duplicated metadata from
the OSD directory for devices that don’t support native bdev labels

Signed-off-by: Jaya Prakash <jayaprakash@ibm.com>
doc/man/8/ceph-bluestore-tool.rst
src/os/CMakeLists.txt
src/os/bluestore/BlueEnv.cc [new file with mode: 0644]
src/os/bluestore/BlueStore.h
src/os/bluestore/bluestore_tool.cc

index e720f3a4989f0544ce07b5ff78d3262b940aa6d5..9e1dd31ac2eca042d0d92195f70f6af979187d56 100644 (file)
@@ -35,6 +35,8 @@ Synopsis
 | **ceph-bluestore-tool** trim --path *osd path*
 | **ceph-bluestore-tool** zap-device --dev *dev path*
 | **ceph-bluestore-tool** revert-wal-to-plain --path *osd path*
+| **ceph-bluestore-tool** create-bdev-labels --path *osd path* --dev *device*
+
 
 
 Description
@@ -171,6 +173,14 @@ Commands
    Changes WAL files from envelope mode to the legacy plain mode.
    Useful for downgrades, or if you might want to disable this new feature (bluefs_wal_envelope_mode).
 
+:command:`create-bdev-labels` --path *osd path* --dev *device*
+
+   Writes a bdev label to BlueStore devices that originally did not support labeling.
+   Reads metadata (e.g., fsid, ceph version) from --path and writes it to the device at --dev.
+   Only the main device (block) gets full metadata; block.db or block.wal do not.
+   The --dev path must be inside the --path directory, as its name determines the device role.
+   Use --yes-i-really-really-mean-it to recreate corrupted labels.
+
 Options
 =======
 
index 4a96f4290d61c87254e0c21f384d32b785085069..af65d6a7f711e0f1c5645905721563e94ba127cc 100644 (file)
@@ -29,6 +29,7 @@ if(WITH_BLUESTORE)
     bluestore/Writer.cc
     bluestore/Compression.cc
     bluestore/BlueAdmin.cc
+    bluestore/BlueEnv.cc
   )
 endif(WITH_BLUESTORE)
 
diff --git a/src/os/bluestore/BlueEnv.cc b/src/os/bluestore/BlueEnv.cc
new file mode 100644 (file)
index 0000000..01062a1
--- /dev/null
@@ -0,0 +1,113 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <stdio.h>
+#include <string.h>
+#include <filesystem>
+#include <iostream>
+#include <fstream>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "global/global_init.h"
+#include "common/ceph_argparse.h"
+#include "include/stringify.h"
+#include "common/errno.h"
+#include "common/safe_io.h"
+
+#include "os/bluestore/BlueStore.h"
+
+using namespace std;
+
+
+int BlueStore::create_bdev_labels(CephContext *cct,
+                                 const std::string& path,
+                                 const std::vector<std::string>& devs,
+                                std::vector<uint64_t>* valid_positions,
+                                bool force)
+{
+  std::vector<std::string> metadata_files = {
+    "bfm_blocks",
+    "bfm_blocks_per_key",
+    "bfm_bytes_per_block",
+    "bfm_size",
+    "bluefs",
+    "ceph_fsid",
+    "ceph_version_when_created",
+    "created_at",
+    "elastic_shared_blobs",
+    "fsid",
+    "kv_backend",
+    "magic",
+    "osd_key",
+    "ready",
+    "require_osd_release",
+    "type",
+    "whoami"
+  };
+
+  unique_ptr<BlockDevice> bdev(BlockDevice::create(cct, devs.front(), nullptr, nullptr, nullptr, nullptr));
+  int r = bdev->open(devs.front());
+  if (r < 0) {
+    return r;
+  }
+  uint64_t size = bdev->get_size();
+
+  if (bdev->supported_bdev_label() && !force) {
+    bdev->close();
+    return -EPERM;
+  }
+
+  bdev->close();
+
+  bluestore_bdev_label_t label;
+  std::vector<uint64_t> out_positions;
+  bool is_multi = false;
+  int64_t epoch = -1;
+
+  r = BlueStore::read_bdev_label(cct, devs.front(), &label,
+    &out_positions, &is_multi, &epoch);
+
+  if (r == 0 && !force)
+    return -EEXIST;
+
+  label = bluestore_bdev_label_t();
+  label.btime = ceph_clock_now();
+
+  if (devs.front().ends_with("block")) {
+    label.description = "main";
+  } else if (devs.front().ends_with("block.db")) {
+    label.description = "bluefs db";
+  } else if (devs.front().ends_with("block.wal")) {
+    label.description = "bluefs wal";
+  }
+
+  label.size = size;
+
+  for (const auto& file : metadata_files) {
+    std::ifstream infile(path + "/" + file);
+    if (infile) {
+      std::string value((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
+      value.erase(std::remove(value.begin(), value.end(), '\n'), value.end());
+      if (file == "fsid") {
+        label.osd_uuid.parse(value.c_str());
+      } else if (label.description == "main") {
+        label.meta[file] = value;
+      }
+    } else {
+      cerr << "Warning: unable to read metadata file: " << file << std::endl;
+    }
+  }
+
+  bool wrote_at_least_one = false;
+  for (uint64_t position : *valid_positions) {
+    r = BlueStore::write_bdev_label(cct, devs.front(), label, position);
+    if (r < 0) {
+      cerr << "unable to write label at 0x" << std::hex << position << std::dec
+           << ": " << cpp_strerror(r) << std::endl;
+    } else {
+      wrote_at_least_one = true;
+    }
+  }
+  return wrote_at_least_one ? 0 : -EIO;
+}
index 909efa568b96349c57c0721bd2e7cc2ad6d779b5..bfa900d4c699b9f132d45404e2f88b9cca3d4dcf 100644 (file)
@@ -4175,6 +4175,13 @@ private:
 
   void _fsck_check_objects(FSCKDepth depth,
     FSCK_ObjectCtx& ctx);
+
+public:
+  static int create_bdev_labels(CephContext *cct,
+                          const std::string& path,
+                          const std::vector<std::string>& devs,
+                         std::vector<uint64_t>* valid_positions,
+                         bool force);
 };
 
 inline std::ostream& operator<<(std::ostream& out, const BlueStore::volatile_statfs& s) {
index 9fff0a08278da6e3e915caeeb5dd6865d9e41fef..ad1f8d30841df94b6df152c3570829f09da47e7a 100644 (file)
@@ -357,6 +357,7 @@ int main(int argc, char **argv)
         "show-label, "
         "show-label-at, "
         "set-label-key, "
+       "create-bdev-labels, "
         "rm-label-key, "
         "prime-osd-dir, "
         "bluefs-super-dump, "
@@ -520,6 +521,16 @@ int main(int argc, char **argv)
       exit(EXIT_FAILURE);
     }
   }
+  if (action == "create-bdev-labels") {
+    if (path.empty()) {
+      cerr << "must specify bluestore path" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+    if (devs.size() != 1) {
+      cerr << "must specify the main bluestore device" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
   if (action == "show-label") {
     if (devs.empty() && path.empty()) {
       cerr << "must specify bluestore path *or* raw device(s)" << std::endl;
@@ -837,6 +848,32 @@ int main(int argc, char **argv)
     jf.close_section();
     jf.flush(cout);
   }
+  else if (action == "create-bdev-labels") {
+
+    std::vector<uint64_t> valid_positions = {0};
+
+    bool force = vm.count("yes-i-really-really-mean-it");
+    int r = BlueStore::create_bdev_labels(cct.get(), path, devs, &valid_positions, force);
+    if (r == -EPERM && !force) {
+      cerr << "device " << devs.front()
+           << " already supports bdev label refusing to create a new label without --yes-i-really-really-mean-it"
+           << std::endl;
+      exit(EXIT_FAILURE);
+    }
+
+    if (r == -EEXIST && !force) {
+      cerr << "device " << devs.front() << " already has a label" << std::endl;
+      cerr << "Creating a new label on top of an existing one is a dangerous operation "
+          << "which could cause data loss.\n"
+          << "Please confirm with --yes-i-really-really-mean-it option" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+
+    if (r < 0) {
+      cerr << "Failed to create bdev label: " << cpp_strerror(r) << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
   else if (action == "set-label-key") {
     bluestore_bdev_label_t label;
     std::vector<uint64_t> valid_positions;