Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0f23603 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

[PATCH] Remove semi-softlockup from invalidate_mapping_pages



If invalidate_mapping_pages is called to invalidate a very large mapping
(e.g.  a very large block device) and if the only active page in that
device is near the end (or at least, at a very large index), such as, say,
the superblock of an md array, and if that page happens to be locked when
invalidate_mapping_pages is called, then

  pagevec_lookup will return this page and
  as it is locked, 'next' will be incremented and pagevec_lookup
  will be called again. and again. and again.
  while we count from 0 upto a very large number.

We should really always set 'next' to 'page->index+1' before going around
the loop again, not just if the page isn't locked.

Cc: "Steinar H. Gunderson" <sgunderson@bigfoot.com>
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 57ae2508
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -230,14 +230,24 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
			pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
		for (i = 0; i < pagevec_count(&pvec); i++) {
			struct page *page = pvec.pages[i];
			pgoff_t index;
			int lock_failed;

			if (TestSetPageLocked(page)) {
			lock_failed = TestSetPageLocked(page);

			/*
			 * We really shouldn't be looking at the ->index of an
			 * unlocked page.  But we're not allowed to lock these
			 * pages.  So we rely upon nobody altering the ->index
			 * of this (pinned-by-us) page.
			 */
			index = page->index;
			if (index > next)
				next = index;
			next++;
			if (lock_failed)
				continue;
			}
			if (page->index > next)
				next = page->index;
			next++;

			if (PageDirty(page) || PageWriteback(page))
				goto unlock;
			if (page_mapped(page))