attachToLoopDevice associates free loop device with backing file. There might have race condition. It needs to retry when it runs into EBUSY. REF: https://man7.org/linux/man-pages/man4/loop.4.html
(backingFile string)
| 24 | // |
| 25 | // REF: https://man7.org/linux/man-pages/man4/loop.4.html |
| 26 | func attachToLoopDevice(backingFile string) (string, error) { |
| 27 | backingFd, err := os.OpenFile(backingFile, os.O_RDWR, 0) |
| 28 | if err != nil { |
| 29 | return "", fmt.Errorf("failed to open loop device's backing file %s: %w", |
| 30 | backingFile, err) |
| 31 | } |
| 32 | defer backingFd.Close() |
| 33 | |
| 34 | for i := 0; i < maxRetryToAttach; i++ { |
| 35 | loop, err := getFreeLoopDevice() |
| 36 | if err != nil { |
| 37 | return "", fmt.Errorf("failed to get free loop device: %w", err) |
| 38 | } |
| 39 | |
| 40 | err = func() error { |
| 41 | loopFd, err := os.OpenFile(loop, os.O_RDWR, 0) |
| 42 | if err != nil { |
| 43 | return err |
| 44 | } |
| 45 | defer loopFd.Close() |
| 46 | |
| 47 | return unix.IoctlSetInt(int(loopFd.Fd()), |
| 48 | unix.LOOP_SET_FD, int(backingFd.Fd())) |
| 49 | }() |
| 50 | if err != nil { |
| 51 | if errors.Is(err, unix.EBUSY) { |
| 52 | time.Sleep(500 * time.Millisecond) |
| 53 | continue |
| 54 | } |
| 55 | return "", err |
| 56 | } |
| 57 | return loop, nil |
| 58 | } |
| 59 | return "", fmt.Errorf("failed to associate free loop device with backing file %s after retry %v", |
| 60 | backingFile, maxRetryToAttach) |
| 61 | } |
| 62 | |
| 63 | // detachLoopDevice disassociates the loop device from any backing file. |
| 64 | // |
no test coverage detected