Change:
When we merged - we introduced comparison of subpath sources: But subpaths source comparison never works properly for all volume types, even if subpath and source remains unchaged. This is because we are comparing wrong things. For a given volume - is usually: But according - the root is - . This means that - if creation of a container times out, then another container can not start until old container exits, because subapth comparison above will be false and kubelet will try to umount the subpath bind mount and it will keep failing with "device is busy" errors. So subpath bind mount can not be reused at all. This is sort of expensive, for containers that use selinux. Because it means each container creation will potentially run recursive chcon again on the entire subpath etc.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig node /sig storage
cc
/remove-sig node

Discussion:
"golang.org/x/sys/unix" "k8s.io/klog/v2" <del> "k8s.io/kubernetes/pkg/volume/util/hostutil" </del> "k8s.io/mount-utils" )

notMount = true } if !notMount { <del> linuxHostUtil := hostutil.NewHostUtil() mntInfo, err := linuxHostUtil.FindMountInfo(bindPathTarget) </del> <ins> // It's already mounted, so check if it's bind-mounted to the same path samePath, err := checkSubPathFileEqual(subpath, bindPathTarget) </ins> if err != nil { <del> return false, "", fmt.Errorf("error calling findMountInfo for %s: %s", bindPathTarget, err) </del> <ins> return false, "", fmt.Errorf("error checking subpath mount info for %s: %s", bindPathTarget, err) </ins> } <del> if mntInfo.Root != subpath.Path { </del> <ins> if !samePath { </ins> // It's already mounted but not what we want, unmount it if err = mounter.Unmount(bindPathTarget); err != nil { return false, "", fmt.Errorf("error ummounting %s: %s", bindPathTarget, err)

return false, bindPathTarget, nil } <ins> func checkSubPathFileEqual(subpath Subpath, bindMountTarget string) (bool, error) { s, err := os.Lstat(subpath.Path) if err != nil { return false, fmt.Errorf("stat %s failed: %s", subpath.Path, err) } t, err := os.Lstat(bindMountTarget) if err != nil { return false, fmt.Errorf("lstat %s failed: %s", bindMountTarget, err) } if !os.SameFile(s, t) { return false, nil } return true, nil } </ins> func getSubpathBindTarget(subpath Subpath) string { // containerName is DNS label, i.e. safe as a directory name. return filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName, strconv.Itoa(subpath.VolumeMountIndex))

} } <ins> func TestSubpath_PrepareSafeSubpath(t *testing.T) { //complete code defaultPerm := os.FileMode(0750) tests := []struct { name string // Function that prepares directory structure for the test under given // base. prepare      func(base string) ([]string, string, string, error) expectError  bool expectAction []mount.FakeAction mountExists  bool }{ { name: "subpath-mount-already-exists-with-mismatching-mount", prepare: func(base string) ([]string, string, string, error) { volpath, subpathMount := getTestPaths(base) mounts := []string{subpathMount} if err := os.MkdirAll(subpathMount, defaultPerm); err != nil { return nil, "", "", err } subpath := filepath.Join(volpath, "dir0") return mounts, volpath, subpath, os.MkdirAll(subpath, defaultPerm) }, expectError:  false, expectAction: []mount.FakeAction{{Action: "unmount"}}, mountExists:  false, }, { name: "subpath-mount-already-exists-with-samefile", prepare: func(base string) ([]string, string, string, error) { volpath, subpathMount := getTestPaths(base) mounts := []string{subpathMount} subpathMountRoot := filepath.Dir(subpathMount) if err := os.MkdirAll(subpathMountRoot, defaultPerm); err != nil { return nil, "", "", err } targetFile, err := os.Create(subpathMount) if err != nil { return nil, "", "", err } defer targetFile.Close() if err := os.MkdirAll(volpath, defaultPerm); err != nil { return nil, "", "", err } subpath := filepath.Join(volpath, "file0") // using hard link to simulate bind mounts err = os.Link(subpathMount, subpath) if err != nil { return nil, "", "", err } return mounts, volpath, subpath, nil }, expectError:  false, expectAction: []mount.FakeAction{}, mountExists:  true, }, } for _, test := range tests { klog.V(4).Infof("test %q", test.name) base, err := ioutil.TempDir("", "bind-subpath-"+test.name+"-") if err != nil { t.Fatalf(err.Error()) } defer os.RemoveAll(base) mounts, volPath, subPath, err := test.prepare(base) if err != nil { os.RemoveAll(base) t.Fatalf("failed to prepare test %q: %v", test.name, err.Error()) } fm := setupFakeMounter(mounts) subpath := Subpath{ VolumeMountIndex: testSubpath, Path:             subPath, VolumeName:       testVol, VolumePath:       volPath, PodDir:           filepath.Join(base, "pod0"), ContainerName:    testContainer, } _, subpathMount := getTestPaths(base) bindMountExists, bindPathTarget, err := prepareSubpathTarget(fm, subpath) if bindMountExists != test.mountExists { t.Errorf("test %q failed: expected bindMountExists %v, got %v", test.name, test.mountExists, bindMountExists) } logActions := fm.GetLog() if len(test.expectAction) == 0 && len(logActions) > 0 { t.Errorf("test %q failed: expected no actions, got %v", test.name, logActions) } if len(test.expectAction) > 0 { foundMatchingAction := false testAction := test.expectAction[0] for _, action := range logActions { if action.Action == testAction.Action { foundMatchingAction = true break } } if !foundMatchingAction { t.Errorf("test %q failed: expected action %q, got %v", test.name, testAction.Action, logActions) } } if test.expectError { if err == nil { t.Errorf("test %q failed: expected error, got success", test.name) } if bindPathTarget != "" { t.Errorf("test %q failed: expected empty bindPathTarget, got %v", test.name, bindPathTarget) } if err = validateDirNotExists(subpathMount); err != nil { t.Errorf("test %q failed: %v", test.name, err) } } if !test.expectError { if err != nil { t.Errorf("test %q failed: %v", test.name, err) } if bindPathTarget != subpathMount { t.Errorf("test %q failed: expected bindPathTarget %v, got %v", test.name, subpathMount, bindPathTarget) } if err = validateFileExists(subpathMount); err != nil { t.Errorf("test %q failed: %v", test.name, err) } } } } </ins> func TestSafeOpen(t *testing.T) { defaultPerm := os.FileMode(0750)