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
c68cf93c
Commit
c68cf93c
authored
Mar 04, 2020
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
f7a8b297
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
73 additions
and
30 deletions
+73
-30
wcfs/client/wcfs.cpp
wcfs/client/wcfs.cpp
+71
-29
wcfs/client/wcfs.h
wcfs/client/wcfs.h
+2
-1
No files found.
wcfs/client/wcfs.cpp
View file @
c68cf93c
...
@@ -258,6 +258,15 @@ static global<error> errConnClosed = errors::New("connection closed");
...
@@ -258,6 +258,15 @@ static global<error> errConnClosed = errors::New("connection closed");
error
_Conn
::
close
()
{
error
_Conn
::
close
()
{
_Conn
&
wconn
=
*
this
;
_Conn
&
wconn
=
*
this
;
// lock virtmem early. TODO more granular virtmem locking (see __pin1 for
// details and why virt_lock currently goes first)
virt_lock
();
bool
virtUnlocked
=
false
;
defer
([
&
]()
{
if
(
!
virtUnlocked
)
virt_unlock
();
});
wconn
.
_atMu
.
RLock
();
wconn
.
_atMu
.
RLock
();
defer
([
&
]()
{
defer
([
&
]()
{
wconn
.
_atMu
.
RUnlock
();
wconn
.
_atMu
.
RUnlock
();
...
@@ -272,6 +281,7 @@ error _Conn::close() {
...
@@ -272,6 +281,7 @@ error _Conn::close() {
eret
=
err
;
eret
=
err
;
};
};
// mark wconn as closed, so that no new wconn.open might be spawned.
bool
alreadyClosed
=
false
;
bool
alreadyClosed
=
false
;
wconn
.
_filehMu
.
Lock
();
wconn
.
_filehMu
.
Lock
();
alreadyClosed
=
(
wconn
.
_downErr
==
errConnClosed
);
alreadyClosed
=
(
wconn
.
_downErr
==
errConnClosed
);
...
@@ -280,39 +290,54 @@ error _Conn::close() {
...
@@ -280,39 +290,54 @@ error _Conn::close() {
if
(
alreadyClosed
)
if
(
alreadyClosed
)
return
nil
;
return
nil
;
// close wlink and signal to pinner to stop outside of wconn.filehMu
// close all files - both that have no mappings and that still have opened
err
=
wconn
.
_wlink
->
close
();
// XXX ok under atMu?
// mappings. We have to close files before shutting down pinner, because
if
(
err
!=
nil
)
// wcfs might send pin messages due to file access by other clients. So to
reterr1
(
err
);
// avoid being killed we have to unwatch all files before stopping the
wconn
.
_pinCancel
();
// pinner.
err
=
wconn
.
_pinWG
->
wait
();
// XXX ok under atMu?
if
(
!
errors
::
Is
(
err
,
context
::
canceled
))
// canceled - ok
reterr1
(
err
);
// pinner is stopped - now close all files - both that have no mappings and
// that still have opened mappings.
//
//
// NOTE after file is closed mappings could continue to survive, but we can no
// NOTE after file is closed, its mappings could continue to survive, but
// longer maintain consistent view. For this reason we change mappings to
// we can no longer maintain consistent view. For this reason we change
// something that gives EFAULT on access. XXX implement
// mappings to give EFAULT on access.
while
(
1
)
{
FileH
f
=
nil
;
// pick up any fileh
wconn
.
_filehMu
.
Lock
();
wconn
.
_filehMu
.
Lock
();
defer
([
&
]()
{
if
(
!
wconn
.
_filehTab
.
empty
())
f
=
wconn
.
_filehTab
.
begin
()
->
second
;
wconn
.
_filehMu
.
Unlock
();
wconn
.
_filehMu
.
Unlock
();
});
// XXX f locking
if
(
f
==
nil
)
for
(
auto
_
:
wconn
.
_filehTab
)
{
break
;
// all closed
//zodb::Oid fid = _.first;
FileH
f
=
_
.
second
;
// XXX vvv only for !opening state
err
=
f
->
_headf
->
close
();
// XXX mark fileh as down so that fileh.close does not say "bad fd"
// close f under
// - XXX virt_lock
// - wconn.atMu.R
// - wconn.filehMu unlocked
err
=
f
->
_closeLocked
();
if
(
err
!=
nil
)
if
(
err
!=
nil
)
reterr1
(
err
);
reterr1
(
err
);
f
->
_headf
=
nil
;
// XXX stop watching f XXX ok under mu?
// wait for f close to complete, as it might be that f.close was called
// simultaneously to wconn.close
f
->
_closedq
.
recv
();
}
}
wconn
.
_filehTab
.
clear
();
// close wlink and signal to pinner to stop.
// we have to release virt_lock, to avoid deadlocking with pinner.
virtUnlocked
=
true
;
virt_unlock
();
err
=
wconn
.
_wlink
->
close
();
if
(
err
!=
nil
)
reterr1
(
err
);
wconn
.
_pinCancel
();
err
=
wconn
.
_pinWG
->
wait
();
if
(
!
errors
::
Is
(
err
,
context
::
canceled
))
// canceled - ok
reterr1
(
err
);
return
E
(
eret
);
return
E
(
eret
);
}
}
...
@@ -682,10 +707,10 @@ pair<FileH, error> _Conn::open(zodb::Oid foid) {
...
@@ -682,10 +707,10 @@ pair<FileH, error> _Conn::open(zodb::Oid foid) {
return
make_pair
(
nil
,
E
(
err
));
return
make_pair
(
nil
,
E
(
err
));
}
}
// XXX ensure f<foid>
@ wconn.at exists?
// XXX ensure f<foid>@ wconn.at exists?
// XXX else we get pins to non-exists state from wcfs.
// XXX else we get pins to non-exists state from wcfs.
//
//
// XXX -> better teach wcfs to reject "watch <foid> @at" for @at where f
oid
did not existed.
// XXX -> better teach wcfs to reject "watch <foid> @at" for @at where f did not existed.
retry:
retry:
FileH
f
;
bool
ok
;
FileH
f
;
bool
ok
;
...
@@ -758,6 +783,8 @@ retry:
...
@@ -758,6 +783,8 @@ retry:
if
(
f
->
_openErr
!=
nil
)
if
(
f
->
_openErr
!=
nil
)
return
make_pair
(
nil
,
E
(
f
->
_openErr
));
return
make_pair
(
nil
,
E
(
f
->
_openErr
));
// XXX recheck the wconn was not closed while the open was in progress
retok
=
true
;
retok
=
true
;
return
make_pair
(
f
,
nil
);
return
make_pair
(
f
,
nil
);
}
}
...
@@ -816,7 +843,7 @@ error _FileH::close() {
...
@@ -816,7 +843,7 @@ error _FileH::close() {
_FileH
&
fileh
=
*
this
;
_FileH
&
fileh
=
*
this
;
Conn
wconn
=
fileh
.
wconn
;
Conn
wconn
=
fileh
.
wconn
;
// lock virtmem
first
. TODO more granular virtmem locking (see __pin1 for
// lock virtmem
early
. TODO more granular virtmem locking (see __pin1 for
// details and why virt_lock currently goes first)
// details and why virt_lock currently goes first)
virt_lock
();
virt_lock
();
defer
([
&
]()
{
defer
([
&
]()
{
...
@@ -824,10 +851,25 @@ error _FileH::close() {
...
@@ -824,10 +851,25 @@ error _FileH::close() {
});
});
wconn
->
_atMu
.
RLock
();
wconn
->
_atMu
.
RLock
();
defer
([
&
]()
{
wconn
->
_atMu
.
RUnlock
();
});
return
fileh
.
_closeLocked
();
}
// _closeLocked serves FileH.close and Conn.close.
//
// Must be called with the following locks held by caller:
// - virt_lock
// - wconn.atMu
error
_FileH
::
_closeLocked
()
{
_FileH
&
fileh
=
*
this
;
Conn
wconn
=
fileh
.
wconn
;
wconn
->
_filehMu
.
Lock
();
wconn
->
_filehMu
.
Lock
();
defer
([
&
]()
{
defer
([
&
]()
{
wconn
->
_filehMu
.
Unlock
();
wconn
->
_filehMu
.
Unlock
();
wconn
->
_atMu
.
RUnlock
();
});
});
// fileh.close can be called several times. just return nil for second close.
// fileh.close can be called several times. just return nil for second close.
...
...
wcfs/client/wcfs.h
View file @
c68cf93c
...
@@ -261,9 +261,10 @@ public:
...
@@ -261,9 +261,10 @@ public:
public:
public:
error
close
();
error
close
();
pair
<
Mapping
,
error
>
mmap
(
int64_t
blk_start
,
int64_t
blk_len
,
VMA
*
vma
=
nil
);
pair
<
Mapping
,
error
>
mmap
(
int64_t
blk_start
,
int64_t
blk_len
,
VMA
*
vma
=
nil
);
string
String
()
const
;
error
_open
();
error
_open
();
string
String
()
const
;
error
_closeLocked
()
;
};
};
// Mapping represents one memory mapping of FileH.
// Mapping represents one memory mapping of FileH.
...
...
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