mirror of
https://github.com/ceph/ceph
synced 2025-01-24 20:13:45 +00:00
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>
This commit is contained in:
parent
a48dee547c
commit
fdc5e5d187
@ -180,6 +180,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() {}
|
||||
};
|
||||
|
@ -4464,6 +4464,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;
|
||||
|
@ -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);
|
||||
|
@ -148,6 +148,9 @@ public:
|
||||
/// @see CollectionIndex
|
||||
int cleanup();
|
||||
|
||||
/// @see CollectionIndex
|
||||
int prep_delete();
|
||||
|
||||
/// @see CollectionIndex
|
||||
int _split(
|
||||
uint32_t match,
|
||||
@ -186,6 +189,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 col_split
|
||||
int start_col_split(
|
||||
const vector<string> &path ///< [in] path to split
|
||||
|
Loading…
Reference in New Issue
Block a user