From 341fb208aa32117f58ed4ce623f4b152f64ac72e Mon Sep 17 00:00:00 2001 From: Samuel Just Date: Wed, 17 Aug 2011 16:23:00 -0700 Subject: [PATCH] FileStore: Add filestore version stamp 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 --- src/common/config.cc | 1 + src/common/config.h | 1 + src/os/CollectionIndex.h | 7 ++ src/os/FileStore.cc | 146 ++++++++++++++++++++++++++++++++++----- src/os/FileStore.h | 7 +- src/os/FlatIndex.h | 3 + src/os/LFNIndex.h | 2 +- src/os/ObjectStore.h | 5 ++ 8 files changed, 154 insertions(+), 18 deletions(-) diff --git a/src/common/config.cc b/src/common/config.cc index 0c4e3b7b6859d..c75e066b51f31 100644 --- a/src/common/config.cc +++ b/src/common/config.cc @@ -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), diff --git a/src/common/config.h b/src/common/config.h index cc9044cc2cb7c..1d4bfbfc9bece 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -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; diff --git a/src/os/CollectionIndex.h b/src/os/CollectionIndex.h index 8697779b7cad5..1d7fe08749c1f 100644 --- a/src/os/CollectionIndex.h +++ b/src/os/CollectionIndex.h @@ -58,6 +58,13 @@ protected: /// Type of returned paths typedef std::tr1::shared_ptr 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. * diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc index d92a0d52dc30a..70cb69e82c919 100644 --- a/src/os/FileStore.cc +++ b/src/os/FileStore.cc @@ -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& 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 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 int FileStore::collection_list(coll_t c, vector& 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) diff --git a/src/os/FileStore.h b/src/os/FileStore.h index 6382875fd8c62..76b3007d00416 100644 --- a/src/os/FileStore.h +++ b/src/os/FileStore.h @@ -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& 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); diff --git a/src/os/FlatIndex.h b/src/os/FlatIndex.h index d4da5998766da..d94edf3f69e6a 100644 --- a/src/os/FlatIndex.h +++ b/src/os/FlatIndex.h @@ -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 ref); diff --git a/src/os/LFNIndex.h b/src/os/LFNIndex.h index e85c300d47bfc..dedd8465a2869 100644 --- a/src/os/LFNIndex.h +++ b/src/os/LFNIndex.h @@ -76,7 +76,7 @@ class LFNIndex : public CollectionIndex { /// For reference counting the collection @see Path std::tr1::weak_ptr self_ref; -protected: +public: /// Constructor LFNIndex(const char *base_path) ///< [in] path to Index root : base_path(base_path) {} diff --git a/src/os/ObjectStore.h b/src/os/ObjectStore.h index 25cc4d7ddfc22..01f5425d40a57 100644 --- a/src/os/ObjectStore.h +++ b/src/os/ObjectStore.h @@ -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& 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; -- 2.39.5