Skip to content

Commit

Permalink
Merge pull request #1325 from saschagrunert/recreate-backingFsBlockDev
Browse files Browse the repository at this point in the history
[main] Recreate missing backingFsBlockDev on setting xfs project quota
  • Loading branch information
giuseppe authored Nov 8, 2022
2 parents 74e3743 + aa0d394 commit 63defa3
Showing 1 changed file with 40 additions and 16 deletions.
56 changes: 40 additions & 16 deletions drivers/quota/projectquota.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct fsxattr {
*/
import "C"
import (
"errors"
"fmt"
"math"
"os"
Expand Down Expand Up @@ -78,6 +79,7 @@ type Control struct {
backingFsBlockDev string
nextProjectID uint32
quotas map[string]uint32
basePath string
}

// Attempt to generate a unigue projectid. Multiple directories
Expand Down Expand Up @@ -158,20 +160,22 @@ func NewControl(basePath string) (*Control, error) {
Size: 0,
Inodes: 0,
}
if err := setProjectQuota(backingFsBlockDev, minProjectID, quota); err != nil {
return nil, err
}

q := Control{
backingFsBlockDev: backingFsBlockDev,
nextProjectID: minProjectID + 1,
quotas: make(map[string]uint32),
basePath: basePath,
}

if err := q.setProjectQuota(minProjectID, quota); err != nil {
return nil, err
}

//
// get first project id to be used for next container
//
err = q.findNextProjectID(basePath)
err = q.findNextProjectID()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -204,11 +208,11 @@ func (q *Control) SetQuota(targetPath string, quota Quota) error {
// set the quota limit for the container's project id
//
logrus.Debugf("SetQuota path=%s, size=%d, inodes=%d, projectID=%d", targetPath, quota.Size, quota.Inodes, projectID)
return setProjectQuota(q.backingFsBlockDev, projectID, quota)
return q.setProjectQuota(projectID, quota)
}

// setProjectQuota - set the quota for project id on xfs block device
func setProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) error {
func (q *Control) setProjectQuota(projectID uint32, quota Quota) error {
var d C.fs_disk_quota_t
d.d_version = C.FS_DQUOT_VERSION
d.d_id = C.__u32(projectID)
Expand All @@ -225,15 +229,35 @@ func setProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) er
d.d_ino_softlimit = d.d_ino_hardlimit
}

var cs = C.CString(backingFsBlockDev)
var cs = C.CString(q.backingFsBlockDev)
defer C.free(unsafe.Pointer(cs))

_, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XSETPQLIM,
uintptr(unsafe.Pointer(cs)), uintptr(d.d_id),
uintptr(unsafe.Pointer(&d)), 0, 0)
if errno != 0 {
runQuotactl := func() syscall.Errno {
_, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XSETPQLIM,
uintptr(unsafe.Pointer(cs)), uintptr(d.d_id),
uintptr(unsafe.Pointer(&d)), 0, 0)
return errno
}

errno := runQuotactl()

// If the backingFsBlockDev does not exist any more then try to recreate it.
if errors.Is(errno, unix.ENOENT) {
if _, err := makeBackingFsDev(q.basePath); err != nil {
return fmt.Errorf(
"failed to recreate missing backingFsBlockDev %s for projid %d: %w",
q.backingFsBlockDev, projectID, err,
)
}

if errno := runQuotactl(); errno != 0 {
return fmt.Errorf("failed to set quota limit for projid %d on %s after backingFsBlockDev recreation: %w",
projectID, q.backingFsBlockDev, errno)
}

} else if errno != 0 {
return fmt.Errorf("failed to set quota limit for projid %d on %s: %w",
projectID, backingFsBlockDev, errno)
projectID, q.backingFsBlockDev, errno)
}

return nil
Expand Down Expand Up @@ -332,16 +356,16 @@ func setProjectID(targetPath string, projectID uint32) error {

// findNextProjectID - find the next project id to be used for containers
// by scanning driver home directory to find used project ids
func (q *Control) findNextProjectID(home string) error {
files, err := os.ReadDir(home)
func (q *Control) findNextProjectID() error {
files, err := os.ReadDir(q.basePath)
if err != nil {
return fmt.Errorf("read directory failed : %s", home)
return fmt.Errorf("read directory failed : %s", q.basePath)
}
for _, file := range files {
if !file.IsDir() {
continue
}
path := filepath.Join(home, file.Name())
path := filepath.Join(q.basePath, file.Name())
projid, err := getProjectID(path)
if err != nil {
return err
Expand Down

0 comments on commit 63defa3

Please sign in to comment.