summaryrefslogtreecommitdiffstats
path: root/src/os/HashIndex.cc
diff options
context:
space:
mode:
authorSamuel Just <sam.just@inktank.com>2012-11-18 03:18:23 +0100
committerSamuel Just <sam.just@inktank.com>2012-12-05 20:34:18 +0100
commitfdc5e5d1877d7d7ed3851b9ec01f884559748249 (patch)
tree0c7b8317f05fc5f4c1255c88e747b233edc81555 /src/os/HashIndex.cc
parentos/: Add failure CollectionIndex failure injection (diff)
downloadceph-fdc5e5d1877d7d7ed3851b9ec01f884559748249.tar.xz
ceph-fdc5e5d1877d7d7ed3851b9ec01f884559748249.zip
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>
Diffstat (limited to 'src/os/HashIndex.cc')
-rw-r--r--src/os/HashIndex.cc28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/os/HashIndex.cc b/src/os/HashIndex.cc
index 479e85107d9..705558bd154 100644
--- a/src/os/HashIndex.cc
+++ b/src/os/HashIndex.cc
@@ -333,6 +333,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_col_split(const vector<string> &path) {
bufferlist bl;
InProgressOp op_tag(InProgressOp::COL_SPLIT, path);