From be2f4ce6cd3767c9211335f990e9048d9c7ba4d7 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Sun, 15 Mar 2026 00:49:57 +0000 Subject: util/nvmutil: extra race-condition check in prw even with OFF_RESET, we still want some error checking. if the check fails again immediately after, then it suggests that another program really is modifying the file, so we should stop. the first check is done on the theory that another program *was* working on it, but now isn't. once again, this isn't perfect. use read pread/pwrite if you need thread safety (and even then, you still need to actually check your code) Signed-off-by: Leah Rowe --- util/nvmutil/nvmutil.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'util/nvmutil/nvmutil.c') diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index 59d2facd..120586a9 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -2073,25 +2073,8 @@ 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. - * - * 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. + * changed it. Enabled if + * off_reset is OFF_RESET. */ if (off != verified) { if (!off_reset) @@ -2112,6 +2095,24 @@ real_pread_pwrite: return -1; } + verified = lseek_loop(fd, (off_t)0, SEEK_CUR, + loop_eagain, loop_eintr); + + /* + * 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. + */ + if (verified != off) + goto err_prw; + do { if (rw_type == IO_PREAD) r = read(fd, mem, nrw); -- cgit v1.2.1