VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   55 Tags
ae98043f5f7fa (Ryusuke Konishi    2018-09-04 15:46:30 -0700   1) // SPDX-License-Identifier: GPL-2.0+
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700   2) /*
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700   3)  * page.c - buffer/page management specific to NILFS
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700   4)  *
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700   5)  * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700   6)  *
4b420ab4eedc7 (Ryusuke Konishi    2016-05-23 16:23:09 -0700   7)  * Written by Ryusuke Konishi and Seiji Kihara.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700   8)  */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700   9) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  10) #include <linux/pagemap.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  11) #include <linux/writeback.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  12) #include <linux/swap.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  13) #include <linux/bitops.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  14) #include <linux/page-flags.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  15) #include <linux/list.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  16) #include <linux/highmem.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  17) #include <linux/pagevec.h>
5a0e3ad6af866 (Tejun Heo          2010-03-24 17:04:11 +0900  18) #include <linux/gfp.h>
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  19) #include "nilfs.h"
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  20) #include "page.h"
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  21) #include "mdt.h"
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  22) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  23) 
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700  24) #define NILFS_BUFFER_INHERENT_BITS					\
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700  25) 	(BIT(BH_Uptodate) | BIT(BH_Mapped) | BIT(BH_NILFS_Node) |	\
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700  26) 	 BIT(BH_NILFS_Volatile) | BIT(BH_NILFS_Checked))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  27) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  28) static struct buffer_head *
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  29) __nilfs_get_page_block(struct page *page, unsigned long block, pgoff_t index,
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  30) 		       int blkbits, unsigned long b_state)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  31) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  32) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  33) 	unsigned long first_block;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  34) 	struct buffer_head *bh;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  35) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  36) 	if (!page_has_buffers(page))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  37) 		create_empty_buffers(page, 1 << blkbits, b_state);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  38) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  39) 	first_block = (unsigned long)index << (PAGE_SHIFT - blkbits);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  40) 	bh = nilfs_page_get_nth_block(page, block - first_block);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  41) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  42) 	touch_buffer(bh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  43) 	wait_on_buffer(bh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  44) 	return bh;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  45) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  46) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  47) struct buffer_head *nilfs_grab_buffer(struct inode *inode,
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  48) 				      struct address_space *mapping,
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  49) 				      unsigned long blkoff,
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  50) 				      unsigned long b_state)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  51) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  52) 	int blkbits = inode->i_blkbits;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  53) 	pgoff_t index = blkoff >> (PAGE_SHIFT - blkbits);
c1c1d70920720 (Ryusuke Konishi    2010-08-29 12:44:56 +0900  54) 	struct page *page;
c1c1d70920720 (Ryusuke Konishi    2010-08-29 12:44:56 +0900  55) 	struct buffer_head *bh;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  56) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  57) 	page = grab_cache_page(mapping, index);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  58) 	if (unlikely(!page))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  59) 		return NULL;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  60) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  61) 	bh = __nilfs_get_page_block(page, blkoff, index, blkbits, b_state);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  62) 	if (unlikely(!bh)) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  63) 		unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  64) 		put_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  65) 		return NULL;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  66) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  67) 	return bh;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  68) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  69) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  70) /**
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  71)  * nilfs_forget_buffer - discard dirty state
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  72)  * @bh: buffer head of the buffer to be discarded
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  73)  */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  74) void nilfs_forget_buffer(struct buffer_head *bh)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  75) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  76) 	struct page *page = bh->b_page;
ead8ecffa3e18 (Ryusuke Konishi    2015-04-16 12:46:28 -0700  77) 	const unsigned long clear_bits =
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700  78) 		(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700  79) 		 BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700  80) 		 BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected));
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  81) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  82) 	lock_buffer(bh);
ead8ecffa3e18 (Ryusuke Konishi    2015-04-16 12:46:28 -0700  83) 	set_mask_bits(&bh->b_state, clear_bits, 0);
843382370ec61 (Ryusuke Konishi    2009-05-05 21:52:06 +0900  84) 	if (nilfs_page_buffers_clean(page))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  85) 		__nilfs_clear_page_dirty(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  86) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  87) 	bh->b_blocknr = -1;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  88) 	ClearPageUptodate(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  89) 	ClearPageMappedToDisk(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  90) 	unlock_buffer(bh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  91) 	brelse(bh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  92) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  93) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  94) /**
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  95)  * nilfs_copy_buffer -- copy buffer data and flags
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  96)  * @dbh: destination buffer
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  97)  * @sbh: source buffer
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  98)  */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700  99) void nilfs_copy_buffer(struct buffer_head *dbh, struct buffer_head *sbh)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 100) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 101) 	void *kaddr0, *kaddr1;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 102) 	unsigned long bits;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 103) 	struct page *spage = sbh->b_page, *dpage = dbh->b_page;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 104) 	struct buffer_head *bh;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 105) 
7b9c0976ac5e5 (Cong Wang          2011-11-25 23:14:33 +0800 106) 	kaddr0 = kmap_atomic(spage);
7b9c0976ac5e5 (Cong Wang          2011-11-25 23:14:33 +0800 107) 	kaddr1 = kmap_atomic(dpage);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 108) 	memcpy(kaddr1 + bh_offset(dbh), kaddr0 + bh_offset(sbh), sbh->b_size);
7b9c0976ac5e5 (Cong Wang          2011-11-25 23:14:33 +0800 109) 	kunmap_atomic(kaddr1);
7b9c0976ac5e5 (Cong Wang          2011-11-25 23:14:33 +0800 110) 	kunmap_atomic(kaddr0);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 111) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 112) 	dbh->b_state = sbh->b_state & NILFS_BUFFER_INHERENT_BITS;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 113) 	dbh->b_blocknr = sbh->b_blocknr;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 114) 	dbh->b_bdev = sbh->b_bdev;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 115) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 116) 	bh = dbh;
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700 117) 	bits = sbh->b_state & (BIT(BH_Uptodate) | BIT(BH_Mapped));
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 118) 	while ((bh = bh->b_this_page) != dbh) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 119) 		lock_buffer(bh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 120) 		bits &= bh->b_state;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 121) 		unlock_buffer(bh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 122) 	}
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700 123) 	if (bits & BIT(BH_Uptodate))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 124) 		SetPageUptodate(dpage);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 125) 	else
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 126) 		ClearPageUptodate(dpage);
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700 127) 	if (bits & BIT(BH_Mapped))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 128) 		SetPageMappedToDisk(dpage);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 129) 	else
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 130) 		ClearPageMappedToDisk(dpage);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 131) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 132) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 133) /**
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 134)  * nilfs_page_buffers_clean - check if a page has dirty buffers or not.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 135)  * @page: page to be checked
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 136)  *
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 137)  * nilfs_page_buffers_clean() returns zero if the page has dirty buffers.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 138)  * Otherwise, it returns non-zero value.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 139)  */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 140) int nilfs_page_buffers_clean(struct page *page)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 141) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 142) 	struct buffer_head *bh, *head;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 143) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 144) 	bh = head = page_buffers(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 145) 	do {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 146) 		if (buffer_dirty(bh))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 147) 			return 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 148) 		bh = bh->b_this_page;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 149) 	} while (bh != head);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 150) 	return 1;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 151) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 152) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 153) void nilfs_page_bug(struct page *page)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 154) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 155) 	struct address_space *m;
aa405b1f42384 (Ryusuke Konishi    2011-05-05 12:56:51 +0900 156) 	unsigned long ino;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 157) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 158) 	if (unlikely(!page)) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 159) 		printk(KERN_CRIT "NILFS_PAGE_BUG(NULL)\n");
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 160) 		return;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 161) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 162) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 163) 	m = page->mapping;
aa405b1f42384 (Ryusuke Konishi    2011-05-05 12:56:51 +0900 164) 	ino = m ? m->host->i_ino : 0;
aa405b1f42384 (Ryusuke Konishi    2011-05-05 12:56:51 +0900 165) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 166) 	printk(KERN_CRIT "NILFS_PAGE_BUG(%p): cnt=%d index#=%llu flags=0x%lx "
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 167) 	       "mapping=%p ino=%lu\n",
fe896d1878949 (Joonsoo Kim        2016-03-17 14:19:26 -0700 168) 	       page, page_ref_count(page),
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 169) 	       (unsigned long long)page->index, page->flags, m, ino);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 170) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 171) 	if (page_has_buffers(page)) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 172) 		struct buffer_head *bh, *head;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 173) 		int i = 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 174) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 175) 		bh = head = page_buffers(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 176) 		do {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 177) 			printk(KERN_CRIT
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 178) 			       " BH[%d] %p: cnt=%d block#=%llu state=0x%lx\n",
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 179) 			       i++, bh, atomic_read(&bh->b_count),
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 180) 			       (unsigned long long)bh->b_blocknr, bh->b_state);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 181) 			bh = bh->b_this_page;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 182) 		} while (bh != head);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 183) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 184) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 185) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 186) /**
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 187)  * nilfs_copy_page -- copy the page with buffers
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 188)  * @dst: destination page
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 189)  * @src: source page
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 190)  * @copy_dirty: flag whether to copy dirty states on the page's buffer heads.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 191)  *
7a65004bbaa6a (Ryusuke Konishi    2010-03-14 03:32:40 +0900 192)  * This function is for both data pages and btnode pages.  The dirty flag
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 193)  * should be treated by caller.  The page must not be under i/o.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 194)  * Both src and dst page must be locked
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 195)  */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 196) static void nilfs_copy_page(struct page *dst, struct page *src, int copy_dirty)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 197) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 198) 	struct buffer_head *dbh, *dbufs, *sbh, *sbufs;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 199) 	unsigned long mask = NILFS_BUFFER_INHERENT_BITS;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 200) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 201) 	BUG_ON(PageWriteback(dst));
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 202) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 203) 	sbh = sbufs = page_buffers(src);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 204) 	if (!page_has_buffers(dst))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 205) 		create_empty_buffers(dst, sbh->b_size, 0);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 206) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 207) 	if (copy_dirty)
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700 208) 		mask |= BIT(BH_Dirty);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 209) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 210) 	dbh = dbufs = page_buffers(dst);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 211) 	do {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 212) 		lock_buffer(sbh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 213) 		lock_buffer(dbh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 214) 		dbh->b_state = sbh->b_state & mask;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 215) 		dbh->b_blocknr = sbh->b_blocknr;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 216) 		dbh->b_bdev = sbh->b_bdev;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 217) 		sbh = sbh->b_this_page;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 218) 		dbh = dbh->b_this_page;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 219) 	} while (dbh != dbufs);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 220) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 221) 	copy_highpage(dst, src);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 222) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 223) 	if (PageUptodate(src) && !PageUptodate(dst))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 224) 		SetPageUptodate(dst);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 225) 	else if (!PageUptodate(src) && PageUptodate(dst))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 226) 		ClearPageUptodate(dst);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 227) 	if (PageMappedToDisk(src) && !PageMappedToDisk(dst))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 228) 		SetPageMappedToDisk(dst);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 229) 	else if (!PageMappedToDisk(src) && PageMappedToDisk(dst))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 230) 		ClearPageMappedToDisk(dst);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 231) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 232) 	do {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 233) 		unlock_buffer(sbh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 234) 		unlock_buffer(dbh);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 235) 		sbh = sbh->b_this_page;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 236) 		dbh = dbh->b_this_page;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 237) 	} while (dbh != dbufs);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 238) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 239) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 240) int nilfs_copy_dirty_pages(struct address_space *dmap,
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 241) 			   struct address_space *smap)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 242) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 243) 	struct pagevec pvec;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 244) 	unsigned int i;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 245) 	pgoff_t index = 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 246) 	int err = 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 247) 
8667982014d60 (Mel Gorman         2017-11-15 17:37:52 -0800 248) 	pagevec_init(&pvec);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 249) repeat:
67fd707f46814 (Jan Kara           2017-11-15 17:35:19 -0800 250) 	if (!pagevec_lookup_tag(&pvec, smap, &index, PAGECACHE_TAG_DIRTY))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 251) 		return 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 252) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 253) 	for (i = 0; i < pagevec_count(&pvec); i++) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 254) 		struct page *page = pvec.pages[i], *dpage;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 255) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 256) 		lock_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 257) 		if (unlikely(!PageDirty(page)))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 258) 			NILFS_PAGE_BUG(page, "inconsistent dirty state");
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 259) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 260) 		dpage = grab_cache_page(dmap, page->index);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 261) 		if (unlikely(!dpage)) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 262) 			/* No empty page is added to the page cache */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 263) 			err = -ENOMEM;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 264) 			unlock_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 265) 			break;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 266) 		}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 267) 		if (unlikely(!page_has_buffers(page)))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 268) 			NILFS_PAGE_BUG(page,
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 269) 				       "found empty page in dat page cache");
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 270) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 271) 		nilfs_copy_page(dpage, page, 1);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 272) 		__set_page_dirty_nobuffers(dpage);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 273) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 274) 		unlock_page(dpage);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 275) 		put_page(dpage);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 276) 		unlock_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 277) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 278) 	pagevec_release(&pvec);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 279) 	cond_resched();
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 280) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 281) 	if (likely(!err))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 282) 		goto repeat;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 283) 	return err;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 284) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 285) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 286) /**
7a65004bbaa6a (Ryusuke Konishi    2010-03-14 03:32:40 +0900 287)  * nilfs_copy_back_pages -- copy back pages to original cache from shadow cache
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 288)  * @dmap: destination page cache
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 289)  * @smap: source page cache
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 290)  *
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 291)  * No pages must be added to the cache during this process.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 292)  * This must be ensured by the caller.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 293)  */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 294) void nilfs_copy_back_pages(struct address_space *dmap,
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 295) 			   struct address_space *smap)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 296) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 297) 	struct pagevec pvec;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 298) 	unsigned int i, n;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 299) 	pgoff_t index = 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 300) 
8667982014d60 (Mel Gorman         2017-11-15 17:37:52 -0800 301) 	pagevec_init(&pvec);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 302) repeat:
397162ffa2ed1 (Jan Kara           2017-09-06 16:21:43 -0700 303) 	n = pagevec_lookup(&pvec, smap, &index);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 304) 	if (!n)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 305) 		return;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 306) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 307) 	for (i = 0; i < pagevec_count(&pvec); i++) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 308) 		struct page *page = pvec.pages[i], *dpage;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 309) 		pgoff_t offset = page->index;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 310) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 311) 		lock_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 312) 		dpage = find_lock_page(dmap, offset);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 313) 		if (dpage) {
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 314) 			/* overwrite existing page in the destination cache */
1f5abe7e7dbcd (Ryusuke Konishi    2009-04-06 19:01:55 -0700 315) 			WARN_ON(PageDirty(dpage));
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 316) 			nilfs_copy_page(dpage, page, 0);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 317) 			unlock_page(dpage);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 318) 			put_page(dpage);
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 319) 			/* Do we not need to remove page from smap here? */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 320) 		} else {
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 321) 			struct page *p;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 322) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 323) 			/* move the page to the destination cache */
b93b016313b3b (Matthew Wilcox     2018-04-10 16:36:56 -0700 324) 			xa_lock_irq(&smap->i_pages);
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 325) 			p = __xa_erase(&smap->i_pages, offset);
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 326) 			WARN_ON(page != p);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 327) 			smap->nrpages--;
b93b016313b3b (Matthew Wilcox     2018-04-10 16:36:56 -0700 328) 			xa_unlock_irq(&smap->i_pages);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 329) 
b93b016313b3b (Matthew Wilcox     2018-04-10 16:36:56 -0700 330) 			xa_lock_irq(&dmap->i_pages);
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 331) 			p = __xa_store(&dmap->i_pages, offset, page, GFP_NOFS);
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 332) 			if (unlikely(p)) {
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 333) 				/* Probably -ENOMEM */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 334) 				page->mapping = NULL;
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 335) 				put_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 336) 			} else {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 337) 				page->mapping = dmap;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 338) 				dmap->nrpages++;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 339) 				if (PageDirty(page))
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 340) 					__xa_set_mark(&dmap->i_pages, offset,
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 341) 							PAGECACHE_TAG_DIRTY);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 342) 			}
b93b016313b3b (Matthew Wilcox     2018-04-10 16:36:56 -0700 343) 			xa_unlock_irq(&dmap->i_pages);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 344) 		}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 345) 		unlock_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 346) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 347) 	pagevec_release(&pvec);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 348) 	cond_resched();
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 349) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 350) 	goto repeat;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 351) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 352) 
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 353) /**
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 354)  * nilfs_clear_dirty_pages - discard dirty pages in address space
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 355)  * @mapping: address space with dirty pages for discarding
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 356)  * @silent: suppress [true] or print [false] warning messages
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 357)  */
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 358) void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 359) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 360) 	struct pagevec pvec;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 361) 	unsigned int i;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 362) 	pgoff_t index = 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 363) 
8667982014d60 (Mel Gorman         2017-11-15 17:37:52 -0800 364) 	pagevec_init(&pvec);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 365) 
67fd707f46814 (Jan Kara           2017-11-15 17:35:19 -0800 366) 	while (pagevec_lookup_tag(&pvec, mapping, &index,
67fd707f46814 (Jan Kara           2017-11-15 17:35:19 -0800 367) 					PAGECACHE_TAG_DIRTY)) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 368) 		for (i = 0; i < pagevec_count(&pvec); i++) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 369) 			struct page *page = pvec.pages[i];
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 370) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 371) 			lock_page(page);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 372) 			nilfs_clear_dirty_page(page, silent);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 373) 			unlock_page(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 374) 		}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 375) 		pagevec_release(&pvec);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 376) 		cond_resched();
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 377) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 378) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 379) 
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 380) /**
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 381)  * nilfs_clear_dirty_page - discard dirty page
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 382)  * @page: dirty page that will be discarded
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 383)  * @silent: suppress [true] or print [false] warning messages
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 384)  */
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 385) void nilfs_clear_dirty_page(struct page *page, bool silent)
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 386) {
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 387) 	struct inode *inode = page->mapping->host;
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 388) 	struct super_block *sb = inode->i_sb;
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 389) 
dc33f5f3c9988 (Vyacheslav Dubeyko 2013-04-30 15:27:50 -0700 390) 	BUG_ON(!PageLocked(page));
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 391) 
d6517deb01495 (Ryusuke Konishi    2016-08-02 14:05:14 -0700 392) 	if (!silent)
a1d0747a393a0 (Joe Perches        2020-08-11 18:35:49 -0700 393) 		nilfs_warn(sb, "discard dirty page: offset=%lld, ino=%lu",
a1d0747a393a0 (Joe Perches        2020-08-11 18:35:49 -0700 394) 			   page_offset(page), inode->i_ino);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 395) 
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 396) 	ClearPageUptodate(page);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 397) 	ClearPageMappedToDisk(page);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 398) 
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 399) 	if (page_has_buffers(page)) {
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 400) 		struct buffer_head *bh, *head;
ead8ecffa3e18 (Ryusuke Konishi    2015-04-16 12:46:28 -0700 401) 		const unsigned long clear_bits =
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700 402) 			(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700 403) 			 BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
4ce5c3426cbe9 (Ryusuke Konishi    2016-08-02 14:05:28 -0700 404) 			 BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected));
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 405) 
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 406) 		bh = head = page_buffers(page);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 407) 		do {
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 408) 			lock_buffer(bh);
d6517deb01495 (Ryusuke Konishi    2016-08-02 14:05:14 -0700 409) 			if (!silent)
a1d0747a393a0 (Joe Perches        2020-08-11 18:35:49 -0700 410) 				nilfs_warn(sb,
a1d0747a393a0 (Joe Perches        2020-08-11 18:35:49 -0700 411) 					   "discard dirty block: blocknr=%llu, size=%zu",
a1d0747a393a0 (Joe Perches        2020-08-11 18:35:49 -0700 412) 					   (u64)bh->b_blocknr, bh->b_size);
d6517deb01495 (Ryusuke Konishi    2016-08-02 14:05:14 -0700 413) 
ead8ecffa3e18 (Ryusuke Konishi    2015-04-16 12:46:28 -0700 414) 			set_mask_bits(&bh->b_state, clear_bits, 0);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 415) 			unlock_buffer(bh);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 416) 		} while (bh = bh->b_this_page, bh != head);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 417) 	}
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 418) 
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 419) 	__nilfs_clear_page_dirty(page);
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 420) }
8c26c4e2694a1 (Vyacheslav Dubeyko 2013-04-30 15:27:48 -0700 421) 
0c6c44cb9f93f (Ryusuke Konishi    2016-05-23 16:23:39 -0700 422) unsigned int nilfs_page_count_clean_buffers(struct page *page,
0c6c44cb9f93f (Ryusuke Konishi    2016-05-23 16:23:39 -0700 423) 					    unsigned int from, unsigned int to)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 424) {
0c6c44cb9f93f (Ryusuke Konishi    2016-05-23 16:23:39 -0700 425) 	unsigned int block_start, block_end;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 426) 	struct buffer_head *bh, *head;
0c6c44cb9f93f (Ryusuke Konishi    2016-05-23 16:23:39 -0700 427) 	unsigned int nc = 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 428) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 429) 	for (bh = head = page_buffers(page), block_start = 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 430) 	     bh != head || !block_start;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 431) 	     block_start = block_end, bh = bh->b_this_page) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 432) 		block_end = block_start + bh->b_size;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 433) 		if (block_end > from && block_start < to && !buffer_dirty(bh))
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 434) 			nc++;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 435) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 436) 	return nc;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 437) }
ae53a0a2ce2a8 (Ryusuke Konishi    2010-12-26 23:30:02 +0900 438) 
b83ae6d421435 (Christoph Hellwig  2015-01-14 10:42:37 +0100 439) void nilfs_mapping_init(struct address_space *mapping, struct inode *inode)
ebdfed4dc59d1 (Ryusuke Konishi    2010-09-06 12:05:43 +0900 440) {
aa405b1f42384 (Ryusuke Konishi    2011-05-05 12:56:51 +0900 441) 	mapping->host = inode;
ebdfed4dc59d1 (Ryusuke Konishi    2010-09-06 12:05:43 +0900 442) 	mapping->flags = 0;
ebdfed4dc59d1 (Ryusuke Konishi    2010-09-06 12:05:43 +0900 443) 	mapping_set_gfp_mask(mapping, GFP_NOFS);
252aa6f5be64c (Rafael Aquini      2012-12-11 16:02:35 -0800 444) 	mapping->private_data = NULL;
d611b22f1a5dd (Ryusuke Konishi    2011-03-30 11:49:20 +0900 445) 	mapping->a_ops = &empty_aops;
ebdfed4dc59d1 (Ryusuke Konishi    2010-09-06 12:05:43 +0900 446) }
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 447) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 448) /*
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 449)  * NILFS2 needs clear_page_dirty() in the following two cases:
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 450)  *
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 451)  * 1) For B-tree node pages and data pages of the dat/gcdat, NILFS2 clears
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 452)  *    page dirty flags when it copies back pages from the shadow cache
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 453)  *    (gcdat->{i_mapping,i_btnode_cache}) to its original cache
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 454)  *    (dat->{i_mapping,i_btnode_cache}).
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 455)  *
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 456)  * 2) Some B-tree operations like insertion or deletion may dispose buffers
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 457)  *    in dirty state, and this needs to cancel the dirty state of their pages.
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 458)  */
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 459) int __nilfs_clear_page_dirty(struct page *page)
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 460) {
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 461) 	struct address_space *mapping = page->mapping;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 462) 
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 463) 	if (mapping) {
b93b016313b3b (Matthew Wilcox     2018-04-10 16:36:56 -0700 464) 		xa_lock_irq(&mapping->i_pages);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 465) 		if (test_bit(PG_dirty, &page->flags)) {
f611ff63751af (Matthew Wilcox     2017-12-04 19:33:30 -0500 466) 			__xa_clear_mark(&mapping->i_pages, page_index(page),
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 467) 					     PAGECACHE_TAG_DIRTY);
b93b016313b3b (Matthew Wilcox     2018-04-10 16:36:56 -0700 468) 			xa_unlock_irq(&mapping->i_pages);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 469) 			return clear_page_dirty_for_io(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 470) 		}
b93b016313b3b (Matthew Wilcox     2018-04-10 16:36:56 -0700 471) 		xa_unlock_irq(&mapping->i_pages);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 472) 		return 0;
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 473) 	}
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 474) 	return TestClearPageDirty(page);
0bd49f9446130 (Ryusuke Konishi    2009-04-06 19:01:27 -0700 475) }
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 476) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 477) /**
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 478)  * nilfs_find_uncommitted_extent - find extent of uncommitted data
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 479)  * @inode: inode
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 480)  * @start_blk: start block offset (in)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 481)  * @blkoff: start offset of the found extent (out)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 482)  *
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 483)  * This function searches an extent of buffers marked "delayed" which
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 484)  * starts from a block offset equal to or larger than @start_blk.  If
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 485)  * such an extent was found, this will store the start offset in
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 486)  * @blkoff and return its length in blocks.  Otherwise, zero is
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 487)  * returned.
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 488)  */
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 489) unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 490) 					    sector_t start_blk,
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 491) 					    sector_t *blkoff)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 492) {
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 493) 	unsigned int i;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 494) 	pgoff_t index;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 495) 	unsigned int nblocks_in_page;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 496) 	unsigned long length = 0;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 497) 	sector_t b;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 498) 	struct pagevec pvec;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 499) 	struct page *page;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 500) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 501) 	if (inode->i_mapping->nrpages == 0)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 502) 		return 0;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 503) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 504) 	index = start_blk >> (PAGE_SHIFT - inode->i_blkbits);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 505) 	nblocks_in_page = 1U << (PAGE_SHIFT - inode->i_blkbits);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 506) 
8667982014d60 (Mel Gorman         2017-11-15 17:37:52 -0800 507) 	pagevec_init(&pvec);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 508) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 509) repeat:
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 510) 	pvec.nr = find_get_pages_contig(inode->i_mapping, index, PAGEVEC_SIZE,
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 511) 					pvec.pages);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 512) 	if (pvec.nr == 0)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 513) 		return length;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 514) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 515) 	if (length > 0 && pvec.pages[0]->index > index)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 516) 		goto out;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 517) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 518) 	b = pvec.pages[0]->index << (PAGE_SHIFT - inode->i_blkbits);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 519) 	i = 0;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 520) 	do {
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 521) 		page = pvec.pages[i];
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 522) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 523) 		lock_page(page);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 524) 		if (page_has_buffers(page)) {
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 525) 			struct buffer_head *bh, *head;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 526) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 527) 			bh = head = page_buffers(page);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 528) 			do {
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 529) 				if (b < start_blk)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 530) 					continue;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 531) 				if (buffer_delay(bh)) {
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 532) 					if (length == 0)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 533) 						*blkoff = b;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 534) 					length++;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 535) 				} else if (length > 0) {
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 536) 					goto out_locked;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 537) 				}
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 538) 			} while (++b, bh = bh->b_this_page, bh != head);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 539) 		} else {
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 540) 			if (length > 0)
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 541) 				goto out_locked;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 542) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 543) 			b += nblocks_in_page;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 544) 		}
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 545) 		unlock_page(page);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 546) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 547) 	} while (++i < pagevec_count(&pvec));
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 548) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 549) 	index = page->index + 1;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 550) 	pagevec_release(&pvec);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 551) 	cond_resched();
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 552) 	goto repeat;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 553) 
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 554) out_locked:
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 555) 	unlock_page(page);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 556) out:
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 557) 	pagevec_release(&pvec);
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 558) 	return length;
622daaff0a897 (Ryusuke Konishi    2010-12-26 16:38:43 +0900 559) }