[Bug 1081022] New: VFAT mount option "iocharset=utf8" breaks filename case sensitivity

http://bugzilla.opensuse.org/show_bug.cgi?id=1081022 Bug ID: 1081022 Summary: VFAT mount option "iocharset=utf8" breaks filename case sensitivity Classification: openSUSE Product: openSUSE Tumbleweed Version: Current Hardware: x86-64 OS: openSUSE Factory Status: NEW Severity: Normal Priority: P5 - None Component: Kernel Assignee: kernel-maintainers@forge.provo.novell.com Reporter: shundhammer@suse.com QA Contact: qa-bugs@suse.de Found By: --- Blocker: --- Created attachment 760171 --> http://bugzilla.opensuse.org/attachment.cgi?id=760171&action=edit Sample shell session (layout not broken by Bugzilla) I found this while investigating what mount options to use for bug #1080731: When a VFAT filesystem is mounted with option "iocharset=utf8", case sensitivity in file/directory names changes its behaviour in weird ways: "mkdir -p" can fail with EEXIST ("mkdir: cannot create directory ‘/mnt/efi’: File exists") which according to the mkdir man page should never happen. Using mount option "utf8" instead which should be the same according to the "mount" man page changes the behaviour to normal. For one thing, "mkdir -p" should never fail with EEXIST. But that's a matter of that tool which might do the check if a directory already exists the wrong way. That's not what this bug is all about. The weird behaviour is that this check behaves inconsistently depending on the mount options used: "iocharset=utf8" should not change the way at all that a purely ASCII file/directory name is treated. There are no non-ASCII characters involved at all. And there appears to be a difference if a VFAT "long name" exists or not: If there is only a "short name" (the old MS-DOS 8+3 filename), the bug appears. If there is also a "long name", everything works fine. In addition to that, the promise that mount option "utf8" is equivalent to "iocharset=utf8" is broken: Obviously, they behave differently. Sample shell session (also attached): [root @ morgul] ~ # uname -a Linux morgul 4.14.9-1-default #1 SMP PREEMPT Mon Dec 25 15:42:48 UTC 2017 (9423ca2) x86_64 x86_64 x86_64 GNU/Linux # # Using iocharset=utf8 # # FAIL # [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o iocharset=utf8 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=utf8,shortname=mixed,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o iocharset=utf8 /dev/sdb1 /mnt [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=utf8,shortname=mixed,errors=remount-ro 0 0 [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # umount /dev/sdb1 # # Using default mount options (i.e. implicitly iocharset=iso8859-1) # # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # # Using iocharset=iso8859-15 # # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o iocharset=iso8859-15 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=iso8859-15,shortname=mixed,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o iocharset=iso8859-15 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=iso8859-15,shortname=mixed,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # # Using utf8 (which should be equivalent to iocharset=utf8) # # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o utf8 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o utf8 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # Using utf8 and iocharset=utf8 combined # # FAIL # [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o utf8,iocharset=utf8 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # umount /dev/sdb1 # OK [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o utf8,iocharset=utf8 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=utf8,shortname=mixed,utf8,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 # FAIL [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o iocharset=utf8,utf8 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # grep sdb /proc/mounts /dev/sdb1 /mnt vfat rw,relatime,fmask=0002,dmask=0002,allow_utime=0020,codepage=437,iocharset=utf8,shortname=mixed,utf8,errors=remount-ro 0 0 [root @ morgul] ~ # umount /dev/sdb1 -- You are receiving this mail because: You are on the CC list for the bug.

http://bugzilla.opensuse.org/show_bug.cgi?id=1081022 Stefan Hundhammer <shundhammer@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rw@suse.de -- You are receiving this mail because: You are on the CC list for the bug.

http://bugzilla.opensuse.org/show_bug.cgi?id=1081022 http://bugzilla.opensuse.org/show_bug.cgi?id=1081022#c1 --- Comment #1 from Stefan Hundhammer <shundhammer@suse.com> --- I also tried with additional "shortname=" options in all combinations, but that doesn't change very much: [root @ morgul] ~ # mkfs.vfat /dev/sdb1 mkfs.fat 4.1 (2017-01-24) [root @ morgul] ~ # mount -t vfat -o iocharset=utf8,shortname=win95 /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists [root @ morgul] ~ # umount /dev/sdb1 [root @ morgul] ~ # mount -t vfat -o iocharset=utf8,shortname=lower /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot mkdir: cannot create directory ‘/mnt/EFI’: File exists [root @ morgul] ~ # mkdir -p /mnt/EFI/boot mkdir: cannot create directory ‘/mnt/EFI’: File exists [root @ morgul] ~ # mkdir -p /mnt/efi/boot [root @ morgul] ~ # umount /dev/sdb1 [root @ morgul] ~ # mount -t vfat -o iocharset=utf8,shortname=winnt /dev/sdb1 /mnt [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/EFI/boot [root @ morgul] ~ # mkdir -p /mnt/efi/boot mkdir: cannot create directory ‘/mnt/efi’: File exists With "shortname=lower" it just reverses when the error appears, all other cases remain the same. -- You are receiving this mail because: You are on the CC list for the bug.

http://bugzilla.opensuse.org/show_bug.cgi?id=1081022 http://bugzilla.opensuse.org/show_bug.cgi?id=1081022#c2 Takashi Iwai <tiwai@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |tiwai@suse.com --- Comment #2 from Takashi Iwai <tiwai@suse.com> --- The UTF-8 handling in vfat looks really confusing. The iocharset=utf8 seems still like a non-recommended option (and the kernel warns you, too). The documentation tells that it results in the case-sensitive problem, which is likely what you saw. Meanwhile, "utf8" mount option (or "utf8=true") while keeping isocharset as default would allow UTF-8 in a different way. Does this work better? -- You are receiving this mail because: You are on the CC list for the bug.

http://bugzilla.opensuse.org/show_bug.cgi?id=1081022 http://bugzilla.opensuse.org/show_bug.cgi?id=1081022#c3 --- Comment #3 from Stefan Hundhammer <shundhammer@suse.com> --- (In reply to Takashi Iwai from comment #2)
The UTF-8 handling in vfat looks really confusing. The iocharset=utf8 seems still like a non-recommended option (and the kernel warns you, too). The documentation tells that it results in the case-sensitive problem, which is likely what you saw.
Meanwhile, "utf8" mount option (or "utf8=true") while keeping isocharset as default would allow UTF-8 in a different way. Does this work better?
Yes, using "utf8" instead of "iocharset=utf8" does not show this problem - see shell session above. But IIRC the "mount" man page explicitly says that this is deprecated, and "iocharset=utf8" should be used instead. It is also unclear what's the difference between those two; I couldn't find any hint. I understood that they should be equivalent, but obviously, they are not; at least not in this context. -- You are receiving this mail because: You are on the CC list for the bug.

http://bugzilla.opensuse.org/show_bug.cgi?id=1081022 http://bugzilla.opensuse.org/show_bug.cgi?id=1081022#c4 --- Comment #4 from Takashi Iwai <tiwai@suse.com> --- (In reply to Stefan Hundhammer from comment #3)
(In reply to Takashi Iwai from comment #2)
The UTF-8 handling in vfat looks really confusing. The iocharset=utf8 seems still like a non-recommended option (and the kernel warns you, too). The documentation tells that it results in the case-sensitive problem, which is likely what you saw.
Meanwhile, "utf8" mount option (or "utf8=true") while keeping isocharset as default would allow UTF-8 in a different way. Does this work better?
Yes, using "utf8" instead of "iocharset=utf8" does not show this problem - see shell session above.
Ah I overlooked it, thanks.
But IIRC the "mount" man page explicitly says that this is deprecated, and "iocharset=utf8" should be used instead.
Hm, I couldn't find that description in man page on TW... OTOH, the kernel warning with iocharset=utf8 is still valid with the latest upstream kernel.
It is also unclear what's the difference between those two; I couldn't find any hint. I understood that they should be equivalent, but obviously, they are not; at least not in this context.
They should serve equivalently but the UTF-8 translation is applied differently. With iocharset=utf8, the translation is done via NLS layer, which is outside the vfat driver. Meanwhile, with utf8=true, the vfat driver itself performs the UTF-8 translation. -- You are receiving this mail because: You are on the CC list for the bug.

http://bugzilla.opensuse.org/show_bug.cgi?id=1081022 http://bugzilla.opensuse.org/show_bug.cgi?id=1081022#c7 Takashi Iwai <tiwai@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution|--- |FEATURE --- Comment #7 from Takashi Iwai <tiwai@suse.com> --- Let's close as FEATURE. Not ideal, but it's life. -- You are receiving this mail because: You are on the CC list for the bug.
participants (1)
-
bugzilla_noreply@novell.com