Bug 467751

Summary: Unmounting certain SD cards can triggers an immediate remount when using "automount on attach" setting
Product: [Frameworks and Libraries] frameworks-solid Reporter: Alberto Garcia <berto>
Component: generalAssignee: Unassigned bugs mailing-list <unassigned-bugs>
Status: ASSIGNED ---    
Severity: normal CC: kdelibs-bugs, lukas, mr, nate, stefan.bruens
Priority: NOR    
Version: 5.103.0   
Target Milestone: ---   
Platform: Other   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: strace output

Description Alberto Garcia 2023-03-24 13:11:10 UTC
SUMMARY
Unmounting an SD card results in it being re-mounted again if "automount on attach is enabled".


STEPS TO REPRODUCE
1. Enable "Automount all known devices on attach" on the desktop settings.
2. Insert an SD card in the reader (can be reproduced on a VM). The volume should be mounted automatically.
3. Click on "Safely remove" to unmount the volume.


OBSERVED RESULT
The volume is re-mounted again immediately.


EXPECTED RESULT
The volume remains unmounted.


SOFTWARE/OS VERSIONS
KDE Plasma Version: 5.27.2
KDE Frameworks Version: 5.103.0
Qt Version: 5.15.8


ADDITIONAL INFORMATION
Hi,

I'm unsure about whether this is an actual bug in KDE, UDisks, or not a bug at all, so let me explain the situation.

SD card readers have the "MediaRemovable" flag set in UDisks: https://github.com/storaged-project/udisks/blob/2.9.x-branch/src/udiskslinuxdrive.c#L368

This, according to the UDisks documentation, seems to only mean that "the media can be removed from the drive".

However, Solid uses that information to decide whether to _eject_ the volume when the user tries to "Safely remove" the volume from the desktop. The "Ejectable" flag from UDisks was previously used for this purpose but it was discarded because it was considered broken (bug #402096, commit https://github.com/KDE/solid/commit/6d260195cf75604d835235d2a1b02166ee8b514a).

The UDisks Eject command runs /usr/bin/eject under the hood, but this won't actually eject the card from the reader, so it fails (I'm using a VM in this example but the same happens with real hardware):

   $ busctl call org.freedesktop.UDisks2 /org/freedesktop/UDisks2/drives/QEMU__0xdeadbeef org.freedesktop.UDisks2.Drive Eject 'a{sv}' 0
   Call failed: Error ejecting /dev/mmcblk0: Command-line `eject '/dev/mmcblk0'' exited with non-zero exit status 1: eject: unable to eject

This results in the following udev events:

   UDEV  [9144.057110] remove   /devices/pci0000:00/0000:00:04.0/mmc_host/mmc0/mmc0:4567/block/mmcblk0/mmcblk0p1 (block)
   UDEV  [9144.105960] change   /devices/pci0000:00/0000:00:04.0/mmc_host/mmc0/mmc0:4567/block/mmcblk0 (block)
   UDEV  [9144.193215] add      /devices/pci0000:00/0000:00:04.0/mmc_host/mmc0/mmc0:4567/block/mmcblk0/mmcblk0p1 (block)

Because of these remove+add events, if "Automount all known devices on attach" is set under the removable devices settings and you try to safely remove an SD card then the volume is immediately re-mounted again.

I also noticed that this does not happen in GNOME and this is due to a workaround there: if a volume appears much later than the drive (as in this case) then it is not mounted automatically: https://gitlab.gnome.org/GNOME/gvfs/-/commit/b4800b987b4a8423a52306c9aef35b3777464cc5

So while doing something like this would be a possibility, is it maybe possible to find a way to know whether the media in a certain drive is actually ejectable, and not simply removable? Otherwise it seems that Solid should not try to use eject based only on the "MediaRemovable" flag.

Opinions?
Comment 1 Alberto Garcia 2023-03-24 13:14:57 UTC
*** Bug 446395 has been marked as a duplicate of this bug. ***
Comment 2 Nate Graham 2023-03-28 18:20:09 UTC
Can't reproduce with my card and card reader, FWIW. So I think it depends on the hardware's adherence to the spec, which underscores the flakiness here.

Perhaps Solid can grow the ability to check for  whether an unmounted volume immediately gets an "add" event from udisks, and ignore it if it's under a certain timeout. Say, 100ms.
Comment 3 Alberto Garcia 2023-03-29 12:20:50 UTC
In case you want to give it a try with QEMU, here's a very simple test case:

1) Boot a VM with a virtual SD card reader, like this: -device sdhci-pci -device sd-card,drive=mmc0 -drive if=none,file=card.qcow2,id=mmc0
2) Add a partition to the SD card, no need to format it (you can use GPT or DOS/MBR, it doesn't matter).
3) Run `udevadm monitor` and in a different terminal run `eject /dev/mmcblk0`

This is enough to see the udev events I mentioned earlier.

The check that you describe seems fine (assuming that timeout is not too small). Thanks!
Comment 4 Bug Janitor Service 2023-03-30 12:16:21 UTC
A possibly relevant merge request was started @ https://invent.kde.org/frameworks/solid/-/merge_requests/128
Comment 5 Bug Janitor Service 2023-03-31 11:33:39 UTC
A possibly relevant merge request was started @ https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/1454
Comment 6 Stefan Brüns 2023-03-31 13:32:36 UTC
"eject"  in this context forces the card reader/drive to flush any pending operations from its caches.

The timestamp based heuristic does not work in all cases, as a card reader will have a constant "TimeDetected" timestamp, and plugging a card into it will result in a significantly later  "TimeMediaDetected".


@ Alberto:

Can you please provide the output of "udisctl monitor", when you run "/usr/bin/eject /dev/mmcblk0; echo $? "?.
Comment 7 Stefan Brüns 2023-03-31 13:40:53 UTC
(You likely have to run "eject" as root, e.g. via sudo. In case eject returns with a non-zero exit code, stracing it may reveal further information - "sudo strace -s 200 eject /dev/mmcblk0".)
Comment 8 Alberto Garcia 2023-03-31 13:51:25 UTC
Created attachment 157742 [details]
strace output

The strace output is attached. Here's the output of the eject and monitor commands:

# /usr/bin/eject /dev/mmcblk0; echo $? 
eject: unable to eject
1


# udisksctl monitor
Monitoring the udisks daemon. Press Ctrl+C to exit.
15:43:49.633: The udisks-daemon is running (name-owner :1.29).
15:43:50.504: Removed /org/freedesktop/UDisks2/block_devices/mmcblk0p1
15:43:50.538: /org/freedesktop/UDisks2/block_devices/mmcblk0: org.freedesktop.UDisks2.PartitionTable: Properties Changed
  Partitions:           
15:43:50.629: Added /org/freedesktop/UDisks2/block_devices/mmcblk0p1
  org.freedesktop.UDisks2.Block:
    Configuration:              []
    CryptoBackingDevice:        '/'
    Device:                     /dev/mmcblk0p1
    DeviceNumber:               45825
    Drive:                      '/org/freedesktop/UDisks2/drives/SL16G_0x8c9ed258'
    HintAuto:                   true
    HintIconName:               
    HintIgnore:                 false
    HintName:                   
    HintPartitionable:          true
    HintSymbolicIconName:       
    HintSystem:                 false
    Id:                         by-uuid-9019398f-1e38-4f69-bca4-6feb56d98ed7
    IdLabel:                    SD_CARD
    IdType:                     ext4
    IdUUID:                     9019398f-1e38-4f69-bca4-6feb56d98ed7
    IdUsage:                    filesystem
    IdVersion:                  1.0
    MDRaid:                     '/'
    MDRaidMember:               '/'
    PreferredDevice:            /dev/mmcblk0p1
    ReadOnly:                   false
    Size:                       15929966592
    Symlinks:                   /dev/disk/by-id/mmc-SL16G_0x8c9ed258-part1
                                /dev/disk/by-label/SD_CARD
                                /dev/disk/by-partlabel/primary
                                /dev/disk/by-partuuid/679ecb89-c2df-4e55-ac6a-e8be61e2709d
                                /dev/disk/by-uuid/9019398f-1e38-4f69-bca4-6feb56d98ed7
    UserspaceMountOptions:      
  org.freedesktop.UDisks2.Filesystem:
    MountPoints:        
    Size:               15929966592
  org.freedesktop.UDisks2.Partition:
    Flags:              0
    IsContained:        false
    IsContainer:        false
    Name:               primary
    Number:             1
    Offset:             1048576
    Size:               15929966592
    Table:              '/org/freedesktop/UDisks2/block_devices/mmcblk0'
    Type:               0fc63daf-8483-4772-8e79-3d69d8477de4
    UUID:               679ecb89-c2df-4e55-ac6a-e8be61e2709d
15:43:50.629: /org/freedesktop/UDisks2/block_devices/mmcblk0: org.freedesktop.UDisks2.PartitionTable: Properties Changed
  Partitions:           /org/freedesktop/UDisks2/block_devices/mmcblk0p1
Comment 9 Stefan Brüns 2023-03-31 15:17:40 UTC
According to the strace output, the drive supports none of the four attempted methods of eject, i.e. the ioctl's 'CDROM_LOCKDOOR', 'SG_IO(...)', 'FDEJECT' and 'MTIOCTOP'.

I can confirm the behavior by issuing e.g. 'eject -f ...', as FDEJECT is not supported by my card reader (it supports the SCSI ioctl) I also get the UDEV REMOVED/CHANGED/ADDED sequence.
Comment 10 Alberto Garcia 2023-03-31 16:02:53 UTC
(In reply to Stefan Brüns from comment #9)
> According to the strace output, the drive supports none of the four
> attempted methods of eject, i.e. the ioctl's 'CDROM_LOCKDOOR', 'SG_IO(...)',
> 'FDEJECT' and 'MTIOCTOP'.

FWIW the same happens with QEMU's virtual SD card reader (the strace output I attached earlier is from actual hardware).
Comment 11 Alberto Garcia 2023-04-12 16:03:27 UTC
There's one more thing to take into account with the "5 seconds since plugged" heuristic: the case when the volume was present at coldplug (i.e. it was already there when the session started).

Related links for the GNOME implementation:

https://gitlab.gnome.org/GNOME/gvfs/-/commit/e30a67f3215d829e95ee7e358c67af7d67635fe8

https://bugzilla.redhat.com/show_bug.cgi?id=813069
Comment 12 David Edmundson 2023-06-21 10:48:37 UTC
Git commit 41eaa14d3375e303e68e0d2f39090f5ed4f48c82 by David Edmundson.
Committed on 21/06/2023 at 10:45.
Pushed by davidedmundson into branch 'master'.

Expose StorageDevice timeDetected/timeMediaDetected

For automounting purposes it's useful to know when a drive appeared in
relation to when StorageVolumes appear.

Rather than adding tracking in front-end code we can make use of udisk's
existing information.

M  +10   -0    src/solid/devices/backends/fakehw/fakestorage.cpp
M  +3    -0    src/solid/devices/backends/fakehw/fakestorage.h
M  +20   -0    src/solid/devices/backends/udisks2/udisksstoragedrive.cpp
M  +3    -0    src/solid/devices/backends/udisks2/udisksstoragedrive.h
M  +12   -0    src/solid/devices/frontend/storagedrive.cpp
M  +21   -0    src/solid/devices/frontend/storagedrive.h
M  +10   -0    src/solid/devices/ifaces/storagedrive.cpp
M  +12   -0    src/solid/devices/ifaces/storagedrive.h

https://invent.kde.org/frameworks/solid/-/commit/41eaa14d3375e303e68e0d2f39090f5ed4f48c82