mirror of
https://github.com/tailscale/tailscale.git
synced 2026-06-26 08:45:40 -04:00
This applies the same treatment from PR #20162 (netlog) and PR #20171 (wglog) to the local Taildrive filesystem wiring, ending the per-netmap-update O(n) rebuild of the drive remotes list. This moves the O(n peers) taildrive-remote list rebuild from every peer change (which previously happened regardless of whether you were even using taildrive) to instead happen only as needed. That running on every netmap update and was a contributor to the broader quadratic behavior we want to eliminate when a single peer is added or removed. Instead, this introduces drive.RemoteSource, a small interface the Taildrive filesystem pulls from lazily on incoming WebDAV requests, and caches by a generation counter. ipn/ipnlocal installs a driveRemoteSource once at NewLocalBackend time and bumps LocalBackend.driveGen on the three events that can actually flip the drive-capable peer set: full netmap installs (domain + self caps), UpdateNetmapDelta (peer add/remove or per-peer address changes), and updatePacketFilter (since PeerCapability values are derived from the packet filter rules, not from peer.CapMap). The hook itself is kept but narrowed: it no longer takes a *netmap.NetworkMap and its only remaining job is to re-notify IPN bus listeners of the current local shares list on full installs. This is a dependency to removing the netmap.NetworkMap type from upstream callers, like wgengine.Engine in general. (Also add a bunch more tests) Updates #12542 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I7e3d2f5b4a9c8e1d6f0a3b7c9e2d4f8a1b6c5e9d
69 lines
2.4 KiB
Go
69 lines
2.4 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
// Package drive provides a filesystem that allows sharing folders between
|
|
// Tailscale nodes using WebDAV. The actual implementation of the core Taildrive
|
|
// functionality lives in package driveimpl. These packages are separated to
|
|
// allow users of Taildrive to refer to the interfaces without having a hard
|
|
// dependency on Taildrive, so that programs which don't actually use Taildrive can
|
|
// avoid its transitive dependencies.
|
|
package drive
|
|
|
|
import (
|
|
"iter"
|
|
"net"
|
|
"net/http"
|
|
)
|
|
|
|
// Remote represents a remote Taildrive node.
|
|
type Remote struct {
|
|
Name string
|
|
URL func() string
|
|
Available func() bool
|
|
}
|
|
|
|
// RemoteSource provides the current set of remote Taildrive nodes
|
|
// on demand. The drive filesystem consults Generation on each request
|
|
// and only rebuilds its internal child list when the value differs
|
|
// from the previously cached one. This lets callers avoid the
|
|
// per-netmap O(n) rebuild that an eager SetRemotes call would
|
|
// require.
|
|
//
|
|
// All methods may be called concurrently.
|
|
type RemoteSource interface {
|
|
// Domain returns the current tailnet domain under which remotes
|
|
// appear as sub-folders.
|
|
Domain() string
|
|
|
|
// Transport returns the http.RoundTripper used to reach remotes.
|
|
Transport() http.RoundTripper
|
|
|
|
// Remotes yields the current set of remote nodes.
|
|
// It is called by the drive filesystem only when Generation has
|
|
// changed since the last call.
|
|
Remotes() iter.Seq[*Remote]
|
|
|
|
// Generation returns a monotonically-increasing counter that
|
|
// changes whenever the values returned by Domain, Transport, or
|
|
// Remotes might have changed. The drive filesystem reads it on
|
|
// every request and skips the rebuild path entirely when it
|
|
// matches the previously-cached value.
|
|
Generation() uint64
|
|
}
|
|
|
|
// FileSystemForLocal is the Taildrive filesystem exposed to local clients. It
|
|
// provides a unified WebDAV interface to remote Taildrive shares on other nodes.
|
|
type FileSystemForLocal interface {
|
|
// HandleConn handles connections from local WebDAV clients
|
|
HandleConn(conn net.Conn, remoteAddr net.Addr) error
|
|
|
|
// SetRemoteSource sets the source from which the filesystem
|
|
// reads the current set of remotes. The source is consulted
|
|
// lazily on incoming WebDAV requests, so a stale cap or empty
|
|
// tailnet costs nothing per netmap update.
|
|
SetRemoteSource(source RemoteSource)
|
|
|
|
// Close() stops serving the WebDAV content
|
|
Close() error
|
|
}
|