-
Notifications
You must be signed in to change notification settings - Fork 91
/
main.go
146 lines (131 loc) · 3.68 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"fmt"
"log"
"os"
"strings"
"syscall"
"github.com/pkg/errors"
"github.com/urfave/cli/v2"
"golang.org/x/sys/unix"
)
const (
// Extra mount option to pass Nydus specific information from snapshotter to runtime through containerd.
extraOptionKey = "extraoption="
// Kata virtual volume infmation passed from snapshotter to runtime through containerd, superset of `extraOptionKey`.
// Please refer to `KataVirtualVolume` in https://github.com/kata-containers/kata-containers/blob/main/src/libs/kata-types/src/mount.rs
kataVolumeOptionKey = "io.katacontainers.volume="
)
var (
Version = "v0.1"
BuildTime = "unknown"
)
/*
containerd run fuse.mount format: nydus-overlayfs overlay /tmp/ctd-volume107067851
-o lowerdir=/foo/lower2:/foo/lower1,upperdir=/foo/upper,workdir=/foo/work,extraoption={...},dev,suid]
*/
type mountArgs struct {
fsType string
target string
options []string
}
func parseArgs(args []string) (*mountArgs, error) {
margs := &mountArgs{
fsType: args[0],
target: args[1],
}
if margs.fsType != "overlay" {
return nil, errors.Errorf("invalid filesystem type %s for overlayfs", margs.fsType)
}
if len(margs.target) == 0 {
return nil, errors.New("empty overlayfs mount target")
}
if args[2] == "-o" && len(args[3]) != 0 {
for _, opt := range strings.Split(args[3], ",") {
// filter Nydus specific options
if strings.HasPrefix(opt, extraOptionKey) || strings.HasPrefix(opt, kataVolumeOptionKey) {
continue
}
margs.options = append(margs.options, opt)
}
}
if len(margs.options) == 0 {
return nil, errors.New("empty overlayfs mount options")
}
return margs, nil
}
func parseOptions(options []string) (int, string) {
flagsTable := map[string]int{
"async": unix.MS_SYNCHRONOUS,
"atime": unix.MS_NOATIME,
"bind": unix.MS_BIND,
"defaults": 0,
"dev": unix.MS_NODEV,
"diratime": unix.MS_NODIRATIME,
"dirsync": unix.MS_DIRSYNC,
"exec": unix.MS_NOEXEC,
"mand": unix.MS_MANDLOCK,
"noatime": unix.MS_NOATIME,
"nodev": unix.MS_NODEV,
"nodiratime": unix.MS_NODIRATIME,
"noexec": unix.MS_NOEXEC,
"nomand": unix.MS_MANDLOCK,
"norelatime": unix.MS_RELATIME,
"nostrictatime": unix.MS_STRICTATIME,
"nosuid": unix.MS_NOSUID,
"rbind": unix.MS_BIND | unix.MS_REC,
"relatime": unix.MS_RELATIME,
"remount": unix.MS_REMOUNT,
"ro": unix.MS_RDONLY,
"rw": unix.MS_RDONLY,
"strictatime": unix.MS_STRICTATIME,
"suid": unix.MS_NOSUID,
"sync": unix.MS_SYNCHRONOUS,
}
var (
flags int
data []string
)
for _, o := range options {
if f, exist := flagsTable[o]; exist {
flags |= f
} else {
data = append(data, o)
}
}
return flags, strings.Join(data, ",")
}
func run(args cli.Args) error {
margs, err := parseArgs(args.Slice())
if err != nil {
return errors.Wrap(err, "parse mount options")
}
flags, data := parseOptions(margs.options)
err = syscall.Mount(margs.fsType, margs.target, margs.fsType, uintptr(flags), data)
if err != nil {
return errors.Wrapf(err, "mount overlayfs by syscall")
}
return nil
}
func main() {
app := &cli.App{
Name: "NydusOverlayfs",
Usage: "FUSE mount helper for containerd to filter out Nydus specific options",
Version: fmt.Sprintf("%s.%s", Version, BuildTime),
UsageText: "[Usage]: nydus-overlayfs overlay <target> -o <options>",
Action: func(c *cli.Context) error {
return run(c.Args())
},
Before: func(c *cli.Context) error {
if c.NArg() != 4 {
cli.ShowAppHelpAndExit(c, 1)
}
return nil
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
os.Exit(0)
}