Commit 9617c6c4 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 08bf269a
...@@ -142,6 +142,19 @@ ...@@ -142,6 +142,19 @@
// //
// - Conn.atMu // - Conn.atMu
// - Conn.mu // - Conn.mu
//
// XXX pinner takes the following locks (XXX recheck)
//
// - wconn.mu.W
// - wconn.mu.R
//
// - wconn.atMu.R
// - wconn.mu.R
// - fileh.mu (R:.mmaps W:.pinned)
//
// - virt_lock
//
//
#include "wcfs_misc.h" #include "wcfs_misc.h"
...@@ -555,7 +568,7 @@ error _Conn::resync(zodb::Tid at) { ...@@ -555,7 +568,7 @@ error _Conn::resync(zodb::Tid at) {
// - we need atMu to be not Wlocked, because under atMu.W pinner cannot run simultaneously to us. // - we need atMu to be not Wlocked, because under atMu.W pinner cannot run simultaneously to us.
// - we need to hold atMu.R to avoid race wrt e.g. other resync which changes at. // - we need to hold atMu.R to avoid race wrt e.g. other resync which changes at.
// - we cannot just do regular `atMu.Unlock + atMu.RLock()` because then // - we cannot just do regular `atMu.Unlock + atMu.RLock()` because then
// there is a race window in between Unlock and RLock where wconn.at can be changed. // there is e.g. a race window in between Unlock and RLock where wconn.at can be changed.
// XXX also deadlock, because it will become wconn._mu.lock + wconn._atMu lock // XXX also deadlock, because it will become wconn._mu.lock + wconn._atMu lock
// //
// Now other calls, e.g. Conn.open, can be running simultaneously to us, // Now other calls, e.g. Conn.open, can be running simultaneously to us,
...@@ -576,7 +589,10 @@ error _Conn::resync(zodb::Tid at) { ...@@ -576,7 +589,10 @@ error _Conn::resync(zodb::Tid at) {
//FileH f = fit.second; //FileH f = fit.second;
// XXX need to lock f.mu because wconn.atMu is only R now. // XXX need to lock f.mu because wconn.atMu is only R now.
// XXX need to coordinate with e.g. FileH.close
string ack; string ack;
// XXX f._watchMu.lock() + unlock()
// XXX + recheck status before sending the watch?
tie(ack, err) = wconn._wlink->sendReq(context::background(), fmt::sprintf("watch %s @%s", v(foid), v(at))); tie(ack, err) = wconn._wlink->sendReq(context::background(), fmt::sprintf("watch %s @%s", v(foid), v(at)));
if (err != nil) if (err != nil)
return E(err); return E(err);
...@@ -605,8 +621,9 @@ pair<FileH, error> _Conn::open(zodb::Oid foid) { ...@@ -605,8 +621,9 @@ pair<FileH, error> _Conn::open(zodb::Oid foid) {
wconn._mu.Lock(); wconn._mu.Lock();
if (wconn._downErr != nil) { if (wconn._downErr != nil) {
err = wconn._downErr;
wconn._mu.Unlock(); wconn._mu.Unlock();
return make_pair(nil, E(wconn._downErr)); return make_pair(nil, E(err));
} }
FileH f; bool ok; FileH f; bool ok;
...@@ -695,6 +712,8 @@ error _FileH::_open() { ...@@ -695,6 +712,8 @@ error _FileH::_open() {
// NOTE we are _not_ holding wconn.mu nor f.mu - only wconn.atMu to rely on wconn.at being stable. // NOTE we are _not_ holding wconn.mu nor f.mu - only wconn.atMu to rely on wconn.at being stable.
// NOTE wcfs will reply "ok" only after wcfs/head/at ≥ wconn.at // NOTE wcfs will reply "ok" only after wcfs/head/at ≥ wconn.at
string ack; string ack;
// XXX f._watchMu.lock() + unlock ?
// XXX + recheck status before sending the watch?
tie(ack, err) = wconn->_wlink->sendReq(context::background(), fmt::sprintf("watch %s @%s", v(foid), v(wconn->at))); tie(ack, err) = wconn->_wlink->sendReq(context::background(), fmt::sprintf("watch %s @%s", v(foid), v(wconn->at)));
if (err != nil) if (err != nil)
return err; return err;
...@@ -744,6 +763,8 @@ error _FileH::close() { ...@@ -744,6 +763,8 @@ error _FileH::close() {
// stop watching f XXX ok under f.mu ? // stop watching f XXX ok under f.mu ?
string ack; string ack;
// XXX f._watchMu.lock() + unlock
// XXX + recheck status before sending the watch?
tie(ack, err) = wconn->_wlink->sendReq(context::background(), fmt::sprintf("watch %s -", v(foid))); tie(ack, err) = wconn->_wlink->sendReq(context::background(), fmt::sprintf("watch %s -", v(foid)));
if (err != nil) if (err != nil)
reterr1(err); reterr1(err);
...@@ -752,7 +773,8 @@ error _FileH::close() { ...@@ -752,7 +773,8 @@ error _FileH::close() {
// remove fileh from wconn._filehTab // remove fileh from wconn._filehTab
wconn->_mu.Lock(); // FIXME lock order vs fileh._mu wconn->_mu.Lock(); // FIXME lock order vs fileh._mu
if (wconn->_filehTab.get(fileh.foid)._ptr() == &fileh) // XXX -> panic(BUG) if (wconn->_filehTab.get(fileh.foid)._ptr() != &fileh)
panic("BUG: fileh.close: wconn.filehTab[fileh.foid] != fileh");
wconn->_filehTab.erase(fileh.foid); wconn->_filehTab.erase(fileh.foid);
wconn->_mu.Unlock(); wconn->_mu.Unlock();
......
...@@ -243,6 +243,9 @@ struct _FileH : object { ...@@ -243,6 +243,9 @@ struct _FileH : object {
int _nopen; // number of times Conn.open returned this fileh int _nopen; // number of times Conn.open returned this fileh
bool _closed; // y after .close() bool _closed; // y after .close()
// "watch <.foid> ..." requests we send to wcfs are serialized via FileH._watchMu
// XXX sync::Mutex _watchMu;
// don't new - create via Conn.open // don't new - create via Conn.open
private: private:
_FileH(); _FileH();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment