Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
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
Levin Zimmermann
go-fuse
Commits
a3b1fcbf
Commit
a3b1fcbf
authored
Jun 24, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add HandleMap and Handled for generic and checked int64 handle
conversion.
parent
0d29657a
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
216 additions
and
1 deletion
+216
-1
fuse/Makefile
fuse/Makefile
+2
-1
fuse/handle.go
fuse/handle.go
+118
-0
fuse/handle_test.go
fuse/handle_test.go
+96
-0
No files found.
fuse/Makefile
View file @
a3b1fcbf
...
...
@@ -9,7 +9,8 @@ MANUAL_GOFILES=api.go \
default.go
\
direntry.go
\
files.go
\
fuse.go
\
fuse.go
\
handle.go
\
latencymap.go
\
lockingfs.go
\
loggingfs.go
\
...
...
fuse/handle.go
0 → 100644
View file @
a3b1fcbf
package
fuse
import
(
"fmt"
"unsafe"
"sync"
)
// HandleMap translates objects in Go space to 64-bit handles that can
// be given out to -say- the linux kernel. It uses the free bits
// (16+3 on x64_64 and 32 on x86) to do an extra sanity check on the
// data. (Thanks to Russ Cox for this suggestion). In addition, it
// stores the object in a map, so the Go runtime will not garbage
// collect it.
//
// To use it, include Handled as first member of the structure
// you wish to export.
//
// This structure is thread-safe.
type
HandleMap
struct
{
mutex
sync
.
Mutex
handles
map
[
uint64
]
*
Handled
nextFree
uint32
}
func
(
me
*
HandleMap
)
verify
()
{
if
!
paranoia
{
return
}
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
for
k
,
v
:=
range
me
.
handles
{
if
DecodeHandle
(
k
)
!=
v
{
panic
(
"handle map out of sync"
)
}
}
}
func
NewHandleMap
()
*
HandleMap
{
return
&
HandleMap
{
handles
:
make
(
map
[
uint64
]
*
Handled
),
nextFree
:
1
,
// to make tests easier.
}
}
type
Handled
struct
{
check
uint32
}
func
(
me
*
HandleMap
)
Count
()
int
{
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
return
len
(
me
.
handles
)
}
func
(
me
*
HandleMap
)
Register
(
obj
*
Handled
)
(
handle
uint64
)
{
if
obj
.
check
!=
0
{
panic
(
"Object already has a handle."
)
}
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
handle
=
uint64
(
uintptr
(
unsafe
.
Pointer
(
obj
)))
check
:=
me
.
nextFree
me
.
nextFree
++
if
unsafe
.
Sizeof
(
obj
)
==
8
{
me
.
nextFree
=
me
.
nextFree
&
(
1
<<
(
64
-
48
+
3
)
-
1
)
rest
:=
(
handle
&^
(
1
<<
48
-
1
))
|
(
handle
&
(
1
<<
3
-
1
))
if
rest
!=
0
{
panic
(
"unaligned ptr or more than 48 bits in address"
)
}
handle
>>=
3
handle
|=
uint64
(
obj
.
check
)
<<
(
64
-
48
+
3
)
}
if
unsafe
.
Sizeof
(
obj
)
==
4
{
rest
:=
(
handle
&
0x3
)
if
rest
!=
0
{
panic
(
"unaligned ptr"
)
}
handle
|=
uint64
(
check
)
<<
32
}
obj
.
check
=
check
me
.
handles
[
handle
]
=
obj
return
handle
}
func
(
me
*
HandleMap
)
Forget
(
handle
uint64
)
(
val
*
Handled
)
{
val
=
DecodeHandle
(
handle
)
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
val
.
check
=
0
me
.
handles
[
handle
]
=
nil
,
false
return
val
}
func
DecodeHandle
(
handle
uint64
)
(
val
*
Handled
)
{
var
check
uint32
if
unsafe
.
Sizeof
(
val
)
==
8
{
ptrBits
:=
uintptr
(
handle
&
(
1
<<
45
-
1
))
check
=
uint32
(
handle
>>
45
)
val
=
(
*
Handled
)(
unsafe
.
Pointer
(
ptrBits
<<
3
))
}
if
unsafe
.
Sizeof
(
val
)
==
4
{
check
=
uint32
(
handle
>>
32
)
val
=
(
*
Handled
)(
unsafe
.
Pointer
(
uintptr
(
handle
&
((
1
<<
32
)
-
1
))))
}
if
val
.
check
!=
check
{
msg
:=
fmt
.
Sprintf
(
"handle check mismatch; handle has 0x%x, object has 0x%x"
,
check
,
val
.
check
)
panic
(
msg
)
}
return
val
}
fuse/handle_test.go
0 → 100644
View file @
a3b1fcbf
package
fuse
import
(
"log"
"strings"
"testing"
"unsafe"
)
func
markSeen
(
substr
string
)
{
if
r
:=
recover
();
r
!=
nil
{
s
:=
r
.
(
string
)
if
strings
.
Contains
(
s
,
substr
)
{
log
.
Println
(
"expected recovery from: "
,
r
)
}
else
{
panic
(
s
)
}
}
}
func
TestHandleMapDoubleRegister
(
t
*
testing
.
T
)
{
log
.
Println
(
"TestDoubleRegister"
)
defer
markSeen
(
"already has a handle"
)
hm
:=
NewHandleMap
()
hm
.
Register
(
&
Handled
{})
v
:=
&
Handled
{}
hm
.
Register
(
v
)
hm
.
Register
(
v
)
t
.
Error
(
"Double register did not panic"
)
}
func
TestHandleMapUnaligned
(
t
*
testing
.
T
)
{
hm
:=
NewHandleMap
()
b
:=
make
([]
byte
,
100
)
v
:=
(
*
Handled
)(
unsafe
.
Pointer
(
&
b
[
1
]))
defer
markSeen
(
"unaligned"
)
hm
.
Register
(
v
)
t
.
Error
(
"Unaligned register did not panic"
)
}
func
TestHandleMapPointerLayout
(
t
*
testing
.
T
)
{
if
unsafe
.
Sizeof
(
t
)
==
4
{
return
}
hm
:=
NewHandleMap
()
bogus
:=
uint64
(
1
)
<<
uint32
((
8
*
(
unsafe
.
Sizeof
(
t
)
-
1
)))
p
:=
uintptr
(
bogus
)
v
:=
(
*
Handled
)(
unsafe
.
Pointer
(
p
))
defer
markSeen
(
"48"
)
hm
.
Register
(
v
)
t
.
Error
(
"bogus register did not panic"
)
}
func
TestHandleMapBasic
(
t
*
testing
.
T
)
{
v
:=
new
(
Handled
)
hm
:=
NewHandleMap
()
h
:=
hm
.
Register
(
v
)
log
.
Printf
(
"Got handle 0x%x"
,
h
)
if
DecodeHandle
(
h
)
!=
v
{
t
.
Fatal
(
"address mismatch"
)
}
if
hm
.
Count
()
!=
1
{
t
.
Fatal
(
"count error"
)
}
hm
.
Forget
(
h
)
if
hm
.
Count
()
!=
0
{
t
.
Fatal
(
"count error"
)
}
}
func
TestHandleMapMultiple
(
t
*
testing
.
T
)
{
hm
:=
NewHandleMap
()
for
i
:=
0
;
i
<
10
;
i
++
{
v
:=
&
Handled
{}
h
:=
hm
.
Register
(
v
)
if
DecodeHandle
(
h
)
!=
v
{
t
.
Fatal
(
"address mismatch"
)
}
if
hm
.
Count
()
!=
i
+
1
{
t
.
Fatal
(
"count error"
)
}
}
}
func
TestHandleMapCheckFail
(
t
*
testing
.
T
)
{
defer
markSeen
(
"check mismatch"
)
v
:=
new
(
Handled
)
hm
:=
NewHandleMap
()
h
:=
hm
.
Register
(
v
)
DecodeHandle
(
h
|
(
uint64
(
1
)
<<
63
))
t
.
Error
(
"Borked decode did not panic"
)
}
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