| Summary: | [util-linux/mount/umount.c] umount -d does not check for LD_FLAGS_AUTOCLEAR flag | ||
|---|---|---|---|
| Product: | Red Hat Enterprise Linux 7 | Reporter: | Boris Ranto <branto> |
| Component: | util-linux | Assignee: | Karel Zak <kzak> |
| Status: | CLOSED NOTABUG | QA Contact: | |
| Severity: | unspecified | Docs Contact: | |
| Priority: | unspecified | ||
| Version: | 7.0 | Keywords: | Regression |
| Target Milestone: | rc | ||
| Target Release: | --- | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | Bug Fix | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2012-04-02 16:06:27 UTC | Type: | --- |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
For RHEL7 we will use util-linux 2.21 where is pure libmount based umount(8)(rebase requested :bug #804780). Anyway, I have ported your patch to the current upstream code, because old mount(8) is still upstream default. (commit 72bec4d0dd5c94f15ed7c17d3452ba87ed737209) |
Description of problem: The umount command (with -d option) in rhel7 will attempt to release loop device even when it is set to be cleared automatically (LD_FLAGS_AUTOCLEAR). Version-Release number of selected component (if applicable): util-linux-2.20.1 How reproducible: Always Steps to Reproduce: 1. truncate -s 5G fs.img; mkfs.xfs fs.img 2. mount -o loop fs.img /media 3. umount -d /media Actual results: Umount tries to release the loop device that is set to be cleared automatically. Expected results: Umount does not try to release the loop device once it was already released. Additional info: This seems to be caused by a missing condition in mount/umount.c:303 (although the commentary references the missing condition): 299 /* 300 * Ignore the option "-d" for non-loop devices and loop devices with 301 * LO_FLAGS_AUTOCLEAR flag. 302 */ 303 if (delloop && is_loop_device(spec)) 304 myloop = 1; 305 Further looking at the code, the condition just moved to line 411, the problem is that the condition is called once the umount unmounted the file system (and even released the loop device in case of the autoclear mechanism). This means that the condition will be satisfied and the umount command will attempt to release a loop device that was already released. I've tested the umount behaviour with the following simple patch and it fixed the issue for me: --- mount/umount-old.c 2012-03-15 11:34:41.294141058 -0400 +++ mount/umount.c 2012-03-15 11:45:43.900117187 -0400 @@ -300,7 +300,7 @@ umount_one (const char *spec, const char * Ignore the option "-d" for non-loop devices and loop devices with * LO_FLAGS_AUTOCLEAR flag. */ - if (delloop && is_loop_device(spec)) + if (delloop && is_loop_device(spec) && !is_loop_autoclear(spec)) myloop = 1; if (restricted) { @@ -408,7 +408,7 @@ umount_one (const char *spec, const char loopdev = spec; } gotloop: - if (loopdev && !is_loop_autoclear(loopdev)) + if (loopdev) del_loop(loopdev); writemtab: I suspect that the reason for the move was to fix the cases when the loop autoclear mechanism fails (this occurred several times while using xfstests test no. 073). Then it would probably make more sense to move the condition completely. The problem is that if we move the condition completely it will succeed trivially for a released loop device (the device will be a loop device and it will not have the autoclear flag set) and the code will try to release already released device, again. In this case the best fix would probably be to check that the device is assigned and without the autoclear flag, i.e something like this (assuming the function is_loop_assigned is defined somewhere else and tests whether the given device is an assigned loop device): --- mount/umount-old.c 2012-03-15 11:34:41.294141058 -0400 +++ mount/umount.c 2012-03-15 12:42:02.171998383 -0400 @@ -271,7 +271,6 @@ umount_one (const char *spec, const char int extra_flags = 0; const char *loopdev, *target = node; char *targetbuf = NULL; - int myloop = 0; /* Special case for root. As of 0.99pl10 we can (almost) unmount root; the kernel will remount it readonly so that we can carry on running @@ -296,12 +295,6 @@ umount_one (const char *spec, const char /* Skip the actual umounting for --fake */ if (fake) goto writemtab; - /* - * Ignore the option "-d" for non-loop devices and loop devices with - * LO_FLAGS_AUTOCLEAR flag. - */ - if (delloop && is_loop_device(spec)) - myloop = 1; if (restricted) { if (umount_nofollow_support()) @@ -403,12 +396,16 @@ umount_one (const char *spec, const char node = mc->m.mnt_dir; } - /* Also free loop devices when -d flag is given */ - if (myloop) + /* Also attemp to free loop devices when -d flag is given */ + if (delloop) loopdev = spec; } gotloop: - if (loopdev && !is_loop_autoclear(loopdev)) + /* + * Ignore the option "-d" for non-loop devices and loop devices with + * LO_FLAGS_AUTOCLEAR flag. + */ + if (loopdev && is_loop_assigned(loopdev) && !is_loop_autoclear(loopdev)) del_loop(loopdev); writemtab: