From 39a4b6a5e52182920d6fbfef4af357f6edbd97b3 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Wed, 5 Aug 2015 23:46:15 -0700 Subject: [PATCH] pkg/fileutil: support perallocate --- pkg/fileutil/perallocate_unsupported.go | 23 +++++++++++ pkg/fileutil/preallocate.go | 28 +++++++++++++ pkg/fileutil/preallocate_test.go | 53 +++++++++++++++++++++++++ wal/wal.go | 13 ++++++ 4 files changed, 117 insertions(+) create mode 100644 pkg/fileutil/perallocate_unsupported.go create mode 100644 pkg/fileutil/preallocate.go create mode 100644 pkg/fileutil/preallocate_test.go diff --git a/pkg/fileutil/perallocate_unsupported.go b/pkg/fileutil/perallocate_unsupported.go new file mode 100644 index 000000000..15e9fc811 --- /dev/null +++ b/pkg/fileutil/perallocate_unsupported.go @@ -0,0 +1,23 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !linux + +package fileutil + +import "os" + +func Preallocate(f *os.File, sizeInBytes int) error { + return nil +} diff --git a/pkg/fileutil/preallocate.go b/pkg/fileutil/preallocate.go new file mode 100644 index 000000000..f579bdf48 --- /dev/null +++ b/pkg/fileutil/preallocate.go @@ -0,0 +1,28 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build linux + +package fileutil + +import ( + "os" + "syscall" +) + +func Preallocate(f *os.File, sizeInBytes int) error { + // use mode = 1 to keep size + // see FALLOC_FL_KEEP_SIZE + return syscall.Fallocate(int(f.Fd()), 1, 0, int64(sizeInBytes)) +} diff --git a/pkg/fileutil/preallocate_test.go b/pkg/fileutil/preallocate_test.go new file mode 100644 index 000000000..d5f2a71f3 --- /dev/null +++ b/pkg/fileutil/preallocate_test.go @@ -0,0 +1,53 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fileutil + +import ( + "io/ioutil" + "os" + "runtime" + "testing" +) + +func TestPreallocate(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skipf("skip testPreallocate, OS = %s", runtime.GOOS) + } + + p, err := ioutil.TempDir(os.TempDir(), "preallocateTest") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(p) + + f, err := ioutil.TempFile(p, "") + if err != nil { + t.Fatal(err) + } + + size := 64 * 1000 + err = Preallocate(f, size) + if err != nil { + t.Fatal(err) + } + + stat, err := f.Stat() + if err != nil { + t.Fatal(err) + } + if stat.Size() != 0 { + t.Errorf("size = %d, want %d", stat.Size(), 0) + } +} diff --git a/wal/wal.go b/wal/wal.go index 22d3f9b90..d92c0619a 100644 --- a/wal/wal.go +++ b/wal/wal.go @@ -203,6 +203,12 @@ func openAtIndex(dirpath string, snap walpb.Snapshot, write bool) (*WAL, error) rc.Close() return nil, err } + err = fileutil.Preallocate(f, segmentSizeBytes) + if err != nil { + rc.Close() + plog.Errorf("failed to allocate space when creating new wal file (%v)", err) + return nil, err + } w.f = f w.seq = seq @@ -360,6 +366,12 @@ func (w *WAL) cut() error { if err != nil { return err } + err = fileutil.Preallocate(f, segmentSizeBytes) + if err != nil { + plog.Errorf("failed to allocate space when creating new wal file (%v)", err) + return err + } + w.f = f prevCrc = w.encoder.crc.Sum32() w.encoder = newEncoder(w.f, prevCrc) @@ -369,6 +381,7 @@ func (w *WAL) cut() error { if err != nil { return err } + err = l.Lock() if err != nil { return err