Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Joshua
wendelin.core
Commits
66e106ec
Commit
66e106ec
authored
Mar 05, 2020
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
10a7981d
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
42 additions
and
16 deletions
+42
-16
wcfs/client/wcfs.cpp
wcfs/client/wcfs.cpp
+42
-16
No files found.
wcfs/client/wcfs.cpp
View file @
66e106ec
...
@@ -116,15 +116,29 @@
...
@@ -116,15 +116,29 @@
// Wcfs client locking organization
// Wcfs client locking organization
//
//
// XXX locking -> explain atMu + slaves and refer to "Locking" in wcfs.go
// Wcfs client needs to synchronize regular user threads vs each other and vs
// pinner. A major lock Conn.atMu protects updates to changes to Conn's view of
// the database. Whenever atMu.W is taken - Conn.at is changing (Conn.resync),
// and contrary whenever atMu.R is taken - Conn.at is stable (roughly speaking
// Conn.resync is not running).
//
//
// Conn.atMu > Conn.filehMu > FileH.mmapMu
// Similarly to wcfs.go(*) several locks that protect internal data structures
// are minor to Conn.atMu - they need to be taken only under atMu.R (to
// synchronize e.g. multiple fileh open running simultaneously), but do not
// need to be taken at all if atMu.W is taken. In data structures such locks
// are noted as follows
//
// sync::Mutex xMu; // atMu.W | atMu.R + xMu
//
// After atMu, Conn.filehMu protects registry of opened file handles
// (Conn._filehTab), and FileH.mmapMu protects registry of created Mappings
// (FileH.mmaps) and FileH.pinned.
//
//
// Several locks are RWMutex instead of just Mutex not only to allow more
// Several locks are RWMutex instead of just Mutex not only to allow more
// concurrency, but, in the first place for correctness: pinner thread being
// concurrency, but, in the first place for correctness: pinner thread being
// core element in handling WCFS isolation protocol, is effectively invoked
// core element in handling WCFS isolation protocol, is effectively invoked
// synchronously from other threads via messages coming through wcfs server.
// synchronously from other threads via messages coming through wcfs server.
// For example Conn.resync sends watch request to wcfs and waits for the
// For example Conn.resync sends watch request to wcfs
server
and waits for the
// answer. Wcfs server, in turn, might send corresponding pin messages to the
// answer. Wcfs server, in turn, might send corresponding pin messages to the
// pinner and _wait_ for the answer before answering to resync:
// pinner and _wait_ for the answer before answering to resync:
//
//
...
@@ -138,24 +152,36 @@
...
@@ -138,24 +152,36 @@
// client process
// client process
//
//
// This creates the necessity to use RWMutex for locks that pinner and other
// This creates the necessity to use RWMutex for locks that pinner and other
// parts of the code could be using at the same time in synchronous scenario
u
s
// parts of the code could be using at the same time in synchronous scenarios
// similar to the above. This locks are:
// similar to the above. This locks are:
//
//
// - Conn.atMu
// - Conn.atMu
// - Conn.filehMu
// - Conn.filehMu
//
//
// XXX pinner takes the following locks (XXX recheck)
// Note that FileH.mmapMu is regular - not RW - mutex, since nothing in wcfs
// client calls into wcfs server via watchlink with mmapMu held.
//
//
// - wconn.filehMu.W
// To synchronize with virtmem layer, wcfs client takes and releases big
// - wconn.filehMu.R
// virtmem lock around places that touch virtmem (calls to virt_lock and
// virt_unlock). Also virtmem calls several wcfs client entrypoints with
// virtmem lock already taken. Thus, to avoid AB-BA style deadlocks, wcfs
// client needs to take virtmem lock as the first lock, whenever it needs to
// take both virtmem lock, and another lock - e.g. atMu(%).
//
// The ordering of locks is:
//
// virt_lock > Conn.atMu > Conn.filehMu > FileH.mmapMu
//
// The pinner takes the following locks:
//
//
// - virt_lock
// - virt_lock
// - wconn.atMu.R
// - wconn.atMu.R
// - wconn.filehMu.R
// - wconn.filehMu.R
// - fileh.mmapMu (
R:.mmaps W:
.pinned)
// - fileh.mmapMu (
to read .mmaps + write
.pinned)
//
//
//
//
// XXX note on virt_lock in pinner and deadlocks.
// (*) see "Wcfs locking organization" in wcfs.go
// (%) see related comment in Conn.__pin1 for details.
#include "wcfs_misc.h"
#include "wcfs_misc.h"
...
@@ -209,7 +235,7 @@ static error mmap_into_ro(void *addr, size_t size, os::File f, off_t offset);
...
@@ -209,7 +235,7 @@ static error mmap_into_ro(void *addr, size_t size, os::File f, off_t offset);
//
//
// _headWait is currently needed, because client stats wcfs/head/f to get f
// _headWait is currently needed, because client stats wcfs/head/f to get f
// size assuming that f size only ↑. The assumption is not generally valid
// size assuming that f size only ↑. The assumption is not generally valid
// (e.g. f might be truncated = hole puched for block at tail), but holds true
// (e.g. f might be truncated = hole pu
n
ched for block at tail), but holds true
// for now. However to get correct results wcfs/head/f has to be statt'ed
// for now. However to get correct results wcfs/head/f has to be statt'ed
// _after_ wcfs view of the database becomes ≥ wconn.at.
// _after_ wcfs view of the database becomes ≥ wconn.at.
//
//
...
@@ -218,7 +244,7 @@ static error mmap_into_ro(void *addr, size_t size, os::File f, off_t offset);
...
@@ -218,7 +244,7 @@ static error mmap_into_ro(void *addr, size_t size, os::File f, off_t offset);
// file size @at will be returned by wcfs itself, which will also work if
// file size @at will be returned by wcfs itself, which will also work if
// wcfs/head/f size is changed arbitrarily.
// wcfs/head/f size is changed arbitrarily.
//
//
// (*) equival
i
ent might be to send something like "pin #<bsize>.. Z" (pin
// (*) equivalent might be to send something like "pin #<bsize>.. Z" (pin
// blocks bsize till ∞ to zeros).
// blocks bsize till ∞ to zeros).
error
WCFS
::
_headWait
(
zodb
::
Tid
at
)
{
error
WCFS
::
_headWait
(
zodb
::
Tid
at
)
{
WCFS
*
wc
=
this
;
WCFS
*
wc
=
this
;
...
@@ -578,7 +604,7 @@ error _Conn::__pin1(PinReq *req) {
...
@@ -578,7 +604,7 @@ error _Conn::__pin1(PinReq *req) {
// resync resyncs connection and its file mappings onto different database view.
// resync resyncs connection and its file mappings onto different database view.
//
//
// bigfile/_file_zob.pyx arranges to call Conn.resync at transaction boundaries
// bigfile/_file_zo
d
b.pyx arranges to call Conn.resync at transaction boundaries
// to keep Conn view in sync with updated zconn database view.
// to keep Conn view in sync with updated zconn database view.
error
_Conn
::
resync
(
zodb
::
Tid
at
)
{
error
_Conn
::
resync
(
zodb
::
Tid
at
)
{
_Conn
&
wconn
=
*
this
;
_Conn
&
wconn
=
*
this
;
...
@@ -821,8 +847,8 @@ retry:
...
@@ -821,8 +847,8 @@ retry:
f
->
_openReady
.
close
();
f
->
_openReady
.
close
();
});
});
// do the actual
l
open.
// do the actual open.
// we hold only wconn.atMu.R, but n
ie
ther wconn.filehMu, nor f.mmapMu .
// we hold only wconn.atMu.R, but n
ei
ther wconn.filehMu, nor f.mmapMu .
f
->
_openErr
=
f
->
_open
();
f
->
_openErr
=
f
->
_open
();
if
(
f
->
_openErr
!=
nil
)
if
(
f
->
_openErr
!=
nil
)
return
make_pair
(
nil
,
E
(
f
->
_openErr
));
return
make_pair
(
nil
,
E
(
f
->
_openErr
));
...
@@ -1089,7 +1115,7 @@ pair<Mapping, error> _FileH::mmap(int64_t blk_start, int64_t blk_len, VMA *vma)
...
@@ -1089,7 +1115,7 @@ pair<Mapping, error> _FileH::mmap(int64_t blk_start, int64_t blk_len, VMA *vma)
return
make_pair
(
mmap
,
nil
);
return
make_pair
(
mmap
,
nil
);
}
}
// __remmapEfault remmaps Mapping memory to cause SIGSEGV on access.
// __remmap
As
Efault remmaps Mapping memory to cause SIGSEGV on access.
//
//
// It is used on FileH shutdown to turn all fileh mappings into incorrect ones,
// It is used on FileH shutdown to turn all fileh mappings into incorrect ones,
// because after fileh is down, it is not possible to continue to provide
// because after fileh is down, it is not possible to continue to provide
...
@@ -1193,7 +1219,7 @@ error _Mapping::_remmapblk(int64_t blk, zodb::Tid at) {
...
@@ -1193,7 +1219,7 @@ error _Mapping::_remmapblk(int64_t blk, zodb::Tid at) {
ASSERT
(
mmap
->
blk_start
<=
blk
&&
blk
<
mmap
->
blk_stop
());
ASSERT
(
mmap
->
blk_start
<=
blk
&&
blk
<
mmap
->
blk_stop
());
// a mmapping is efaulted only for closed files, i.e. fileh is removed from wconn._filehTab
// a mmapping is efaulted only for closed files, i.e. fileh is removed from wconn._filehTab
// -> pinner should not see the fileh and so sh
uo
ld not see this mapping.
// -> pinner should not see the fileh and so sh
ou
ld not see this mapping.
ASSERT
(
!
mmap
->
efaulted
);
ASSERT
(
!
mmap
->
efaulted
);
uint8_t
*
blkmem
=
mmap
->
mem_start
+
(
blk
-
mmap
->
blk_start
)
*
f
->
blksize
;
uint8_t
*
blkmem
=
mmap
->
mem_start
+
(
blk
-
mmap
->
blk_start
)
*
f
->
blksize
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment