cephfs: add StatFS implementing ceph_statfs

Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
John Mulligan 2020-07-17 16:05:53 -04:00 committed by John Mulligan
parent 8b45a01b7d
commit d3f8f0cf70
2 changed files with 108 additions and 0 deletions

74
cephfs/statfs.go Normal file
View File

@ -0,0 +1,74 @@
package cephfs
/*
#cgo LDFLAGS: -lcephfs
#cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64
#include <stdlib.h>
#include <cephfs/libcephfs.h>
*/
import "C"
import (
"unsafe"
)
// CephStatVFS instances are returned from the StatFS call. It reports
// file-system wide statistics.
type CephStatVFS struct {
// Bsize reports the file system's block size.
Bsize int64
// Fragment reports the file system's fragment size.
Frsize int64
// Blocks reports the number of blocks in the file system.
Blocks uint64
// Bfree reports the number of free blocks.
Bfree uint64
// Bavail reports the number of free blocks for unprivileged users.
Bavail uint64
// Files reports the number of inodes in the file system.
Files uint64
// Ffree reports the number of free indoes.
Ffree uint64
// Favail reports the number of free indoes for unprivileged users.
Favail uint64
// Fsid reports the file system ID number.
Fsid int64
// Flag reports the file system mount flags.
Flag int64
// Namemax reports the maximum file name length.
Namemax int64
}
// StatFS returns file system wide statistics.
// NOTE: Many of the statistics fields reported by ceph are not filled in with
// useful values.
//
// Implements:
// int ceph_statfs(struct ceph_mount_info *cmount, const char *path, struct statvfs *stbuf);
func (mount *MountInfo) StatFS(path string) (*CephStatVFS, error) {
if err := mount.validate(); err != nil {
return nil, err
}
cPath := C.CString(path)
defer C.free(unsafe.Pointer(cPath))
var statvfs C.struct_statvfs
ret := C.ceph_statfs(mount.mount, cPath, &statvfs)
if ret != 0 {
return nil, getError(ret)
}
csfs := &CephStatVFS{
Bsize: int64(statvfs.f_bsize),
Frsize: int64(statvfs.f_frsize),
Blocks: uint64(statvfs.f_blocks),
Bfree: uint64(statvfs.f_bfree),
Bavail: uint64(statvfs.f_bavail),
Files: uint64(statvfs.f_files),
Ffree: uint64(statvfs.f_ffree),
Favail: uint64(statvfs.f_favail),
Fsid: int64(statvfs.f_fsid),
Flag: int64(statvfs.f_flag),
Namemax: int64(statvfs.f_namemax),
}
return csfs, nil
}

34
cephfs/statfs_test.go Normal file
View File

@ -0,0 +1,34 @@
package cephfs
import (
"testing"
"github.com/stretchr/testify/assert"
)
// TestStatFSRootDir does not assert much about every field as these can vary
// between runs. Similarly, some stats might vary between sub-trees but we
// trust the ceph libs to be correct here and just make sure the wrapper code
// behaves.
func TestStatFSRootDir(t *testing.T) {
t.Run("invalid", func(t *testing.T) {
m := &MountInfo{}
sfs, err := m.StatFS("/")
assert.Error(t, err)
assert.Nil(t, sfs)
})
// half the stats as reported by ceph are pretty useless/dummy values.
// (see src/client/Client.cc)
// some stuff gets filled in only if a quota is set, but we're not
// up to that right now, so we don't really check much value-wise.
t.Run("valid", func(t *testing.T) {
mount := fsConnect(t)
defer fsDisconnect(t, mount)
sfs, err := mount.StatFS("/")
assert.NoError(t, err)
assert.NotNil(t, sfs)
assert.Equal(t, sfs.Namemax, int64(255))
})
}