github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/pkg/mount/sharedsubtree_linux_test.go (about)

     1  // +build linux
     2  
     3  package mount // import "github.com/docker/docker/pkg/mount"
     4  
     5  import (
     6  	"os"
     7  	"path"
     8  	"testing"
     9  
    10  	"github.com/pkg/errors"
    11  	"golang.org/x/sys/unix"
    12  )
    13  
    14  // nothing is propagated in or out
    15  func TestSubtreePrivate(t *testing.T) {
    16  	if os.Getuid() != 0 {
    17  		t.Skip("root required")
    18  	}
    19  
    20  	tmp := path.Join(os.TempDir(), "mount-tests")
    21  	if err := os.MkdirAll(tmp, 0777); err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	defer os.RemoveAll(tmp)
    25  
    26  	var (
    27  		sourceDir   = path.Join(tmp, "source")
    28  		targetDir   = path.Join(tmp, "target")
    29  		outside1Dir = path.Join(tmp, "outside1")
    30  		outside2Dir = path.Join(tmp, "outside2")
    31  
    32  		outside1Path      = path.Join(outside1Dir, "file.txt")
    33  		outside2Path      = path.Join(outside2Dir, "file.txt")
    34  		outside1CheckPath = path.Join(targetDir, "a", "file.txt")
    35  		outside2CheckPath = path.Join(sourceDir, "b", "file.txt")
    36  	)
    37  	if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	if err := os.MkdirAll(path.Join(sourceDir, "b"), 0777); err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	if err := os.Mkdir(targetDir, 0777); err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	if err := os.Mkdir(outside1Dir, 0777); err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	if err := os.Mkdir(outside2Dir, 0777); err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	if err := createFile(outside1Path); err != nil {
    54  		t.Fatal(err)
    55  	}
    56  	if err := createFile(outside2Path); err != nil {
    57  		t.Fatal(err)
    58  	}
    59  
    60  	// mount the shared directory to a target
    61  	if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	defer func() {
    65  		if err := Unmount(targetDir); err != nil {
    66  			t.Fatal(err)
    67  		}
    68  	}()
    69  
    70  	// next, make the target private
    71  	if err := MakePrivate(targetDir); err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	defer func() {
    75  		if err := Unmount(targetDir); err != nil {
    76  			t.Fatal(err)
    77  		}
    78  	}()
    79  
    80  	// mount in an outside path to a mounted path inside the _source_
    81  	if err := Mount(outside1Dir, path.Join(sourceDir, "a"), "none", "bind,rw"); err != nil {
    82  		t.Fatal(err)
    83  	}
    84  	defer func() {
    85  		if err := Unmount(path.Join(sourceDir, "a")); err != nil {
    86  			t.Fatal(err)
    87  		}
    88  	}()
    89  
    90  	// check that this file _does_not_ show in the _target_
    91  	if _, err := os.Stat(outside1CheckPath); err != nil && !os.IsNotExist(err) {
    92  		t.Fatal(err)
    93  	} else if err == nil {
    94  		t.Fatalf("%q should not be visible, but is", outside1CheckPath)
    95  	}
    96  
    97  	// next mount outside2Dir into the _target_
    98  	if err := Mount(outside2Dir, path.Join(targetDir, "b"), "none", "bind,rw"); err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	defer func() {
   102  		if err := Unmount(path.Join(targetDir, "b")); err != nil {
   103  			t.Fatal(err)
   104  		}
   105  	}()
   106  
   107  	// check that this file _does_not_ show in the _source_
   108  	if _, err := os.Stat(outside2CheckPath); err != nil && !os.IsNotExist(err) {
   109  		t.Fatal(err)
   110  	} else if err == nil {
   111  		t.Fatalf("%q should not be visible, but is", outside2CheckPath)
   112  	}
   113  }
   114  
   115  // Testing that when a target is a shared mount,
   116  // then child mounts propagate to the source
   117  func TestSubtreeShared(t *testing.T) {
   118  	if os.Getuid() != 0 {
   119  		t.Skip("root required")
   120  	}
   121  
   122  	tmp := path.Join(os.TempDir(), "mount-tests")
   123  	if err := os.MkdirAll(tmp, 0777); err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	defer os.RemoveAll(tmp)
   127  
   128  	var (
   129  		sourceDir  = path.Join(tmp, "source")
   130  		targetDir  = path.Join(tmp, "target")
   131  		outsideDir = path.Join(tmp, "outside")
   132  
   133  		outsidePath     = path.Join(outsideDir, "file.txt")
   134  		sourceCheckPath = path.Join(sourceDir, "a", "file.txt")
   135  	)
   136  
   137  	if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil {
   138  		t.Fatal(err)
   139  	}
   140  	if err := os.Mkdir(targetDir, 0777); err != nil {
   141  		t.Fatal(err)
   142  	}
   143  	if err := os.Mkdir(outsideDir, 0777); err != nil {
   144  		t.Fatal(err)
   145  	}
   146  
   147  	if err := createFile(outsidePath); err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	// mount the source as shared
   152  	if err := MakeShared(sourceDir); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  	defer func() {
   156  		if err := Unmount(sourceDir); err != nil {
   157  			t.Fatal(err)
   158  		}
   159  	}()
   160  
   161  	// mount the shared directory to a target
   162  	if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	defer func() {
   166  		if err := Unmount(targetDir); err != nil {
   167  			t.Fatal(err)
   168  		}
   169  	}()
   170  
   171  	// mount in an outside path to a mounted path inside the target
   172  	if err := Mount(outsideDir, path.Join(targetDir, "a"), "none", "bind,rw"); err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	defer func() {
   176  		if err := Unmount(path.Join(targetDir, "a")); err != nil {
   177  			t.Fatal(err)
   178  		}
   179  	}()
   180  
   181  	// NOW, check that the file from the outside directory is available in the source directory
   182  	if _, err := os.Stat(sourceCheckPath); err != nil {
   183  		t.Fatal(err)
   184  	}
   185  }
   186  
   187  // testing that mounts to a shared source show up in the slave target,
   188  // and that mounts into a slave target do _not_ show up in the shared source
   189  func TestSubtreeSharedSlave(t *testing.T) {
   190  	if os.Getuid() != 0 {
   191  		t.Skip("root required")
   192  	}
   193  
   194  	tmp := path.Join(os.TempDir(), "mount-tests")
   195  	if err := os.MkdirAll(tmp, 0777); err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	defer os.RemoveAll(tmp)
   199  
   200  	var (
   201  		sourceDir   = path.Join(tmp, "source")
   202  		targetDir   = path.Join(tmp, "target")
   203  		outside1Dir = path.Join(tmp, "outside1")
   204  		outside2Dir = path.Join(tmp, "outside2")
   205  
   206  		outside1Path      = path.Join(outside1Dir, "file.txt")
   207  		outside2Path      = path.Join(outside2Dir, "file.txt")
   208  		outside1CheckPath = path.Join(targetDir, "a", "file.txt")
   209  		outside2CheckPath = path.Join(sourceDir, "b", "file.txt")
   210  	)
   211  	if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil {
   212  		t.Fatal(err)
   213  	}
   214  	if err := os.MkdirAll(path.Join(sourceDir, "b"), 0777); err != nil {
   215  		t.Fatal(err)
   216  	}
   217  	if err := os.Mkdir(targetDir, 0777); err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if err := os.Mkdir(outside1Dir, 0777); err != nil {
   221  		t.Fatal(err)
   222  	}
   223  	if err := os.Mkdir(outside2Dir, 0777); err != nil {
   224  		t.Fatal(err)
   225  	}
   226  
   227  	if err := createFile(outside1Path); err != nil {
   228  		t.Fatal(err)
   229  	}
   230  	if err := createFile(outside2Path); err != nil {
   231  		t.Fatal(err)
   232  	}
   233  
   234  	// mount the source as shared
   235  	if err := MakeShared(sourceDir); err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	defer func() {
   239  		if err := Unmount(sourceDir); err != nil {
   240  			t.Fatal(err)
   241  		}
   242  	}()
   243  
   244  	// mount the shared directory to a target
   245  	if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil {
   246  		t.Fatal(err)
   247  	}
   248  	defer func() {
   249  		if err := Unmount(targetDir); err != nil {
   250  			t.Fatal(err)
   251  		}
   252  	}()
   253  
   254  	// next, make the target slave
   255  	if err := MakeSlave(targetDir); err != nil {
   256  		t.Fatal(err)
   257  	}
   258  	defer func() {
   259  		if err := Unmount(targetDir); err != nil {
   260  			t.Fatal(err)
   261  		}
   262  	}()
   263  
   264  	// mount in an outside path to a mounted path inside the _source_
   265  	if err := Mount(outside1Dir, path.Join(sourceDir, "a"), "none", "bind,rw"); err != nil {
   266  		t.Fatal(err)
   267  	}
   268  	defer func() {
   269  		if err := Unmount(path.Join(sourceDir, "a")); err != nil {
   270  			t.Fatal(err)
   271  		}
   272  	}()
   273  
   274  	// check that this file _does_ show in the _target_
   275  	if _, err := os.Stat(outside1CheckPath); err != nil {
   276  		t.Fatal(err)
   277  	}
   278  
   279  	// next mount outside2Dir into the _target_
   280  	if err := Mount(outside2Dir, path.Join(targetDir, "b"), "none", "bind,rw"); err != nil {
   281  		t.Fatal(err)
   282  	}
   283  	defer func() {
   284  		if err := Unmount(path.Join(targetDir, "b")); err != nil {
   285  			t.Fatal(err)
   286  		}
   287  	}()
   288  
   289  	// check that this file _does_not_ show in the _source_
   290  	if _, err := os.Stat(outside2CheckPath); err != nil && !os.IsNotExist(err) {
   291  		t.Fatal(err)
   292  	} else if err == nil {
   293  		t.Fatalf("%q should not be visible, but is", outside2CheckPath)
   294  	}
   295  }
   296  
   297  func TestSubtreeUnbindable(t *testing.T) {
   298  	if os.Getuid() != 0 {
   299  		t.Skip("root required")
   300  	}
   301  
   302  	tmp := path.Join(os.TempDir(), "mount-tests")
   303  	if err := os.MkdirAll(tmp, 0777); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  	defer os.RemoveAll(tmp)
   307  
   308  	var (
   309  		sourceDir = path.Join(tmp, "source")
   310  		targetDir = path.Join(tmp, "target")
   311  	)
   312  	if err := os.MkdirAll(sourceDir, 0777); err != nil {
   313  		t.Fatal(err)
   314  	}
   315  	if err := os.MkdirAll(targetDir, 0777); err != nil {
   316  		t.Fatal(err)
   317  	}
   318  
   319  	// next, make the source unbindable
   320  	if err := MakeUnbindable(sourceDir); err != nil {
   321  		t.Fatal(err)
   322  	}
   323  	defer func() {
   324  		if err := Unmount(sourceDir); err != nil {
   325  			t.Fatal(err)
   326  		}
   327  	}()
   328  
   329  	// then attempt to mount it to target. It should fail
   330  	if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil && errors.Cause(err) != unix.EINVAL {
   331  		t.Fatal(err)
   332  	} else if err == nil {
   333  		t.Fatalf("%q should not have been bindable", sourceDir)
   334  	}
   335  	defer func() {
   336  		if err := Unmount(targetDir); err != nil {
   337  			t.Fatal(err)
   338  		}
   339  	}()
   340  }
   341  
   342  func createFile(path string) error {
   343  	f, err := os.Create(path)
   344  	if err != nil {
   345  		return err
   346  	}
   347  	f.WriteString("hello world!")
   348  	return f.Close()
   349  }