]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
FileStore: Add filestore version stamp
authorSamuel Just <samuel.just@dreamhost.com>
Wed, 17 Aug 2011 23:23:00 +0000 (16:23 -0700)
committerSamuel Just <samuel.just@dreamhost.com>
Tue, 30 Aug 2011 00:43:06 +0000 (17:43 -0700)
A filestore will now be tagged with a version stamp during
mkfs.  If on mount the version stamp detected lags the current
version, the mount will fail unless filestore_update_collections
is set in gconf.  If it is set, opening a collection will cause
the version stamp on the collection to be read and the
appropriate indexing implmentation to be used.  This will allow
for conversion from old collection indexing schemes to new
ones.

Signed-off-by: Samuel Just <samuel.just@dreamhost.com>
src/common/config.cc
src/common/config.h
src/os/CollectionIndex.h
src/os/FileStore.cc
src/os/FileStore.h
src/os/FlatIndex.h
src/os/LFNIndex.h
src/os/ObjectStore.h

index 0c4e3b7b6859d35723eff8d9283ddf0b11d24438..c75e066b51f31dd7dd6602b5c92773c1d344c9cb 100644 (file)
@@ -409,6 +409,7 @@ struct config_option config_optionsp[] = {
   OPTION(filestore_fiemap_threshold, OPT_INT, 4096),
   OPTION(filestore_merge_threshold, OPT_INT, 10),
   OPTION(filestore_split_multiple, OPT_INT, 2),
+  OPTION(filestore_update_collections, OPT_BOOL, false),
   OPTION(journal_dio, OPT_BOOL, true),
   OPTION(journal_block_align, OPT_BOOL, true),
   OPTION(journal_max_write_bytes, OPT_INT, 10 << 20),
index cc9044cc2cb7c588cca5e50095e435c6760faa00..1d4bfbfc9bece3e0aeda5d4960faeb6f6ffcd8c8 100644 (file)
@@ -537,6 +537,7 @@ public:
   int filestore_fiemap_threshold;
   int filestore_merge_threshold;
   int filestore_split_multiple;
+  bool filestore_update_collections;
 
   // journal
   bool journal_dio;
index 8697779b7cad5a10a67468cd43967b6c5dd03554..1d7fe08749c1fc36b5fcf61a605537ff2a58bf3f 100644 (file)
@@ -58,6 +58,13 @@ protected:
   /// Type of returned paths
   typedef std::tr1::shared_ptr<Path> IndexedPath;
 
+  /**
+   * For tracking Filestore collection versions.
+   *
+   * @return Collection version represented by the Index implementation
+   */
+  virtual uint32_t collection_version() = 0;
+
   /** 
    * For setting the internal weak_ptr to a shared_ptr to this.
    *
index d92a0d52dc30a21e4741bae3e8e07dd439b38f0f..70cb69e82c919dd3048fd360ef7a640854ce6b07 100644 (file)
@@ -175,19 +175,29 @@ int FileStore::get_cdir(coll_t cid, char *s, int len)
   return snprintf(s, len, "%s/current/%s", basedir.c_str(), cid_str.c_str());
 }
 
-Index FileStore::get_index(coll_t cid)
+int FileStore::get_index(coll_t cid, Index *index)
 {
   char path[PATH_MAX];
   get_cdir(cid, path, sizeof(path));
-  return index_manager.get_index(cid, path);
+  return index_manager.get_index(cid, path, index);
+}
+
+int FileStore::init_index(coll_t cid)
+{
+  char path[PATH_MAX];
+  get_cdir(cid, path, sizeof(path));
+  return index_manager.init_index(cid, path, on_disk_version);
 }
 
 int FileStore::lfn_find(coll_t cid, const hobject_t& oid, IndexedPath *path)
 {
-  Index index = get_index(cid);
+  Index index
   int r, exist;
+  r = get_index(cid, &index);
+  if (r < 0)
+    return r;
+
   r = index->lookup(oid, path, &exist);
-  
   if (r < 0)
     return r;
   if (!exist)
@@ -257,9 +267,12 @@ int FileStore::lfn_stat(coll_t cid, const hobject_t& oid, struct stat *buf)
 
 int FileStore::lfn_open(coll_t cid, const hobject_t& oid, int flags, mode_t mode)
 {
-  Index index = get_index(cid);
+  Index index;
   IndexedPath path;
   int r, fd, exist;
+  r = get_index(cid, &index);
+  if (r < 0)
+    return r;
   r = index->lookup(oid, &path, &exist);
   if (r < 0) {
     return r;
@@ -292,11 +305,19 @@ int FileStore::lfn_link(coll_t c, coll_t cid, const hobject_t& o)
   int exist;
   int r;
   if (c < cid) {
-    index_new = get_index(cid);
-    index_old = get_index(c);
+    r = get_index(cid, &index_new);
+    if (r < 0)
+      return r;
+    r = get_index(c, &index_old);
+    if (r < 0)
+      return r;
   } else {
-    index_old = get_index(c);
-    index_new = get_index(cid);
+    r = get_index(c, &index_old);
+    if (r < 0)
+      return r;
+    r = get_index(cid, &index_new);
+    if (r < 0)
+      return r;
   }
 
   r = index_old->lookup(o, &path_old, &exist);
@@ -325,7 +346,10 @@ int FileStore::lfn_link(coll_t c, coll_t cid, const hobject_t& o)
 
 int FileStore::lfn_unlink(coll_t cid, const hobject_t& o)
 {
-  Index index = get_index(cid);
+  Index index;
+  int r = get_index(cid, &index);
+  if (r < 0)
+    return r;
   return index->unlink(o);
 }
 
@@ -846,6 +870,13 @@ int FileStore::mkfs()
   fsid_fd = -1;
   dout(10) << "mkfs fsid is " << fsid << dendl;
 
+  ret = write_version_stamp();
+  if (ret < 0) {
+    derr << "Firestore::mkfs: write_version_stamp() failed: "
+        << cpp_strerror(ret) << dendl;
+    goto close_fsid_fd;
+  }
+
   // current
   memset(&volargs, 0, sizeof(volargs));
   basedir_fd = ::open(basedir.c_str(), O_RDONLY);
@@ -952,7 +983,6 @@ int FileStore::mkjournal()
   return ret;
 }
 
-
 int FileStore::lock_fsid()
 {
   struct flock l;
@@ -1223,6 +1253,48 @@ int FileStore::_sanity_check_fs()
   return 0;
 }
 
+int FileStore::version_stamp_is_valid(uint32_t *version)
+{
+  char fn[PATH_MAX];
+  snprintf(fn, sizeof(fn), "%s/store_version", basedir.c_str());
+  int fd = ::open(fn, O_RDONLY, 0644);
+  if (fd < 0) {
+    if (errno == ENOENT)
+      return 0;
+    else 
+      return -errno;
+  }
+  bufferptr bp(PATH_MAX);
+  int ret = safe_read(fd, bp.c_str(), bp.length());
+  TEMP_FAILURE_RETRY(::close(op_fd));
+  if (ret < 0)
+    return -errno;
+  bufferlist bl;
+  bl.push_back(bp);
+  bufferlist::iterator i = bl.begin();
+  ::decode(*version, i);
+  if (*version == on_disk_version)
+    return 1;
+  else
+    return 0;
+}
+
+int FileStore::write_version_stamp()
+{
+  char fn[PATH_MAX];
+  snprintf(fn, sizeof(fn), "%s/store_version", basedir.c_str());
+  int fd = ::open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+  if (fd < 0)
+    return -errno;
+  bufferlist bl;
+  ::encode(on_disk_version, bl);
+  
+  int ret = safe_write(fd, bl.c_str(), bl.length());
+  TEMP_FAILURE_RETRY(::close(op_fd));
+  if (ret < 0)
+    return -errno;
+  return 0;
+}
 
 int FileStore::read_op_seq(const char *fn, uint64_t *seq)
 {
@@ -1278,6 +1350,30 @@ int FileStore::mount()
   if (ret)
     goto done;
 
+  uint32_t version_stamp;
+  ret = version_stamp_is_valid(&version_stamp);
+  if (ret < 0) {
+    derr << "FileStore::mount : error in version_stamp_is_valid: "
+        << cpp_strerror(ret) << dendl;
+    goto done;
+  } else if (ret == 0) {
+    if (g_conf->filestore_update_collections) {
+      derr << "FileStore::mount : stale version stamp detected: "
+          << version_stamp 
+          << ". Proceeding, g_conf->filestore_update_collections "
+          << "is set, DO NOT USE THIS OPTION IF YOU DO NOT KNOW WHAT IT DOES."
+          << " More details can be found on the wiki."
+          << dendl;
+    } else {
+      ret = -EINVAL;
+      derr << "FileStore::mount : stale version stamp " << version_stamp
+          << ". Please run the FileStore update script before starting the "
+          << "OSD."
+          << dendl;
+      goto done;
+    }
+  }
+
   // get fsid
   snprintf(buf, sizeof(buf), "%s/fsid", basedir.c_str());
   fsid_fd = ::open(buf, O_RDWR|O_CREAT, 0644);
@@ -3464,6 +3560,19 @@ int FileStore::_collection_rename(const coll_t &cid, const coll_t &ncid)
 // --------------------------
 // collections
 
+int FileStore::collection_version_current(coll_t c, uint32_t *version)
+{
+  Index index;
+  int r = get_index(c, &index);
+  if (r < 0)
+    return r;
+  *version = index->collection_version();
+  if (*version == on_disk_version)
+    return 1;
+  else 
+    return 0;
+}
+
 int FileStore::list_collections(vector<coll_t>& ls) 
 {
   if (fake_collections) return collections.list_collections(ls);
@@ -3562,8 +3671,11 @@ int FileStore::collection_list_partial(coll_t c, snapid_t seq, vector<hobject_t>
                                       collection_list_handle_t *handle)
 {  
   if (fake_collections) return collections.collection_list(c, ls);
-  Index index = get_index(c);
-  int r = index->collection_list_partial(seq, max_count, &ls, handle);
+  Index index;
+  int r = get_index(c, &index);
+  if (r < 0)
+    return r;
+  r = index->collection_list_partial(seq, max_count, &ls, handle);
   if (r < 0)
     return r;
   return 0;
@@ -3572,7 +3684,10 @@ int FileStore::collection_list_partial(coll_t c, snapid_t seq, vector<hobject_t>
 int FileStore::collection_list(coll_t c, vector<hobject_t>& ls) 
 {  
   if (fake_collections) return collections.collection_list(c, ls);
-  Index index = get_index(c);
+  Index index;
+  int r = get_index(c, &index);
+  if (r < 0)
+    return r;
   return index->collection_list(&ls);
 }
 
@@ -3588,8 +3703,7 @@ int FileStore::_create_collection(coll_t c)
   dout(10) << "create_collection " << fn << " = " << r << dendl;
 
   if (r < 0) return r;
-  Index index = get_index(c);
-  return index->init();
+  return init_index(c);
 }
 
 int FileStore::_destroy_collection(coll_t c) 
index 6382875fd8c627302df643a2a36e53e09000d49c..76b3007d00416a7f38c1598644f5a15ebc439930 100644 (file)
@@ -39,6 +39,7 @@ using namespace __gnu_cxx;
 // fake attributes in memory, if we need to.
 
 class FileStore : public JournalingObjectStore {
+  static const uint32_t on_disk_version = 1;
   string basedir, journalpath;
   std::string current_fn;
   std::string current_op_seq_fn;
@@ -68,7 +69,8 @@ class FileStore : public JournalingObjectStore {
 
   // Indexed Collections
   IndexManager index_manager;
-  Index get_index(coll_t c);
+  int get_index(coll_t c, Index *index);
+  int init_index(coll_t c);
   
   Finisher ondisk_finisher;
 
@@ -261,6 +263,8 @@ public:
   int _sanity_check_fs();
   
   bool test_mount_in_use();
+  int write_version_stamp();
+  int version_stamp_is_valid(uint32_t *version);
   int read_op_seq(const char *fn, uint64_t *seq);
   int write_op_seq(int, uint64_t seq);
   int mount();
@@ -340,6 +344,7 @@ public:
 
   // collections
   int list_collections(vector<coll_t>& ls);
+  int collection_version_current(coll_t c, uint32_t *version);
   int collection_stat(coll_t c, struct stat *st);
   bool collection_exists(coll_t c);
   bool collection_empty(coll_t c);
index d4da5998766da1869ed409b0a2e389111663f910..d94edf3f69e6af862061e7b42840bc94cba03cac 100644 (file)
@@ -34,6 +34,9 @@ class FlatIndex : public CollectionIndex {
 public:
   FlatIndex(string base_path) : base_path(base_path) {}
 
+  /// @see CollectionIndex
+  uint32_t collection_version() { return 0; }
+
   /// @see CollectionIndex
   void set_ref(std::tr1::shared_ptr<CollectionIndex> ref);
 
index e85c300d47bfc54d0981221a86e6247b4f201c07..dedd8465a28694efff46476edff00e5f4e08c272 100644 (file)
@@ -76,7 +76,7 @@ class LFNIndex : public CollectionIndex {
   /// For reference counting the collection @see Path
   std::tr1::weak_ptr<CollectionIndex> self_ref;
 
-protected:
+public:
   /// Constructor
   LFNIndex(const char *base_path) ///< [in] path to Index root
     : base_path(base_path) {}
index 25cc4d7ddfc22fbb95c45a22208fe997acd5b905..01f5425d40a57aa3cef2633831dafbdcff206f9b 100644 (file)
@@ -539,6 +539,7 @@ public:
   virtual ~ObjectStore() {}
 
   // mgmt
+  virtual int version_stamp_is_valid(uint32_t *version) { return 1; }
   virtual bool test_mount_in_use() = 0;
   virtual int mount() = 0;
   virtual int umount() = 0;
@@ -595,6 +596,10 @@ public:
     
   // collections
   virtual int list_collections(vector<coll_t>& ls) = 0;
+  virtual int collection_version_current(coll_t c, uint32_t *version) { 
+    *version = 0;
+    return 1;
+  }
   virtual bool collection_exists(coll_t c) = 0;
   virtual int collection_getattr(coll_t cid, const char *name,
                                  void *value, size_t size) = 0;