session->con->send_message(new MClientSession(CEPH_SESSION_FLUSHMSG_ACK, m->get_seq()));
break;
+ case CEPH_SESSION_FORCE_RO:
+ force_session_readonly(session);
+ break;
+
default:
assert(0);
}
// trim unused caps to reduce MDS's cache rejoin time
trim_cache_for_reconnect(session);
+ session->readonly = false;
+
if (session->release) {
session->release->put();
session->release = NULL;
}
ldout(cct, 10) << "waiting for caps need " << ccap_string(need) << " want " << ccap_string(want) << dendl;
}
+
+ if ((need & CEPH_CAP_FILE_WR) && in->auth_cap &&
+ in->auth_cap->session->readonly)
+ return -EROFS;
wait_on_list(in->waitfor_caps);
}
_invalidate_kernel_dcache();
}
+void Client::force_session_readonly(MetaSession *s)
+{
+ s->readonly = true;
+ for (xlist<Cap*>::iterator p = s->caps.begin(); !p.end(); ++p) {
+ Inode *in = (*p)->inode;
+ if (in->caps_wanted() & CEPH_CAP_FILE_WR)
+ signal_cond_list(in->waitfor_caps);
+ }
+}
+
void Client::mark_caps_dirty(Inode *in, int caps)
{
ldout(cct, 10) << "mark_caps_dirty " << *in << " " << ccap_string(in->dirty_caps) << " -> "
void dump_inode(Formatter *f, Inode *in, set<Inode*>& did, bool disconnected);
void dump_cache(Formatter *f); // debug
-
+
+ // force read-only
+ void force_session_readonly(MetaSession *s);
+
// trace generation
ofstream traceout;
STATE_STALE,
} state;
+ bool readonly;
+
list<Context*> waiting_for_open;
xlist<Cap*> caps;
MetaSession()
: mds_num(-1), con(NULL),
seq(0), cap_gen(0), cap_renew_seq(0), num_caps(0),
- state(STATE_NEW), s_cap_iterator(NULL),
+ state(STATE_NEW), readonly(false), s_cap_iterator(NULL),
release(NULL)
{}
~MetaSession();