Skip to content

Commit a54ff8e

Browse files
E4242E4242
E4242
authored and
E4242
committed
Used in debugging imgfs
1 parent 6e7977b commit a54ff8e

22 files changed

+423
-32
lines changed

Makefile

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ build:
1212
bazel build runsc
1313
sudo cp ./bazel-bin/runsc/linux_amd64_pure_stripped/runsc /usr/local/bin
1414

15+
build_debug:
16+
sudo rm -rf /tmp/runsc
17+
bazel build -c dbg runsc
18+
sudo cp ./bazel-bin/runsc/linux_amd64_pure_debug/runsc /usr/local/bin
19+
20+
1521
docker:
1622
sudo apt-get update
1723
sudo apt-get -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

WORKSPACE

+6
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ go_repository(
163163
version = "v0.0.0-20171111001504-be1fbeda1936",
164164
)
165165

166+
go_repository(
167+
name = "com_github_spaolacci_murmur3",
168+
importpath = "github.com/spaolacci/murmur3",
169+
commit = "539464a789e9b9f01bc857458ffe2c5c1a2ed382",
170+
)
171+
166172
go_repository(
167173
name = "org_golang_x_crypto",
168174
importpath = "golang.org/x/crypto",

pkg/filter/BUILD

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package(licenses = ["notice"])
2+
3+
load("@io_bazel_rules_go//go:def.bzl", "go_test")
4+
load("//tools/go_stateify:defs.bzl", "go_library")
5+
6+
go_library(
7+
name = "filter",
8+
srcs = [
9+
"filter.go",
10+
"bloom.go",
11+
],
12+
importpath = "gvisor.dev/gvisor/pkg/filter",
13+
visibility = ["//pkg/sentry:internal"],
14+
deps = [
15+
"@com_github_spaolacci_murmur3//:go_default_library",
16+
],
17+
)

pkg/filter/bloom.go

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package filter
2+
3+
import (
4+
"github.com/spaolacci/murmur3"
5+
"math"
6+
)
7+
8+
const(
9+
DEFAULT_PROB = 0.000001
10+
)
11+
12+
// TODO: Hash in directories
13+
14+
// BloomFilter is a struct for creating a Bloom filter for an image file. A
15+
// A Bloom filter specifies whether a specific file path is "definitily" not
16+
// in the image file or is "maybe" in the file with a certain probability.
17+
// This struct implements the Filter interface.
18+
type BloomFilter struct {
19+
// FPProb (False Positive Probability) is the desired probability of a false positive in the filter
20+
FPProb float64
21+
22+
// NumHashes represents the number of hash functions for this bloom filter (k)
23+
NumHashes uint64
24+
25+
// NumElem represents the number of elements in this filter (n)
26+
NumElem uint64
27+
28+
// FilterSize represents the number of bits in this filter (m)
29+
FilterSize uint64
30+
31+
// BitSet is the array of bits that implements a bloom filter
32+
BitSet []bool
33+
}
34+
35+
36+
// Initialize implements Filter.Initialize. Assumes b.NumElem is set to number of expected elements
37+
// and FPProb is set
38+
func (b *BloomFilter) Initialize() {
39+
// Check for error conditions
40+
if (b.NumElem < 1) {
41+
// Return error
42+
return
43+
}
44+
45+
// Initialize FPProb
46+
if (b.FPProb == 0) { b.FPProb = DEFAULT_PROB }
47+
48+
// Compute filter size and initialize bitarray
49+
b.FilterSize = b.calcFilterSize()
50+
b.BitSet = make([]bool, b.FilterSize)
51+
52+
// Compute number of hashes (k)
53+
b.NumHashes = b.calcNumHashes()
54+
55+
}
56+
57+
// calcFilterSize calculates the optimal size of bit array given prob and elements
58+
// Assumes FPProb and NumElem is set
59+
// m = ceil((n*log(p)) / log(1 / pow(2, log(2)))
60+
func (b *BloomFilter) calcFilterSize() uint64 {
61+
return uint64(math.Ceil((float64(b.NumElem) * math.Log(b.FPProb)) / math.Log(1 / math.Pow(2, math.Log(2)))))
62+
}
63+
64+
// calcNumHashes calculates the aptimal number of hashes given the filter size and the number of elements
65+
// Assumes FilterSize and NumElem set
66+
// k = round((m / n) * log(2))
67+
func (b *BloomFilter) calcNumHashes() uint64 {
68+
return uint64(math.Round(float64(b.FilterSize / b.NumElem) * math.Log(2)))
69+
}
70+
71+
// AddElement implements Filter.AddElement
72+
func (b *BloomFilter) AddElement(elem []byte) {
73+
// Get the hashed value of the element
74+
h1, h2 := b.hashElement(elem)
75+
76+
intHash := h1
77+
78+
// Set bits in bitset to represent added element -> TODO: Does int cast affect anything?
79+
for i:=0; i < int(b.NumHashes); i++ {
80+
intHash += (b.NumHashes*h2)
81+
bitToSet := intHash % b.FilterSize
82+
b.setBit(bitToSet)
83+
}
84+
85+
}
86+
87+
// hashElement hashes the elem passed in based on the murmur hash function
88+
// TODO: Unsure if Sum128 is correct
89+
func (b *BloomFilter) hashElement(elem []byte) (uint64, uint64) {
90+
return murmur3.Sum128(elem)
91+
}
92+
93+
// setBits will set bit at position to true
94+
func (b *BloomFilter) setBit(position uint64) {
95+
b.BitSet[position] = true
96+
}
97+
98+
// RemoveElement removes an element from the filter
99+
//
100+
//
101+
func (b *BloomFilter) RemoveElement() {
102+
// No-op for bloom filter
103+
}
104+
105+
// TestElement implements Filter.TestElement
106+
func (b *BloomFilter) TestElement(elem []byte) bool {
107+
// TODO: Make this modular with add element
108+
// Get the hashed value of the element
109+
h1, h2 := b.hashElement(elem)
110+
111+
intHash := h1
112+
113+
// TODO: Look into this, may be perf issue..
114+
//var testFilter = make([]bool, b.FilterSize)
115+
116+
// Create a test bit array
117+
//copy(testFilter, b.BitSet)
118+
119+
// Set bits in bitset to represent added element
120+
for i:=0; i < int(b.NumHashes); i++ {
121+
intHash += (b.NumHashes*h2)
122+
bitToSet := intHash % b.FilterSize
123+
124+
// Check if bitset in filter
125+
if (!b.BitSet[bitToSet]) {
126+
return false
127+
}
128+
}
129+
130+
// Test if found by checking that all bits set are same as original
131+
return true
132+
}
133+
134+
// checkBitSetEquality checks if a test bloom filter equals the current bloom filter
135+
func (b *BloomFilter) checkBitSetEquality(test []bool) (bool) {
136+
if (len(test) != len(b.BitSet)) { return false }
137+
138+
for i:=0; i < int(b.FilterSize); i++ {
139+
if (b.BitSet[i] != test[i]) { return false }
140+
}
141+
142+
return true
143+
}

pkg/filter/filter.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Package filter implements a library for constructing a filter for img layer
2+
package filter
3+
4+
5+
import (
6+
)
7+
8+
type Filter interface {
9+
// Initialize creates a filter with the specified initial conditions
10+
//
11+
//
12+
Initialize()
13+
14+
// AddElement adds an element to the filter by hashing the element into the filter
15+
//
16+
// elem: Represents an element to add to the bloom filter
17+
AddElement(elem []byte)
18+
19+
// RemoveElement removes an element from the filter
20+
//
21+
//
22+
RemoveElement()
23+
24+
// TestElement checks if the specific element exists in data structure
25+
//
26+
// Return: False if not present in filter, true if possibly present
27+
TestElement(elem []byte) bool
28+
29+
}
30+
31+
// FilterMetadata is a struct that depicts what will get written to the image metadata for a filter
32+
type FilterMetadata struct {
33+
// Active indicates whether or not a bloom filter is enforced for this layer
34+
Active bool
35+
36+
// Name represents the name of the filter used for this layer. Must be same as in ContainerFS
37+
Name string
38+
39+
// FilterStructSize is the numbber of bytes (bits?) that the BloomFilter struct takes up
40+
FilterLoc int64
41+
42+
// FilterStructSize is the size in bytes of the encoded structure
43+
FilterStructSize int64
44+
}

pkg/sentry/fs/fsutil/host_file_mapper.go

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ func (f *HostFileMapper) DecRefOn(mr memmap.MappableRange) {
122122
//
123123
// Preconditions: The caller must hold a reference on all offsets in fr.
124124
func (f *HostFileMapper) MapInternal(fr platform.FileRange, fd int, write bool) (safemem.BlockSeq, error) {
125+
log.Infof("Mapping internally from host")
125126
chunks := ((fr.End + chunkMask) >> chunkShift) - (fr.Start >> chunkShift)
126127
f.mapsMu.Lock()
127128
defer f.mapsMu.Unlock()

pkg/sentry/fs/fsutil/inode_cached.go

+2
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ func (rw *inodeReadWriter) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error) {
616616
mr := memmap.MappableRange{uint64(rw.offset), uint64(end)}
617617
switch {
618618
case seg.Ok():
619+
log.Infof("Get internal mappings to cache")
619620
// Get internal mappings from the cache.
620621
ims, err := mem.MapInternal(seg.FileRangeOf(seg.Range().Intersect(mr)), usermem.Read)
621622
if err != nil {
@@ -723,6 +724,7 @@ func (rw *inodeReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error
723724
mr := memmap.MappableRange{uint64(rw.offset), uint64(end)}
724725
switch {
725726
case seg.Ok() && seg.Start() < mr.End:
727+
log.Infof("Get mappings to cache -")
726728
// Get internal mappings from the cache.
727729
segMR := seg.Range().Intersect(mr)
728730
ims, err := mf.MapInternal(seg.FileRangeOf(segMR), usermem.Write)

pkg/sentry/fs/imgfs/BUILD

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ go_library(
1313
"util.go",
1414
"util_unsafe.go",
1515
],
16-
importpath = "gvisor.googlesource.com/gvisor/pkg/sentry/fs/imgfs",
16+
importpath = "gvisor.dev/gvisor/pkg/sentry/fs/imgfs",
1717
visibility = ["//pkg/sentry:internal"],
1818
deps = [
1919
"//pkg/abi/linux",
@@ -23,6 +23,7 @@ go_library(
2323
"//pkg/metric",
2424
"//pkg/refs",
2525
"//pkg/secio",
26+
"//pkg/filter",
2627
"//pkg/sentry/arch",
2728
"//pkg/sentry/context",
2829
"//pkg/sentry/device",

0 commit comments

Comments
 (0)