mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Automated rollback of changelist 564000728
PiperOrigin-RevId: 567054388
This commit is contained in:
committed by
gVisor bot
parent
1c8e91d04c
commit
1531147bf2
@@ -108,6 +108,10 @@ type Mount struct {
|
||||
// Mount.EndWrite(). The MSB of writers is set if MS_RDONLY is in effect.
|
||||
// writers is accessed using atomic memory operations.
|
||||
writers atomicbitops.Int64
|
||||
|
||||
// pendingChildren is a list of new child mounts that have not yet been
|
||||
// connected to this mount as the parent.
|
||||
pendingChildren []*Mount
|
||||
}
|
||||
|
||||
func newMount(vfs *VirtualFilesystem, fs *Filesystem, root *Dentry, mntns *MountNamespace, opts *MountOptions) *Mount {
|
||||
@@ -322,6 +326,38 @@ func (vfs *VirtualFilesystem) cloneMount(mnt *Mount, root *Dentry, mopts *MountO
|
||||
return clone
|
||||
}
|
||||
|
||||
type cloneTreeNode struct {
|
||||
prevMount *Mount
|
||||
parentMount *Mount
|
||||
}
|
||||
|
||||
// cloneMountTree creates a copy of mnt's tree with the specified root
|
||||
// dentry at root. The new descendents are added to mnt's pending mount list.
|
||||
//
|
||||
// +checklocks:vfs.mountMu
|
||||
func (vfs *VirtualFilesystem) cloneMountTree(ctx context.Context, mnt *Mount, root *Dentry) (*Mount, error) {
|
||||
clone := vfs.cloneMount(mnt, root, nil)
|
||||
queue := []cloneTreeNode{{mnt, clone}}
|
||||
for len(queue) != 0 {
|
||||
p := queue[len(queue)-1]
|
||||
queue = queue[:len(queue)-1]
|
||||
for c := range p.prevMount.children {
|
||||
m := vfs.cloneMount(c, c.root, nil)
|
||||
mp := VirtualDentry{
|
||||
mount: p.parentMount,
|
||||
dentry: c.point(),
|
||||
}
|
||||
mp.IncRef()
|
||||
m.setKey(mp)
|
||||
p.parentMount.pendingChildren = append(p.parentMount.pendingChildren, m)
|
||||
if len(c.children) != 0 {
|
||||
queue = append(queue, cloneTreeNode{c, m})
|
||||
}
|
||||
}
|
||||
}
|
||||
return clone, nil
|
||||
}
|
||||
|
||||
// BindAt creates a clone of the source path's parent mount and mounts it at
|
||||
// the target path. The new mount's root dentry is one pointed to by the source
|
||||
// path.
|
||||
|
||||
+12
-30
@@ -142,6 +142,10 @@ func (vfs *VirtualFilesystem) updateRootAndCWD(ctx context.Context, root *Virtua
|
||||
cwd.mount = dst
|
||||
cwd.mount.IncRef()
|
||||
}
|
||||
for srcChild := range src.children {
|
||||
dstChild := vfs.mounts.Lookup(dst, srcChild.point())
|
||||
vfs.updateRootAndCWD(ctx, root, cwd, srcChild, dstChild)
|
||||
}
|
||||
}
|
||||
|
||||
// NamespaceInodeGetter is an interface that provides the GetNamespaceInode method.
|
||||
@@ -170,38 +174,16 @@ func (vfs *VirtualFilesystem) CloneMountNamespace(
|
||||
vfs.lockMounts()
|
||||
defer vfs.unlockMounts(ctx)
|
||||
|
||||
ns.root.root.IncRef()
|
||||
ns.root.fs.IncRef()
|
||||
newns.root = newMount(vfs, ns.root.fs, ns.root.root, newns, &MountOptions{Flags: ns.root.Flags, ReadOnly: ns.root.ReadOnly()})
|
||||
if ns.root.isShared {
|
||||
vfs.addPeer(ns.root, newns.root)
|
||||
newRoot, err := vfs.cloneMountTree(ctx, ns.root, ns.root.root)
|
||||
if err != nil {
|
||||
newns.DecRef(ctx)
|
||||
vfs.abortTree(ctx, newRoot)
|
||||
return nil, err
|
||||
}
|
||||
newns.root = newRoot
|
||||
newns.root.ns = newns
|
||||
vfs.commitPendingTree(ctx, newRoot)
|
||||
vfs.updateRootAndCWD(ctx, root, cwd, ns.root, newns.root)
|
||||
|
||||
queue := []cloneEntry{cloneEntry{ns.root, newns.root}}
|
||||
for len(queue) != 0 {
|
||||
p := queue[len(queue)-1]
|
||||
queue = queue[:len(queue)-1]
|
||||
for c := range p.prevMount.children {
|
||||
m := vfs.cloneMount(c, c.root, nil)
|
||||
vd := VirtualDentry{
|
||||
mount: p.parentMount,
|
||||
dentry: c.point(),
|
||||
}
|
||||
vd.IncRef()
|
||||
|
||||
err := vfs.connectMountAtLocked(ctx, m, vd)
|
||||
vfs.delayDecRef(m)
|
||||
if err != nil {
|
||||
newns.DecRef(ctx)
|
||||
return nil, err
|
||||
}
|
||||
vfs.updateRootAndCWD(ctx, root, cwd, c, m)
|
||||
if len(c.children) != 0 {
|
||||
queue = append(queue, cloneEntry{c, m})
|
||||
}
|
||||
}
|
||||
}
|
||||
return newns, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,53 @@ func (vfs *VirtualFilesystem) abortPropagationTree(ctx context.Context, tree map
|
||||
}
|
||||
}
|
||||
|
||||
// +checklocks:vfs.mountMu
|
||||
func (vfs *VirtualFilesystem) commitPendingTree(ctx context.Context, mnt *Mount) {
|
||||
for _, c := range mnt.pendingChildren {
|
||||
vfs.commitTree(ctx, c)
|
||||
}
|
||||
mnt.pendingChildren = nil
|
||||
}
|
||||
|
||||
// +checklocks:vfs.mountMu
|
||||
func (vfs *VirtualFilesystem) commitTree(ctx context.Context, mnt *Mount) {
|
||||
mp := mnt.getKey()
|
||||
|
||||
// If there is already a mount at this (parent, point), disconnect it from its
|
||||
// parent and reconnect it to mnt once mnt has been connected.
|
||||
child := vfs.mounts.Lookup(mp.mount, mp.dentry)
|
||||
vfs.mounts.seq.BeginWrite()
|
||||
if child != nil {
|
||||
vfs.delayDecRef(vfs.disconnectLocked(child))
|
||||
}
|
||||
vfs.connectLocked(mnt, mp, mp.mount.ns)
|
||||
vfs.delayDecRef(mnt)
|
||||
|
||||
if child != nil {
|
||||
newmp := VirtualDentry{mnt, mnt.root}
|
||||
newmp.IncRef()
|
||||
vfs.connectLocked(child, newmp, newmp.mount.ns)
|
||||
vfs.delayDecRef(child)
|
||||
}
|
||||
vfs.mounts.seq.EndWrite()
|
||||
vfs.commitPendingTree(ctx, mnt)
|
||||
}
|
||||
|
||||
// abortTree releases references on a pending mount and all its pending
|
||||
// descendants.
|
||||
//
|
||||
// +checklocks:vfs.mountMu
|
||||
func (vfs *VirtualFilesystem) abortTree(ctx context.Context, mnt *Mount) {
|
||||
vfs.delayDecRef(mnt)
|
||||
vfs.delayDecRef(mnt.getKey())
|
||||
mnt.setKey(VirtualDentry{})
|
||||
vfs.setPropagation(mnt, linux.MS_PRIVATE)
|
||||
for _, c := range mnt.pendingChildren {
|
||||
vfs.abortTree(ctx, c)
|
||||
}
|
||||
mnt.pendingChildren = nil
|
||||
}
|
||||
|
||||
// SetMountPropagationAt changes the propagation type of the mount pointed to by
|
||||
// pop.
|
||||
func (vfs *VirtualFilesystem) SetMountPropagationAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, propFlags uint32) error {
|
||||
|
||||
Reference in New Issue
Block a user