diff options
| -rw-r--r-- | util/nvmutil/nvmutil.c | 107 |
1 files changed, 66 insertions, 41 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index bea8ea2c..fe8364f7 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -745,7 +745,10 @@ main(int argc, char *argv[]) #endif #endif +#if !defined(HAVE_ARC4RANDOM_BUF) || \ + (HAVE_ARC4RANDOM_BUF) < 1 srand((uint)(time(NULL) ^ getpid())); +#endif open_gbe_file(); lock_gbe_file(); @@ -944,11 +947,17 @@ xstrxcmp(const char *a, const char *b, size_t maxlen) err(EINVAL, "Empty string in xstrxcmp"); for (i = 0; i < maxlen; i++) { - if (a[i] != b[i]) - return (u8)a[i] - (u8)b[i]; + u8 ac = (u8)a[i]; + u8 bc = (u8)b[i]; - if (a[i] == '\0') - return 0; + if (ac == '\0' || bc == '\0') { + if (ac == bc) + return 0; + return ac - bc; + } + + if (ac != bc) + return ac - bc; } /* @@ -1814,9 +1823,10 @@ rw_gbe_file_exact(int fd, u8 *mem, size_t nrw, { size_t mem_addr; size_t buf_addr; + ssize_t r; - if (mem == NULL) - goto err_rw_gbe_file_exact; + if (io_args(fd, mem, nrw, off, rw_type) == -1) + return -1; mem_addr = (size_t)(void *)mem; buf_addr = (size_t)(void *)buf; @@ -1835,13 +1845,15 @@ rw_gbe_file_exact(int fd, u8 *mem, size_t nrw, if (nrw > (size_t)(gbe_file_size - off)) goto err_rw_gbe_file_exact; - if (nrw > GBE_PART_SIZE) + if (nrw > (size_t)GBE_PART_SIZE) goto err_rw_gbe_file_exact; - return rw_file_exact(fd, mem, nrw, off, rw_type, + r = rw_file_exact(fd, mem, nrw, off, rw_type, NO_LOOP_EAGAIN, LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR); + return rw_over_nrw(r, nrw); + err_rw_gbe_file_exact: errno = EIO; return -1; @@ -1896,7 +1908,7 @@ rw_file_exact(int fd, u8 *mem, size_t nrw, while (1) { /* Prevent theoretical overflow */ - if ((size_t)rv > (nrw - rc)) + if (rv >= 0 && (size_t)rv > (nrw - rc)) goto err_rw_file_exact; rc += rv; @@ -1905,6 +1917,8 @@ rw_file_exact(int fd, u8 *mem, size_t nrw, mem_cur = (void *)(mem + (size_t)rc); nrw_cur = (size_t)(nrw - (size_t)rc); + if (off < 0) + goto err_rw_file_exact; off_cur = (off_t)((size_t)off + (size_t)rc); rv = prw(fd, mem_cur, nrw_cur, off_cur, @@ -2061,42 +2075,49 @@ real_pread_pwrite: * if the offset changed to what * we previously got. If it did, * then another thread may have - * changed it. - * - * This is no substitute for real - * pread/pwrite, which would be - * fully atomic at kernel-level - * and do not use file offsets. + * changed it. Enabled if + * off_reset is OFF_RESET. * - * TODO: Add a toggle to make it - * recover instead, reset - * to known offset, and - * carry on operations. - * - * Failure is the better option - * here, since recovery would - * mask hidden bugs in code. - * We cannot guarantee thread - * safety, except in the event - * that violations cause exit; - * you would then debug it. + * We do this *once*, on the theory + * that nothing is touching it now. */ - if (off != verified) { - if (!off_reset) - goto err_prw; - - if (lseek_loop(fd, off, SEEK_SET, - loop_eagain, loop_eintr) == (off_t)-1) - return -1; - } + if (off_reset && off != verified) + lseek_loop(fd, off, SEEK_SET, + loop_eagain, loop_eintr); do { + /* + * Verify again before I/O + * (even with OFF_ERR) + * + * This implements the first check + * even with OFF_ERR, but without + * the recovery. On ERR_RESET, if + * the check fails again, then we + * know something else is touching + * the file, so it's best that we + * probably leave it alone and err. + * + * In other words, ERR_RESET only + * tolerates one change. Any more + * will cause an exit, including + * per EINTR/EAGAIN re-spin. + */ + verified = lseek_loop(fd, (off_t)0, SEEK_CUR, + loop_eagain, loop_eintr); + + if (off != verified) + goto err_prw; + if (rw_type == IO_PREAD) r = read(fd, mem, nrw); else if (rw_type == IO_PWRITE) r = write(fd, mem, nrw); - r = rw_over_nrw(r, nrw); + if (rw_over_nrw(r, nrw) == -1) { + errno = EIO; + break; + } } while (r == -1 && (errno == try_err(loop_eintr, EINTR) @@ -2104,14 +2125,15 @@ real_pread_pwrite: } saved_errno = errno; + off_last = lseek_loop(fd, off_orig, SEEK_SET, loop_eagain, loop_eintr); - if (off_last == (off_t)-1) { + + if (off_last != off_orig) { errno = saved_errno; - return -1; - } - if (off_last != off_orig) goto err_prw; + } + errno = saved_errno; return rw_over_nrw(r, nrw); @@ -2134,7 +2156,7 @@ io_args(int fd, void *mem, size_t nrw, if (fd < 0) goto err_io_args; - /* prevent underflow */ + /* negative offset */ if (off < 0) goto err_io_args; @@ -2150,6 +2172,9 @@ io_args(int fd, void *mem, size_t nrw, if (((size_t)off + nrw) < (size_t)off) goto err_io_args; + if (rw_type > IO_PWRITE) + goto err_io_args; + return 0; err_io_args: |
