set_pool_mode() converts the no_space_timeout module parameter with
READ_ONCE(no_space_timeout_secs) * HZ. The usual arithmetic conversions
evaluate the product as unsigned int, so it can wrap before being stored
in the unsigned long delay. With HZ=1000, 4294968 seconds becomes 704
jiffies: a pool that runs out of data space switches to
error_if_no_space and fails queued writes with -ENOSPC after about 0.7
seconds.

Widen the value before the multiplication and cap it at
MAX_JIFFY_OFFSET / HZ, so large timeouts no longer wrap into short
delays. On 32-bit kernels, values beyond the supported jiffies range
saturate at the largest whole-second delay not exceeding
MAX_JIFFY_OFFSET. The timer wheel's existing handling of very long
delays is unchanged.

Fixes: 80c578930ce7 ("dm thin: add 'no_space_timeout' dm-thin-pool module 
param")
Cc: [email protected]
Signed-off-by: Yingjie Wang <[email protected]>
---

Notes:
    Tested on x86-64 (HZ=1000) in QEMU with a four-block thin pool whose
    fifth write runs out of data space. The base kernel switched to
    error_if_no_space and failed the write after 804 ms with 4294968
    seconds; with the patch the write was still queued after 4.6 s in three
    boots. 4294967 seconds queued and a 1-second control failed after
    about 1.1 s on both kernels. Also built for i386 with W=1.

 drivers/md/dm-thin.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 358ed77ffb2b..9287ee5c00a4 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2542,7 +2542,9 @@ static void set_pool_mode(struct pool *pool, enum 
pool_mode new_mode)
        struct pool_c *pt = pool->ti->private;
        bool needs_check = dm_pool_metadata_needs_check(pool->pmd);
        enum pool_mode old_mode = get_pool_mode(pool);
-       unsigned long no_space_timeout = READ_ONCE(no_space_timeout_secs) * HZ;
+       unsigned long no_space_timeout =
+               min_t(unsigned long, READ_ONCE(no_space_timeout_secs),
+                     MAX_JIFFY_OFFSET / HZ) * HZ;
 
        /*
         * Never allow the pool to transition to PM_WRITE mode if user

base-commit: 334714e4bdf8868c17a7650a7502ba1c90a8721f
-- 
2.43.0


Reply via email to