From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 09DFCE7718B for ; Wed, 1 Jan 2025 13:22:13 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 0C8516B007B; Wed, 1 Jan 2025 08:22:13 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 077196B0083; Wed, 1 Jan 2025 08:22:13 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id EA7FA6B0085; Wed, 1 Jan 2025 08:22:12 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id CEB9C6B007B for ; Wed, 1 Jan 2025 08:22:12 -0500 (EST) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 55C08120D80 for ; Wed, 1 Jan 2025 13:22:12 +0000 (UTC) X-FDA: 82958944866.21.27E432E Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.2]) by imf09.hostedemail.com (Postfix) with ESMTP id DD81714000B for ; Wed, 1 Jan 2025 13:21:35 +0000 (UTC) Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=163.com header.s=s110527 header.b=LwbN3yXx; dmarc=pass (policy=none) header.from=163.com; spf=pass (imf09.hostedemail.com: domain of jerrydeng079@163.com designates 220.197.31.2 as permitted sender) smtp.mailfrom=jerrydeng079@163.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1735737684; a=rsa-sha256; cv=none; b=6GmwMUqpSU06bAhedY5+MtaX7YSFv6q2c2QII8uZqj9d7Tyeq3jcFoS/6Nyzm0zRULnfn4 Dt9OvPs50Q1RfNxBPGUPrJBdeL8prvospRB2IGdRiNqetjdl6K9doizTx0syJH40a7cESU 9IYjRZW+SGXEDUAHlKF9p8B8gacCymE= ARC-Authentication-Results: i=1; imf09.hostedemail.com; dkim=pass header.d=163.com header.s=s110527 header.b=LwbN3yXx; dmarc=pass (policy=none) header.from=163.com; spf=pass (imf09.hostedemail.com: domain of jerrydeng079@163.com designates 220.197.31.2 as permitted sender) smtp.mailfrom=jerrydeng079@163.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1735737684; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:references:dkim-signature; bh=t+IVN00vfyaGCXL1HKpUe/N6OjICYFcwPF5f8SD3zEI=; b=oo8vbL3/GvWPVJ89vCEDMaILL8pE1tR4/9tflYqBg1JAcEJRG9rTCgCgui/zDHG3NB1swe FsDVtMEvX97TmPqFT9SebpWM7Vj25CkBCmkpiJqt6tUgYYoS/wUHwDmQ7f5S41xpuH26Ly T4JEFW14xOtboHi06l+OawQGL/Bxh8E= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=t+IVN 00vfyaGCXL1HKpUe/N6OjICYFcwPF5f8SD3zEI=; b=LwbN3yXxmKcHOfP6hXYm0 hcTzlNpGw20yK25tmBspkeJAa7jnKpV54YJdgn6JCdx11mEZP6KDOk3e1qRYcKye NDiAEFAVGWQDkJT/8urcDr2BLUWpEbUHsrB9YpQ90Kd5vNky5sdrtWT5v0SjOcD5 AVum1it/6xVaTky3+HpNXg= Received: from Jerry-PC.. (unknown []) by gzga-smtp-mtada-g0-2 (Coremail) with SMTP id _____wBnMgt4QXVnQkWDDA--.50735S2; Wed, 01 Jan 2025 21:22:04 +0800 (CST) From: Jerry To: akpm@linux-foundation.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Jerry Subject: [PATCH] mm: fix dead-loop bug Date: Wed, 1 Jan 2025 21:21:48 +0800 Message-ID: <20250101132148.126393-1-jerrydeng079@163.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID:_____wBnMgt4QXVnQkWDDA--.50735S2 X-Coremail-Antispam: 1Uf129KBjvJXoW3GFW5AryUXF43Cw4rXFy7ZFb_yoWxXw45pF WaywnYyrW8Jry7Wrs3Aa4UZF1agw4xuF43J3W7GasIyrsIkF1UKFyayFyIyr1IkrZ5GrWa vr4YqrW7Gr48Cr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0JUeMKAUUUUU= X-Originating-IP: [183.157.79.109] X-CM-SenderInfo: xmhu25pghqwiixz6il2tof0z/1tbioBfH22d1QDoQQwABsR X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: DD81714000B X-Stat-Signature: 9ayrpmgutd91rdasdr6hn88fjj8w1jry X-Rspam-User: X-HE-Tag: 1735737695-860717 X-HE-Meta: U2FsdGVkX18HZem5/UnP+ZvVVsy3UzHoURfw+c8OPdInQ7h2dgP8FH/7wH8LbOg4jdKTjfdXIMhQ4B/zNZ8WSrP/SMN7c7nxZb3eiFC3XUAnyTnlXfI/18WhRfzcfWDJTGBedBOCneCJWv0WlbzPcP9HKndm3V9K0jVp/S7berwaIiuC4NVFncGewJOTVaKWQRZFYuqN26Vgdd14pTi6XqWP1o5VFMSpPu6wlyivlAl6AGJtVUbcSrLsJFWdt/P15GM+ygIm9+FLUcWqUFDMeUI+OfxSw4q9O9OXgd+cI5AnL47Q8+DKkVqZ1qaMsPYaoRIt8729Eqy3068o3wkcLyjBkVASxlkImWq7fS48E03eIWYPqHCpPcxB1Y69GJUs4WuZvzs8U1hkRonaK29PQkXp3lZq6N10NdjD1Ha5F4fKhrm/agKcregrgu1jWzTJOADVcd/KCNFaAp6/OfMg/kP0cMgTcY331PXqy48eo3yck7IZcc+lS2QCG0HA43g4Yd31UOO8VcFCqR7d8MTPolCd3Ry1FbxxNSx71RbqZ+h+U+yutwIgvHB9X+Wp1LHK5f36TyTzwZeUObFi/FEves06SQUmTR3vKA3DL3vCOzWdFmUB1aeMxyvvAp4WeuTxzsggTGZQ+M7dzXcxrNAPCeoPzgIshae5/JIUOThppUUuQIhKW0yshQhKfGBKBB6erAUuyx3SMJ4805cyYJXiW7+LXvnInoIzdC6bJFOWwZRG/Uk4XptpxKCrXIRceNFVT78Gz8w3QZ2FyxWWnaHhrhyeQ0SCYCAF6cSr6OBcTiARvpJ1TPQweGG7pniacw1Fq6oxUE/Vla9CjUi/v3L9PPpWbuJGKdNUnt5wTw+GoL7CuB8VaYh0W+q7evo+8vwXmLl9dTcdhzvIhGaJBo8Ntv+fIScMsFTtPYZHjBMBjf5L1IGaX9E645WF8ztU9r6wDrBLiEP4mjrt/FmS2bl C+YOEsa6 9P/MfXYaho1R8eYj7rAM/ltwHCK8SXa9DJz/HnASqX4rSfiM9u6gPKoLFu2n946c5TsNMHE9gwwFBvb9CX26hoj6Pv9Z3yTjb0TiPgrAQvYFjMTJyt0XwzxIEZ+RkGOqFPdk/5r/ITrB3sf4MeKRbhwhNKN3quSNhDJaX9Z7h93hLc34Nvk5c77SSzX7yh//AQWwpNxc+I3A2Wh45eS6RA92wx8PdrcoXeR71GpWgzszcfQN58JUlGGf4FipQepHR+/uWhVkq9Uc6VkD3q/1Qd3VGO21/zpZcgnawcnXZEMJNJKpddml9pVWSgz4i7bKwgPCnf65uO6NtpeP0EbLVkKInE4paGhVDGdV+GSDTyRFdU9urFSlQg8tLmj0Y3Xcpvizy X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: KERNEL-5.10.232.generic_perform_write()->balance_dirty_pages_ratelimited()-> balance_dirty_pages() At this point,if the block device removed, the process may trapped in a dead loop.and the memory of the bdi device hass also been released. Insert a USB flash and directly writing to device node. Remove the USB flash while writing, and the writing process may trapped in a dead loop. user code: int fd = open("/dev/sda", O_RDWR); char *p = malloc(0x1000000); memset(p, 0xa, 0x1000000); for(int i=0; i<100; i++) { write(fd, p, 0x1000000); } return; ISSUE 1: Dead loop may occr here. CALL trace: schedule_timeout() io_schedule_timeout() balance_dirty_pages() balance_dirty_pages_ratelimited() balance_dirty_pages_ratelimited) ISSUE 2 , BDI&WB memory illegal . void balance_dirty_pages_ratelimited(struct address_space *mapping) { struct inode *inode = mapping->host; struct backing_dev_info *bdi = inode_to_bdi(inode); struct bdi_writeback *wb = NULL; int ratelimit; ..... } BDI&WB memory belong to SCSI device. If the USB flash remove, The BDI&WB memeory released by below process: bdi_unregister() del_gendisk() sd_remove() __device_release_driver() device_release_driver() bus_remove_device() device_del() __scsi_remove_deice() scsi_forget_host() scsi_remove_host() usb_stor_disconnect() ... usb_unbind_initerface() usb_disable_device() usb_disconnect() Signed-off-by: Jerry --- mm/backing-dev.c | 1 + mm/filemap.c | 6 ++++- mm/page-writeback.c | 56 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index dd08ab928..0b86bd980 100755 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -878,6 +878,7 @@ void bdi_unregister(struct backing_dev_info *bdi) /* make sure nobody finds us on the bdi_list anymore */ bdi_remove_from_list(bdi); wb_shutdown(&bdi->wb); + wake_up(&(bdi->wb_waitq)); cgwb_bdi_unregister(bdi); /* diff --git a/mm/filemap.c b/mm/filemap.c index 3b0d8c6dd..48424240f 100755 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -3300,6 +3300,7 @@ ssize_t generic_perform_write(struct file *file, long status = 0; ssize_t written = 0; unsigned int flags = 0; + errseq_t err = 0; do { struct page *page; @@ -3368,8 +3369,11 @@ ssize_t generic_perform_write(struct file *file, } pos += copied; written += copied; - + balance_dirty_pages_ratelimited(mapping); + err = errseq_check(&mapping->wb_err, 0); + if (err) + return err; } while (iov_iter_count(i)); return written ? written : status; diff --git a/mm/page-writeback.c b/mm/page-writeback.c index b2c916474..001dd0c5e 100755 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -146,6 +146,13 @@ struct dirty_throttle_control { unsigned long pos_ratio; }; +struct bdi_wq_callback_entry { + struct task_struct *tsk; + struct wait_queue_entry wq_entry; + int bdi_unregister; +}; + + /* * Length of period for aging writeout fractions of bdis. This is an * arbitrarily chosen number. The longer the period, the slower fractions will @@ -1567,6 +1574,22 @@ static inline void wb_dirty_limits(struct dirty_throttle_control *dtc) } } + +static int wake_up_bdi_waitq(wait_queue_entry_t *wait, unsigned int mode, + int sync, void *key) +{ + + struct bdi_wq_callback_entry *bwce = + container_of(wait, struct bdi_wq_callback_entry, wq_entry); + + bwce->bdi_unregister = 1; + if (bwce->tsk) + wake_up_process(bwce->tsk); + + return 0; +} + + /* * balance_dirty_pages() must be called by processes which are generating dirty * data. It looks at the number of dirty pages in the machine and will force @@ -1574,7 +1597,7 @@ static inline void wb_dirty_limits(struct dirty_throttle_control *dtc) * If we're over `background_thresh' then the writeback threads are woken to * perform some writeout. */ -static void balance_dirty_pages(struct bdi_writeback *wb, +static int balance_dirty_pages(struct bdi_writeback *wb, unsigned long pages_dirtied) { struct dirty_throttle_control gdtc_stor = { GDTC_INIT(wb) }; @@ -1595,7 +1618,15 @@ static void balance_dirty_pages(struct bdi_writeback *wb, struct backing_dev_info *bdi = wb->bdi; bool strictlimit = bdi->capabilities & BDI_CAP_STRICTLIMIT; unsigned long start_time = jiffies; + struct bdi_wq_callback_entry bwce = {NULL}; + int ret = 0; + if (!test_bit(WB_registered, &wb->state)) + return -EIO; + + init_waitqueue_func_entry(&(bwce.wq_entry), wake_up_bdi_waitq); + bwce.tsk = current; + add_wait_queue(&(bdi->wb_waitq), &(bwce.wq_entry)); for (;;) { unsigned long now = jiffies; unsigned long dirty, thresh, bg_thresh; @@ -1816,6 +1847,11 @@ static void balance_dirty_pages(struct bdi_writeback *wb, wb->dirty_sleep = now; io_schedule_timeout(pause); + /* bid is unregister NULL, all bdi memory is illegal */ + if (bwce.bdi_unregister) { + ret = -EIO; + break; + } current->dirty_paused_when = now + pause; current->nr_dirtied = 0; current->nr_dirtied_pause = nr_dirtied_pause; @@ -1844,11 +1880,14 @@ static void balance_dirty_pages(struct bdi_writeback *wb, break; } + if (bwce.bdi_unregister == 0) + remove_wait_queue(&(bdi->wb_waitq), &(bwce.wq_entry)); + if (!dirty_exceeded && wb->dirty_exceeded) wb->dirty_exceeded = 0; if (writeback_in_progress(wb)) - return; + return ret; /* * In laptop mode, we wait until hitting the higher threshold before @@ -1859,10 +1898,12 @@ static void balance_dirty_pages(struct bdi_writeback *wb, * background_thresh, to keep the amount of dirty memory low. */ if (laptop_mode) - return; + return ret; if (nr_reclaimable > gdtc->bg_thresh) wb_start_background_writeback(wb); + + return ret; } static DEFINE_PER_CPU(int, bdp_ratelimits); @@ -1944,9 +1985,12 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping) } preempt_enable(); - if (unlikely(current->nr_dirtied >= ratelimit)) - balance_dirty_pages(wb, current->nr_dirtied); - + if (unlikely(current->nr_dirtied >= ratelimit)) { + + if (balance_dirty_pages(wb, current->nr_dirtied) < 0) + errseq_set(&(mapping->wb_err), -EIO); + } + wb_put(wb); } EXPORT_SYMBOL(balance_dirty_pages_ratelimited); -- 2.43.0