From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (mail.openvz.org [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id 8A9158017D for ; Tue, 3 Nov 2026 12:44:00 +0000 (UTC) Received: from mail.openvz.org (localhost [127.0.0.1]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A3Cgj9V005216; Tue, 3 Nov 2026 15:42:46 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A3Cgj9V005216 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="kAxoSHSL" Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A3CgOLR005153 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Tue, 3 Nov 2026 15:42:24 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A3CgOLR005153 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-48df5b058ddso2721458f8f.0 for ; Tue, 03 Nov 2026 04:42:24 -0800 (PST) X-Gm-Message-State: APuU4Z9u5YXPw9KAwyZyVanCkE0G9007NOS+cURSugBD1J18sxj0TLSi 4ipqF1EsfiX3Tem6p6AFOUf7eWoalbV3xXuUAOKomTXAHaSqzhl6SnjXxW2eErTk0qXs3GAHwvc EfWXFAMvnMvJJPlnztbiqqIKUu0Zq2TP6LkXLsRsx6mwwXR/UO60kAQ== X-Gm-Gg: AYBFou0MWPrngDEv0aRHOI8snpWs8ZSI1T8cUUpa/ZPwsOFbaEKQB/3xY5g7b96Ugi0 ouDtYCJWr6P//98I/F8IAQF/6DOUANsCFHVtCnTqR3tlMSY3TuXls7HB9LwaHvG86stQUZ3LggU DHHAGtuMEsmu2akBwgWDXkEKTeloJCmZDgbvvXF/ZU3iRKRXiiphS9hPxHwhqYF37CxL0BujRb2 hjY7UokOG1uUINkHCfRlo2pkU9mBUwPA247Ps1pxnT1tdvg16L9q7FYIqPsIYgcLCH1xYW/AfLP T4GI14lc1ejvkbnouIjYA9ewmrBYONmq9x95PmHB4t65bxo04CMpYrJJQlCgggDDWngwG6Giqvt NkL1BaRXaURhh9cBiHKcOapR1M19Zrg== X-Received: by 2002:a5d:4e05:0:b0:48e:21f7:79ff with SMTP id ffacd0b85a97d-48e6e50575emr21934578f8f.33.1793709744091; Tue, 03 Nov 2026 04:42:24 -0800 (PST) X-Received: by 2002:a5d:4e05:0:b0:48e:21f7:79ff with SMTP id ffacd0b85a97d-48e6e50575emr21934530f8f.33.1793709743458; Tue, 03 Nov 2026 04:42:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1793709743; cv=none; d=google.com; s=arc-20260327; b=d2W13HjCeKNZYzRmO+QZA1e0SZzPcIFpUCJiByC9ZTYkRjWKGrF740BrVjNXzdJqx8 KZ5BGCjWwIJB936sahyh9ZkhGeK4vcXNgI4Gtn5Tfg0pWlqXiRXwFqlEfJVz8Vh5FQN9 6zKPBAZa7OUErFA0JJ0if2Wgt1AGkJP9nB4wG6zVbmd6LltATJfkM2YJZ5tpE+OgFcsO WVtbX3iz5FKa50UtzUsUftVn3F7l3MgXLvtc9ZzpElQWuK+OT8Su1VF+8AhIEhPiHlAS 8Meci/kP1NogLNDN6mLNOhIU0wEEYPkemtxDgNjoD8SJp8OHJusJWV+YN4DB8MPZg+4k +Qpw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=EvwB+zKpm3/mop5v9Qpa58Q8/BTzVa3YRUKcb9s84z0=; fh=ElTTnnNtphHTCCOZ+58STyaWac7y7ytLDJZIF4HMMJ4=; b=RK+myVZr+BRIBWbpnak2L61TNt/o8mGyhNHAV94LqJzPrZiKKy/8lcP7ODNvMAYKfQ zDkWgwKBb56q4lyf17Ldor5el+nrVlLQnhlfw5nicQkznBsGvyxyfmBHHz7r4y0P8QrG fIZHIw26KAePkCLMP9q9VUE1usX7F1Ei1UWeAHNLrWIb+F8xj5TWQck0G3U766xb+ZDG Bx7DZnZ7USLKeO5345f6dYtocCw/JLJ7bJhGP+IXd+/8bdmr5ec0aie5rIMk7oDJTvdm pFH2pkUjCBNMcqnB5ObZ28fuSVFN+ElVMKVwCoi5kVIWcRsmopdPUb7ntkLSxAl8jJFQ TJsw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=kAxoSHSL; spf=pass (google.com: domain of andrey.zhadchenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=andrey.zhadchenko@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com Received: from relay.virtuozzo.com (relay.virtuozzo.com. [130.117.225.111]) by mx.google.com with ESMTPS id ffacd0b85a97d-48e71bd8d94si29199475f8f.483.2026.11.03.04.42.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Nov 2026 04:42:23 -0800 (PST) Received-SPF: pass (google.com: domain of andrey.zhadchenko@virtuozzo.com designates 130.117.225.111 as permitted sender) client-ip=130.117.225.111; Authentication-Results: mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=kAxoSHSL; spf=pass (google.com: domain of andrey.zhadchenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=andrey.zhadchenko@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-ID:Date:Subject:From: Content-Type; bh=EvwB+zKpm3/mop5v9Qpa58Q8/BTzVa3YRUKcb9s84z0=; b=kAxoSHSLPEkX C5lRD3phuHYeletgZAW3djXRVYHqPZL7PZ7VwJhpHiy70Gv0F3Urc7zNRawV8TVm9uEOe1U/sDt1E QIyYdCXsrbLRXz8X3XzEo/PWN1f8bXHA2Kmod6wzyWeSI0vHJ/fQ2LaUZJfcR2KnDHG1URGU3CjSg dxBZmn+Q3uQgzkaxZIunqqYHU792G8YumhVC2JXAe5KFYXbsfIwXJ0s56TCPzgeVG0MGFtU3ClTNx DrXbwNx58LsZarTGQjWyLBlCyYGAEZjzxt2qGa9TpxBzkft8ahTANo152Bu9UpgaKjmosZ9eK4aDB 6T1p108dr/5CAgxBtwjpDw==; Received: from [130.117.225.5] (helo=vz9-demens-1.aci.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1xODmN-00FAc4-39; Tue, 03 Nov 2026 13:42:13 +0100 From: Andrey Zhadchenko To: khorenko@virtuozzo.com, alexander.ivanov@virtuozzo.com Date: Tue, 3 Nov 2026 15:38:00 +0300 Message-ID: <20261103123802.846676-6-andrey.zhadchenko@virtuozzo.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20261103123802.846676-1-andrey.zhadchenko@virtuozzo.com> References: <20261103123802.846676-1-andrey.zhadchenko@virtuozzo.com> MIME-Version: 1.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 v5 5/7] drivers/md/push_backup: arm deadline timer under pb->lock X-BeenThere: devel@openvz.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: OpenVZ development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: devel-bounces@openvz.org Errors-To: devel-bounces@openvz.org Both pb_timer_func() and postpone_if_required_for_backup() decide whether to arm the timer under pb->lock but call mod_timer() after dropping it, so the decisions can be applied out of order: CPU1 pb_timer_func() CPU2 postpone_if_required_for_backup() lock; deadline = S64_MAX unlock lock; nr_delayed = 1 deadline_jiffies = now + timeout unlock mod_timer(timeout) mod_timer(from S64_MAX) The late mod_timer() of the callback overwrites the fresh deadline, and the write is delayed with the timer parked in a very distant future. Only a later push_backup_write() that leaves requests delayed re-arms it; if the backup tool stops acknowledging ranges, the backup never expires. Make the decision and the arming atomic: call mod_timer() under pb->lock at both sites, and do not re-arm when nothing is delayed. mod_timer() and queue_work() are fine under a spinlock, and the timer base lock is dropped while the callback runs, so there is no lock inversion. The callback checks pb->nr_delayed rather than pb->alive on purpose. pb_message() clears pb->alive for "push_backup_stop" before taking pb->ctl_rwsem, and if the tool gets a fatal signal while waiting for the rwsem, push_backup_stop() never runs. The deadline must still expire then, so that do_pb_work() releases the delayed writes. cleanup_backup() zeroes nr_delayed under the same lock hold that clears alive, and postpone only delays while alive, so after stop the callback neither re-arms nor queues work. While alive, nr_delayed == 0 is the same as deadline_jiffies == S64_MAX. The callback racing with push_backup_stop() was never handled either. synchronize_rcu() waits for a callback that is already running when it starts, since the timer softirq is an RCU reader, but not for a firing that starts after the grace period. timer_delete_sync_try() is try_to_del_timer_sync(), it returns -1 without waiting when the callback is running, and we only WARN on that. Such a callback could re-arm the timer or queue do_pb_work() after flush_workqueue(), expiring a later session. The same happens in pb_destroy(), which WARNs and goes on to destroy_workqueue() and kfree(pb) under the running callback: a use-after-free. Use timer_delete_sync() in push_backup_stop() and timer_shutdown_sync() in pb_destroy() to wait for it; the work it may have queued is flushed by flush_workqueue()/destroy_workqueue() which follow. As a bonus the rcu_read_lock()/synchronize_rcu() dance between postpone_if_required_for_backup() and push_backup_stop() is no longer needed: the timer is only armed under pb->lock, by postpone while pb->alive is set and by the callback while requests are delayed, both of which cleanup_backup() ends under pb->lock, and the callback itself is waited for. Drop it. push_backup_write() still re-arms the timer outside pb->lock, but it is serialized with push_backup_stop() by pb->ctl_rwsem; the next patch removes that call. Fixes: 62e07487348e ("dm: Add push backup driver") https://virtuozzo.atlassian.net/browse/VSTOR-152912 Signed-off-by: Andrey Zhadchenko Reviewed-by: Alexander Ivanov --- v2: new patch v3: bail out of pb_timer_func() when !pb->alive; wait for a running callback with timer_delete_sync() in push_backup_stop() and timer_shutdown_sync() in pb_destroy() instead of WARNing on timer_delete_sync_try() < 0; fixed the commit message claim about it v4: no changes v5: moved before "do not re-arm deadline timer"; pb_timer_func() checks pb->nr_delayed instead of pb->alive, so an interrupted "push_backup_stop" still expires the deadline; commit message describes the race instead of the harmless parked timer, the synchronize_rcu() window precisely and the pb_destroy() use-after-free; added Fixes: tag drivers/md/dm-push-backup.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/md/dm-push-backup.c b/drivers/md/dm-push-backup.c index b6d1629245235..f0de26add11c2 100644 --- a/drivers/md/dm-push-backup.c +++ b/drivers/md/dm-push-backup.c @@ -241,23 +241,24 @@ static void pb_timer_func(struct timer_list *timer) spin_lock_irqsave(&pb->lock, flags); deadline = pb->deadline_jiffies; - spin_unlock_irqrestore(&pb->lock, flags); - + if (!pb->nr_delayed) + goto unlock; if (unlikely(time_before64(now, deadline))) mod_timer(timer, jiffies + (deadline - now) + 1); else queue_work(pb->wq, &pb->worker); +unlock: + spin_unlock_irqrestore(&pb->lock, flags); } static int postpone_if_required_for_backup(struct push_backup *pb, struct request *rq) { - bool queue_timer = false; struct pb_bio *pbio; unsigned long flags; + bool wake = false; int ret = 0; - rcu_read_lock(); /* See push_backup_stop() */ spin_lock_irqsave(&pb->lock, flags); if (!pb->alive) goto unlock; @@ -272,16 +273,13 @@ static int postpone_if_required_for_backup(struct push_backup *pb, pb->nr_delayed += 1; if (pb->nr_delayed == 1) { pb->deadline_jiffies = get_jiffies_64() + pb->timeout_in_jiffies; - queue_timer = true; + mod_timer(&pb->deadline_timer, jiffies + pb->timeout_in_jiffies + 1); + wake = true; } unlock: spin_unlock_irqrestore(&pb->lock, flags); - if (queue_timer) - mod_timer(&pb->deadline_timer, jiffies + pb->timeout_in_jiffies + 1); - rcu_read_unlock(); - - if (queue_timer) + if (wake) wake_up_interruptible(&pb->waitq); return ret; @@ -400,9 +398,7 @@ static int push_backup_stop(struct push_backup *pb, return -EBADF; cleanup_backup(pb); - /* Wait postpone_if_required_for_backup() starts timer */ - synchronize_rcu(); - WARN_ON_ONCE(timer_delete_sync_try(&pb->deadline_timer) < 0); + timer_delete_sync(&pb->deadline_timer); flush_workqueue(pb->wq); spin_lock_irq(&pb->lock); @@ -632,7 +628,7 @@ static void pb_destroy(struct push_backup *pb) { WARN_ON_ONCE(pb->nr_delayed); - WARN_ON_ONCE(timer_delete_sync_try(&pb->deadline_timer) < 0); + timer_shutdown_sync(&pb->deadline_timer); if (pb->wq) destroy_workqueue(pb->wq); kvfree(pb->map); /* Is's not zero if stop was not called */ -- 2.43.5 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel