mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-11 05:52:36 +02:00
util/nvmutil: re-try reads if errno is EINTR
this is a bit of fault tolerance. a bit bloated too, but it should make the code more resilient. we limited the number of retries to 200 retries. EINTR is when the syscall (read/pread) is interrupted. we still error out on other conditions; we also still error out on EINTR if the number of re-tries surpasses 200. during this re-try loop, if *another* error occurs, we exit as normal. this is done for both files: the gbe file, and /dev/urandom. Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
+44
-7
@@ -27,6 +27,8 @@ static void check_mac_separator(int);
|
||||
static void set_mac_nib(int, int, uint8_t *);
|
||||
static uint8_t hextonum(char);
|
||||
static uint8_t rhex(void);
|
||||
static void read_urandom(uint8_t *, ssize_t);
|
||||
static int valid_read(const char *, ssize_t, ssize_t, int);
|
||||
static int write_mac_part(int);
|
||||
static void cmd_dump(void);
|
||||
static void print_mac_address(int);
|
||||
@@ -57,6 +59,8 @@ static void set_err(int);
|
||||
#define SIZE_16KB 0x4000
|
||||
#define SIZE_128KB 0x20000
|
||||
|
||||
#define MAX_RETRY_READ 200
|
||||
|
||||
#define items(x) (sizeof((x)) / sizeof((x)[0]))
|
||||
|
||||
static uint8_t buf[SIZE_8KB];
|
||||
@@ -241,10 +245,17 @@ read_gbe(void)
|
||||
static void
|
||||
read_gbe_part(int p, int invert)
|
||||
{
|
||||
if (pread(fd, buf + (SIZE_4KB * (p ^ invert)), SIZE_4KB, p * partsize)
|
||||
!= (ssize_t) SIZE_4KB)
|
||||
err(ECANCELED,
|
||||
"Can't read %d b from '%s' p%d", SIZE_4KB, fname, p);
|
||||
int retry;
|
||||
ssize_t rval;
|
||||
|
||||
for (retry = 0; retry < (int) MAX_RETRY_READ; retry++) {
|
||||
rval = pread(fd, buf + (SIZE_4KB * (p ^ invert)),
|
||||
SIZE_4KB, p * partsize);
|
||||
|
||||
if (valid_read(fname, rval, (ssize_t) SIZE_4KB, retry))
|
||||
break;
|
||||
}
|
||||
|
||||
swap(p ^ invert); /* handle big-endian host CPU */
|
||||
}
|
||||
|
||||
@@ -349,14 +360,40 @@ rhex(void)
|
||||
|
||||
if (!n) {
|
||||
n = sizeof(rnum) - 1;
|
||||
if (read(rfd, (uint8_t *) &rnum, sizeof(rnum))
|
||||
!= (ssize_t) (sizeof(rnum)))
|
||||
err(ECANCELED, "Could not read from /dev/urandom");
|
||||
read_urandom((uint8_t *) rnum, sizeof(rnum));
|
||||
}
|
||||
|
||||
return rnum[n--] & 0xf;
|
||||
}
|
||||
|
||||
static void
|
||||
read_urandom(uint8_t *rnum, ssize_t rsize)
|
||||
{
|
||||
int retry = 0;
|
||||
ssize_t rval;
|
||||
|
||||
for (retry = 0; retry < (int) MAX_RETRY_READ; retry++) {
|
||||
rval = read(rfd, (uint8_t *) rnum, rsize);
|
||||
if (valid_read("/dev/urandom", rval, rsize, retry))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
valid_read(const char *rpath, ssize_t rval, ssize_t rsize, int retry)
|
||||
{
|
||||
if (rval == (ssize_t) rsize)
|
||||
return 1;
|
||||
if (rval != -1)
|
||||
err(ECANCELED, "Short read, %lld: %s", rval, rpath);
|
||||
if (errno != EINTR)
|
||||
err(ECANCELED, "read '%s'", rpath);
|
||||
if (retry == MAX_RETRY_READ - 1)
|
||||
err(EINTR, "read: max retries exceeded: %s", rpath);
|
||||
|
||||
return (errno = 0);
|
||||
}
|
||||
|
||||
static int
|
||||
write_mac_part(int partnum)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user