Skip to content

Commit 409496b

Browse files
committed
feat: Monitor netlink events to correctly report connected state of devices managed by the client
1 parent 264e7d6 commit 409496b

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/pojntfx/go-nbd
22

33
go 1.20
4+
5+
require github.com/pilebones/go-udev v0.9.0

go.sum

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
2+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
3+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
4+
github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q=
5+
github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI=

pkg/client/nbd.go

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"syscall"
1111

12+
"github.com/pilebones/go-udev/netlink"
1213
"github.com/pojntfx/go-nbd/pkg/ioctl"
1314
"github.com/pojntfx/go-nbd/pkg/protocol"
1415
"github.com/pojntfx/go-nbd/pkg/server"
@@ -79,6 +80,45 @@ func Connect(conn net.Conn, device *os.File, options *Options) error {
7980
return ErrUnsupportedNetwork
8081
}
8182

83+
fatal := make(chan error)
84+
if options.OnConnected != nil {
85+
udevConn := new(netlink.UEventConn)
86+
if err := udevConn.Connect(netlink.UdevEvent); err != nil {
87+
return err
88+
}
89+
defer udevConn.Close()
90+
91+
var (
92+
udevReadyCh = make(chan netlink.UEvent)
93+
udevErrCh = make(chan error)
94+
udevQuit = udevConn.Monitor(udevReadyCh, udevErrCh, &netlink.RuleDefinitions{
95+
Rules: []netlink.RuleDefinition{
96+
{
97+
Env: map[string]string{
98+
"DEVNAME": device.Name(),
99+
},
100+
},
101+
},
102+
})
103+
)
104+
defer close(udevQuit)
105+
106+
go func() {
107+
select {
108+
case <-udevReadyCh:
109+
close(udevQuit)
110+
111+
options.OnConnected()
112+
113+
return
114+
case err := <-udevErrCh:
115+
fatal <- err
116+
117+
return
118+
}
119+
}()
120+
}
121+
82122
if _, _, err := syscall.Syscall(
83123
syscall.SYS_IOCTL,
84124
device.Fd(),
@@ -204,20 +244,20 @@ n:
204244
return err
205245
}
206246

207-
if options.OnConnected != nil {
208-
options.OnConnected()
209-
}
247+
go func() {
248+
if _, _, err := syscall.Syscall(
249+
syscall.SYS_IOCTL,
250+
device.Fd(),
251+
ioctl.NEGOTIATION_IOCTL_DO_IT,
252+
0,
253+
); err != 0 {
254+
fatal <- err
210255

211-
if _, _, err := syscall.Syscall(
212-
syscall.SYS_IOCTL,
213-
device.Fd(),
214-
ioctl.NEGOTIATION_IOCTL_DO_IT,
215-
0,
216-
); err != 0 {
217-
return err
218-
}
256+
return
257+
}
258+
}()
219259

220-
return nil
260+
return <-fatal
221261
}
222262

223263
func Disconnect(device *os.File) error {

0 commit comments

Comments
 (0)