|
45 | 45 | #include "exit-status.h" |
46 | 46 | #include "def.h" |
47 | 47 |
|
| 48 | +#define RETRY_UMOUNT_MAX 32 |
| 49 | + |
48 | 50 | DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table); |
49 | 51 | DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter); |
50 | 52 |
|
@@ -867,20 +869,28 @@ static void mount_enter_unmounting(Mount *m) { |
867 | 869 |
|
868 | 870 | assert(m); |
869 | 871 |
|
| 872 | + /* Start counting our attempts */ |
| 873 | + if (!IN_SET(m->state, |
| 874 | + MOUNT_UNMOUNTING, |
| 875 | + MOUNT_UNMOUNTING_SIGTERM, |
| 876 | + MOUNT_UNMOUNTING_SIGKILL)) |
| 877 | + m->n_retry_umount = 0; |
| 878 | + |
870 | 879 | m->control_command_id = MOUNT_EXEC_UNMOUNT; |
871 | 880 | m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT; |
872 | 881 |
|
873 | | - if ((r = exec_command_set( |
874 | | - m->control_command, |
| 882 | + r = exec_command_set(m->control_command, |
875 | 883 | "/bin/umount", |
876 | 884 | "-n", |
877 | 885 | m->where, |
878 | | - NULL)) < 0) |
| 886 | + NULL); |
| 887 | + if (r < 0) |
879 | 888 | goto fail; |
880 | 889 |
|
881 | 890 | mount_unwatch_control_pid(m); |
882 | 891 |
|
883 | | - if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0) |
| 892 | + r = mount_spawn(m, m->control_command, &m->control_pid); |
| 893 | + if (r < 0) |
884 | 894 | goto fail; |
885 | 895 |
|
886 | 896 | mount_set_state(m, MOUNT_UNMOUNTING); |
@@ -1239,9 +1249,31 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { |
1239 | 1249 | case MOUNT_UNMOUNTING_SIGKILL: |
1240 | 1250 | case MOUNT_UNMOUNTING_SIGTERM: |
1241 | 1251 |
|
1242 | | - if (f == MOUNT_SUCCESS) |
1243 | | - mount_enter_dead(m, f); |
1244 | | - else if (m->from_proc_self_mountinfo) |
| 1252 | + if (f == MOUNT_SUCCESS) { |
| 1253 | + |
| 1254 | + if (m->from_proc_self_mountinfo) { |
| 1255 | + |
| 1256 | + /* Still a mount point? If so, let's |
| 1257 | + * try again. Most likely there were |
| 1258 | + * multiple mount points stacked on |
| 1259 | + * top of each other. Note that due to |
| 1260 | + * the io event priority logic we can |
| 1261 | + * be sure the new mountinfo is loaded |
| 1262 | + * before we process the SIGCHLD for |
| 1263 | + * the mount command. */ |
| 1264 | + |
| 1265 | + if (m->n_retry_umount < RETRY_UMOUNT_MAX) { |
| 1266 | + log_unit_debug(u->id, "%s: mount still present, trying again.", u->id); |
| 1267 | + m->n_retry_umount++; |
| 1268 | + mount_enter_unmounting(m); |
| 1269 | + } else { |
| 1270 | + log_unit_debug(u->id, "%s: mount still present after %u attempts to unmount, giving up.", u->id, m->n_retry_umount); |
| 1271 | + mount_enter_mounted(m, f); |
| 1272 | + } |
| 1273 | + } else |
| 1274 | + mount_enter_dead(m, f); |
| 1275 | + |
| 1276 | + } else if (m->from_proc_self_mountinfo) |
1245 | 1277 | mount_enter_mounted(m, f); |
1246 | 1278 | else |
1247 | 1279 | mount_enter_dead(m, f); |
|
0 commit comments