From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Tue, 10 Oct 2006 10:18:20 +0200 From: Nick Piggin Subject: Re: [patch] mm: bug in set_page_dirty_buffers Message-ID: <20061010081820.GA24748@wotan.suse.de> References: <20061009222905.ddd270a6.akpm@osdl.org> <20061010054832.GC24600@wotan.suse.de> <20061009230832.7245814e.akpm@osdl.org> <20061010061958.GA25500@wotan.suse.de> <20061009232714.b52f678d.akpm@osdl.org> <20061010063900.GB25500@wotan.suse.de> <20061010065217.GC25500@wotan.suse.de> <20061010000652.bed6f901.akpm@osdl.org> <20061010072129.GB14557@wotan.suse.de> <20061010010742.50cbe1b1.akpm@osdl.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20061010010742.50cbe1b1.akpm@osdl.org> Sender: owner-linux-mm@kvack.org Return-Path: To: Andrew Morton Cc: Linus Torvalds , Peter Zijlstra , Linux Memory Management List , Greg KH List-ID: On Tue, Oct 10, 2006 at 01:07:42AM -0700, Andrew Morton wrote: > On Tue, 10 Oct 2006 09:21:29 +0200 > Nick Piggin wrote: > > > void block_invalidatepage(struct page *page, unsigned long offset) > > { > > + struct address_space *mapping = page->mapping; > > struct buffer_head *head, *bh, *next; > > - unsigned int curr_off = 0; > > + unsigned int curr_off; > > > > BUG_ON(!PageLocked(page)); > > if (!page_has_buffers(page)) > > goto out; > > > > + curr_off = 0; > > head = page_buffers(page); > > bh = head; > > do { > > @@ -1455,6 +1457,24 @@ void block_invalidatepage(struct page *p > > bh = next; > > } while (bh != head); > > > > + /* strip the dirty bits and protect against concurrent set_page_dirty */ > > + spin_lock(&mapping->private_lock); > > + curr_off = 0; > > + head = page_buffers(page); > > + bh = head; > > + do { > > + unsigned int next_off = curr_off + bh->b_size; > > + next = bh->b_this_page; > > + > > + if (offset <= curr_off) { > > + clear_buffer_dirty(bh); > > + set_buffer_invalid(bh); > > + } > > + curr_off = next_off; > > + bh = next; > > + } while (bh != head); > > + spin_unlock(&mapping->private_lock); > > If the buffer's redirtied after discard_buffer() got at it, we've got some > nasty problems in there. > > Are you sure this race can happen? Nobody's allowed to have a page mapped > while it's undergoing truncation (vmtruncate()). Well, not technically. I think it can happen with nonlinear pages now, but that is a bug in truncate and I have some patches to fix them. But anyone who has done a get_user_pages, AFAIKS, can later run a set_page_dirty on the pages. Nasty problem, but I think we are OK to just ignore the dirty bits in this case, because the truncate might well have happened _after_ the get_user_pages guy set the page dirty anyway. > There might be a problem with the final blocks in the page outside i_size. > iirc what happens here is that the bh outside i_size _is_ marked dirty, but > writepage() will notice that it's outside i_size and will just mark it > clean again without doing IO. Didn't think of that. How does it get to writepage though, if it has lost its mapping? -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org