@@ -126,6 +126,35 @@ require_internal_units (const char *normal_dir, const char *early_dir, const cha
126
126
#endif
127
127
}
128
128
129
+ static gboolean
130
+ write_unit_file (int dir_fd , const char * path , GCancellable * cancellable , GError * * error , const char * fmt , ...)
131
+ {
132
+ g_auto (GLnxTmpfile ) tmpf = {
133
+ 0 ,
134
+ };
135
+ if (!glnx_open_tmpfile_linkable_at (dir_fd , "." , O_WRONLY | O_CLOEXEC , & tmpf , error ))
136
+ return FALSE;
137
+ g_autoptr (GOutputStream ) outstream = g_unix_output_stream_new (tmpf .fd , FALSE);
138
+ gsize bytes_written ;
139
+ va_list args ;
140
+ va_start (args , fmt );
141
+ const gboolean r = g_output_stream_vprintf (outstream , & bytes_written , cancellable , error , fmt , args );
142
+ va_end (args );
143
+ if (!r )
144
+ return FALSE;
145
+ if (!g_output_stream_flush (outstream , cancellable , error ))
146
+ return FALSE;
147
+ g_clear_object (& outstream );
148
+ /* It should be readable */
149
+ if (!glnx_fchmod (tmpf .fd , 0644 , error ))
150
+ return FALSE;
151
+ /* Error out if somehow it already exists, that'll help us debug conflicts */
152
+ if (!glnx_link_tmpfile_at (& tmpf , GLNX_LINK_TMPFILE_NOREPLACE , dir_fd , path ,
153
+ error ))
154
+ return FALSE;
155
+ return TRUE;
156
+ }
157
+
129
158
/* Generate var.mount */
130
159
static gboolean
131
160
fstab_generator (const char * ostree_target , const bool is_aboot , const char * normal_dir ,
@@ -135,8 +164,37 @@ fstab_generator (const char *ostree_target, const bool is_aboot, const char *nor
135
164
/* Not currently cancellable, but define a var in case we care later */
136
165
GCancellable * cancellable = NULL ;
137
166
/* Some path constants to avoid typos */
138
- static const char fstab_path [] = "/etc/fstab" ;
139
- static const char var_path [] = "/var" ;
167
+ const char * fstab_path = "/etc/fstab" ;
168
+ const char * var_dst = "/var" ;
169
+ const char * var_src = OTCORE_RUN_OSTREE_PRIVATE "/var" ;
170
+
171
+ /* Prepare to write to the output unit dir; we use the "normal" dir
172
+ * that overrides /usr, but not /etc.
173
+ */
174
+ glnx_autofd int normal_dir_dfd = -1 ;
175
+ if (!glnx_opendirat (AT_FDCWD , normal_dir , TRUE, & normal_dir_dfd , error ))
176
+ return FALSE;
177
+
178
+ /* Generate a unit to unmount var_src */
179
+ if (!write_unit_file (normal_dir_dfd , "ostree-unmount-temp-var.service" , cancellable , error ,
180
+ "##\n# Automatically generated by ostree-system-generator\n##\n\n"
181
+ "[Unit]\n"
182
+ "Documentation=man:ostree(1)\n"
183
+ "ConditionPathIsMountPoint=%s\n"
184
+ "After=var.mount\n"
185
+ "\n"
186
+ "[Service]\n"
187
+ "Type=oneshot\n"
188
+ "ExecStart=/usr/bin/umount --lazy %s\n" ,
189
+ var_src , var_src ))
190
+ return FALSE;
191
+
192
+ if (!glnx_shutil_mkdir_p_at (normal_dir_dfd , "local-fs.target.wants" , 0755 , cancellable ,
193
+ error ))
194
+ return FALSE;
195
+ if (symlinkat ("../ostree-unmount-temp-var.service" , normal_dir_dfd ,
196
+ "local-fs.target.wants/ostree-unmount-temp-var.service" ) < 0 )
197
+ return glnx_throw_errno_prefix (error , "symlinkat" );
140
198
141
199
/* Load /etc/fstab if it exists, and look for a /var mount */
142
200
g_autoptr (OtLibMountFile ) fstab = setmntent (fstab_path , "re" );
@@ -157,7 +215,7 @@ fstab_generator (const char *ostree_target, const bool is_aboot, const char *nor
157
215
path_kill_slashes (where );
158
216
159
217
/* We're only looking for /var here */
160
- if (strcmp (where , var_path ) != 0 )
218
+ if (strcmp (where , var_dst ) != 0 )
161
219
continue ;
162
220
163
221
found_var_mnt = TRUE;
@@ -169,59 +227,19 @@ fstab_generator (const char *ostree_target, const bool is_aboot, const char *nor
169
227
if (found_var_mnt )
170
228
return TRUE;
171
229
172
- /* Prepare to write to the output unit dir; we use the "normal" dir
173
- * that overrides /usr, but not /etc.
174
- */
175
- glnx_autofd int normal_dir_dfd = -1 ;
176
- if (!glnx_opendirat (AT_FDCWD , normal_dir , TRUE, & normal_dir_dfd , error ))
177
- return FALSE;
178
-
179
230
/* Generate our bind mount unit */
180
- const char * var_dir = OTCORE_RUN_OSTREE_PRIVATE "/var" ;
181
-
182
- g_auto (GLnxTmpfile ) tmpf = {
183
- 0 ,
184
- };
185
- if (!glnx_open_tmpfile_linkable_at (normal_dir_dfd , "." , O_WRONLY | O_CLOEXEC , & tmpf , error ))
186
- return FALSE;
187
- g_autoptr (GOutputStream ) outstream = g_unix_output_stream_new (tmpf .fd , FALSE);
188
- gsize bytes_written ;
189
- /* This code is inspired by systemd's fstab-generator.c.
190
- *
191
- * Note that our unit doesn't run if systemd.volatile is enabled;
192
- * see https://github.com/ostreedev/ostree/pull/856
193
- *
194
- * To avoid having submounts of /var propagate into $stateroot/var, the mount
195
- * is made with slave+shared propagation. This means that /var will receive
196
- * mount events from the parent /sysroot mount, but not vice versa. Adding a
197
- * shared peer group below the slave group means that submounts of /var will
198
- * inherit normal shared propagation. See mount_namespaces(7), Linux
199
- * Documentation/filesystems/sharedsubtree.txt and
200
- * https://github.com/ostreedev/ostree/issues/2086. This also happens in
201
- * ostree-prepare-root.c for the INITRAMFS_MOUNT_VAR case.
202
- */
203
- if (!g_output_stream_printf (outstream , & bytes_written , cancellable , error ,
204
- "##\n# Automatically generated by ostree-system-generator\n##\n\n"
205
- "[Unit]\n"
206
- "Documentation=man:ostree(1)\n"
207
- "ConditionKernelCommandLine=!systemd.volatile\n"
208
- "Before=local-fs.target\n"
209
- "\n"
210
- "[Mount]\n"
211
- "Where=%s\n"
212
- "What=%s\n"
213
- "Options=bind,slave,shared\n" ,
214
- var_path , var_dir ))
215
- return FALSE;
216
- if (!g_output_stream_flush (outstream , cancellable , error ))
217
- return FALSE;
218
- g_clear_object (& outstream );
219
- /* It should be readable */
220
- if (!glnx_fchmod (tmpf .fd , 0644 , error ))
221
- return FALSE;
222
- /* Error out if somehow it already exists, that'll help us debug conflicts */
223
- if (!glnx_link_tmpfile_at (& tmpf , GLNX_LINK_TMPFILE_NOREPLACE , normal_dir_dfd , "var.mount" ,
224
- error ))
231
+ if (!write_unit_file (normal_dir_dfd , "var.mount" , cancellable , error ,
232
+ "##\n# Automatically generated by ostree-system-generator\n##\n\n"
233
+ "[Unit]\n"
234
+ "Documentation=man:ostree(1)\n"
235
+ "ConditionKernelCommandLine=!systemd.volatile\n"
236
+ "Before=local-fs.target\n"
237
+ "\n"
238
+ "[Mount]\n"
239
+ "Where=%s\n"
240
+ "What=%s\n"
241
+ "Options=bind,slave,shared\n" ,
242
+ var_dst , var_src ))
225
243
return FALSE;
226
244
227
245
/* And ensure it's required; newer systemd will auto-inject fs dependencies
0 commit comments