geom_gate: Distinguish between classes of errors

The geom_gate API provides 2 distinct paths for exchanging error
details between the kernel and the userland client: Including an error
code in the g_gate_ctl_io structure passed in the ioctl(2) call or
having the ioctl(2) call return -1 with an error code in errno. The
latter reflects errors in the ioctl(2) call itself whilst the former
reflects errors within the geom_gate instance.

The G_GATE_CMD_START ioctl blocks waiting for an I/O request to be
directed to the geom_gate instance and the wait can fail
(necessitating an error return) if the geom_gate instance is destroyed
or if the msleep(9) fails. The code previously treated both error
cases indentically: Returning ECANCELED as a geom_gate instance error
(which the ggatec treats as a fatal error).  Whilst this is the correct
behaviour if the geom_gate instance is destroyed, a msleep(9) failure
is unrelated to the geom_gate instance itself and should be reported
as an ioctl(2) "failure".  The distinction is important because
msleep(9) can return ERESTART, which means the system call should be
retried (and this will occur automatically as part of the generic
syscall return processing).

This change alters the msleep(9) handling to directly return the error
code from msleep(9), which ensures ERESTART is correctly handled,
rather than being treated as a fatal error.

Reviewed by:    Johannes Totz <jo@bruelltuete.com>
MFC after:      1 week
Differential Revision:  https://reviews.freebsd.org/D33996
This commit is contained in:
Peter Jeremy 2022-01-29 21:15:51 +11:00
parent 217481a333
commit afcd121024
No known key found for this signature in database
GPG Key ID: 16A597A0E4A20B34

View File

@ -861,11 +861,10 @@ g_gate_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct threa
mtx_unlock(&sc->sc_queue_mtx);
goto start_end;
}
if (msleep(sc, &sc->sc_queue_mtx,
PPAUSE | PDROP | PCATCH, "ggwait", 0) != 0) {
ggio->gctl_error = ECANCELED;
error = msleep(sc, &sc->sc_queue_mtx,
PPAUSE | PDROP | PCATCH, "ggwait", 0);
if (error != 0)
goto start_end;
}
}
ggio->gctl_cmd = bp->bio_cmd;
if (bp->bio_cmd == BIO_WRITE &&