docker / for-mac

Bug reports for Docker Desktop for Mac
https://www.docker.com/products/docker#/mac
2.43k stars 118 forks source link

gRPC-FUSE sets wrong errno when hard linking is not supported on underlying filesystem #5036

Open dan-hipschman opened 3 years ago

dan-hipschman commented 3 years ago

Hi,

I have a FAT32 filesystem that I'm bind mounting. Note that FAT32 does not support hard links.

I'm running a program in Docker that tries to make a hard link on this filesystem. It's expecting errno to be set to ENOTSUP (which it handles gracefully), but when using the gRPC-FUSE filesystem errno is set to EIO (which causes the program to exit). This makes sense because typically EIO is used for hardware problems, so the program thinks there's a problem with the hardware and gives up. It handles ENOTSUP gracefully because that's used for unsupported operations, so the program falls back to supported operations (such as making a copy).

As further evidence that the correct errno should be ENOTSUP, that is also what is set when trying to do a hard link both natively and with osxfs:

Trying to make a hardlink on Mac:

>>> os.link("test", "test-link")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 45] Operation not supported: 'test' -> 'test-link'

Trying to make a hardlink in container using osxfs:

>>> os.link("test", "test-link")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 95] Operation not supported: 'test' -> 'test-link'

(Apparently ENOTSUP is 45 on Mac and 95 on Linux.)

Trying to make a hardlink in container using gRPC-FUSE:

>>> os.link("test", "test-link")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 5] Input/output error: 'test' -> 'test-link'

Expected behavior

Hard linking on a bind mounted FAT filesystem results in errno being set to ENOTSUP.

Actual behavior

errno is set to EIO.

Information

I tested this on both stable and edge.

Stable version:

$ docker version
Client: Docker Engine - Community
 Cloud integration  0.1.18
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 16:58:31 2020
 OS/Arch:           darwin/amd64
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:07:04 2020
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          v1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Edge version:

Client: Docker Engine - Community
 Cloud integration: 0.1.22
 Version:           20.10.0-beta1
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        ac365d7
 Built:             Tue Oct 13 18:13:53 2020
 OS/Arch:           darwin/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.0-beta1
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       9c15e82
  Built:            Tue Oct 13 18:17:18 2020
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          v1.4.1
  GitCommit:        c623d1b36f09f8ef6536a057bd658b3aa8632828
 runc:
  Version:          1.0.0-rc92
  GitCommit:        ff819c7e9184c13b7c2607fe6c30ae19403a7aff
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Steps to reproduce the behavior

  1. Get a FAT32 formatted thumb drive, plug it in.
  2. docker run -it --mount type=bind,src=/Volumes/DRIVE_NAME,dst=/fat python bash
  3. (Inside container) python -c 'import os; os.link("/fat/some_file", "/fat/foo")'
stephen-turner commented 3 years ago

@djs55 PTAL

docker-robott commented 3 years ago

Issues go stale after 90 days of inactivity. Mark the issue as fresh with /remove-lifecycle stale comment. Stale issues will be closed after an additional 30 days of inactivity.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so.

Send feedback to Docker Community Slack channels #docker-for-mac or #docker-for-windows. /lifecycle stale

dan-hipschman commented 3 years ago

/remove-lifecycle stale

stephen-turner commented 3 years ago

/lifecycle frozen

matu3ba commented 1 year ago

Can you still reproduce this issue? Downstream at Zig, we can not, but maybe we missed something on testing.