summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Just <sam.just@inktank.com>2012-11-17 18:18:23 -0800
committerSamuel Just <sam.just@inktank.com>2013-01-18 10:45:43 -0800
commit7e8e6491a788caf82abc6d6702ce8646655a8730 (patch)
treeb7f359ecd86596878a5897b3fc6f8867bf157e1b
parentdf399da120afa0a4cdac7a7b07dce53b911323fb (diff)
downloadceph-7e8e6491a788caf82abc6d6702ce8646655a8730.tar.gz
os/: Add CollectionIndex::prep_delete
If an unlink is interupted between removing the file and updating the subdir attribute, the attribute will overestimate the number of files in the directory. This is by design, at worst we will merge the collection later than intended, but closing the gap would require a second subdir xattr update. However, this can in extreme cases result in a collection with subdirectories but no objects. FileStore::_destry_collection would therefore see an erroneous -ENOTEMPTY. prep_delete allows the CollectionIndex implementation to clean up state prior to removal. Signed-off-by: Samuel Just <sam.just@inktank.com> (cherry picked from commit fdc5e5d1877d7d7ed3851b9ec01f884559748249) Conflicts: src/os/HashIndex.cc src/os/HashIndex.h
-rw-r--r--src/os/CollectionIndex.h3
-rw-r--r--src/os/FileStore.cc9
-rw-r--r--src/os/HashIndex.cc28
-rw-r--r--src/os/HashIndex.h9
4 files changed, 48 insertions, 1 deletions
diff --git a/src/os/CollectionIndex.h b/src/os/CollectionIndex.h
index d931a88b2d5..4cd1c1762fd 100644
--- a/src/os/CollectionIndex.h
+++ b/src/os/CollectionIndex.h
@@ -166,6 +166,9 @@ protected:
vector<hobject_t> *ls ///< [out] Listed Objects
) = 0;
+ /// Call prior to removing directory
+ virtual int prep_delete() { return 0; }
+
/// Virtual destructor
virtual ~CollectionIndex() {}
};
diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc
index 9ab0e74b9c0..a039348c5e4 100644
--- a/src/os/FileStore.cc
+++ b/src/os/FileStore.cc
@@ -4705,6 +4705,15 @@ int FileStore::_create_collection(coll_t c)
int FileStore::_destroy_collection(coll_t c)
{
+ {
+ Index from;
+ int r = get_index(c, &from);
+ if (r < 0)
+ return r;
+ r = from->prep_delete();
+ if (r < 0)
+ return r;
+ }
char fn[PATH_MAX];
get_cdir(c, fn, sizeof(fn));
dout(15) << "_destroy_collection " << fn << dendl;
diff --git a/src/os/HashIndex.cc b/src/os/HashIndex.cc
index 4c97c8a69cd..a6105e084e4 100644
--- a/src/os/HashIndex.cc
+++ b/src/os/HashIndex.cc
@@ -143,6 +143,34 @@ int HashIndex::_collection_list_partial(const hobject_t &start,
return list_by_hash(path, min_count, max_count, seq, next, ls);
}
+int HashIndex::prep_delete() {
+ return recursive_remove(vector<string>());
+}
+
+int HashIndex::recursive_remove(const vector<string> &path) {
+ set<string> subdirs;
+ int r = list_subdirs(path, &subdirs);
+ if (r < 0)
+ return r;
+ map<string, hobject_t> objects;
+ r = list_objects(path, 0, 0, &objects);
+ if (r < 0)
+ return r;
+ if (objects.size())
+ return -ENOTEMPTY;
+ vector<string> subdir(path);
+ for (set<string>::iterator i = subdirs.begin();
+ i != subdirs.end();
+ ++i) {
+ subdir.push_back(*i);
+ r = recursive_remove(subdir);
+ if (r < 0)
+ return r;
+ subdir.pop_back();
+ }
+ return remove_path(path);
+}
+
int HashIndex::start_split(const vector<string> &path) {
bufferlist bl;
InProgressOp op_tag(InProgressOp::SPLIT, path);
diff --git a/src/os/HashIndex.h b/src/os/HashIndex.h
index cb0a3d2da20..68767bdb867 100644
--- a/src/os/HashIndex.h
+++ b/src/os/HashIndex.h
@@ -143,7 +143,10 @@ public:
/// @see CollectionIndex
int cleanup();
-
+
+ /// @see CollectionIndex
+ int prep_delete();
+
protected:
int _init();
@@ -175,6 +178,10 @@ protected:
hobject_t *next
);
private:
+ /// Recursively remove path and its subdirs
+ int recursive_remove(
+ const vector<string> &path ///< [in] path to remove
+ ); /// @return Error Code, 0 on success
/// Tag root directory at beginning of split
int start_split(
const vector<string> &path ///< [in] path to split