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 AF7D9E77188 for ; Thu, 2 Jan 2025 04:06:34 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D96BF6B007B; Wed, 1 Jan 2025 23:06:33 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id D46AF6B0083; Wed, 1 Jan 2025 23:06:33 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BE71B6B0085; Wed, 1 Jan 2025 23:06:33 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 9FFCD6B007B for ; Wed, 1 Jan 2025 23:06:33 -0500 (EST) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id E126B1C82A6 for ; Thu, 2 Jan 2025 04:06:32 +0000 (UTC) X-FDA: 82961172714.08.BB04359 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) by imf11.hostedemail.com (Postfix) with ESMTP id 8BD1540006 for ; Thu, 2 Jan 2025 04:05:44 +0000 (UTC) Authentication-Results: imf11.hostedemail.com; dkim=pass header.d=infradead.org header.s=casper.20170209 header.b=dMNZe5ql; spf=none (imf11.hostedemail.com: domain of willy@infradead.org has no SPF policy when checking 90.155.50.34) smtp.mailfrom=willy@infradead.org; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1735790757; 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-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=iMLpK7U9WYHmx0iT1T9KJlpKXJYaEu7HU7H6KfDU588=; b=RBCAQ5dCTDYcgR4J0ZD4m7Ov3iYcbZlsI5fuu+R0LYIHbP06dOfF3Q8F1sziWBJvzz2IqO lXIdOyYkzsPOfg+6JHuPD+ZE6jv1wr0xoxZ3cRut0dM3MFmY2ry3bw2MLBua+loIPyEoIA Q7FzCmWNBFgxWTbblL7AWQX8qLxiLDg= ARC-Authentication-Results: i=1; imf11.hostedemail.com; dkim=pass header.d=infradead.org header.s=casper.20170209 header.b=dMNZe5ql; spf=none (imf11.hostedemail.com: domain of willy@infradead.org has no SPF policy when checking 90.155.50.34) smtp.mailfrom=willy@infradead.org; dmarc=none ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1735790757; a=rsa-sha256; cv=none; b=uirQxGNPDsIU3CeAyluzv3/O2v+eeo9kv7CDN/V59apxxGE57TQvGVfeYV39xr9pzdFVd2 2eWYAMpcwmVFDiFTmAoWyHdmAImiq5Ur4lqPeTOsQk3a+wGbja7aeaaEfw7uZ/m45QjEP+ F4De9c6LmDgAFqF/vHe68TtTnn1NkA0= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=iMLpK7U9WYHmx0iT1T9KJlpKXJYaEu7HU7H6KfDU588=; b=dMNZe5qlfMN+VDuQTbBhmp+4Bv QrKPAHI3LFcSRnmBoLSL+g/BDLPFLYYPw/kwlIkqCnrz4LaogbA9VD8hbFlqKG12C2acEd0cuTkb/ MCs4WtPL+VPdiIKQJ/+vqZcNmXsMcKAv9T0lf4eAYE1ecfv/CFrylrt2KA2Z42Ta9irR5fRjQZOR6 XHV+FVYBI6PTpDE9/vcoFdkn3/FoIvM5LDVW4QWYwIBpj9BFe+z9KFFwqRhTn0ejfRES70jY62/EE i9wlIg07in6ehPSfcIUhasxRZOg9P23V3pm2h3wbbXPrqTwZF9J5dzAmXMYeRlStCZdGikHnohD/0 p9j7Q+Sw==; Received: from willy by casper.infradead.org with local (Exim 4.98 #2 (Red Hat Linux)) id 1tTCTZ-0000000Eyaj-2SUV; Thu, 02 Jan 2025 04:06:25 +0000 Date: Thu, 2 Jan 2025 04:06:25 +0000 From: Matthew Wilcox To: Jerry Cc: akpm@linux-foundation.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, linux-scsi@vger.kernel.org Subject: Re: [PATCH] mm: fix dead-loop bug Message-ID: References: <20250101132148.126393-1-jerrydeng079@163.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20250101132148.126393-1-jerrydeng079@163.com> X-Rspamd-Server: rspam05 X-Stat-Signature: r6zgt9jp497jrj391hhsnojzjdem5k5i X-Rspamd-Queue-Id: 8BD1540006 X-Rspam-User: X-HE-Tag: 1735790744-138055 X-HE-Meta: U2FsdGVkX18Souyf9iau2iMqyhLSXUla7ayLnD7BlrEuNDkJUruJo8CnIKyq110d6micSVhMDH1YMNw7uGC0LW5NZnaGDk3KEJhQADn9vs8AkqQqluNFCGtSkSmYVuIt8Y+6kWDTpRjwThkxyNF0VwK9gg1SIeyjowBo7R/GQhIu2esQ+Q7NuHOLDJ1qJWgsP2iD0P2W5nUQuRDZ3vCPLVVLSCHK9WuL3K+2R1blyX2cKBOZEJHu2Cphv7SY6n5i12bbpzs/f5mqxwNUg5C7pgXiaeRQoZObtFnucAN2XmgJoL5bpAtW33FedEL0v/ouz3UwIC0xEkdpmnRHIw1oFhucxPCi+aTueOH0JCuA3tQKIfvuCvwbLDxXhVJV6YgRS+Fhvr82bPrdcgU2+fCLMMaWG5O4laZoyVYwI4JhNYwl80fmhFfVGAV06nm8G6m5qhps7fm0GWxXmxo4qlTNeE++H0zIOzYMldAWKx8fnJmd+zJ75+WRfdUNMpPoKaQIerEaL6YVOVfqVoCB9TPFIBAZOft5a4pPMDFFX1d3VI/OzlTXIwN6IqXKIP4dC+ty/1yZENdylMPWY4HtnO8V8bfRc5+NCpO8aViy6LSRO1f6NwE4wA18b8PBL6uywl867nnD0LEah4qAPwKaCqO/IOjLzoNz2HKVwfXphnP1qGPA5By6qzLBHZyIQFyVZzzpMnDvxDmhRz5LpHh7d5n0r6z1/RgquwlbeTREhUyhxkj9hWrSR6l/A9a6CzAvk1FHcxI5FCW7/oTtpKaxpi3uYXNd5UjnUD/EhegtGexFMLIbWppBaV1feVY/ipv6u7OEIRHik4uLmkNumT78Sv7LM99nAnSwbTgbEs+o+uYzMmmO216lBdtC+lxbcHzVjIbacOpRf2jbtY9R4YRSiAeusptEBK5RJRIZgXKFzrUKbAZ55BbL7nFek/X0L9o5TOpCs1U3pav5KDmVuQMn+ti KSZnfyRE NCdevQ9dDjlQVvVegDJCcL7EbfbgTHPZagCLTrmx7RHREfz8cR6DDqguF+fo5Er3XnxWuqg/vQl6g4Hu/DG7//EDb4axW8uJsvP7TH2Z93EgqQ5lShwlKWAcjxZg3rXVwmYy3boTy9VEgWTFfhDhH07C2CMoQHYT1fZGGGudNgh46ZX2qMbN45gaWYcCAR+ywwI4qto9JY1TaaTPcdDg4A3TnN90GYK/d9Nj/2rzDQl6sWe/YHCTBq1nVe4M/fGoOc+/RX61EfNE91plLVA1/G3U7NflnnBNPAGryvX4p2ex2GnlE9aGeSMn0gDwQOu6+goSaPQ93B0opi+oZUGd36s9Rlw== 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: On Wed, Jan 01, 2025 at 09:21:48PM +0800, Jerry wrote: > KERNEL-5.10.232.generic_perform_write()->balance_dirty_pages_ratelimited()-> Can you reproduce this with a kernel that's newer than four years old? > 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. I think this is a block layer bug, not an MM bug. Devices shouldn't go away while the MM is still writing to them. > 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 > >