Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

save device type instead of caching it #2023

Merged
merged 9 commits into from
Aug 21, 2023
2 changes: 1 addition & 1 deletion pkg/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const (

// VolatileDir creates a new cache directory that is stored on a tmpfs.
// This means data stored in this directory will NOT survive a reboot.
// Use this when you need to store data that needs to survice deamon reboot but not between reboots
// Use this when you need to store data that needs to survive deamon reboot but not between reboots
// It is the caller's responsibility to remove the directory when no longer needed.
// If the directory already exist error of type os.IsExist will be returned
func VolatileDir(name string, size uint64) (string, error) {
Expand Down
32 changes: 31 additions & 1 deletion pkg/storage/filesystem/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/threefoldtech/zos/pkg"
"github.com/threefoldtech/zos/pkg/gridtypes/zos"
)

Expand Down Expand Up @@ -68,10 +70,38 @@ func (i *DeviceInfo) Used() bool {
return len(i.Label) != 0 || len(i.Filesystem) != 0
}

func (d *DeviceInfo) Type() (zos.DeviceType, error) {
// DetectType returns the device type according to seektime
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First time for me to know about the seektime tool, maybe we can enhance it to include that it's an approximation too https://github.com/maxux/seektime not 100% correct

func (d *DeviceInfo) DetectType() (zos.DeviceType, error) {
return d.mgr.Seektime(context.Background(), d.Path)
}

// SetType sets the device type to the disk
func (d *DeviceInfo) SetType(typ pkg.DeviceType) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we use zos.DeviceType? I'm not sure why we created that alias declaration DeviceType = DeviceType?
Also the rest of the functions DetectType, Type are working with zos.DeviceType

if err := os.WriteFile(filepath.Join("/mnt", d.Name(), ".seektime"), []byte(typ), 0644); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's extract the first argument of WriteFile into a varilable to improve the readability

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually I believe we shouldn't use .seektime extension, as it denotes the results of seektime (rpm/seektime) instead of actual harddisk type string, however if it's considered as "the output of seektime" tool, I'm good with that

return errors.Wrapf(err, "failed to store device type for '%s'", d.Name())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please include the full path as well so /mnt/d.Name(), ...

}

return nil
}

// Type gets the device type from the disk
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's expand the docstring, that's based on .seektime file existing in the /mnt/DeviceName.seektime, that contains the device type being SSD or HDD maybe

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also i'm not sure of the behavior of the return type device, bool, err

func (d *DeviceInfo) Type() (zos.DeviceType, bool, error) {
data, err := os.ReadFile(filepath.Join("/mnt", d.Name(), ".seektime"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • let's extract to its own variable
  • let's rename data to disktype

if os.IsNotExist(err) {
return "", false, nil
}

if err != nil {
rawdaGastan marked this conversation as resolved.
Show resolved Hide resolved
return "", false, err
}

if len(data) == 0 {
return "", false, nil
}

return pkg.DeviceType(data), true, nil
}

func (d *DeviceInfo) Mountpoint(ctx context.Context) (string, error) {
return d.mgr.Mountpoint(ctx, d.Path)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/filesystem/device_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestDeviceManagerScan(t *testing.T) {
// make sure all types are set.
expected := []zos.DeviceType{zos.SSDDevice, zos.HDDDevice}
for i, dev := range cached {
typ, err := dev.Type()
typ, err := dev.DetectType()
require.NoError(err)
require.Equal(expected[i], typ)
}
Expand Down
82 changes: 49 additions & 33 deletions pkg/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,6 @@ type TypeCache struct {
base string
}

func (t *TypeCache) Set(name string, typ pkg.DeviceType) error {
if err := os.WriteFile(filepath.Join(t.base, name), []byte(typ), 0644); err != nil {
return errors.Wrapf(err, "failed to store device type for '%s'", name)
}

return nil
}

func (t *TypeCache) Get(name string) (pkg.DeviceType, bool) {
data, err := os.ReadFile(filepath.Join(t.base, name))
if err != nil {
Expand Down Expand Up @@ -157,6 +149,50 @@ func (s *Module) dump() {

}

// deviceType gets the device type of a disk
func (s *Module) deviceType(device filesystem.DeviceInfo, vm bool) (zos.DeviceType, error) {
var typ zos.DeviceType

// for development purposes only
if vm {
// force ssd device for vms
typ = zos.SSDDevice

if device.Path == "/dev/vdd" || device.Path == "/dev/vde" {
typ = zos.HDDDevice
}
return typ, nil
}

log.Debug().Str("device", device.Path).Msg("checking device type in disk")
typ, ok, err := device.Type()
if err != nil {
return "", errors.Wrap(err, "failed to get device type")
}

if ok {
log.Debug().Str("device", device.Path).Str("type", typ.String()).Msg("device type loaded from disk")
return typ, nil
}

log.Debug().Str("device", device.Path).Msg("checking device type in cache")
typ, ok = s.cache.Get(device.Name())
if !ok {
log.Debug().Str("device", device.Path).Msg("detecting device type")
typ, err = device.DetectType()
if err != nil {
return "", errors.Wrap(err, "failed to detect device type")
}
}

log.Debug().Str("device", device.Path).Str("type", typ.String()).Msg("setting device type")
if err := device.SetType(typ); err != nil {
return "", errors.Wrap(err, "failed to set device type")
}

return typ, nil
}

/*
*
initialize, must be called at least onetime each boot.
Expand Down Expand Up @@ -206,31 +242,11 @@ func (s *Module) initialize(ctx context.Context) error {
log.Error().Err(err).Str("pool", pool.Name()).Str("device", device.Path).Msg("failed to get usage of pool")
}

typ, ok := s.cache.Get(device.Name())
if !ok {
log.Debug().Str("device", device.Path).Msg("detecting device type")
typ, err = device.Type()
if err != nil {
log.Error().Str("device", device.Path).Err(err).Msg("failed to check device type")
continue
}

// for development purposes only
if vm {
// force ssd device for vms
typ = zos.SSDDevice

if device.Path == "/dev/vdd" || device.Path == "/dev/vde" {
typ = zos.HDDDevice
}
}

log.Debug().Str("device", device.Path).Str("type", typ.String()).Msg("caching device type")
if err := s.cache.Set(device.Name(), typ); err != nil {
log.Error().Str("device", device.Path).Err(err).Msg("failed to cache device type")
}
} else {
log.Debug().Str("device", device.Path).Str("type", typ.String()).Msg("device type loaded from cache")
typ, err := s.deviceType(device, vm)
if err != nil {
log.Error().Str("device", device.Path).Err(err).Msg("failed to get device type")
rawdaGastan marked this conversation as resolved.
Show resolved Hide resolved
s.brokenDevices = append(s.brokenDevices, pkg.BrokenDevice{Path: device.Path, Err: err})
continue
}

switch typ {
Expand Down