Browse Source

feat: set NOCOW for log directory when in btrfs

Yicheng Qin 11 years ago
parent
commit
b06d2796f8
5 changed files with 90 additions and 0 deletions
  1. 6 0
      etcd/etcd.go
  2. BIN
      pkg/fs/.util_linux.go.swp
  3. 60 0
      pkg/fs/fs.go
  4. 21 0
      pkg/fs/fs_test.go
  5. 3 0
      test.sh

+ 6 - 0
etcd/etcd.go

@@ -33,6 +33,7 @@ import (
 	ehttp "github.com/coreos/etcd/http"
 	ehttp "github.com/coreos/etcd/http"
 	"github.com/coreos/etcd/log"
 	"github.com/coreos/etcd/log"
 	"github.com/coreos/etcd/metrics"
 	"github.com/coreos/etcd/metrics"
+	"github.com/coreos/etcd/pkg/fs"
 	"github.com/coreos/etcd/server"
 	"github.com/coreos/etcd/server"
 	"github.com/coreos/etcd/store"
 	"github.com/coreos/etcd/store"
 )
 )
@@ -102,6 +103,11 @@ func (e *Etcd) Run() {
 		log.Warnf("All cached configuration is now ignored. The file %s can be removed.", info)
 		log.Warnf("All cached configuration is now ignored. The file %s can be removed.", info)
 	}
 	}
 
 
+	// Set NOCOW for data directory in btrfs
+	if fs.IsBtrfs(e.Config.DataDir) {
+		fs.SetNOCOW(e.Config.DataDir)
+	}
+
 	var mbName string
 	var mbName string
 	if e.Config.Trace() {
 	if e.Config.Trace() {
 		mbName = e.Config.MetricsBucketName()
 		mbName = e.Config.MetricsBucketName()

BIN
pkg/fs/.util_linux.go.swp


+ 60 - 0
pkg/fs/fs.go

@@ -0,0 +1,60 @@
+package fs
+
+import (
+	"os"
+	"runtime"
+	"syscall"
+	"unsafe"
+
+	"github.com/coreos/etcd/log"
+)
+
+const (
+	// from Linux/include/uapi/linux/magic.h
+	BTRFS_SUPER_MAGIC = 0x9123683E
+
+	// from Linux/include/uapi/linux/fs.h
+	FS_NOCOW_FL = 0x00800000
+	FS_IOC_GETFLAGS = 0x80086601
+	FS_IOC_SETFLAGS = 0x40086602
+)
+
+// IsBtrfs checks whether the file is in btrfs
+func IsBtrfs(path string) bool {
+	// btrfs is developed on linux only
+	if runtime.GOOS != "linux" {
+		return false
+	}
+	var buf syscall.Statfs_t
+	if err := syscall.Statfs(path, &buf); err != nil {
+		log.Warnf("Failed to statfs: %v", err)
+		return false
+	}
+	log.Debugf("The type of path %v is %v", path, buf.Type)
+	if buf.Type != BTRFS_SUPER_MAGIC {
+		return false
+	}
+	log.Infof("The path %v is in btrfs", path)
+	return true
+}
+
+// SetNOCOW sets NOCOW flag for the file
+func SetNOCOW(path string) {
+	file, err := os.Open(path)
+	if err != nil {
+		log.Warnf("Failed to open %v: %v", path, err)
+		return
+	}
+	defer file.Close()
+	var attr int
+	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), FS_IOC_GETFLAGS, uintptr(unsafe.Pointer(&attr))); errno != 0 {
+		log.Warnf("Failed to get file flags: %v", errno.Error())
+		return
+	}
+	attr |= FS_NOCOW_FL
+	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), FS_IOC_SETFLAGS, uintptr(unsafe.Pointer(&attr))); errno != 0 {
+		log.Warnf("Failed to set file flags: %v", errno.Error())
+		return
+	}
+	log.Infof("Set NOCOW to path %v succeed", path)
+}

+ 21 - 0
pkg/fs/fs_test.go

@@ -0,0 +1,21 @@
+package fs
+
+import (
+	"os/exec"
+	"strings"
+	"testing"
+)
+
+func TestSetNOCOW(t *testing.T) {
+	if IsBtrfs("/") {
+		SetNOCOW("/")
+		cmd := exec.Command("lsattr", "/")
+		out, err := cmd.Output()
+		if err != nil {
+			t.Fatal("Failed executing lsattr")
+		}
+		if strings.Contains(string(out), "---------------C") {
+			t.Fatal("Failed setting NOCOW:\n", out)
+		}
+	}
+}

+ 3 - 0
test.sh

@@ -23,6 +23,9 @@ go test -v ./server/v2/tests
 go test -i ./mod/lock/v2/tests
 go test -i ./mod/lock/v2/tests
 go test -v ./mod/lock/v2/tests
 go test -v ./mod/lock/v2/tests
 
 
+go test -i ./pkg/fs
+go test -v ./pkg/fs
+
 go test -i ./tests/functional
 go test -i ./tests/functional
 ETCD_BIN_PATH=$(pwd)/bin/etcd go test -v ./tests/functional
 ETCD_BIN_PATH=$(pwd)/bin/etcd go test -v ./tests/functional