Skip to content

Commit

Permalink
Merge pull request #10104: jewel: mds: enforce a dirfrag limit on ent…
Browse files Browse the repository at this point in the history
…ries

Reviewed-by: Loic Dachary <ldachary@redhat.com>
  • Loading branch information
Loic Dachary committed Aug 8, 2016
2 parents b2f694f + d244b7a commit 49659fb
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/common/config_opts.h
Expand Up @@ -483,6 +483,7 @@ OPTION(mds_bal_merge_rd, OPT_FLOAT, 1000)
OPTION(mds_bal_merge_wr, OPT_FLOAT, 1000)
OPTION(mds_bal_interval, OPT_INT, 10) // seconds
OPTION(mds_bal_fragment_interval, OPT_INT, 5) // seconds
OPTION(mds_bal_fragment_size_max, OPT_INT, 10000*10) // order of magnitude higher than split size
OPTION(mds_bal_idle_threshold, OPT_FLOAT, 0)
OPTION(mds_bal_max, OPT_INT, -1)
OPTION(mds_bal_max_until, OPT_INT, -1)
Expand Down
10 changes: 9 additions & 1 deletion src/mds/MDCache.cc
Expand Up @@ -720,7 +720,7 @@ void MDCache::open_foreign_mdsdir(inodeno_t ino, MDSInternalContextBase *fin)
discover_base_ino(ino, fin, mds_rank_t(ino & (MAX_MDS-1)));
}

CDentry *MDCache::get_or_create_stray_dentry(CInode *in)
CDir *MDCache::get_stray_dir(CInode *in)
{
string straydname;
in->name_stray_dentry(straydname);
Expand All @@ -730,6 +730,14 @@ CDentry *MDCache::get_or_create_stray_dentry(CInode *in)
frag_t fg = strayi->pick_dirfrag(straydname);
CDir *straydir = strayi->get_dirfrag(fg);
assert(straydir);
return straydir;
}

CDentry *MDCache::get_or_create_stray_dentry(CInode *in)
{
CDir *straydir = get_stray_dir(in);
string straydname;
in->name_stray_dentry(straydname);
CDentry *straydn = straydir->lookup(straydname);
if (!straydn) {
straydn = straydir->add_null_dentry(straydname);
Expand Down
1 change: 1 addition & 0 deletions src/mds/MDCache.h
Expand Up @@ -836,6 +836,7 @@ class MDCache {
version_t dpv, MDSInternalContextBase *fin);

void open_foreign_mdsdir(inodeno_t ino, MDSInternalContextBase *c);
CDir *get_stray_dir(CInode *in);
CDentry *get_or_create_stray_dentry(CInode *in);

MDSInternalContextBase *_get_waiter(MDRequestRef& mdr, Message *req, MDSInternalContextBase *fin);
Expand Down
59 changes: 53 additions & 6 deletions src/mds/Server.cc
Expand Up @@ -2149,6 +2149,23 @@ bool Server::check_access(MDRequestRef& mdr, CInode *in, unsigned mask)
return true;
}

/**
* check whether fragment has reached maximum size
*
*/
bool Server::check_fragment_space(MDRequestRef &mdr, CDir *in)
{
const auto size = in->get_frag_size();
if (size >= g_conf->mds_bal_fragment_size_max) {
dout(10) << "fragment " << *in << " size exceeds " << g_conf->mds_bal_fragment_size_max << " (ENOSPC)" << dendl;
respond_to_request(mdr, -ENOSPC);
return false;
}

return true;
}


/** validate_dentry_dir
*
* verify that the dir exists and would own the dname.
Expand Down Expand Up @@ -2233,15 +2250,20 @@ CDentry* Server::prepare_stray_dentry(MDRequestRef& mdr, CInode *in)
{
CDentry *straydn = mdr->straydn;
if (straydn) {
string name;
in->name_stray_dentry(name);
if (straydn->get_name() == name)
string straydname;
in->name_stray_dentry(straydname);
if (straydn->get_name() == straydname)
return straydn;

assert(!mdr->done_locking);
mdr->unpin(straydn);
}

CDir *straydir = mdcache->get_stray_dir(in);

if (!check_fragment_space(mdr, straydir))
return NULL;

straydn = mdcache->get_or_create_stray_dentry(in);
mdr->straydn = straydn;
mdr->pin(straydn);
Expand Down Expand Up @@ -3181,14 +3203,18 @@ void Server::handle_client_openc(MDRequestRef& mdr)
return;
}

CInode *diri = dn->get_dir()->get_inode();
CDir *dir = dn->get_dir();
CInode *diri = dir->get_inode();
rdlocks.insert(&diri->authlock);
if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
return;

if (!check_access(mdr, diri, access))
return;

if (!check_fragment_space(mdr, dir))
return;

CDentry::linkage_t *dnl = dn->get_projected_linkage();

if (!dnl->is_null()) {
Expand Down Expand Up @@ -4590,6 +4616,9 @@ void Server::handle_client_mknod(MDRequestRef& mdr)
if (!check_access(mdr, diri, MAY_WRITE))
return;

if (!check_fragment_space(mdr, dn->get_dir()))
return;

unsigned mode = req->head.args.mknod.mode;
if ((mode & S_IFMT) == 0)
mode |= S_IFREG;
Expand Down Expand Up @@ -4673,7 +4702,8 @@ void Server::handle_client_mkdir(MDRequestRef& mdr)
respond_to_request(mdr, -EROFS);
return;
}
CInode *diri = dn->get_dir()->get_inode();
CDir *dir = dn->get_dir();
CInode *diri = dir->get_inode();
rdlocks.insert(&diri->authlock);
if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
return;
Expand All @@ -4682,6 +4712,9 @@ void Server::handle_client_mkdir(MDRequestRef& mdr)
if (!check_access(mdr, diri, MAY_WRITE))
return;

if (!check_fragment_space(mdr, dir))
return;

// new inode
SnapRealm *realm = dn->get_dir()->inode->find_snaprealm();
snapid_t follows = realm->get_newest_seq();
Expand Down Expand Up @@ -4753,14 +4786,18 @@ void Server::handle_client_symlink(MDRequestRef& mdr)
respond_to_request(mdr, -EROFS);
return;
}
CInode *diri = dn->get_dir()->get_inode();
CDir *dir = dn->get_dir();
CInode *diri = dir->get_inode();
rdlocks.insert(&diri->authlock);
if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
return;

if (!check_access(mdr, diri, MAY_WRITE))
return;

if (!check_fragment_space(mdr, dir))
return;

unsigned mode = S_IFLNK | 0777;
CInode *newi = prepare_new_inode(mdr, dn->get_dir(), inodeno_t(req->head.ino), mode);
assert(newi);
Expand Down Expand Up @@ -4834,6 +4871,9 @@ void Server::handle_client_link(MDRequestRef& mdr)
if (!check_access(mdr, dir->get_inode(), MAY_WRITE))
return;

if (!check_fragment_space(mdr, dir))
return;

// go!
assert(g_conf->mds_kill_link_at != 1);

Expand Down Expand Up @@ -5405,6 +5445,8 @@ void Server::handle_client_unlink(MDRequestRef& mdr)
CDentry *straydn = NULL;
if (dnl->is_primary()) {
straydn = prepare_stray_dentry(mdr, dnl->get_inode());
if (!straydn)
return;
dout(10) << " straydn is " << *straydn << dendl;
} else if (mdr->straydn) {
mdr->unpin(mdr->straydn);
Expand Down Expand Up @@ -6185,6 +6227,8 @@ void Server::handle_client_rename(MDRequestRef& mdr)
CDentry *straydn = NULL;
if (destdnl->is_primary() && !linkmerge) {
straydn = prepare_stray_dentry(mdr, destdnl->get_inode());
if (!straydn)
return;
dout(10) << " straydn is " << *straydn << dendl;
} else if (mdr->straydn) {
mdr->unpin(mdr->straydn);
Expand Down Expand Up @@ -6295,6 +6339,9 @@ void Server::handle_client_rename(MDRequestRef& mdr)
if (!check_access(mdr, destdn->get_dir()->get_inode(), MAY_WRITE))
return;

if (!check_fragment_space(mdr, destdn->get_dir()))
return;

if (!check_access(mdr, srci, MAY_WRITE))
return;

Expand Down
1 change: 1 addition & 0 deletions src/mds/Server.h
Expand Up @@ -134,6 +134,7 @@ class Server {
void handle_slave_auth_pin_ack(MDRequestRef& mdr, MMDSSlaveRequest *ack);

// some helpers
bool check_fragment_space(MDRequestRef& mdr, CDir *in);
bool check_access(MDRequestRef& mdr, CInode *in, unsigned mask);
bool _check_access(Session *session, CInode *in, unsigned mask, int caller_uid, int caller_gid, int setattr_uid, int setattr_gid);
CDir *validate_dentry_dir(MDRequestRef& mdr, CInode *diri, const string& dname);
Expand Down

0 comments on commit 49659fb

Please sign in to comment.