From d9453c146c15b175e4e384150b21e2b897a041c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Fri, 8 Apr 2022 15:36:32 +0200 Subject: [PATCH 1/6] Align atomics on arm32 --- lib/reversetunnel/conn.go | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/reversetunnel/conn.go b/lib/reversetunnel/conn.go index 557b585f2b8fa..2122a1a9a0f73 100644 --- a/lib/reversetunnel/conn.go +++ b/lib/reversetunnel/conn.go @@ -57,20 +57,20 @@ type remoteConn struct { // invalid indicates the connection is invalid and connections can no longer // be made on it. - invalid int32 + invalid *int32 // lastError is the last error that occurred before this connection became // invalid. lastError error // Used to make sure calling Close on the connection multiple times is safe. - closed int32 + closed *int32 // clock is used to control time in tests. clock clockwork.Clock // lastHeartbeat is the last time a heartbeat was received. - lastHeartbeat int64 + lastHeartbeat *int64 } // connConfig is the configuration for the remoteConn. @@ -104,9 +104,12 @@ func newRemoteConn(cfg *connConfig) *remoteConn { log: logrus.WithFields(logrus.Fields{ trace.Component: "discovery", }), - connConfig: cfg, - clock: clockwork.NewRealClock(), - newProxiesC: make(chan []types.Server, 100), + connConfig: cfg, + clock: clockwork.NewRealClock(), + newProxiesC: make(chan []types.Server, 100), + closed: new(int32), + invalid: new(int32), + lastHeartbeat: new(int64), } return c @@ -118,7 +121,7 @@ func (c *remoteConn) String() string { func (c *remoteConn) Close() error { // If the connection has already been closed, return right away. - if !atomic.CompareAndSwapInt32(&c.closed, 0, 1) { + if !atomic.CompareAndSwapInt32(c.closed, 0, 1) { return nil } @@ -157,23 +160,23 @@ func (c *remoteConn) markInvalid(err error) { c.mu.Lock() defer c.mu.Unlock() - atomic.StoreInt32(&c.invalid, 1) + atomic.StoreInt32(c.invalid, 1) c.lastError = err c.log.Debugf("Disconnecting connection to %v %v: %v.", c.clusterName, c.conn.RemoteAddr(), err) } func (c *remoteConn) isInvalid() bool { - return atomic.LoadInt32(&c.invalid) == 1 + return atomic.LoadInt32(c.invalid) == 1 } func (c *remoteConn) setLastHeartbeat(tm time.Time) { - atomic.StoreInt64(&c.lastHeartbeat, tm.UnixNano()) + atomic.StoreInt64(c.lastHeartbeat, tm.UnixNano()) } // isReady returns true when connection is ready to be tried, // it returns true when connection has received the first heartbeat func (c *remoteConn) isReady() bool { - return atomic.LoadInt64(&c.lastHeartbeat) != 0 + return atomic.LoadInt64(c.lastHeartbeat) != 0 } func (c *remoteConn) openDiscoveryChannel() (ssh.Channel, error) { From bf535072e5a019dfa47ce0910097c8d2c8a20603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Fri, 8 Apr 2022 19:25:38 +0200 Subject: [PATCH 2/6] test align --- lib/srv/keepalive_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/srv/keepalive_test.go b/lib/srv/keepalive_test.go index 068bec7d36a61..cf712fa39b224 100644 --- a/lib/srv/keepalive_test.go +++ b/lib/srv/keepalive_test.go @@ -123,8 +123,8 @@ func waitForRequests(requestSender *testRequestSender, count int) error { } type testRequestSender struct { + count int64 // intentionally placed first to ensure 64-bit alignment reply bool - count int64 } func (n *testRequestSender) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { From 949b2318136c59ebb6efb44e9e06e58c559f0448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Fri, 8 Apr 2022 19:42:22 +0200 Subject: [PATCH 3/6] 64-bit ctr only --- lib/reversetunnel/conn.go | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/reversetunnel/conn.go b/lib/reversetunnel/conn.go index 2122a1a9a0f73..a0d4915217014 100644 --- a/lib/reversetunnel/conn.go +++ b/lib/reversetunnel/conn.go @@ -45,6 +45,10 @@ type connKey struct { // remoteConn holds a connection to a remote host, either node or proxy. type remoteConn struct { + // lastHeartbeat is the last time a heartbeat was received. + // intentionally placed first to ensure 64-bit alignment + lastHeartbeat int64 + *connConfig mu sync.Mutex log *logrus.Entry @@ -57,20 +61,17 @@ type remoteConn struct { // invalid indicates the connection is invalid and connections can no longer // be made on it. - invalid *int32 + invalid int32 // lastError is the last error that occurred before this connection became // invalid. lastError error // Used to make sure calling Close on the connection multiple times is safe. - closed *int32 + closed int32 // clock is used to control time in tests. clock clockwork.Clock - - // lastHeartbeat is the last time a heartbeat was received. - lastHeartbeat *int64 } // connConfig is the configuration for the remoteConn. @@ -104,12 +105,9 @@ func newRemoteConn(cfg *connConfig) *remoteConn { log: logrus.WithFields(logrus.Fields{ trace.Component: "discovery", }), - connConfig: cfg, - clock: clockwork.NewRealClock(), - newProxiesC: make(chan []types.Server, 100), - closed: new(int32), - invalid: new(int32), - lastHeartbeat: new(int64), + connConfig: cfg, + clock: clockwork.NewRealClock(), + newProxiesC: make(chan []types.Server, 100), } return c @@ -121,7 +119,7 @@ func (c *remoteConn) String() string { func (c *remoteConn) Close() error { // If the connection has already been closed, return right away. - if !atomic.CompareAndSwapInt32(c.closed, 0, 1) { + if !atomic.CompareAndSwapInt32(&c.closed, 0, 1) { return nil } @@ -160,23 +158,23 @@ func (c *remoteConn) markInvalid(err error) { c.mu.Lock() defer c.mu.Unlock() - atomic.StoreInt32(c.invalid, 1) + atomic.StoreInt32(&c.invalid, 1) c.lastError = err c.log.Debugf("Disconnecting connection to %v %v: %v.", c.clusterName, c.conn.RemoteAddr(), err) } func (c *remoteConn) isInvalid() bool { - return atomic.LoadInt32(c.invalid) == 1 + return atomic.LoadInt32(&c.invalid) == 1 } func (c *remoteConn) setLastHeartbeat(tm time.Time) { - atomic.StoreInt64(c.lastHeartbeat, tm.UnixNano()) + atomic.StoreInt64(&c.lastHeartbeat, tm.UnixNano()) } // isReady returns true when connection is ready to be tried, // it returns true when connection has received the first heartbeat func (c *remoteConn) isReady() bool { - return atomic.LoadInt64(c.lastHeartbeat) != 0 + return atomic.LoadInt64(&c.lastHeartbeat) != 0 } func (c *remoteConn) openDiscoveryChannel() (ssh.Channel, error) { From 41e5d110cfa75662b117963595041dc47e4524d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Fri, 8 Apr 2022 19:47:01 +0200 Subject: [PATCH 4/6] fix another one --- lib/utils/conn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/conn.go b/lib/utils/conn.go index 07a47b759eff7..a0ad0611ce48b 100644 --- a/lib/utils/conn.go +++ b/lib/utils/conn.go @@ -174,8 +174,8 @@ func (r *TrackingReader) Read(b []byte) (int, error) { // written. // It's thread-safe if the underlying io.Writer is thread-safe. type TrackingWriter struct { + count uint64 // intentionally placed first to ensure 64-bit alignment w io.Writer - count uint64 } // NewTrackingWriter creates a TrackingWriter around w. From 514b2fc664669466f8e1f503cf94351cf3507f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Fri, 8 Apr 2022 20:15:28 +0200 Subject: [PATCH 5/6] another one --- lib/backend/memory/memory.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/backend/memory/memory.go b/lib/backend/memory/memory.go index 58a384f96a498..0e2b9acb2c621 100644 --- a/lib/backend/memory/memory.go +++ b/lib/backend/memory/memory.go @@ -113,6 +113,10 @@ func New(cfg Config) (*Memory, error) { // Memory is a memory B-Tree based backend type Memory struct { + // nextID is a next record ID + // intentionally placed first to ensure 64-bit alignment + nextID int64 + *sync.Mutex *log.Entry Config @@ -126,8 +130,6 @@ type Memory struct { // ctx is a context signalling close ctx context.Context buf *backend.CircularBuffer - // nextID is a next record ID - nextID int64 } // Close closes memory backend From db522c9457bd340bb81149bcb8b187030f101497 Mon Sep 17 00:00:00 2001 From: Joel Date: Tue, 12 Apr 2022 16:03:58 +0200 Subject: [PATCH 6/6] Update lib/backend/memory/memory.go Co-authored-by: Zac Bergquist --- lib/backend/memory/memory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/backend/memory/memory.go b/lib/backend/memory/memory.go index 0e2b9acb2c621..1b78e9e2dfc94 100644 --- a/lib/backend/memory/memory.go +++ b/lib/backend/memory/memory.go @@ -113,7 +113,7 @@ func New(cfg Config) (*Memory, error) { // Memory is a memory B-Tree based backend type Memory struct { - // nextID is a next record ID + // nextID is a next record ID // intentionally placed first to ensure 64-bit alignment nextID int64