github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/daemon/snapshotter/mount.go (about)

     1  package snapshotter
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/containerd/containerd/mount"
     9  	"github.com/containerd/log"
    10  	"github.com/Prakhar-Agarwal-byte/moby/daemon/graphdriver"
    11  	"github.com/Prakhar-Agarwal-byte/moby/pkg/idtools"
    12  	"github.com/moby/locker"
    13  )
    14  
    15  const mountsDir = "rootfs"
    16  
    17  // List of known filesystems that can't be re-mounted or have shared layers
    18  var refCountedFileSystems = []string{"fuse-overlayfs", "overlayfs", "stargz", "zfs"}
    19  
    20  // Mounter handles mounting/unmounting things coming in from a snapshotter
    21  // with optional reference counting if needed by the filesystem
    22  type Mounter interface {
    23  	// Mount mounts the rootfs for a container and returns the mount point
    24  	Mount(mounts []mount.Mount, containerID string) (string, error)
    25  	// Unmount unmounts the container rootfs
    26  	Unmount(target string) error
    27  }
    28  
    29  // inSlice tests whether a string is contained in a slice of strings or not.
    30  // Comparison is case sensitive
    31  func inSlice(slice []string, s string) bool {
    32  	for _, ss := range slice {
    33  		if s == ss {
    34  			return true
    35  		}
    36  	}
    37  	return false
    38  }
    39  
    40  // NewMounter creates a new mounter for the provided snapshotter
    41  func NewMounter(home string, snapshotter string, idMap idtools.IdentityMapping) Mounter {
    42  	if inSlice(refCountedFileSystems, snapshotter) {
    43  		return &refCountMounter{
    44  			home:        home,
    45  			snapshotter: snapshotter,
    46  			rc:          graphdriver.NewRefCounter(checker()),
    47  			locker:      locker.New(),
    48  			idMap:       idMap,
    49  		}
    50  	}
    51  
    52  	return mounter{
    53  		home:        home,
    54  		snapshotter: snapshotter,
    55  		idMap:       idMap,
    56  	}
    57  }
    58  
    59  type refCountMounter struct {
    60  	home        string
    61  	snapshotter string
    62  	rc          *graphdriver.RefCounter
    63  	locker      *locker.Locker
    64  	idMap       idtools.IdentityMapping
    65  }
    66  
    67  func (m *refCountMounter) Mount(mounts []mount.Mount, containerID string) (target string, retErr error) {
    68  	target = filepath.Join(m.home, mountsDir, m.snapshotter, containerID)
    69  
    70  	_, err := os.Stat(target)
    71  	if err != nil && !os.IsNotExist(err) {
    72  		return "", err
    73  	}
    74  
    75  	if count := m.rc.Increment(target); count > 1 {
    76  		return target, nil
    77  	}
    78  
    79  	m.locker.Lock(target)
    80  	defer m.locker.Unlock(target)
    81  
    82  	defer func() {
    83  		if retErr != nil {
    84  			if c := m.rc.Decrement(target); c <= 0 {
    85  				if mntErr := unmount(target); mntErr != nil {
    86  					log.G(context.TODO()).Errorf("error unmounting %s: %v", target, mntErr)
    87  				}
    88  				if rmErr := os.Remove(target); rmErr != nil && !os.IsNotExist(rmErr) {
    89  					log.G(context.TODO()).Debugf("Failed to remove %s: %v: %v", target, rmErr, err)
    90  				}
    91  			}
    92  		}
    93  	}()
    94  
    95  	root := m.idMap.RootPair()
    96  	if err := idtools.MkdirAllAndChown(filepath.Dir(target), 0o710, idtools.Identity{
    97  		UID: idtools.CurrentIdentity().UID,
    98  		GID: root.GID,
    99  	}); err != nil {
   100  		return "", err
   101  	}
   102  	if err := idtools.MkdirAllAndChown(target, 0o710, root); err != nil {
   103  		return "", err
   104  	}
   105  
   106  	return target, mount.All(mounts, target)
   107  }
   108  
   109  func (m *refCountMounter) Unmount(target string) error {
   110  	if count := m.rc.Decrement(target); count > 0 {
   111  		return nil
   112  	}
   113  
   114  	m.locker.Lock(target)
   115  	defer m.locker.Unlock(target)
   116  
   117  	if err := unmount(target); err != nil {
   118  		log.G(context.TODO()).Debugf("Failed to unmount %s: %v", target, err)
   119  	}
   120  
   121  	if err := os.Remove(target); err != nil {
   122  		log.G(context.TODO()).WithError(err).WithField("dir", target).Error("failed to remove mount temp dir")
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  type mounter struct {
   129  	home        string
   130  	snapshotter string
   131  	idMap       idtools.IdentityMapping
   132  }
   133  
   134  func (m mounter) Mount(mounts []mount.Mount, containerID string) (string, error) {
   135  	target := filepath.Join(m.home, mountsDir, m.snapshotter, containerID)
   136  
   137  	root := m.idMap.RootPair()
   138  	if err := idtools.MkdirAndChown(target, 0o700, root); err != nil {
   139  		return "", err
   140  	}
   141  
   142  	return target, mount.All(mounts, target)
   143  }
   144  
   145  func (m mounter) Unmount(target string) error {
   146  	return unmount(target)
   147  }