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

cephfs: wait for FUSE to exit after unmount #233

Merged
merged 2 commits into from
Feb 27, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 49 additions & 3 deletions pkg/cephfs/volumemounter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ limitations under the License.
package cephfs

import (
"bytes"
"errors"
"fmt"
"os"
"os/exec"
"regexp"
"strconv"
"sync"

"k8s.io/klog"
)

const (
Expand All @@ -31,6 +35,12 @@ const (

var (
availableMounters []string

// maps a mountpoint to PID of its FUSE daemon
fusePidMap = make(map[string]int)
fusePidMapMtx sync.Mutex

fusePidRx = regexp.MustCompile(`(?m)^ceph-fuse\[(.+)\]: starting fuse$`)
)

// Load available ceph mounters installed on system into availableMounters
Expand Down Expand Up @@ -116,10 +126,24 @@ func mountFuse(mountPoint string, cr *credentials, volOptions *volumeOptions, vo
return err
}

if !bytes.Contains(stderr, []byte("starting fuse")) {
// Parse the output:
Copy link
Member

Choose a reason for hiding this comment

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

can you provide a sample output? It helps understand the parsing below. Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This doesn't output anything unfortunately, but i can sketch it out:

this is the stderr output from ceph-fuse

2019-02-26 21:30:52.556 7f0fb5589c00 -1 auth: unable to find a keyring on /etc/ceph/ceph.client.admin.keyring,/etc/ceph/ceph.keyring,/etc/ceph/keyring,/etc/ceph/keyring.bin,: (2) No such file or directory
2019-02-26 21:30:52.568 7f0fb5589c00 -1 init, newargv = 0x1339e30 newargc=9
ceph-fuse[274]: starting ceph client
2019-02-26 21:30:52.568 7f0fb5589c00 -1 auth: unable to find a keyring on /etc/ceph/ceph.client.admin.keyring,/etc/ceph/ceph.keyring,/etc/ceph/keyring,/etc/ceph/keyring.bin,: (2) No such file or directory
ceph-fuse[274]: starting fuse
         ^   ^  ^
         |   |  |
----------------+ idx points to 's'
         |   |
-------------+ pidEnd points to ']'
         |
---------+ pidStart points to '['

First, we need to search for starting fuse string to make sure the mount is ok. The PID of the daemon is delimited by [ and ]: since we already have the starting position of that string in idx, and we know what the output should look like, we can start searching for the right bracket, starting at the end of the string (as opposed to starting the search at the beginning of the output - this would be less "optimal"). Once we have the position of the right bracket in pidEnd, the same thing is repeated for the left bracket [, whose position is stored in pidStart. The PID should be in between pidStart and pidEnd, i.e. stderr[pidStart+1 : pidEnd]

Copy link
Member

@rootfs rootfs Feb 27, 2019

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Uff... this is a nice case of over-complicating things, isn't it? :P I'll send a fix

// We need "starting fuse" meaning the mount is ok
// and PID of the ceph-fuse daemon for unmount

match := fusePidRx.FindSubmatch(stderr)
if len(match) != 2 {
return fmt.Errorf("ceph-fuse failed: %s", stderr)
}

pid, err := strconv.Atoi(string(match[1]))
if err != nil {
return fmt.Errorf("failed to parse FUSE daemon PID: %v", err)
}

fusePidMapMtx.Lock()
fusePidMap[mountPoint] = pid
fusePidMapMtx.Unlock()

return nil
}

Expand Down Expand Up @@ -173,7 +197,29 @@ func bindMount(from, to string, readOnly bool) error {
}

func unmountVolume(mountPoint string) error {
return execCommandErr("umount", mountPoint)
if err := execCommandErr("umount", mountPoint); err != nil {
return err
}

fusePidMapMtx.Lock()
pid, ok := fusePidMap[mountPoint]
if ok {
delete(fusePidMap, mountPoint)
}
fusePidMapMtx.Unlock()

if ok {
p, err := os.FindProcess(pid)
if err != nil {
klog.Warningf("failed to find process %d: %v", pid, err)
} else {
if _, err = p.Wait(); err != nil {
klog.Warningf("%d is not a child process: %v", pid, err)
}
}
}

return nil
}

func createMountPoint(root string) error {
Expand Down