check_inode_max_size(in);
}
+
+void Locker::revoke_stale_caps(Capability *cap)
+{
+ CInode *in = cap->get_inode();
+ if (in->state_test(CInode::STATE_EXPORTINGCAPS)) {
+ // if export succeeds, the cap will be removed. if export fails, we need to
+ // revoke the cap if it's still stale.
+ in->state_set(CInode::STATE_EVALSTALECAPS);
+ return;
+ }
+
+ int issued = cap->issued();
+ if (issued & ~CEPH_CAP_PIN) {
+ dout(10) << " revoking " << ccap_string(issued) << " on " << *in << dendl;
+ cap->revoke();
+
+ if (in->is_auth() &&
+ in->inode.client_ranges.count(cap->get_client()))
+ in->state_set(CInode::STATE_NEEDSRECOVER);
+
+ if (!in->filelock.is_stable()) eval_gather(&in->filelock);
+ if (!in->linklock.is_stable()) eval_gather(&in->linklock);
+ if (!in->authlock.is_stable()) eval_gather(&in->authlock);
+ if (!in->xattrlock.is_stable()) eval_gather(&in->xattrlock);
+
+ if (in->is_auth()) {
+ try_eval(in, CEPH_CAP_LOCKS);
+ } else {
+ request_inode_file_caps(in);
+ }
+ }
+}
+
void Locker::revoke_stale_caps(Session *session)
{
dout(10) << "revoke_stale_caps for " << session->info.inst.name << dendl;
- client_t client = session->get_client();
for (xlist<Capability*>::iterator p = session->caps.begin(); !p.end(); ++p) {
Capability *cap = *p;
cap->mark_stale();
- CInode *in = cap->get_inode();
- int issued = cap->issued();
- if (issued & ~CEPH_CAP_PIN) {
- dout(10) << " revoking " << ccap_string(issued) << " on " << *in << dendl;
- cap->revoke();
-
- if (in->is_auth() &&
- in->inode.client_ranges.count(client))
- in->state_set(CInode::STATE_NEEDSRECOVER);
-
- if (!in->filelock.is_stable()) eval_gather(&in->filelock);
- if (!in->linklock.is_stable()) eval_gather(&in->linklock);
- if (!in->authlock.is_stable()) eval_gather(&in->authlock);
- if (!in->xattrlock.is_stable()) eval_gather(&in->xattrlock);
-
- if (in->is_auth()) {
- try_eval(in, CEPH_CAP_LOCKS);
- } else {
- request_inode_file_caps(in);
- }
- } else {
- dout(10) << " nothing issued on " << *in << dendl;
- }
+ revoke_stale_caps(cap);
}
}
if (cap->is_stale()) {
dout(10) << " clearing stale flag on " << *in << dendl;
cap->clear_stale();
+
+ if (in->state_test(CInode::STATE_EXPORTINGCAPS)) {
+ // if export succeeds, the cap will be removed. if export fails,
+ // we need to re-issue the cap if it's not stale.
+ in->state_set(CInode::STATE_EVALSTALECAPS);
+ continue;
+ }
+
if (!in->is_auth() || !eval(in, CEPH_CAP_LOCKS))
issue_caps(in, cap);
}
void mark_updated_Filelock(ScatterLock *lock);
// -- file i/o --
- public:
+public:
version_t issue_file_data_version(CInode *in);
Capability* issue_new_caps(CInode *in, int mode, Session *session, SnapRealm *conrealm, bool is_replay);
bool issue_caps(CInode *in, Capability *only_cap=0);
void issue_caps_set(set<CInode*>& inset);
void issue_truncate(CInode *in);
void revoke_stale_caps(Session *session);
+ void revoke_stale_caps(Capability *cap);
void resume_stale_caps(Session *session);
void remove_stale_leases(Session *session);
{
dout(7) << "export_reverse " << *dir << dendl;
+ set<CInode*> to_eval;
+
set<CDir*> bounds;
cache->get_subtree_bounds(dir, bounds);
continue;
CInode *in = p->second->get_linkage()->get_inode();
in->abort_export();
+ if (in->state_test(CInode::STATE_EVALSTALECAPS)) {
+ in->state_clear(CInode::STATE_EVALSTALECAPS);
+ to_eval.insert(in);
+ }
if (in->is_dir())
in->get_nested_dirfrags(rq);
}
// unfreeze
dir->unfreeze_tree();
+ // revoke/resume stale caps
+ for (auto in : to_eval) {
+ bool need_issue = false;
+ for (auto& p : in->get_client_caps()) {
+ Capability *cap = p.second;
+ if (cap->is_stale()) {
+ mds->locker->revoke_stale_caps(cap);
+ } else {
+ need_issue = true;
+ }
+ }
+ if (need_issue &&
+ (!in->is_auth() || !mds->locker->eval(in, CEPH_CAP_LOCKS)))
+ mds->locker->issue_caps(in);
+ }
+
cache->show_cache();
}