filer: honor a storage rule's rack/data-center constraint instead of falling back (#11804)

filer: stop widening a storage rule's location on assign failure
This commit is contained in:
Chris Lu authored and GitHub committed 2026-10-17 22:28:53 -07:00
1 parent 6ab6926c94
commit 2ff7888546
4 files changed
+61 -9

No files matched your search

+9 -4
View File
@@ -193,12 +193,20 @@ type StorageOption struct {
MaxFileNameLength uint32
Fsync bool
SaveInside bool
// EnforceLocation marks a location that came from a placement rule or an
// explicit request rather than a filer-level default: it must fail the
// assign when unsatisfiable instead of widening to anywhere.
EnforceLocation bool
}
func (so *StorageOption) TtlString() string {
return needle.SecondsToTTL(so.TtlSeconds)
}
// ToAssignRequests builds the assign request for this storage option. When the
// location came from a filer-level default rather than a placement rule or an
// explicit request, it also returns a location-stripped fallback for the case
// where the preferred location cannot serve the write at all.
func (so *StorageOption) ToAssignRequests(count int) (ar *VolumeAssignRequest, altRequest *VolumeAssignRequest) {
ar = &VolumeAssignRequest{
Count: uint64(count),
@@ -211,16 +219,13 @@ func (so *StorageOption) ToAssignRequests(count int) (ar *VolumeAssignRequest, a
DataNode: so.DataNode,
WritableVolumeCount: so.VolumeGrowthCount,
}
if so.DataCenter != "" || so.Rack != "" || so.DataNode != "" {
if !so.EnforceLocation && (so.DataCenter != "" || so.Rack != "" || so.DataNode != "") {
altRequest = &VolumeAssignRequest{
Count: uint64(count),
Replication: so.Replication,
Collection: so.Collection,
Ttl: so.TtlString(),
DiskType: so.DiskType,
DataCenter: "",
Rack: "",
DataNode: "",
WritableVolumeCount: so.VolumeGrowthCount,
}
}
+42
View File
@@ -0,0 +1,42 @@
package operation
import "testing"
// An enforced location on a storage option is a placement contract: the assign
// request must carry it, and no widened fallback may follow it.
func TestToAssignRequestsKeepsEnforcedLocation(t *testing.T) {
so := &StorageOption{
Collection: "dump",
Rack: "l1000",
DataCenter: "dc1",
EnforceLocation: true,
}
ar, alt := so.ToAssignRequests(1)
if ar.DataCenter != "dc1" || ar.Rack != "l1000" {
t.Fatalf("expected the rule's location, got dc=%q rack=%q", ar.DataCenter, ar.Rack)
}
if alt != nil {
t.Fatalf("enforced location must not be widened, got alt dc=%q rack=%q", alt.DataCenter, alt.Rack)
}
}
// A filer-level default location is a preference: the request still carries
// it, and a location-stripped fallback follows so a preferred but unservable
// location does not fail the write.
func TestToAssignRequestsWidensDefaultLocation(t *testing.T) {
so := &StorageOption{
Collection: "dump",
Rack: "l1000",
DataCenter: "dc1",
}
ar, alt := so.ToAssignRequests(1)
if ar.DataCenter != "dc1" || ar.Rack != "l1000" {
t.Fatalf("expected the preferred location, got dc=%q rack=%q", ar.DataCenter, ar.Rack)
}
if alt == nil || alt.DataCenter != "" || alt.Rack != "" {
t.Fatalf("default location should keep a widened fallback, got %+v", alt)
}
if alt.Collection != "dump" || alt.Replication != ar.Replication {
t.Fatalf("fallback must preserve the rest of the option, got %+v", alt)
}
}
+5 -5
View File
@@ -772,11 +772,11 @@ func (fs *FilerServer) SubscribeMetadata(req *filer_pb.SubscribeMetadataRequest,
var readPersistedLogErr error
var readInMemoryLogErr error
var isDone bool
var lastCheckedFlushTsNs int64 = -1 // Track the last local flush we read the disk under
var lastCheckedFlushLowTsNs int64 = -1 // Track the last peer flush low-watermark we read the disk under
var lastDiskReadTsNs int64 = -1 // Track the last read position we used for disk read
var lastDiskRefsStopTsNs int64 = -1 // Track the last chunk listing bound we read the disk under
var lastDiskPassAt time.Time // Paces re-probes for files no watermark signals
var lastCheckedFlushTsNs int64 = -1 // Track the last local flush we read the disk under
var lastCheckedFlushLowTsNs int64 = -1 // Track the last peer flush low-watermark we read the disk under
var lastDiskReadTsNs int64 = -1 // Track the last read position we used for disk read
var lastDiskRefsStopTsNs int64 = -1 // Track the last chunk listing bound we read the disk under
var lastDiskPassAt time.Time // Paces re-probes for files no watermark signals
sentRefs := make(map[string]sentRefState)
aggBuffer := fs.filer.MetaAggregator.MetaLogBuffer
@@ -335,6 +335,11 @@ func (fs *FilerServer) detectStorageOption(ctx context.Context, requestURI, qCol
Fsync: rule.Fsync,
VolumeGrowthCount: rule.VolumeGrowthCount,
MaxFileNameLength: maxFileNameLength,
// A location that survives from a request parameter, a placement
// overlay, or the path rule is a contract; only a bare filer default
// is a preference that may still be widened.
EnforceLocation: dataCenter != "" || overlayDataCenter != "" || rule.DataCenter != "" ||
rack != "" || rule.Rack != "" || dataNode != "" || rule.DataNode != "",
}, nil
}