Inode *Client::get_quota_root(Inode *in, const UserPerm& perms)
{
- Inode *cur = in;
- utime_t now = ceph_clock_now();
-
- while (cur) {
- if (cur != in && cur->quota.is_enable())
- break;
+ Inode *quota_in = root_ancestor;
+ SnapRealm *realm = in->snaprealm;
+ while (realm) {
+ ldout(cct, 10) << __func__ << " realm " << realm->ino << dendl;
+ if (realm->ino != in->ino) {
+ auto p = inode_map.find(vinodeno_t(realm->ino, CEPH_NOSNAP));
+ if (p == inode_map.end())
+ break;
- Inode *parent_in = NULL;
- if (!cur->dentries.empty()) {
- for (auto dn : cur->dentries) {
- if (dn->lease_mds >= 0 &&
- dn->lease_ttl > now &&
- mds_sessions.count(dn->lease_mds)) {
- parent_in = dn->dir->parent_inode;
- } else {
- Inode *diri = dn->dir->parent_inode;
- if (diri->caps_issued_mask(CEPH_CAP_FILE_SHARED) &&
- diri->shared_gen == dn->cap_shared_gen) {
- parent_in = dn->dir->parent_inode;
- }
- }
- if (parent_in)
- break;
+ if (p->second->quota.is_enable()) {
+ quota_in = p->second;
+ break;
}
- } else if (root_parents.count(cur)) {
- parent_in = root_parents[cur].get();
- }
-
- if (parent_in) {
- cur = parent_in;
- continue;
}
-
- if (cur == root_ancestor)
- break;
-
- // deleted inode
- if (cur->nlink == 0) {
- cur = root_ancestor;
- break;
- }
-
- MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPNAME);
- filepath path(cur->ino);
- req->set_filepath(path);
- req->set_inode(cur);
-
- InodeRef parent_ref;
- int ret = make_request(req, perms, &parent_ref);
- if (ret < 0) {
- ldout(cct, 1) << __func__ << " " << in->vino()
- << " failed to find parent of " << cur->vino()
- << " err " << ret << dendl;
- // FIXME: what to do?
- cur = root_ancestor;
- break;
- }
-
- now = ceph_clock_now();
- if (cur == in)
- cur = parent_ref.get();
- else
- cur = in; // start over
+ realm = realm->pparent;
}
-
- ldout(cct, 10) << __func__ << " " << in->vino() << " -> " << cur->vino() << dendl;
- return cur;
+ ldout(cct, 10) << __func__ << " " << in->vino() << " -> " << quota_in->vino() << dendl;
+ return quota_in;
}
/**
*/
class C_MDS_inode_update_finish : public ServerLogContext {
CInode *in;
- bool truncating_smaller, changed_ranges;
+ bool truncating_smaller, changed_ranges, new_realm;
public:
C_MDS_inode_update_finish(Server *s, MDRequestRef& r, CInode *i,
- bool sm=false, bool cr=false) :
- ServerLogContext(s, r), in(i), truncating_smaller(sm), changed_ranges(cr) { }
+ bool sm=false, bool cr=false, bool nr=false) :
+ ServerLogContext(s, r), in(i),
+ truncating_smaller(sm), changed_ranges(cr), new_realm(nr) { }
void finish(int r) override {
assert(r == 0);
in->pop_and_dirty_projected_inode(mdr->ls);
mdr->apply();
+ MDSRank *mds = get_mds();
+
// notify any clients
if (truncating_smaller && in->inode.is_truncating()) {
- get_mds()->locker->issue_truncate(in);
- get_mds()->mdcache->truncate_inode(in, mdr->ls);
+ mds->locker->issue_truncate(in);
+ mds->mdcache->truncate_inode(in, mdr->ls);
}
- get_mds()->balancer->hit_inode(mdr->get_mds_stamp(), in, META_POP_IWR);
+ if (new_realm) {
+ int op = CEPH_SNAP_OP_SPLIT;
+ mds->mdcache->do_realm_invalidate_and_update_notify(in, op);
+ }
+
+ mds->balancer->hit_inode(mdr->get_mds_stamp(), in, META_POP_IWR);
server->respond_to_request(mdr, 0);
return;
}
+ bool new_realm = false;
if (name.compare(0, 15, "ceph.dir.layout") == 0) {
if (!cur->is_dir()) {
respond_to_request(mdr, -EINVAL);
}
xlocks.insert(&cur->policylock);
+ if (quota.is_enable() && !cur->get_projected_srnode()) {
+ xlocks.insert(&cur->snaplock);
+ new_realm = true;
+ }
+
if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
return;
pi = cur->project_inode();
pi->quota = quota;
+
+ if (new_realm) {
+ SnapRealm *realm = cur->find_snaprealm();
+ sr_t *newsnap = cur->project_snaprealm(realm->get_newest_seq());
+ newsnap->seq = realm->get_newest_seq();
+ }
mdr->no_early_reply = true;
} else if (name.find("ceph.dir.pin") == 0) {
if (!cur->is_dir() || cur->is_root()) {
mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY);
mdcache->journal_dirty_inode(mdr.get(), &le->metablob, cur);
- journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(this, mdr, cur));
+ journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(this, mdr, cur,
+ false, false, new_realm));
return;
}