diff --git a/main.go b/main.go index a357fe4..231315e 100644 --- a/main.go +++ b/main.go @@ -37,7 +37,7 @@ import ( type ofsVolume struct { Volume *volume.Volume Fs string - Opts string + Opts []string Env []string Asap bool // Create a snaphot on each mount (and delete the previous one) @@ -57,7 +57,7 @@ type ofsDriver struct { volumedb *bolt.DB volumeRt map[string]*ofsVolumeRt defEnv map[string]string - defMountOpt string + defMountOpt map[string]string defMountSnapshots bool } @@ -88,22 +88,23 @@ func (d *ofsDriver) Create(r *volume.CreateRequest) error { v := &ofsVolume{} v.Volume = &volume.Volume{Name: r.Name, Mountpoint: filepath.Join(volume.DefaultDockerRootDirectory, "objectivefs", r.Name), CreatedAt: time.Now().Format(time.RFC3339Nano)} - v.Opts = d.defMountOpt v.Fs = r.Name v.MountSnapshots = d.defMountSnapshots env := make(map[string]string) for id, val := range d.defEnv { env[id] = val } + opts := make(map[string]string) + for id, val := range d.defMountOpt { + opts[id] = val + } for key, val := range r.Options { switch key { case "fs": v.Fs = val case "options", "ptions": - if len(v.Opts) == 0 { - v.Opts = val - } else { - v.Opts = v.Opts + "," + val + for _, i := range strings.Split(val, ",") { + addMountOption(opts, i) } case "asap": v.Asap = true @@ -121,6 +122,16 @@ func (d *ofsDriver) Create(r *volume.CreateRequest) error { v.Env = append(v.Env, id+"="+val) } + for id, val := range opts { + var keyVal string + if val == "" { + keyVal = id + } else { + keyVal = id + "=" + val + } + v.Opts = append(v.Opts, keyVal) + } + if err := d.storeVolumeInfo(tx, r.Name, v); err != nil { return err } @@ -356,7 +367,7 @@ func (d *ofsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) if len(v.Opts) == 0 { cmd = exec.Command("/sbin/mount.objectivefs", "mount", fs, mountPath) } else { - cmd = exec.Command("/sbin/mount.objectivefs", "mount", "-o"+v.Opts, fs, mountPath) + cmd = exec.Command("/sbin/mount.objectivefs", "mount", "-o"+strings.Join(v.Opts, ","), fs, mountPath) } cmd.Env = v.Env @@ -485,7 +496,7 @@ func (d *ofsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) if len(v.Opts) == 0 { ssCmd = exec.Command("/sbin/mount.objectivefs", name, dest) } else { - ssCmd = exec.Command("/sbin/mount.objectivefs", "-o"+v.Opts, name, dest) + ssCmd = exec.Command("/sbin/mount.objectivefs", "-o"+strings.Join(v.Opts, ","), name, dest) } if err := applyEnv(ssCmd, makeSnapshotEnv(v.Env)).Run(); err != nil { log.WithFields(log.Fields{"name": r.Name, "snapshot": i}).Warn("Failed to mount a new snapshot.") @@ -603,7 +614,11 @@ func main() { } } - defMountOpt := os.Getenv("OBJECTIVEFS_MOUNT_OPTIONS") + defMountOptS := os.Getenv("OBJECTIVEFS_MOUNT_OPTIONS") + defMountOpt := make(map[string]string) + for _, i := range strings.Split(defMountOptS, ",") { + addMountOption(defMountOpt, i) + } defMountSnapshots := os.Getenv("OBJECTIVEFS_MOUNT_SNAPSHOTS") == "yes" @@ -829,3 +844,120 @@ func setIntersect[TKey comparable, TValue any, TValue2 any](a map[TKey]TValue, b } return result } + +func addMountOption(mountOpts map[string]string, keyVal string) { + keyValA := strings.SplitAfterN(keyVal, "=", 2) + key := keyValA[0] + var val string + if len(keyValA) <= 1 { + val = "" + } else { + val = keyValA[1] + } + switch key { + case "bulkdata": + delete(mountOpts, "nobulkdata") + mountOpts[key] = "" + case "nobulkdata": + delete(mountOpts, "bulkdata") + mountOpts[key] = "" + case "clean": + delete(mountOpts, "noclean") + mountOpts[key] = val + case "noclean": + delete(mountOpts, "clean") + mountOpts[key] = "" + case "compact": + delete(mountOpts, "nocompact") + mountOpts[key] = val + case "nocompact": + delete(mountOpts, "compact") + mountOpts[key] = "" + case "freebw": + delete(mountOpts, "nofreebw") + delete(mountOpts, "autofreebw") + mountOpts[key] = "" + case "nofreebw": + delete(mountOpts, "freebw") + delete(mountOpts, "autofreebw") + mountOpts[key] = "" + case "autofreebw": + delete(mountOpts, "freebw") + delete(mountOpts, "nofreebw") + mountOpts[key] = "" + case "hpc": + delete(mountOpts, "nohpc") + mountOpts[key] = "" + case "nohpc": + delete(mountOpts, "hpc") + mountOpts[key] = "" + case "mboost": + delete(mountOpts, "nomboost") + mountOpts[key] = val + case "nomboost": + delete(mountOpts, "mboost") + mountOpts[key] = "" + case "mt": + delete(mountOpts, "mtplus") + delete(mountOpts, "nomt") + delete(mountOpts, "cputhreads") + delete(mountOpts, "iothreads") + mountOpts[key] = "" + case "mtplus": + delete(mountOpts, "mt") + delete(mountOpts, "nomt") + delete(mountOpts, "cputhreads") + delete(mountOpts, "iothreads") + mountOpts[key] = "" + case "nomt": + delete(mountOpts, "mt") + delete(mountOpts, "mtplus") + delete(mountOpts, "cputhreads") + delete(mountOpts, "iothreads") + mountOpts[key] = "" + case "cputhreads": + delete(mountOpts, "mt") + delete(mountOpts, "mtplus") + delete(mountOpts, "nomt") + delete(mountOpts, "iothreads") + mountOpts[key] = val + case "iothreads": + delete(mountOpts, "mt") + delete(mountOpts, "mtplus") + delete(mountOpts, "nomt") + delete(mountOpts, "cputhreads") + mountOpts[key] = val + case "ocache": + delete(mountOpts, "noocache") + mountOpts[key] = "" + case "noocache": + delete(mountOpts, "ocache") + mountOpts[key] = "" + case "oob": + delete(mountOpts, "nooob") + mountOpts[key] = "" + case "nooob": + delete(mountOpts, "oob") + mountOpts[key] = "" + case "oom": + delete(mountOpts, "nooom") + mountOpts[key] = "" + case "nooom": + delete(mountOpts, "oom") + mountOpts[key] = "" + case "ratelimit": + delete(mountOpts, "noratelimit") + mountOpts[key] = "" + case "noratelimit": + delete(mountOpts, "ratelimit") + mountOpts[key] = "" + case "snapshots": + delete(mountOpts, "nosnapshots") + mountOpts[key] = "" + case "nosnapshots": + delete(mountOpts, "snapshots") + mountOpts[key] = "" + default: + mountOpts[key] = val + } +}