Gentoo Archives: gentoo-commits

From: Matt Turner <mattst88@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/catalyst:pending/mattst88 commit in: catalyst/base/
Date: Thu, 29 Oct 2020 16:14:30
Message-Id: 1603988027.a8a92a00b53e99b66b5c2bc9f44c2a3ba22ad454.mattst88@gentoo
1 commit: a8a92a00b53e99b66b5c2bc9f44c2a3ba22ad454
2 Author: Matt Turner <mattst88 <AT> gentoo <DOT> org>
3 AuthorDate: Sat May 16 21:44:37 2020 +0000
4 Commit: Matt Turner <mattst88 <AT> gentoo <DOT> org>
5 CommitDate: Thu Oct 29 16:13:47 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/catalyst.git/commit/?id=a8a92a00
7
8 catalyst: Use libmount for handling mounts
9
10 Handle the mounts/unmounts in all in process rather than shelling out
11 (pun intended!) to an external program.
12
13 While we're here, change some log.notice to log.debug since those cases
14 are normal and expected.
15
16 Signed-off-by: Matt Turner <mattst88 <AT> gentoo.org>
17
18 catalyst/base/stagebase.py | 57 ++++++++++++++++++++++++++++------------------
19 1 file changed, 35 insertions(+), 22 deletions(-)
20
21 diff --git a/catalyst/base/stagebase.py b/catalyst/base/stagebase.py
22 index e71ce344..73eacfbe 100644
23 --- a/catalyst/base/stagebase.py
24 +++ b/catalyst/base/stagebase.py
25 @@ -6,6 +6,7 @@ import sys
26
27 from pathlib import Path
28
29 +import libmount
30 import toml
31
32 from snakeoil import fileutils
33 @@ -853,7 +854,8 @@ class StageBase(TargetBase, ClearBase, GenBase):
34
35 source = str(self.mount[x]['source'])
36 target = self.settings['chroot_path'] + str(self.mount[x]['target'])
37 - mount = ['mount']
38 + fstype = ''
39 + options = ''
40
41 log.debug('bind %s: "%s" -> "%s"', x, source, target)
42
43 @@ -861,18 +863,20 @@ class StageBase(TargetBase, ClearBase, GenBase):
44 if 'var_tmpfs_portage' not in self.settings:
45 continue
46
47 - mount += ['-t', 'tmpfs', '-o',
48 - f"size={self.settings['var_tmpfs_portage']}G"]
49 + fstype = 'tmpfs'
50 + options = f"size={self.settings['var_tmpfs_portage']}G"
51 elif source == 'tmpfs':
52 - mount += ['-t', 'tmpfs']
53 + fstype = 'tmpfs'
54 elif source == 'shm':
55 - mount += ['-t', 'tmpfs', '-o', 'noexec,nosuid,nodev']
56 + fstype = 'tmpfs'
57 + options = 'noexec,nosuid,nodev'
58 else:
59 source_path = Path(self.mount[x]['source'])
60 if source_path.suffix == '.sqfs':
61 - mount += ['-o', 'ro']
62 + fstype = 'squashfs'
63 + options = 'ro,loop'
64 else:
65 - mount.append('--bind')
66 + options = 'bind'
67
68 # We may need to create the source of the bind mount. E.g., in the
69 # case of an empty package cache we must create the directory that
70 @@ -881,38 +885,47 @@ class StageBase(TargetBase, ClearBase, GenBase):
71
72 Path(target).mkdir(mode=0o755, parents=True, exist_ok=True)
73
74 - cmd(mount + [source, target], env=self.env, fail_func=self.unbind)
75 + try:
76 + cxt = libmount.Context(source=source, target=target,
77 + fstype=fstype, options=options)
78 + cxt.mount()
79 + except OSError as e:
80 + self.unbind()
81 + raise CatalystError(f"Couldn't mount: {source}, {e.strerror}")
82
83 def unbind(self):
84 - ouch = 0
85 - mypath = self.settings["chroot_path"]
86 + chroot_path = self.settings["chroot_path"]
87 + umount_failed = False
88
89 # Unmount in reverse order
90 - for x in [x for x in reversed(self.mount) if self.mount[x]['enable']]:
91 - target = normpath(mypath + self.mount[x]['target'])
92 - if not os.path.exists(target):
93 - log.notice('%s does not exist. Skipping', target)
94 + for target in [Path(chroot_path + self.mount[x]['target'])
95 + for x in reversed(self.mount)
96 + if self.mount[x]['enable']]:
97 + if not target.exists():
98 + log.debug('%s does not exist. Skipping', target)
99 continue
100
101 if not ismount(target):
102 - log.notice('%s is not a mount point. Skipping', target)
103 + log.debug('%s is not a mount point. Skipping', target)
104 continue
105
106 try:
107 - cmd(['umount', target], env=self.env)
108 - except CatalystError:
109 + cxt = libmount.Context(target=str(target))
110 + cxt.umount()
111 + except OSError:
112 log.warning('First attempt to unmount failed: %s', target)
113 log.warning('Killing any pids still running in the chroot')
114
115 self.kill_chroot_pids()
116
117 try:
118 - cmd(['umount', target], env=self.env)
119 - except CatalystError:
120 - ouch = 1
121 - log.warning("Couldn't umount bind mount: %s", target)
122 + cxt.umount()
123 + except OSError as e:
124 + umount_failed = True
125 + log.warning("Couldn't umount: %s, %s", target,
126 + e.strerror)
127
128 - if ouch:
129 + if umount_failed:
130 # if any bind mounts really failed, then we need to raise
131 # this to potentially prevent an upcoming bash stage cleanup script
132 # from wiping our bind mounts.