Browse Source

Merge pull request #8921 from gyuho/fileutil-darwin

pkg/fileutil: fix preallocate under OS X kernel
Gyuho Lee 8 years ago
parent
commit
608961b2b8
1 changed files with 22 additions and 0 deletions
  1. 22 0
      pkg/fileutil/preallocate_darwin.go

+ 22 - 0
pkg/fileutil/preallocate_darwin.go

@@ -30,6 +30,8 @@ func preallocExtend(f *os.File, sizeInBytes int64) error {
 }
 
 func preallocFixed(f *os.File, sizeInBytes int64) error {
+	// allocate all requested space or no space at all
+	// TODO: allocate contiguous space on disk with F_ALLOCATECONTIG flag
 	fstore := &syscall.Fstore_t{
 		Flags:   syscall.F_ALLOCATEALL,
 		Posmode: syscall.F_PEOFPOSMODE,
@@ -39,5 +41,25 @@ func preallocFixed(f *os.File, sizeInBytes int64) error {
 	if errno == 0 || errno == syscall.ENOTSUP {
 		return nil
 	}
+
+	// wrong argument to fallocate syscall
+	if errno == syscall.EINVAL {
+		// filesystem "st_blocks" are allocated in the units of
+		// "Allocation Block Size" (run "diskutil info /" command)
+		var stat syscall.Stat_t
+		syscall.Fstat(int(f.Fd()), &stat)
+
+		// syscall.Statfs_t.Bsize is "optimal transfer block size"
+		// and contains matching 4096 value when latest OS X kernel
+		// supports 4,096 KB filesystem block size
+		var statfs syscall.Statfs_t
+		syscall.Fstatfs(int(f.Fd()), &statfs)
+		blockSize := int64(statfs.Bsize)
+
+		if stat.Blocks*blockSize >= sizeInBytes {
+			// enough blocks are already allocated
+			return nil
+		}
+	}
 	return errno
 }