Skip to content

Commit a8d0929

Browse files
Merge pull request ceph#63917 from rishabh-d-dave/vols-purge-trash-entry
pybind/cephfs, mgr/volumes: introduce non-recurisve rmtree(), refactor purge() to use it and add MDS optimizations Reviewed-by: Patrick Donnelly <[email protected]>
2 parents 0582fc5 + c38a913 commit a8d0929

File tree

21 files changed

+1376
-353
lines changed

21 files changed

+1376
-353
lines changed

qa/workunits/fs/test_python.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
#!/bin/sh -ex
22

3-
# Running as root because the filesystem root directory will be
4-
# owned by uid 0, and that's where we're writing.
5-
sudo python3 -m pytest -v $(dirname $0)/../../../src/test/pybind/test_cephfs.py
3+
python3 -m pytest -v $(dirname $0)/../../../src/test/pybind/test_cephfs.py
64
exit 0

src/client/Client.cc

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7729,7 +7729,10 @@ int Client::path_walk(InodeRef dirinode, const filepath& origpath, InodeRef *end
77297729
return rc;
77307730
}
77317731

7732-
int Client::path_walk(InodeRef dirinode, const filepath& origpath, walk_dentry_result* result, const UserPerm& perms, const PathWalk_ExtraOptions& extra_options)
7732+
int Client::path_walk(InodeRef dirinode, const filepath& origpath,
7733+
walk_dentry_result* result, const UserPerm& perms,
7734+
const PathWalk_ExtraOptions& extra_options,
7735+
std::string trimmed_path)
77337736
{
77347737
int rc = 0;
77357738
filepath path = origpath;
@@ -7753,7 +7756,11 @@ int Client::path_walk(InodeRef dirinode, const filepath& origpath, walk_dentry_r
77537756
int symlinks = 0;
77547757
unsigned i = 0;
77557758

7756-
ldout(cct, 10) << __func__ << ": cur=" << *diri << " path=" << path << dendl;
7759+
if (trimmed_path == "") {
7760+
std::string trimmed_path = path.get_trimmed_path();
7761+
}
7762+
7763+
ldout(cct, 10) << __func__ << ": cur=" << *diri << " path=" << trimmed_path << dendl;
77577764

77587765
if (path.depth() == 0) {
77597766
/* diri/dname can also be used as a filepath; or target */
@@ -7767,7 +7774,7 @@ int Client::path_walk(InodeRef dirinode, const filepath& origpath, walk_dentry_r
77677774
int caps = 0;
77687775
dname = path[i];
77697776
ldout(cct, 10) << " " << i << " " << *diri << " " << dname << dendl;
7770-
ldout(cct, 20) << " (path is " << path << ")" << dendl;
7777+
ldout(cct, 20) << " (path is " << trimmed_path << ")" << dendl;
77717778
InodeRef next;
77727779
if (!diri.get()->is_dir()) {
77737780
ldout(cct, 20) << diri.get() << " is not a dir inode, name " << dname.c_str() << dendl;
@@ -15471,11 +15478,12 @@ int Client::ll_unlink(Inode *in, const char *name, const UserPerm& perm)
1547115478

1547215479
int Client::_rmdir(Inode *dir, const char *name, const UserPerm& perms, bool check_perms)
1547315480
{
15474-
ldout(cct, 8) << "_rmdir(" << dir->ino << " " << name << " uid "
15481+
std::string trimmed_path = filepath(name).get_trimmed_path();
15482+
ldout(cct, 8) << "_rmdir(" << dir->ino << " " << trimmed_path << " uid "
1547515483
<< perms.uid() << " gid " << perms.gid() << ")" << dendl;
1547615484

1547715485
walk_dentry_result wdr;
15478-
if (int rc = path_walk(dir, filepath(name), &wdr, perms, {.followsym = false}); rc < 0) {
15486+
if (int rc = path_walk(dir, filepath(name), &wdr, perms, {.followsym = false}, trimmed_path); rc < 0) {
1547915487
return rc;
1548015488
}
1548115489

src/client/Client.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ class Client : public Dispatcher, public md_config_obs_t {
11081108
bool is_rename = false;
11091109
bool require_target = true;
11101110
};
1111-
int path_walk(InodeRef dirinode, const filepath& fp, struct walk_dentry_result* result, const UserPerm& perms, const PathWalk_ExtraOptions& extra_options);
1111+
int path_walk(InodeRef dirinode, const filepath& fp, struct walk_dentry_result* result, const UserPerm& perms, const PathWalk_ExtraOptions& extra_options, std::string trimmed_path=std::string());
11121112
int path_walk(InodeRef dirinode, const filepath& fp, InodeRef *end, const UserPerm& perms, const PathWalk_ExtraOptions& extra_options);
11131113

11141114
// fake inode number for 32-bits ino_t

src/common/strescape.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,21 @@ inline std::string binstrprint(std::string_view sv, size_t maxlen=0)
3434
return s;
3535
}
3636

37+
inline std::string get_trimmed_path_str(const std::string& path)
38+
{
39+
// index of '/' before 10th component (count from end of the path).
40+
size_t n = 0;
41+
42+
for (int i = 1; i <= 10; ++i) {
43+
n = path.rfind("/", n - 1);
44+
if (n == std::string::npos) {
45+
// path doesn't contain 10 components, return path as it is.
46+
return path;
47+
break;
48+
}
49+
}
50+
51+
return std::string("..." + path.substr(n, -1));
52+
}
53+
3754
#endif

src/include/filepath.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@
1717

1818
#include <ostream>
1919

20+
/* Trim given path to final 10 components and return it by prefixing it with
21+
* "..." to indicate that the path has been trimmed. */
22+
std::string filepath::get_trimmed_path() const
23+
{
24+
std::size_t n = 0;
25+
for (int i = 1; i <= 10; ++i) {
26+
n = path.rfind("/", n - 1);
27+
if (n == std::string::npos) {
28+
return std::string(path);
29+
}
30+
}
31+
32+
return std::string("..." + path.substr(n, -1));
33+
}
34+
2035
void filepath::rebuild_path() {
2136
path.clear();
2237
for (unsigned i=0; i<bits.size(); i++) {
@@ -41,6 +56,14 @@ void filepath::parse_bits() const {
4156
}
4257
}
4358

59+
void filepath::set_trimmed() {
60+
if (trimmed)
61+
return;
62+
// indicates that the path has been shortened.
63+
path += "...";
64+
trimmed = true;
65+
}
66+
4467
void filepath::set_path(std::string_view s) {
4568
if (!s.empty() && s[0] == '/') {
4669
path = s.substr(1);

src/include/filepath.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ namespace ceph { class Formatter; }
3838
class filepath {
3939
inodeno_t ino = 0; // base inode. ino=0 implies pure relative path.
4040
std::string path; // relative path.
41+
// tells get_path() whether it should prefix path with "..." to indicate that
42+
// it was shortened.
43+
bool trimmed = false;
4144

4245
/** bits - path segments
4346
* this is ['a', 'b', 'c'] for both the aboslute and relative case.
@@ -82,6 +85,8 @@ class filepath {
8285
// accessors
8386
inodeno_t get_ino() const { return ino; }
8487
const std::string& get_path() const { return path; }
88+
void set_trimmed();
89+
std::string get_trimmed_path() const;
8590
const char *c_str() const { return path.c_str(); }
8691

8792
int length() const { return path.length(); }

src/mds/CDentry.cc

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ const LockType CDentry::versionlock_type(CEPH_LOCK_DVERSION);
8585
ostream& operator<<(ostream& out, const CDentry& dn)
8686
{
8787
filepath path;
88-
dn.make_path(path);
88+
dn.make_trimmed_path(path);
8989

9090
out << "[dentry " << path;
9191

@@ -300,24 +300,74 @@ void CDentry::clear_auth()
300300
}
301301
}
302302

303-
void CDentry::make_path_string(string& s, bool projected) const
303+
void CDentry::make_path_string(string& s, bool projected,
304+
int path_comp_count) const
304305
{
305306
if (dir) {
306-
dir->inode->make_path_string(s, projected);
307+
dir->inode->make_path_string(s, projected, NULL, path_comp_count);
307308
} else {
308309
s = "???";
309310
}
310311
s += "/";
311312
s.append(name.data(), name.length());
312313
}
313314

314-
void CDentry::make_path(filepath& fp, bool projected) const
315+
/* path_comp_count = path component count. default value is 10 which implies
316+
* generate entire path.
317+
*
318+
* XXX Generating more than 10 components of a path for printing in logs will
319+
* consume too much time when the path is too long (imagine a path with 2000
320+
* components) since the path would've to be generated indidividually for each
321+
* log entry.
322+
*
323+
* Besides consuming too much time, such long paths in logs are not only not
324+
* useful but also it makes reading logs harder. Therefore, shorten the path
325+
* when used for logging.
326+
*/
327+
void CDentry::make_trimmed_path_string(string& s, bool projected,
328+
int path_comp_count) const
315329
{
316-
ceph_assert(dir);
317-
dir->inode->make_path(fp, projected);
318-
fp.push_dentry(get_name());
330+
make_path_string(s, projected, path_comp_count);
331+
}
332+
333+
/* path_comp_count = path component count. default value is -1 which implies
334+
* generate entire path.
335+
*/
336+
void CDentry::make_path(filepath& fp, bool projected,
337+
int path_comp_count) const
338+
{
339+
fp.set_trimmed();
340+
341+
if (path_comp_count == -1) {
342+
ceph_assert(dir);
343+
dir->inode->make_path(fp, projected, path_comp_count);
344+
fp.push_dentry(get_name());
345+
} else if (path_comp_count >= 1) {
346+
--path_comp_count;
347+
348+
ceph_assert(dir);
349+
dir->inode->make_path(fp, projected, path_comp_count);
350+
fp.push_dentry(get_name());
351+
}
319352
}
320353

354+
/* path_comp_count = path component count. default value is 10 which implies
355+
* generate entire path.
356+
*
357+
* XXX Generating more than 10 components of a path for printing in logs will
358+
* consume too much time when the path is too long (imagine a path with 2000
359+
* components) since the path would've to be generated indidividually for each
360+
* log entry.
361+
*
362+
* Besides consuming too much time, such long paths in logs are not only not
363+
* useful but also it makes reading logs harder. Therefore, shorten the path
364+
* when used for logging.
365+
*/
366+
void CDentry::make_trimmed_path(filepath& fp, bool projected,
367+
int path_comp_count) const
368+
{
369+
make_path(fp, projected, path_comp_count);
370+
}
321371
/*
322372
* we only add ourselves to remote_parents when the linkage is
323373
* active (no longer projected). if the passed dnl is projected,

src/mds/CDentry.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,14 @@ class CDentry : public MDSCacheObject, public LRUObject, public Counter<CDentry>
252252
const CDentry& operator= (const CDentry& right);
253253

254254
// misc
255-
void make_path_string(std::string& s, bool projected=false) const;
256-
void make_path(filepath& fp, bool projected=false) const;
255+
void make_trimmed_path_string(std::string& s, bool projected,
256+
int path_comp_count=10) const;
257+
void make_path_string(std::string& s, bool projected=false,
258+
int path_comp_count=-1) const;
259+
void make_path(filepath& fp, bool projected=false,
260+
int path_comp_count=-1) const;
261+
void make_trimmed_path(filepath& fp, bool projected=false,
262+
int path_comp_count=10) const;
257263

258264
// -- version --
259265
version_t get_version() const { return version; }

src/mds/CDir.cc

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class CDirIOContext : public MDSIOContextBase
9191

9292
ostream& operator<<(ostream& out, const CDir& dir)
9393
{
94-
out << "[dir " << dir.dirfrag() << " " << dir.get_path() << "/"
94+
out << "[dir " << dir.dirfrag() << " " << dir.get_trimmed_path() << "/"
9595
<< " [" << dir.first << ",head]";
9696
if (dir.is_auth()) {
9797
out << " auth";
@@ -2094,8 +2094,8 @@ CDentry *CDir::_load_dentry(
20942094
<< " mode " << ref_in->get_inode()->mode
20952095
<< " mtime " << ref_in->get_inode()->mtime << dendl;
20962096
string dirpath, inopath;
2097-
this->inode->make_path_string(dirpath);
2098-
ref_in->make_path_string(inopath);
2097+
this->inode->make_trimmed_path_string(dirpath);
2098+
ref_in->make_trimmed_path_string(inopath);
20992099
mdcache->mds->clog->error() << "loaded dup referent inode " << inode_data.inode->ino
21002100
<< " [" << first << "," << last << "] v" << inode_data.inode->version
21012101
<< " at " << dirpath << "/" << dname
@@ -2245,7 +2245,7 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap,
22452245
dout(0) << "_fetched missing object for " << *this << dendl;
22462246

22472247
clog->error() << "dir " << dirfrag() << " object missing on disk; some "
2248-
"files may be lost (" << get_path() << ")";
2248+
"files may be lost (" << get_trimmed_path() << ")";
22492249

22502250
go_bad(complete);
22512251
return;
@@ -2260,14 +2260,14 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap,
22602260
derr << "Corrupt fnode in dirfrag " << dirfrag()
22612261
<< ": " << err.what() << dendl;
22622262
clog->warn() << "Corrupt fnode header in " << dirfrag() << ": "
2263-
<< err.what() << " (" << get_path() << ")";
2263+
<< err.what() << " (" << get_trimmed_path() << ")";
22642264
go_bad(complete);
22652265
return;
22662266
}
22672267
if (!p.end()) {
22682268
clog->warn() << "header buffer of dir " << dirfrag() << " has "
22692269
<< hdrbl.length() - p.get_off() << " extra bytes ("
2270-
<< get_path() << ")";
2270+
<< get_trimmed_path() << ")";
22712271
go_bad(complete);
22722272
return;
22732273
}
@@ -2385,7 +2385,7 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap,
23852385
} catch (const buffer::error &err) {
23862386
mdcache->mds->clog->warn() << "Corrupt dentry '" << key.name << "' in "
23872387
"dir frag " << dirfrag() << ": "
2388-
<< err.what() << "(" << get_path() << ")";
2388+
<< err.what() << "(" << get_trimmed_path() << ")";
23892389

23902390
// Remember that this dentry is damaged. Subsequent operations
23912391
// that try to act directly on it will get their EIOs, but this
@@ -4057,7 +4057,22 @@ bool CDir::scrub_local()
40574057
return good;
40584058
}
40594059

4060-
std::string CDir::get_path() const
4060+
/* XXX: Return string containing only final 10 components of the path. This
4061+
* shortened path is to be used usually for only logging. This prevents the
4062+
* unnecessary generation of full version of a very long path (imagine a path
4063+
* with 2000 components) from inode because not only repeatedly printing long
4064+
* path in logs is unnecessary and unreadable but more importantly because it
4065+
* is an expensive process (since it's done for more or less individual log
4066+
* entries).
4067+
*/
4068+
std::string CDir::get_trimmed_path() const
4069+
{
4070+
std::string path;
4071+
get_inode()->make_trimmed_path_string(path, true);
4072+
return path;
4073+
}
4074+
4075+
std::string CDir::get_path(bool trim_path) const
40614076
{
40624077
std::string path;
40634078
get_inode()->make_path_string(path, true);

src/mds/CDir.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,8 @@ class CDir : public MDSCacheObject, public Counter<CDir> {
786786
void steal_dentry(CDentry *dn); // from another dir. used by merge/split.
787787
void finish_old_fragment(std::vector<MDSContext*>& waiters, bool replay);
788788
void init_fragment_pins();
789-
std::string get_path() const;
789+
std::string get_trimmed_path() const;
790+
std::string get_path(bool trim_path=false) const;
790791

791792
// -- authority --
792793
/*

0 commit comments

Comments
 (0)