The `ioctl` interface for the `LOOP_CTL_GET_FREE` request on
`/dev/loop-control` is a little different from what `unix.IoctlGetInt`
expects: the first index is the returned status in `r1`, not an `int`
pointer as the first parameter.
Unfortunately we have to go a little lower level to get the appropriate
loop device index out, using `unix.Syscall` directly to read from
`r1`. Internally, the index is returned as a signed integer to match the
internal `ioctl` expectations of interpreting a negative signed integer
as an error at the userspace ABI boundary, so the direct interface of
`ioctlLoopCtlGetFree` can remain as-is.
[@kolyshkin: it still worked before this fix because of
/dev scan fallback in ioctlLoopCtlGetFree()]
Signed-off-by: Daniel Sweet <danieljsweet@icloud.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit db2bc43017b45dbb4e2aa51e093eab3fbb86ead1)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
| ... | ... |
@@ -9,11 +9,15 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
func ioctlLoopCtlGetFree(fd uintptr) (int, error) {
|
| 12 |
- index, err := unix.IoctlGetInt(int(fd), LoopCtlGetFree) |
|
| 13 |
- if err != nil {
|
|
| 12 |
+ // The ioctl interface for /dev/loop-control (since Linux 3.1) is a bit |
|
| 13 |
+ // off compared to what you'd expect: instead of writing an integer to a |
|
| 14 |
+ // parameter pointer like unix.IoctlGetInt() expects, it returns the first |
|
| 15 |
+ // available loop device index directly. |
|
| 16 |
+ ioctlReturn, _, err := unix.Syscall(unix.SYS_IOCTL, fd, LoopCtlGetFree, 0) |
|
| 17 |
+ if err != 0 {
|
|
| 14 | 18 |
return 0, err |
| 15 | 19 |
} |
| 16 |
- return index, nil |
|
| 20 |
+ return int(ioctlReturn), nil |
|
| 17 | 21 |
} |
| 18 | 22 |
|
| 19 | 23 |
func ioctlLoopSetFd(loopFd, sparseFd uintptr) error {
|