linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kara <jack@suse.cz>
To: Wu Fengguang <fengguang.wu@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Christoph Hellwig <hch@infradead.org>,
	Al Viro <viro@ZenIV.linux.org.uk>,
	linux-fsdevel@vger.kernel.org, Jan Kara <jack@suse.cz>
Subject: [PATCH 1/2] mm: Make task in balance_dirty_pages() killable
Date: Mon, 14 Nov 2011 17:15:23 +0100	[thread overview]
Message-ID: <1321287324-15121-2-git-send-email-jack@suse.cz> (raw)
In-Reply-To: <1321287324-15121-1-git-send-email-jack@suse.cz>

There is no reason why task in balance_dirty_pages() shouldn't be killable
and it helps in recovering from some error conditions (like when filesystem
goes in error state and cannot accept writeback anymore but we still want to
kill processes using it to be able to unmount it).

Reported-by: Kazuya Mio <k-mio@sx.jp.nec.com>
Tested-by: Kazuya Mio <k-mio@sx.jp.nec.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 include/linux/writeback.h |    8 ++++----
 mm/page-writeback.c       |   27 +++++++++++++++++++--------
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index a378c29..eb3ecca 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -170,13 +170,13 @@ void __bdi_update_bandwidth(struct backing_dev_info *bdi,
 			    unsigned long start_time);
 
 void page_writeback_init(void);
-void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
-					unsigned long nr_pages_dirtied);
+int balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
+				       unsigned long nr_pages_dirtied);
 
-static inline void
+static inline int
 balance_dirty_pages_ratelimited(struct address_space *mapping)
 {
-	balance_dirty_pages_ratelimited_nr(mapping, 1);
+	return balance_dirty_pages_ratelimited_nr(mapping, 1);
 }
 
 typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc,
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 0360d1b..380279c 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1000,8 +1000,11 @@ static unsigned long bdi_max_pause(struct backing_dev_info *bdi,
  * the caller to wait once crossing the (background_thresh + dirty_thresh) / 2.
  * If we're over `background_thresh' then the writeback threads are woken to
  * perform some writeout.
+ *
+ * We return 0 if nothing special happened, EINTR if our wait has been
+ * interrupted by a fatal signal.
  */
-static void balance_dirty_pages(struct address_space *mapping,
+static int balance_dirty_pages(struct address_space *mapping,
 				unsigned long pages_dirtied)
 {
 	unsigned long nr_reclaimable;	/* = file_dirty + unstable_nfs */
@@ -1020,6 +1023,7 @@ static void balance_dirty_pages(struct address_space *mapping,
 	unsigned long pos_ratio;
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	unsigned long start_time = jiffies;
+	int err = 0;
 
 	for (;;) {
 		/*
@@ -1133,7 +1137,7 @@ pause:
 					  pages_dirtied,
 					  pause,
 					  start_time);
-		__set_current_state(TASK_UNINTERRUPTIBLE);
+		__set_current_state(TASK_KILLABLE);
 		io_schedule_timeout(pause);
 
 		dirty_thresh = hard_dirty_limit(dirty_thresh);
@@ -1145,6 +1149,11 @@ pause:
 		 */
 		if (nr_dirty < dirty_thresh)
 			break;
+
+		if (fatal_signal_pending(current)) {
+			err = -EINTR;
+			break;
+		}
 	}
 
 	if (!dirty_exceeded && bdi->dirty_exceeded)
@@ -1168,7 +1177,7 @@ pause:
 	}
 
 	if (writeback_in_progress(bdi))
-		return;
+		return err;
 
 	/*
 	 * In laptop mode, we wait until hitting the higher threshold before
@@ -1179,10 +1188,11 @@ pause:
 	 * background_thresh, to keep the amount of dirty memory low.
 	 */
 	if (laptop_mode)
-		return;
+		return err;
 
 	if (nr_reclaimable > background_thresh)
 		bdi_start_background_writeback(bdi);
+	return err;
 }
 
 void set_page_dirty_balance(struct page *page, int page_mkwrite)
@@ -1211,15 +1221,15 @@ static DEFINE_PER_CPU(int, bdp_ratelimits);
  * limit we decrease the ratelimiting by a lot, to prevent individual processes
  * from overshooting the limit by (ratelimit_pages) each.
  */
-void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
-					unsigned long nr_pages_dirtied)
+int balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
+				       unsigned long nr_pages_dirtied)
 {
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	int ratelimit;
 	int *p;
 
 	if (!bdi_cap_account_dirty(bdi))
-		return;
+		return 0;
 
 	ratelimit = current->nr_dirtied_pause;
 	if (bdi->dirty_exceeded)
@@ -1247,7 +1257,8 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
 	preempt_enable();
 
 	if (unlikely(current->nr_dirtied >= ratelimit))
-		balance_dirty_pages(mapping, current->nr_dirtied);
+		return balance_dirty_pages(mapping, current->nr_dirtied);
+	return 0;
 }
 EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr);
 
-- 
1.7.1


  reply	other threads:[~2011-11-14 16:15 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-14 16:15 [PATCH 0/2 v2] Make task in balance_dirty_pages() killable Jan Kara
2011-11-14 16:15 ` Jan Kara [this message]
2011-11-14 16:23   ` [PATCH 1/2] mm: " Christoph Hellwig
2011-11-15 11:48   ` Wu Fengguang
2011-11-15 13:41     ` Jan Kara
2011-11-15 14:15       ` Wu Fengguang
2011-11-15 14:44         ` Jan Kara
2011-11-14 16:15 ` [PATCH 2/2] fs: Make write(2) interruptible by a signal Jan Kara
2011-11-14 16:26   ` Christoph Hellwig
2011-11-14 16:46     ` Jan Kara
2011-11-14 20:13       ` Christoph Hellwig
2011-11-14 22:19   ` Andrew Morton
2011-11-15 11:23     ` Jan Kara
  -- strict thread matches above, loose matches on Subject: below --
2011-11-16 11:12 [PATCH 0/2 v3] Make task in balance_dirty_pages() killable Jan Kara
2011-11-16 11:12 ` [PATCH 1/2] mm: " Jan Kara
2011-11-16 11:28   ` Wu Fengguang
2011-11-16 12:58     ` Jan Kara
2011-11-14 11:10 [PATCH 0/2] Make task doing heavy writing killable Jan Kara
2011-11-14 11:10 ` [PATCH 1/2] mm: Make task in balance_dirty_pages() killable Jan Kara
2011-11-14 12:12   ` Wu Fengguang
2011-11-14 12:37     ` Jan Kara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1321287324-15121-2-git-send-email-jack@suse.cz \
    --to=jack@suse.cz \
    --cc=akpm@linux-foundation.org \
    --cc=fengguang.wu@intel.com \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).