From 0f6db15c59e3b46a46e3eafa2b0e561b90a7b1b7 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 12:47:00 +1100 Subject: [PATCH 01/13] buffer: give OutMessage's public API a makeover. Use int where appropriate, fix up documentation, and clarify. Delete the implementation where it will soon need to change. --- internal/buffer/out_message.go | 86 ++++++++++------------------------ 1 file changed, 26 insertions(+), 60 deletions(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index 7392cf0..48721c2 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -23,14 +23,9 @@ import ( "github.com/jacobsa/fuse/internal/fusekernel" ) -const outHeaderSize = unsafe.Sizeof(fusekernel.OutHeader{}) - -// OutMessage structs begin life with Len() == OutMessageInitialSize. -const OutMessageInitialSize = outHeaderSize - -// We size out messages to be large enough to hold a header for the response -// plus the largest read that may come in. -const outMessageSize = outHeaderSize + MaxReadSize +// OutMessageHeaderSize is the size of the leading header in every +// properly-constructed OutMessage. Reset brings the message back to this size. +const OutMessageHeaderSize = unsafe.Sizeof(fusekernel.OutHeader{}) // OutMessage provides a mechanism for constructing a single contiguous fuse // message from multiple segments, where the first segment is always a @@ -38,8 +33,6 @@ const outMessageSize = outHeaderSize + MaxReadSize // // Must be initialized with Reset. type OutMessage struct { - offset uintptr - storage [outMessageSize]byte } // Make sure alignment works out correctly, at least for the header. @@ -53,57 +46,30 @@ func init() { } } -// Reset the message so that it is ready to be used again. Afterward, the -// contents are solely a zeroed header. -func (m *OutMessage) Reset() { - m.offset = OutMessageInitialSize - memclr(unsafe.Pointer(&m.storage), OutMessageInitialSize) -} +// Reset resets m so that it's ready to be used again. Afterward, the contents +// are solely a zeroed fusekernel.OutHeader struct. +func (m *OutMessage) Reset() -// Return a pointer to the header at the start of the message. -func (b *OutMessage) OutHeader() (h *fusekernel.OutHeader) { - h = (*fusekernel.OutHeader)(unsafe.Pointer(&b.storage)) - return -} +// OutHeader returns a pointer to the header at the start of the message. +func (m *OutMessage) OutHeader() (h *fusekernel.OutHeader) -// Grow the buffer by the supplied number of bytes, returning a pointer to the -// start of the new segment, which is zeroed. If there is no space left, return -// the nil pointer. -func (b *OutMessage) Grow(size uintptr) (p unsafe.Pointer) { - p = b.GrowNoZero(size) - if p != nil { - memclr(p, size) - } +// Grow grows m's buffer by the given number of bytes, returning a pointer to +// the start of the new segment, which is guaranteed to be zeroed. If there is +// insufficient space, it returns nil. +func (b *OutMessage) Grow(n int) (p unsafe.Pointer) - return -} +// GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use +// with caution! +func (b *OutMessage) GrowNoZero(n int) (p unsafe.Pointer) -// Equivalent to Grow, except the new segment is not zeroed. Use with caution! -func (b *OutMessage) GrowNoZero(size uintptr) (p unsafe.Pointer) { - if outMessageSize-b.offset < size { - return - } +// ShrinkTo shrinks m to the given size. It panics if the size is greater than +// Len() or less than OutMessageHeaderSize. +func (b *OutMessage) ShrinkTo(n int) - p = unsafe.Pointer(uintptr(unsafe.Pointer(&b.storage)) + b.offset) - b.offset += size - - return -} - -// Shrink to the supplied size. Panic if the size is greater than Len() or less -// than OutMessageInitialSize. -func (b *OutMessage) ShrinkTo(n uintptr) { - if n < OutMessageInitialSize || n > b.offset { - panic(fmt.Sprintf("ShrinkTo(%d) out of range for offset %d", n, b.offset)) - } - - b.offset = n -} - -// Equivalent to growing by the length of p, then copying p over the new -// segment. Panics if there is not enough room available. +// Append is equivalent to growing by len(src), then copying src over the new +// segment. Int panics if there is not enough room available. func (b *OutMessage) Append(src []byte) { - p := b.GrowNoZero(uintptr(len(src))) + p := b.GrowNoZero(len(src)) if p == nil { panic(fmt.Sprintf("Can't grow %d bytes", len(src))) } @@ -114,10 +80,9 @@ func (b *OutMessage) Append(src []byte) { return } -// Equivalent to growing by the length of s, then copying s over the new -// segment. Panics if there is not enough room available. +// AppendString is like Append, but accepts string input. func (b *OutMessage) AppendString(src string) { - p := b.GrowNoZero(uintptr(len(src))) + p := b.GrowNoZero(len(src)) if p == nil { panic(fmt.Sprintf("Can't grow %d bytes", len(src))) } @@ -128,12 +93,13 @@ func (b *OutMessage) AppendString(src string) { return } -// Return the current size of the buffer. +// Len returns the current size of the message, including the leading header. func (b *OutMessage) Len() int { return int(b.offset) } -// Return a reference to the current contents of the buffer. +// Bytes returns a reference to the current contents of the buffer, including +// the leading header. func (b *OutMessage) Bytes() []byte { return b.storage[:int(b.offset)] } From 6e5247d16d15ea2723a050793bb1617d47b378df Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 12:49:25 +1100 Subject: [PATCH 02/13] buffer_test: make use of the new API. --- internal/buffer/out_message_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/buffer/out_message_test.go b/internal/buffer/out_message_test.go index d411461..b693ea2 100644 --- a/internal/buffer/out_message_test.go +++ b/internal/buffer/out_message_test.go @@ -101,7 +101,7 @@ func TestOutMessageAppend(t *testing.T) { om.Append(wantPayload[4:]) // The result should be a zeroed header followed by the desired payload. - const wantLen = int(OutMessageInitialSize) + len(wantPayloadStr) + const wantLen = OutMessageHeaderSize + len(wantPayloadStr) if got, want := om.Len(), wantLen; got != want { t.Errorf("om.Len() = %d, want %d", got, want) @@ -113,7 +113,7 @@ func TestOutMessageAppend(t *testing.T) { } want := append( - make([]byte, OutMessageInitialSize), + make([]byte, OutMessageHeaderSize), wantPayload...) if !bytes.Equal(b, want) { @@ -131,7 +131,7 @@ func TestOutMessageAppendString(t *testing.T) { om.AppendString(wantPayload[4:]) // The result should be a zeroed header followed by the desired payload. - const wantLen = int(OutMessageInitialSize) + len(wantPayload) + const wantLen = OutMessageHeaderSize + len(wantPayload) if got, want := om.Len(), wantLen; got != want { t.Errorf("om.Len() = %d, want %d", got, want) @@ -143,7 +143,7 @@ func TestOutMessageAppendString(t *testing.T) { } want := append( - make([]byte, OutMessageInitialSize), + make([]byte, OutMessageHeaderSize), wantPayload...) if !bytes.Equal(b, want) { @@ -159,10 +159,10 @@ func TestOutMessageShrinkTo(t *testing.T) { om.AppendString("burrito") // Shrink it. - om.ShrinkTo(OutMessageInitialSize + uintptr(len("taco"))) + om.ShrinkTo(OutMessageHeaderSize + len("taco")) // The result should be a zeroed header followed by "taco". - const wantLen = int(OutMessageInitialSize) + len("taco") + const wantLen = OutMessageHeaderSize + len("taco") if got, want := om.Len(), wantLen; got != want { t.Errorf("om.Len() = %d, want %d", got, want) @@ -174,7 +174,7 @@ func TestOutMessageShrinkTo(t *testing.T) { } want := append( - make([]byte, OutMessageInitialSize), + make([]byte, OutMessageHeaderSize), "taco"...) if !bytes.Equal(b, want) { @@ -233,7 +233,7 @@ func TestOutMessageReset(t *testing.T) { om.Reset() // Check that the length was updated. - if got, want := int(om.Len()), int(OutMessageInitialSize); got != want { + if got, want := om.Len(), OutMessageHeaderSize; got != want { t.Fatalf("om.Len() = %d, want %d", got, want) } @@ -269,7 +269,7 @@ func TestOutMessageGrow(t *testing.T) { t.Fatalf("fillWithGarbage: %v", err) } - om.ShrinkTo(OutMessageInitialSize) + om.ShrinkTo(OutMessageHeaderSize) } // Call Grow. @@ -278,7 +278,7 @@ func TestOutMessageGrow(t *testing.T) { } // Check the resulting length in two ways. - const wantLen = int(payloadSize + OutMessageInitialSize) + const wantLen = payloadSize + OutMessageHeaderSize if got, want := om.Len(), wantLen; got != want { t.Errorf("om.Len() = %d, want %d", got) } @@ -289,7 +289,7 @@ func TestOutMessageGrow(t *testing.T) { } // Check that the payload was zeroed. - for i, x := range b[OutMessageInitialSize:] { + for i, x := range b[OutMessageHeaderSize:] { if x != 0 { t.Fatalf("non-zero byte 0x%02x at payload offset %d", x, i) } @@ -331,7 +331,7 @@ func BenchmarkOutMessageGrowShrink(b *testing.B) { var om OutMessage for i := 0; i < b.N; i++ { om.Grow(MaxReadSize) - om.ShrinkTo(OutMessageInitialSize) + om.ShrinkTo(OutMessageHeaderSize) } b.SetBytes(int64(MaxReadSize)) @@ -349,7 +349,7 @@ func BenchmarkOutMessageGrowShrink(b *testing.B) { for i := 0; i < b.N; i++ { oms[i%numMessages].Grow(MaxReadSize) - oms[i%numMessages].ShrinkTo(OutMessageInitialSize) + oms[i%numMessages].ShrinkTo(OutMessageHeaderSize) } b.SetBytes(int64(MaxReadSize)) From 9eb5e0793f4abb51814df2667aa50e0b6125b12f Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 12:53:32 +1100 Subject: [PATCH 03/13] buffer: define OutMessage's contents. --- internal/buffer/out_message.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index 48721c2..f867015 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -33,12 +33,18 @@ const OutMessageHeaderSize = unsafe.Sizeof(fusekernel.OutHeader{}) // // Must be initialized with Reset. type OutMessage struct { + // The offset into payload to which we're currently writing. + payloadOffset int + + header [OutMessageHeaderSize]byte + payload [MaxReadSize]byte } -// Make sure alignment works out correctly, at least for the header. +// Make sure that the header field is aligned correctly for +// fusekernel.OutHeader type punning. func init() { a := unsafe.Alignof(OutMessage{}) - o := unsafe.Offsetof(OutMessage{}.storage) + o := unsafe.Offsetof(OutMessage{}.header) e := unsafe.Alignof(fusekernel.OutHeader{}) if a%e != 0 || o%e != 0 { @@ -46,6 +52,18 @@ func init() { } } +// Make sure that the header and payload are contiguous. +func init() { + a := unsafe.Offsetof(OutMessage{}.header) + OutMessageHeaderSize + b := unsafe.Offsetof(OutMessage{}.payload) + + if a != b { + log.Panicf( + "header ends at offset %d, but payload starts at offset %d", + a, b) + } +} + // Reset resets m so that it's ready to be used again. Afterward, the contents // are solely a zeroed fusekernel.OutHeader struct. func (m *OutMessage) Reset() From 98a2b634bf76ea398c2d197638fde9c3ea76e1ad Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 12:54:54 +1100 Subject: [PATCH 04/13] OutMessage.Reset --- internal/buffer/out_message.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index f867015..38bbc85 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -66,7 +66,10 @@ func init() { // Reset resets m so that it's ready to be used again. Afterward, the contents // are solely a zeroed fusekernel.OutHeader struct. -func (m *OutMessage) Reset() +func (m *OutMessage) Reset() { + m.payloadOffset = 0 + memclr(unsafe.Pointer(&m.header), OutMessageHeaderSize) +} // OutHeader returns a pointer to the header at the start of the message. func (m *OutMessage) OutHeader() (h *fusekernel.OutHeader) From 6f4af617346904487bf2ce578ed9a25ca93dd450 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 12:55:34 +1100 Subject: [PATCH 05/13] buffer: consistently use 'm' for OutMessage receivers. --- internal/buffer/out_message.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index 38bbc85..eaa1bfd 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -77,20 +77,20 @@ func (m *OutMessage) OutHeader() (h *fusekernel.OutHeader) // Grow grows m's buffer by the given number of bytes, returning a pointer to // the start of the new segment, which is guaranteed to be zeroed. If there is // insufficient space, it returns nil. -func (b *OutMessage) Grow(n int) (p unsafe.Pointer) +func (m *OutMessage) Grow(n int) (p unsafe.Pointer) // GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use // with caution! -func (b *OutMessage) GrowNoZero(n int) (p unsafe.Pointer) +func (m *OutMessage) GrowNoZero(n int) (p unsafe.Pointer) // ShrinkTo shrinks m to the given size. It panics if the size is greater than // Len() or less than OutMessageHeaderSize. -func (b *OutMessage) ShrinkTo(n int) +func (m *OutMessage) ShrinkTo(n int) // Append is equivalent to growing by len(src), then copying src over the new // segment. Int panics if there is not enough room available. -func (b *OutMessage) Append(src []byte) { - p := b.GrowNoZero(len(src)) +func (m *OutMessage) Append(src []byte) { + p := m.GrowNoZero(len(src)) if p == nil { panic(fmt.Sprintf("Can't grow %d bytes", len(src))) } @@ -102,8 +102,8 @@ func (b *OutMessage) Append(src []byte) { } // AppendString is like Append, but accepts string input. -func (b *OutMessage) AppendString(src string) { - p := b.GrowNoZero(len(src)) +func (m *OutMessage) AppendString(src string) { + p := m.GrowNoZero(len(src)) if p == nil { panic(fmt.Sprintf("Can't grow %d bytes", len(src))) } @@ -115,12 +115,12 @@ func (b *OutMessage) AppendString(src string) { } // Len returns the current size of the message, including the leading header. -func (b *OutMessage) Len() int { - return int(b.offset) +func (m *OutMessage) Len() int { + return OutMessageHeaderSize + m.payloadOffset } // Bytes returns a reference to the current contents of the buffer, including // the leading header. -func (b *OutMessage) Bytes() []byte { - return b.storage[:int(b.offset)] +func (m *OutMessage) Bytes() []byte { + return int(m.offset) } From 0a22738acf1afcb3b0b00547ca611e9490baa97d Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 12:57:08 +1100 Subject: [PATCH 06/13] OutMessage.Bytes --- internal/buffer/out_message.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index eaa1bfd..02e1bf6 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -25,7 +25,7 @@ import ( // OutMessageHeaderSize is the size of the leading header in every // properly-constructed OutMessage. Reset brings the message back to this size. -const OutMessageHeaderSize = unsafe.Sizeof(fusekernel.OutHeader{}) +const OutMessageHeaderSize = int(unsafe.Sizeof(fusekernel.OutHeader{})) // OutMessage provides a mechanism for constructing a single contiguous fuse // message from multiple segments, where the first segment is always a @@ -54,7 +54,7 @@ func init() { // Make sure that the header and payload are contiguous. func init() { - a := unsafe.Offsetof(OutMessage{}.header) + OutMessageHeaderSize + a := unsafe.Offsetof(OutMessage{}.header) + uintptr(OutMessageHeaderSize) b := unsafe.Offsetof(OutMessage{}.payload) if a != b { @@ -68,7 +68,7 @@ func init() { // are solely a zeroed fusekernel.OutHeader struct. func (m *OutMessage) Reset() { m.payloadOffset = 0 - memclr(unsafe.Pointer(&m.header), OutMessageHeaderSize) + memclr(unsafe.Pointer(&m.header), uintptr(OutMessageHeaderSize)) } // OutHeader returns a pointer to the header at the start of the message. @@ -122,5 +122,12 @@ func (m *OutMessage) Len() int { // Bytes returns a reference to the current contents of the buffer, including // the leading header. func (m *OutMessage) Bytes() []byte { - return int(m.offset) + l := m.Len() + sh := reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(&m.header)), + Len: l, + Cap: l, + } + + return *(*[]byte)(unsafe.Pointer(&sh)) } From a7c1a1474af27e340de630b3bf99866a871d3173 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 12:58:55 +1100 Subject: [PATCH 07/13] buffer_test: fix build errors. --- internal/buffer/out_message_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/buffer/out_message_test.go b/internal/buffer/out_message_test.go index b693ea2..b6bae8b 100644 --- a/internal/buffer/out_message_test.go +++ b/internal/buffer/out_message_test.go @@ -304,7 +304,7 @@ func BenchmarkOutMessageReset(b *testing.B) { om.Reset() } - b.SetBytes(int64(unsafe.Offsetof(om.storage)) + int64(om.offset)) + b.SetBytes(int64(unsafe.Offsetof(om.payload))) }) // Many megabytes worth of buffers, which should defeat the CPU cache. @@ -321,7 +321,7 @@ func BenchmarkOutMessageReset(b *testing.B) { oms[i%numMessages].Reset() } - b.SetBytes(int64(unsafe.Offsetof(oms[0].storage)) + int64(oms[0].offset)) + b.SetBytes(int64(unsafe.Offsetof(oms[0].payload))) }) } From d1ed507a5a624811ce873c6361471e1019243f26 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:01:45 +1100 Subject: [PATCH 08/13] OutMessage.GrowNoZero --- internal/buffer/out_message.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index 02e1bf6..49a43ca 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -81,7 +81,18 @@ func (m *OutMessage) Grow(n int) (p unsafe.Pointer) // GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use // with caution! -func (m *OutMessage) GrowNoZero(n int) (p unsafe.Pointer) +func (m *OutMessage) GrowNoZero(n int) (p unsafe.Pointer) { + // Will we overflow the buffer? + o := m.payloadOffset + if len(m.payload)-o < n { + return + } + + p = unsafe.Pointer(uintptr(unsafe.Pointer(&m.payload)) + uintptr(o)) + m.payloadOffset = o + n + + return +} // ShrinkTo shrinks m to the given size. It panics if the size is greater than // Len() or less than OutMessageHeaderSize. From e03fa52bbfd7b6f046ec8640051628efd9330fcc Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:02:19 +1100 Subject: [PATCH 09/13] OutMessage.Grow --- internal/buffer/out_message.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index 49a43ca..a503dcc 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -77,7 +77,14 @@ func (m *OutMessage) OutHeader() (h *fusekernel.OutHeader) // Grow grows m's buffer by the given number of bytes, returning a pointer to // the start of the new segment, which is guaranteed to be zeroed. If there is // insufficient space, it returns nil. -func (m *OutMessage) Grow(n int) (p unsafe.Pointer) +func (m *OutMessage) Grow(n int) (p unsafe.Pointer) { + p = m.GrowNoZero(n) + if p != nil { + memclr(p, uintptr(n)) + } + + return +} // GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use // with caution! From 849f53b080840c072994bdff6af0cbf7155671ef Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:04:02 +1100 Subject: [PATCH 10/13] OutMessage.ShrinkTo --- internal/buffer/out_message.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index a503dcc..b94ea50 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -103,7 +103,16 @@ func (m *OutMessage) GrowNoZero(n int) (p unsafe.Pointer) { // ShrinkTo shrinks m to the given size. It panics if the size is greater than // Len() or less than OutMessageHeaderSize. -func (m *OutMessage) ShrinkTo(n int) +func (m *OutMessage) ShrinkTo(n int) { + if n < OutMessageHeaderSize || n > m.Len() { + panic(fmt.Sprintf( + "ShrinkTo(%d) out of range (current Len: %d)", + n, + m.Len())) + } + + m.payloadOffset = n - OutMessageHeaderSize +} // Append is equivalent to growing by len(src), then copying src over the new // segment. Int panics if there is not enough room available. From d1ff915b0b5f2c10e2a3b84f6c9d39c80fea9038 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:04:54 +1100 Subject: [PATCH 11/13] OutMessage.OutHeader --- internal/buffer/out_message.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index b94ea50..d5e3aff 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -72,7 +72,9 @@ func (m *OutMessage) Reset() { } // OutHeader returns a pointer to the header at the start of the message. -func (m *OutMessage) OutHeader() (h *fusekernel.OutHeader) +func (m *OutMessage) OutHeader() *fusekernel.OutHeader { + return (*fusekernel.OutHeader)(unsafe.Pointer(&m.header)) +} // Grow grows m's buffer by the given number of bytes, returning a pointer to // the start of the new segment, which is guaranteed to be zeroed. If there is From 0cd689f56078d066190bc66e8a9bcd7d4b27c9f5 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:06:39 +1100 Subject: [PATCH 12/13] buffer: simplify storage of the header. --- internal/buffer/out_message.go | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index d5e3aff..bd46ae2 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -36,22 +36,10 @@ type OutMessage struct { // The offset into payload to which we're currently writing. payloadOffset int - header [OutMessageHeaderSize]byte + header fusekernel.OutHeader payload [MaxReadSize]byte } -// Make sure that the header field is aligned correctly for -// fusekernel.OutHeader type punning. -func init() { - a := unsafe.Alignof(OutMessage{}) - o := unsafe.Offsetof(OutMessage{}.header) - e := unsafe.Alignof(fusekernel.OutHeader{}) - - if a%e != 0 || o%e != 0 { - log.Panicf("Bad alignment or offset: %d, %d, need %d", a, o, e) - } -} - // Make sure that the header and payload are contiguous. func init() { a := unsafe.Offsetof(OutMessage{}.header) + uintptr(OutMessageHeaderSize) @@ -73,7 +61,7 @@ func (m *OutMessage) Reset() { // OutHeader returns a pointer to the header at the start of the message. func (m *OutMessage) OutHeader() *fusekernel.OutHeader { - return (*fusekernel.OutHeader)(unsafe.Pointer(&m.header)) + return &m.header } // Grow grows m's buffer by the given number of bytes, returning a pointer to From 95e4d8b12e38c9b2c2036dfdfc3aa1c7f962a1a9 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:17:49 +1100 Subject: [PATCH 13/13] conversions.go: use the new buffer API. --- conversions.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/conversions.go b/conversions.go index 78ded6d..b1246bc 100644 --- a/conversions.go +++ b/conversions.go @@ -279,7 +279,7 @@ func convertInMessage( o = to readSize := int(in.Size) - p := outMsg.GrowNoZero(uintptr(readSize)) + p := outMsg.GrowNoZero(readSize) if p == nil { err = fmt.Errorf("Can't grow for %d-byte read", readSize) return @@ -305,7 +305,7 @@ func convertInMessage( o = to readSize := int(in.Size) - p := outMsg.GrowNoZero(uintptr(readSize)) + p := outMsg.GrowNoZero(readSize) if p == nil { err = fmt.Errorf("Can't grow for %d-byte read", readSize) return @@ -469,7 +469,7 @@ func (c *Connection) kernelResponse( // the header, because on OS X the kernel otherwise returns EINVAL when we // attempt to write an error response with a length that extends beyond the // header. - m.ShrinkTo(buffer.OutMessageInitialSize) + m.ShrinkTo(buffer.OutMessageHeaderSize) } // Otherwise, fill in the rest of the response. @@ -489,45 +489,45 @@ func (c *Connection) kernelResponseForOp( // Create the appropriate output message switch o := op.(type) { case *fuseops.LookUpInodeOp: - size := fusekernel.EntryOutSize(c.protocol) + size := int(fusekernel.EntryOutSize(c.protocol)) out := (*fusekernel.EntryOut)(m.Grow(size)) convertChildInodeEntry(&o.Entry, out) case *fuseops.GetInodeAttributesOp: - size := fusekernel.AttrOutSize(c.protocol) + size := int(fusekernel.AttrOutSize(c.protocol)) out := (*fusekernel.AttrOut)(m.Grow(size)) out.AttrValid, out.AttrValidNsec = convertExpirationTime( o.AttributesExpiration) convertAttributes(o.Inode, &o.Attributes, &out.Attr) case *fuseops.SetInodeAttributesOp: - size := fusekernel.AttrOutSize(c.protocol) + size := int(fusekernel.AttrOutSize(c.protocol)) out := (*fusekernel.AttrOut)(m.Grow(size)) out.AttrValid, out.AttrValidNsec = convertExpirationTime( o.AttributesExpiration) convertAttributes(o.Inode, &o.Attributes, &out.Attr) case *fuseops.MkDirOp: - size := fusekernel.EntryOutSize(c.protocol) + size := int(fusekernel.EntryOutSize(c.protocol)) out := (*fusekernel.EntryOut)(m.Grow(size)) convertChildInodeEntry(&o.Entry, out) case *fuseops.MkNodeOp: - size := fusekernel.EntryOutSize(c.protocol) + size := int(fusekernel.EntryOutSize(c.protocol)) out := (*fusekernel.EntryOut)(m.Grow(size)) convertChildInodeEntry(&o.Entry, out) case *fuseops.CreateFileOp: - eSize := fusekernel.EntryOutSize(c.protocol) + eSize := int(fusekernel.EntryOutSize(c.protocol)) e := (*fusekernel.EntryOut)(m.Grow(eSize)) convertChildInodeEntry(&o.Entry, e) - oo := (*fusekernel.OpenOut)(m.Grow(unsafe.Sizeof(fusekernel.OpenOut{}))) + oo := (*fusekernel.OpenOut)(m.Grow(int(unsafe.Sizeof(fusekernel.OpenOut{})))) oo.Fh = uint64(o.Handle) case *fuseops.CreateSymlinkOp: - size := fusekernel.EntryOutSize(c.protocol) + size := int(fusekernel.EntryOutSize(c.protocol)) out := (*fusekernel.EntryOut)(m.Grow(size)) convertChildInodeEntry(&o.Entry, out) @@ -541,20 +541,20 @@ func (c *Connection) kernelResponseForOp( // Empty response case *fuseops.OpenDirOp: - out := (*fusekernel.OpenOut)(m.Grow(unsafe.Sizeof(fusekernel.OpenOut{}))) + out := (*fusekernel.OpenOut)(m.Grow(int(unsafe.Sizeof(fusekernel.OpenOut{})))) out.Fh = uint64(o.Handle) case *fuseops.ReadDirOp: // convertInMessage already set up the destination buffer to be at the end // of the out message. We need only shrink to the right size based on how // much the user read. - m.ShrinkTo(buffer.OutMessageInitialSize + uintptr(o.BytesRead)) + m.ShrinkTo(buffer.OutMessageHeaderSize + o.BytesRead) case *fuseops.ReleaseDirHandleOp: // Empty response case *fuseops.OpenFileOp: - out := (*fusekernel.OpenOut)(m.Grow(unsafe.Sizeof(fusekernel.OpenOut{}))) + out := (*fusekernel.OpenOut)(m.Grow(int(unsafe.Sizeof(fusekernel.OpenOut{})))) out.Fh = uint64(o.Handle) if o.KeepPageCache { @@ -565,10 +565,10 @@ func (c *Connection) kernelResponseForOp( // convertInMessage already set up the destination buffer to be at the end // of the out message. We need only shrink to the right size based on how // much the user read. - m.ShrinkTo(buffer.OutMessageInitialSize + uintptr(o.BytesRead)) + m.ShrinkTo(buffer.OutMessageHeaderSize + o.BytesRead) case *fuseops.WriteFileOp: - out := (*fusekernel.WriteOut)(m.Grow(unsafe.Sizeof(fusekernel.WriteOut{}))) + out := (*fusekernel.WriteOut)(m.Grow(int(unsafe.Sizeof(fusekernel.WriteOut{})))) out.Size = uint32(len(o.Data)) case *fuseops.SyncFileOp: @@ -584,7 +584,7 @@ func (c *Connection) kernelResponseForOp( m.AppendString(o.Target) case *fuseops.StatFSOp: - out := (*fusekernel.StatfsOut)(m.Grow(unsafe.Sizeof(fusekernel.StatfsOut{}))) + out := (*fusekernel.StatfsOut)(m.Grow(int(unsafe.Sizeof(fusekernel.StatfsOut{})))) out.St.Blocks = o.Blocks out.St.Bfree = o.BlocksFree out.St.Bavail = o.BlocksAvailable @@ -620,7 +620,7 @@ func (c *Connection) kernelResponseForOp( out.St.Frsize = o.BlockSize case *initOp: - out := (*fusekernel.InitOut)(m.Grow(unsafe.Sizeof(fusekernel.InitOut{}))) + out := (*fusekernel.InitOut)(m.Grow(int(unsafe.Sizeof(fusekernel.InitOut{})))) out.Major = o.Library.Major out.Minor = o.Library.Minor