Skip to content
This repository was archived by the owner on Oct 13, 2023. It is now read-only.

Commit 6b7330d

Browse files
authored
Merge pull request #310 from kolyshkin/19.03-quota-map
[19.03] backport projectquota: protect concurrent map access (ENGCORE-920)
2 parents 8ecf540 + b0f01be commit 6b7330d

File tree

7 files changed

+88
-38
lines changed

7 files changed

+88
-38
lines changed

daemon/graphdriver/copy/copy.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
22

33
package copy // import "github.com/docker/docker/daemon/graphdriver/copy"
44

5-
/*
6-
#include <linux/fs.h>
7-
8-
#ifndef FICLONE
9-
#define FICLONE _IOW(0x94, 9, int)
10-
#endif
11-
*/
12-
import "C"
135
import (
146
"container/list"
157
"fmt"
@@ -50,7 +42,7 @@ func copyRegular(srcPath, dstPath string, fileinfo os.FileInfo, copyWithFileRang
5042
defer dstFile.Close()
5143

5244
if *copyWithFileClone {
53-
_, _, err = unix.Syscall(unix.SYS_IOCTL, dstFile.Fd(), C.FICLONE, srcFile.Fd())
45+
err = fiClone(srcFile, dstFile)
5446
if err == nil {
5547
return nil
5648
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// +build linux,cgo
2+
3+
package copy // import "github.com/docker/docker/daemon/graphdriver/copy"
4+
5+
/*
6+
#include <linux/fs.h>
7+
8+
#ifndef FICLONE
9+
#define FICLONE _IOW(0x94, 9, int)
10+
#endif
11+
*/
12+
import "C"
13+
import (
14+
"os"
15+
16+
"golang.org/x/sys/unix"
17+
)
18+
19+
func fiClone(srcFile, dstFile *os.File) error {
20+
_, _, err := unix.Syscall(unix.SYS_IOCTL, dstFile.Fd(), C.FICLONE, srcFile.Fd())
21+
return err
22+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// +build linux,!cgo
2+
3+
package copy // import "github.com/docker/docker/daemon/graphdriver/copy"
4+
5+
import (
6+
"os"
7+
8+
"golang.org/x/sys/unix"
9+
)
10+
11+
func fiClone(srcFile, dstFile *os.File) error {
12+
return unix.ENOSYS
13+
}

daemon/graphdriver/quota/projectquota.go

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build linux
1+
// +build linux,!exclude_disk_quota
22

33
//
44
// projectquota.go - implements XFS project quota controls
@@ -63,19 +63,6 @@ import (
6363
"golang.org/x/sys/unix"
6464
)
6565

66-
// Quota limit params - currently we only control blocks hard limit
67-
type Quota struct {
68-
Size uint64
69-
}
70-
71-
// Control - Context to be used by storage driver (e.g. overlay)
72-
// who wants to apply project quotas to container dirs
73-
type Control struct {
74-
backingFsBlockDev string
75-
nextProjectID uint32
76-
quotas map[string]uint32
77-
}
78-
7966
// NewControl - initialize project quota support.
8067
// Test to make sure that quota can be set on a test dir and find
8168
// the first project id to be used for the next container create.
@@ -166,21 +153,24 @@ func NewControl(basePath string) (*Control, error) {
166153
// SetQuota - assign a unique project id to directory and set the quota limits
167154
// for that project id
168155
func (q *Control) SetQuota(targetPath string, quota Quota) error {
169-
156+
q.RLock()
170157
projectID, ok := q.quotas[targetPath]
158+
q.RUnlock()
171159
if !ok {
160+
q.Lock()
172161
projectID = q.nextProjectID
173162

174163
//
175164
// assign project id to new container directory
176165
//
177166
err := setProjectID(targetPath, projectID)
178167
if err != nil {
168+
q.Unlock()
179169
return err
180170
}
181-
182171
q.quotas[targetPath] = projectID
183172
q.nextProjectID++
173+
q.Unlock()
184174
}
185175

186176
//
@@ -217,8 +207,9 @@ func setProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) er
217207

218208
// GetQuota - get the quota limits of a directory that was configured with SetQuota
219209
func (q *Control) GetQuota(targetPath string, quota *Quota) error {
220-
210+
q.RLock()
221211
projectID, ok := q.quotas[targetPath]
212+
q.RUnlock()
222213
if !ok {
223214
return errors.Errorf("quota not found for path: %s", targetPath)
224215
}
@@ -289,6 +280,8 @@ func setProjectID(targetPath string, projectID uint32) error {
289280
// findNextProjectID - find the next project id to be used for containers
290281
// by scanning driver home directory to find used project ids
291282
func (q *Control) findNextProjectID(home string) error {
283+
q.Lock()
284+
defer q.Unlock()
292285
files, err := ioutil.ReadDir(home)
293286
if err != nil {
294287
return errors.Errorf("read directory failed: %s", home)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// +build linux,exclude_disk_quota
2+
3+
package quota // import "github.com/docker/docker/daemon/graphdriver/quota"
4+
5+
func NewControl(basePath string) (*Control, error) {
6+
return nil, ErrQuotaNotSupported
7+
}
8+
9+
// SetQuota - assign a unique project id to directory and set the quota limits
10+
// for that project id
11+
func (q *Control) SetQuota(targetPath string, quota Quota) error {
12+
return ErrQuotaNotSupported
13+
}
14+
15+
// GetQuota - get the quota limits of a directory that was configured with SetQuota
16+
func (q *Control) GetQuota(targetPath string, quota *Quota) error {
17+
return ErrQuotaNotSupported
18+
}

daemon/graphdriver/quota/types.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// +build linux
2+
3+
package quota // import "github.com/docker/docker/daemon/graphdriver/quota"
4+
5+
import "sync"
6+
7+
// Quota limit params - currently we only control blocks hard limit
8+
type Quota struct {
9+
Size uint64
10+
}
11+
12+
// Control - Context to be used by storage driver (e.g. overlay)
13+
// who wants to apply project quotas to container dirs
14+
type Control struct {
15+
backingFsBlockDev string
16+
sync.RWMutex // protect nextProjectID and quotas map
17+
nextProjectID uint32
18+
quotas map[string]uint32
19+
}

daemon/stats/collector_unix.go

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ import (
99
"strings"
1010

1111
"github.com/opencontainers/runc/libcontainer/system"
12+
"golang.org/x/sys/unix"
1213
)
1314

14-
/*
15-
#include <unistd.h>
16-
*/
17-
import "C"
18-
1915
// platformNewStatsCollector performs platform specific initialisation of the
2016
// Collector structure.
2117
func platformNewStatsCollector(s *Collector) {
@@ -70,13 +66,10 @@ func (s *Collector) getSystemCPUUsage() (uint64, error) {
7066
}
7167

7268
func (s *Collector) getNumberOnlineCPUs() (uint32, error) {
73-
i, err := C.sysconf(C._SC_NPROCESSORS_ONLN)
74-
// According to POSIX - errno is undefined after successful
75-
// sysconf, and can be non-zero in several cases, so look for
76-
// error in returned value not in errno.
77-
// (https://sourceware.org/bugzilla/show_bug.cgi?id=21536)
78-
if i == -1 {
69+
var cpuset unix.CPUSet
70+
err := unix.SchedGetaffinity(0, &cpuset)
71+
if err != nil {
7972
return 0, err
8073
}
81-
return uint32(i), nil
74+
return uint32(cpuset.Count()), nil
8275
}

0 commit comments

Comments
 (0)