We can construct tree of mount points, based on their mount-id and parent-id numbers and recursively detach the leaves until we reach the point that we wanted to unmount.
In pseudo python code:
func detach(path, mount_id=None):
# Get a fresh mountinfo table
# Due to mount event propagation using a cached copy
# is probably impossible without correctly re-implementing
# kernel propagation logic.
mi = mountinfo()
# If we don't know the mount_id of the path we want to detach
# we must scan the mount table in reverse, since the last entry
# is the most recent one.
if mount_id is None:
for mie in reversed(mi.entries):
if mie.mount_point == path:
mount_id = mie.mount_id
break
else:
raise Exception(f"{path} is not a mount point")
# Construct a tree where each mount info entry knows about
# the children based on parent-id, mount-id association.
tree = treeify(mi)
# Find the node we want to detach
node = tree.find(mount_id=mount_id)
assert node.mount_point == path
# Detach each child, those will only be the mount entries
# that are immediately underneath this mount point.
for child in node.children():
detach(child.mount_point, child.mount_id)
umount2(node.mount_point, MS_DETACH)
We can construct tree of mount points, based on their mount-id and parent-id numbers and recursively detach the leaves until we reach the point that we wanted to unmount.
In pseudo python code:
func detach(path, mount_id=None): mi.entries) : mount_id= mount_id) child.mount_ point, child.mount_id) node.mount_ point, MS_DETACH)
# Get a fresh mountinfo table
# Due to mount event propagation using a cached copy
# is probably impossible without correctly re-implementing
# kernel propagation logic.
mi = mountinfo()
# If we don't know the mount_id of the path we want to detach
# we must scan the mount table in reverse, since the last entry
# is the most recent one.
if mount_id is None:
for mie in reversed(
if mie.mount_point == path:
mount_id = mie.mount_id
break
else:
raise Exception(f"{path} is not a mount point")
# Construct a tree where each mount info entry knows about
# the children based on parent-id, mount-id association.
tree = treeify(mi)
# Find the node we want to detach
node = tree.find(
assert node.mount_point == path
# Detach each child, those will only be the mount entries
# that are immediately underneath this mount point.
for child in node.children():
detach(
umount2(