xref: /openbmc/linux/fs/nilfs2/page.c (revision f6d73b12ca9fd3b1c29a6a725cd751b972c740cf)
1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+
20bd49f94SRyusuke Konishi /*
394ee1d91SRyusuke Konishi  * Buffer/page management specific to NILFS
40bd49f94SRyusuke Konishi  *
50bd49f94SRyusuke Konishi  * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
60bd49f94SRyusuke Konishi  *
74b420ab4SRyusuke Konishi  * Written by Ryusuke Konishi and Seiji Kihara.
80bd49f94SRyusuke Konishi  */
90bd49f94SRyusuke Konishi 
100bd49f94SRyusuke Konishi #include <linux/pagemap.h>
110bd49f94SRyusuke Konishi #include <linux/writeback.h>
120bd49f94SRyusuke Konishi #include <linux/swap.h>
130bd49f94SRyusuke Konishi #include <linux/bitops.h>
140bd49f94SRyusuke Konishi #include <linux/page-flags.h>
150bd49f94SRyusuke Konishi #include <linux/list.h>
160bd49f94SRyusuke Konishi #include <linux/highmem.h>
170bd49f94SRyusuke Konishi #include <linux/pagevec.h>
185a0e3ad6STejun Heo #include <linux/gfp.h>
190bd49f94SRyusuke Konishi #include "nilfs.h"
200bd49f94SRyusuke Konishi #include "page.h"
210bd49f94SRyusuke Konishi #include "mdt.h"
220bd49f94SRyusuke Konishi 
230bd49f94SRyusuke Konishi 
240bd49f94SRyusuke Konishi #define NILFS_BUFFER_INHERENT_BITS					\
254ce5c342SRyusuke Konishi 	(BIT(BH_Uptodate) | BIT(BH_Mapped) | BIT(BH_NILFS_Node) |	\
264ce5c342SRyusuke Konishi 	 BIT(BH_NILFS_Volatile) | BIT(BH_NILFS_Checked))
270bd49f94SRyusuke Konishi 
280bd49f94SRyusuke Konishi static struct buffer_head *
__nilfs_get_page_block(struct page * page,unsigned long block,pgoff_t index,int blkbits,unsigned long b_state)290bd49f94SRyusuke Konishi __nilfs_get_page_block(struct page *page, unsigned long block, pgoff_t index,
300bd49f94SRyusuke Konishi 		       int blkbits, unsigned long b_state)
310bd49f94SRyusuke Konishi 
320bd49f94SRyusuke Konishi {
330bd49f94SRyusuke Konishi 	unsigned long first_block;
340bd49f94SRyusuke Konishi 	struct buffer_head *bh;
350bd49f94SRyusuke Konishi 
360bd49f94SRyusuke Konishi 	if (!page_has_buffers(page))
370bd49f94SRyusuke Konishi 		create_empty_buffers(page, 1 << blkbits, b_state);
380bd49f94SRyusuke Konishi 
3909cbfeafSKirill A. Shutemov 	first_block = (unsigned long)index << (PAGE_SHIFT - blkbits);
400bd49f94SRyusuke Konishi 	bh = nilfs_page_get_nth_block(page, block - first_block);
410bd49f94SRyusuke Konishi 
420bd49f94SRyusuke Konishi 	wait_on_buffer(bh);
430bd49f94SRyusuke Konishi 	return bh;
440bd49f94SRyusuke Konishi }
450bd49f94SRyusuke Konishi 
nilfs_grab_buffer(struct inode * inode,struct address_space * mapping,unsigned long blkoff,unsigned long b_state)460bd49f94SRyusuke Konishi struct buffer_head *nilfs_grab_buffer(struct inode *inode,
470bd49f94SRyusuke Konishi 				      struct address_space *mapping,
480bd49f94SRyusuke Konishi 				      unsigned long blkoff,
490bd49f94SRyusuke Konishi 				      unsigned long b_state)
500bd49f94SRyusuke Konishi {
510bd49f94SRyusuke Konishi 	int blkbits = inode->i_blkbits;
5209cbfeafSKirill A. Shutemov 	pgoff_t index = blkoff >> (PAGE_SHIFT - blkbits);
53c1c1d709SRyusuke Konishi 	struct page *page;
54c1c1d709SRyusuke Konishi 	struct buffer_head *bh;
550bd49f94SRyusuke Konishi 
560bd49f94SRyusuke Konishi 	page = grab_cache_page(mapping, index);
570bd49f94SRyusuke Konishi 	if (unlikely(!page))
580bd49f94SRyusuke Konishi 		return NULL;
590bd49f94SRyusuke Konishi 
600bd49f94SRyusuke Konishi 	bh = __nilfs_get_page_block(page, blkoff, index, blkbits, b_state);
610bd49f94SRyusuke Konishi 	if (unlikely(!bh)) {
620bd49f94SRyusuke Konishi 		unlock_page(page);
6309cbfeafSKirill A. Shutemov 		put_page(page);
640bd49f94SRyusuke Konishi 		return NULL;
650bd49f94SRyusuke Konishi 	}
66*b0e47657SRyusuke Konishi 	bh->b_bdev = inode->i_sb->s_bdev;
670bd49f94SRyusuke Konishi 	return bh;
680bd49f94SRyusuke Konishi }
690bd49f94SRyusuke Konishi 
700bd49f94SRyusuke Konishi /**
710bd49f94SRyusuke Konishi  * nilfs_forget_buffer - discard dirty state
720bd49f94SRyusuke Konishi  * @bh: buffer head of the buffer to be discarded
730bd49f94SRyusuke Konishi  */
nilfs_forget_buffer(struct buffer_head * bh)740bd49f94SRyusuke Konishi void nilfs_forget_buffer(struct buffer_head *bh)
750bd49f94SRyusuke Konishi {
760bd49f94SRyusuke Konishi 	struct page *page = bh->b_page;
77ead8ecffSRyusuke Konishi 	const unsigned long clear_bits =
784ce5c342SRyusuke Konishi 		(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
794ce5c342SRyusuke Konishi 		 BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
80743c78d4SRyusuke Konishi 		 BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected) |
81743c78d4SRyusuke Konishi 		 BIT(BH_Delay));
820bd49f94SRyusuke Konishi 
830bd49f94SRyusuke Konishi 	lock_buffer(bh);
84ead8ecffSRyusuke Konishi 	set_mask_bits(&bh->b_state, clear_bits, 0);
8584338237SRyusuke Konishi 	if (nilfs_page_buffers_clean(page))
860bd49f94SRyusuke Konishi 		__nilfs_clear_page_dirty(page);
870bd49f94SRyusuke Konishi 
880bd49f94SRyusuke Konishi 	bh->b_blocknr = -1;
890bd49f94SRyusuke Konishi 	ClearPageUptodate(page);
900bd49f94SRyusuke Konishi 	ClearPageMappedToDisk(page);
910bd49f94SRyusuke Konishi 	unlock_buffer(bh);
920bd49f94SRyusuke Konishi 	brelse(bh);
930bd49f94SRyusuke Konishi }
940bd49f94SRyusuke Konishi 
950bd49f94SRyusuke Konishi /**
960bd49f94SRyusuke Konishi  * nilfs_copy_buffer -- copy buffer data and flags
970bd49f94SRyusuke Konishi  * @dbh: destination buffer
980bd49f94SRyusuke Konishi  * @sbh: source buffer
990bd49f94SRyusuke Konishi  */
nilfs_copy_buffer(struct buffer_head * dbh,struct buffer_head * sbh)1000bd49f94SRyusuke Konishi void nilfs_copy_buffer(struct buffer_head *dbh, struct buffer_head *sbh)
1010bd49f94SRyusuke Konishi {
1020bd49f94SRyusuke Konishi 	void *kaddr0, *kaddr1;
1030bd49f94SRyusuke Konishi 	unsigned long bits;
1040bd49f94SRyusuke Konishi 	struct page *spage = sbh->b_page, *dpage = dbh->b_page;
1050bd49f94SRyusuke Konishi 	struct buffer_head *bh;
1060bd49f94SRyusuke Konishi 
1077b9c0976SCong Wang 	kaddr0 = kmap_atomic(spage);
1087b9c0976SCong Wang 	kaddr1 = kmap_atomic(dpage);
1090bd49f94SRyusuke Konishi 	memcpy(kaddr1 + bh_offset(dbh), kaddr0 + bh_offset(sbh), sbh->b_size);
1107b9c0976SCong Wang 	kunmap_atomic(kaddr1);
1117b9c0976SCong Wang 	kunmap_atomic(kaddr0);
1120bd49f94SRyusuke Konishi 
1130bd49f94SRyusuke Konishi 	dbh->b_state = sbh->b_state & NILFS_BUFFER_INHERENT_BITS;
1140bd49f94SRyusuke Konishi 	dbh->b_blocknr = sbh->b_blocknr;
1150bd49f94SRyusuke Konishi 	dbh->b_bdev = sbh->b_bdev;
1160bd49f94SRyusuke Konishi 
1170bd49f94SRyusuke Konishi 	bh = dbh;
1184ce5c342SRyusuke Konishi 	bits = sbh->b_state & (BIT(BH_Uptodate) | BIT(BH_Mapped));
1190bd49f94SRyusuke Konishi 	while ((bh = bh->b_this_page) != dbh) {
1200bd49f94SRyusuke Konishi 		lock_buffer(bh);
1210bd49f94SRyusuke Konishi 		bits &= bh->b_state;
1220bd49f94SRyusuke Konishi 		unlock_buffer(bh);
1230bd49f94SRyusuke Konishi 	}
1244ce5c342SRyusuke Konishi 	if (bits & BIT(BH_Uptodate))
1250bd49f94SRyusuke Konishi 		SetPageUptodate(dpage);
1260bd49f94SRyusuke Konishi 	else
1270bd49f94SRyusuke Konishi 		ClearPageUptodate(dpage);
1284ce5c342SRyusuke Konishi 	if (bits & BIT(BH_Mapped))
1290bd49f94SRyusuke Konishi 		SetPageMappedToDisk(dpage);
1300bd49f94SRyusuke Konishi 	else
1310bd49f94SRyusuke Konishi 		ClearPageMappedToDisk(dpage);
1320bd49f94SRyusuke Konishi }
1330bd49f94SRyusuke Konishi 
1340bd49f94SRyusuke Konishi /**
1350bd49f94SRyusuke Konishi  * nilfs_page_buffers_clean - check if a page has dirty buffers or not.
1360bd49f94SRyusuke Konishi  * @page: page to be checked
1370bd49f94SRyusuke Konishi  *
1380bd49f94SRyusuke Konishi  * nilfs_page_buffers_clean() returns zero if the page has dirty buffers.
1390bd49f94SRyusuke Konishi  * Otherwise, it returns non-zero value.
1400bd49f94SRyusuke Konishi  */
nilfs_page_buffers_clean(struct page * page)1410bd49f94SRyusuke Konishi int nilfs_page_buffers_clean(struct page *page)
1420bd49f94SRyusuke Konishi {
1430bd49f94SRyusuke Konishi 	struct buffer_head *bh, *head;
1440bd49f94SRyusuke Konishi 
1450bd49f94SRyusuke Konishi 	bh = head = page_buffers(page);
1460bd49f94SRyusuke Konishi 	do {
1470bd49f94SRyusuke Konishi 		if (buffer_dirty(bh))
1480bd49f94SRyusuke Konishi 			return 0;
1490bd49f94SRyusuke Konishi 		bh = bh->b_this_page;
1500bd49f94SRyusuke Konishi 	} while (bh != head);
1510bd49f94SRyusuke Konishi 	return 1;
1520bd49f94SRyusuke Konishi }
1530bd49f94SRyusuke Konishi 
nilfs_page_bug(struct page * page)1540bd49f94SRyusuke Konishi void nilfs_page_bug(struct page *page)
1550bd49f94SRyusuke Konishi {
1560bd49f94SRyusuke Konishi 	struct address_space *m;
157aa405b1fSRyusuke Konishi 	unsigned long ino;
1580bd49f94SRyusuke Konishi 
1590bd49f94SRyusuke Konishi 	if (unlikely(!page)) {
1600bd49f94SRyusuke Konishi 		printk(KERN_CRIT "NILFS_PAGE_BUG(NULL)\n");
1610bd49f94SRyusuke Konishi 		return;
1620bd49f94SRyusuke Konishi 	}
1630bd49f94SRyusuke Konishi 
1640bd49f94SRyusuke Konishi 	m = page->mapping;
165aa405b1fSRyusuke Konishi 	ino = m ? m->host->i_ino : 0;
166aa405b1fSRyusuke Konishi 
1670bd49f94SRyusuke Konishi 	printk(KERN_CRIT "NILFS_PAGE_BUG(%p): cnt=%d index#=%llu flags=0x%lx "
1680bd49f94SRyusuke Konishi 	       "mapping=%p ino=%lu\n",
169fe896d18SJoonsoo Kim 	       page, page_ref_count(page),
1700bd49f94SRyusuke Konishi 	       (unsigned long long)page->index, page->flags, m, ino);
1710bd49f94SRyusuke Konishi 
1720bd49f94SRyusuke Konishi 	if (page_has_buffers(page)) {
1730bd49f94SRyusuke Konishi 		struct buffer_head *bh, *head;
1740bd49f94SRyusuke Konishi 		int i = 0;
1750bd49f94SRyusuke Konishi 
1760bd49f94SRyusuke Konishi 		bh = head = page_buffers(page);
1770bd49f94SRyusuke Konishi 		do {
1780bd49f94SRyusuke Konishi 			printk(KERN_CRIT
1790bd49f94SRyusuke Konishi 			       " BH[%d] %p: cnt=%d block#=%llu state=0x%lx\n",
1800bd49f94SRyusuke Konishi 			       i++, bh, atomic_read(&bh->b_count),
1810bd49f94SRyusuke Konishi 			       (unsigned long long)bh->b_blocknr, bh->b_state);
1820bd49f94SRyusuke Konishi 			bh = bh->b_this_page;
1830bd49f94SRyusuke Konishi 		} while (bh != head);
1840bd49f94SRyusuke Konishi 	}
1850bd49f94SRyusuke Konishi }
1860bd49f94SRyusuke Konishi 
1870bd49f94SRyusuke Konishi /**
1880bd49f94SRyusuke Konishi  * nilfs_copy_page -- copy the page with buffers
1890bd49f94SRyusuke Konishi  * @dst: destination page
1900bd49f94SRyusuke Konishi  * @src: source page
1910bd49f94SRyusuke Konishi  * @copy_dirty: flag whether to copy dirty states on the page's buffer heads.
1920bd49f94SRyusuke Konishi  *
1937a65004bSRyusuke Konishi  * This function is for both data pages and btnode pages.  The dirty flag
1940bd49f94SRyusuke Konishi  * should be treated by caller.  The page must not be under i/o.
1950bd49f94SRyusuke Konishi  * Both src and dst page must be locked
1960bd49f94SRyusuke Konishi  */
nilfs_copy_page(struct page * dst,struct page * src,int copy_dirty)1970bd49f94SRyusuke Konishi static void nilfs_copy_page(struct page *dst, struct page *src, int copy_dirty)
1980bd49f94SRyusuke Konishi {
199e1ce8a97SColin Ian King 	struct buffer_head *dbh, *dbufs, *sbh;
2000bd49f94SRyusuke Konishi 	unsigned long mask = NILFS_BUFFER_INHERENT_BITS;
2010bd49f94SRyusuke Konishi 
2020bd49f94SRyusuke Konishi 	BUG_ON(PageWriteback(dst));
2030bd49f94SRyusuke Konishi 
204e1ce8a97SColin Ian King 	sbh = page_buffers(src);
2050bd49f94SRyusuke Konishi 	if (!page_has_buffers(dst))
2060bd49f94SRyusuke Konishi 		create_empty_buffers(dst, sbh->b_size, 0);
2070bd49f94SRyusuke Konishi 
2080bd49f94SRyusuke Konishi 	if (copy_dirty)
2094ce5c342SRyusuke Konishi 		mask |= BIT(BH_Dirty);
2100bd49f94SRyusuke Konishi 
2110bd49f94SRyusuke Konishi 	dbh = dbufs = page_buffers(dst);
2120bd49f94SRyusuke Konishi 	do {
2130bd49f94SRyusuke Konishi 		lock_buffer(sbh);
2140bd49f94SRyusuke Konishi 		lock_buffer(dbh);
2150bd49f94SRyusuke Konishi 		dbh->b_state = sbh->b_state & mask;
2160bd49f94SRyusuke Konishi 		dbh->b_blocknr = sbh->b_blocknr;
2170bd49f94SRyusuke Konishi 		dbh->b_bdev = sbh->b_bdev;
2180bd49f94SRyusuke Konishi 		sbh = sbh->b_this_page;
2190bd49f94SRyusuke Konishi 		dbh = dbh->b_this_page;
2200bd49f94SRyusuke Konishi 	} while (dbh != dbufs);
2210bd49f94SRyusuke Konishi 
2220bd49f94SRyusuke Konishi 	copy_highpage(dst, src);
2230bd49f94SRyusuke Konishi 
2240bd49f94SRyusuke Konishi 	if (PageUptodate(src) && !PageUptodate(dst))
2250bd49f94SRyusuke Konishi 		SetPageUptodate(dst);
2260bd49f94SRyusuke Konishi 	else if (!PageUptodate(src) && PageUptodate(dst))
2270bd49f94SRyusuke Konishi 		ClearPageUptodate(dst);
2280bd49f94SRyusuke Konishi 	if (PageMappedToDisk(src) && !PageMappedToDisk(dst))
2290bd49f94SRyusuke Konishi 		SetPageMappedToDisk(dst);
2300bd49f94SRyusuke Konishi 	else if (!PageMappedToDisk(src) && PageMappedToDisk(dst))
2310bd49f94SRyusuke Konishi 		ClearPageMappedToDisk(dst);
2320bd49f94SRyusuke Konishi 
2330bd49f94SRyusuke Konishi 	do {
2340bd49f94SRyusuke Konishi 		unlock_buffer(sbh);
2350bd49f94SRyusuke Konishi 		unlock_buffer(dbh);
2360bd49f94SRyusuke Konishi 		sbh = sbh->b_this_page;
2370bd49f94SRyusuke Konishi 		dbh = dbh->b_this_page;
2380bd49f94SRyusuke Konishi 	} while (dbh != dbufs);
2390bd49f94SRyusuke Konishi }
2400bd49f94SRyusuke Konishi 
nilfs_copy_dirty_pages(struct address_space * dmap,struct address_space * smap)2410bd49f94SRyusuke Konishi int nilfs_copy_dirty_pages(struct address_space *dmap,
2420bd49f94SRyusuke Konishi 			   struct address_space *smap)
2430bd49f94SRyusuke Konishi {
244d4a16d31SVishal Moola (Oracle) 	struct folio_batch fbatch;
2450bd49f94SRyusuke Konishi 	unsigned int i;
2460bd49f94SRyusuke Konishi 	pgoff_t index = 0;
2470bd49f94SRyusuke Konishi 	int err = 0;
2480bd49f94SRyusuke Konishi 
249d4a16d31SVishal Moola (Oracle) 	folio_batch_init(&fbatch);
2500bd49f94SRyusuke Konishi repeat:
251d4a16d31SVishal Moola (Oracle) 	if (!filemap_get_folios_tag(smap, &index, (pgoff_t)-1,
252d4a16d31SVishal Moola (Oracle) 				PAGECACHE_TAG_DIRTY, &fbatch))
2530bd49f94SRyusuke Konishi 		return 0;
2540bd49f94SRyusuke Konishi 
255d4a16d31SVishal Moola (Oracle) 	for (i = 0; i < folio_batch_count(&fbatch); i++) {
256d4a16d31SVishal Moola (Oracle) 		struct folio *folio = fbatch.folios[i], *dfolio;
2570bd49f94SRyusuke Konishi 
258d4a16d31SVishal Moola (Oracle) 		folio_lock(folio);
259d4a16d31SVishal Moola (Oracle) 		if (unlikely(!folio_test_dirty(folio)))
260d4a16d31SVishal Moola (Oracle) 			NILFS_PAGE_BUG(&folio->page, "inconsistent dirty state");
2610bd49f94SRyusuke Konishi 
262d4a16d31SVishal Moola (Oracle) 		dfolio = filemap_grab_folio(dmap, folio->index);
26366dabbb6SChristoph Hellwig 		if (unlikely(IS_ERR(dfolio))) {
2640bd49f94SRyusuke Konishi 			/* No empty page is added to the page cache */
265d4a16d31SVishal Moola (Oracle) 			folio_unlock(folio);
26666dabbb6SChristoph Hellwig 			err = PTR_ERR(dfolio);
2670bd49f94SRyusuke Konishi 			break;
2680bd49f94SRyusuke Konishi 		}
269d4a16d31SVishal Moola (Oracle) 		if (unlikely(!folio_buffers(folio)))
270d4a16d31SVishal Moola (Oracle) 			NILFS_PAGE_BUG(&folio->page,
2710bd49f94SRyusuke Konishi 				       "found empty page in dat page cache");
2720bd49f94SRyusuke Konishi 
273d4a16d31SVishal Moola (Oracle) 		nilfs_copy_page(&dfolio->page, &folio->page, 1);
274d4a16d31SVishal Moola (Oracle) 		filemap_dirty_folio(folio_mapping(dfolio), dfolio);
2750bd49f94SRyusuke Konishi 
276d4a16d31SVishal Moola (Oracle) 		folio_unlock(dfolio);
277d4a16d31SVishal Moola (Oracle) 		folio_put(dfolio);
278d4a16d31SVishal Moola (Oracle) 		folio_unlock(folio);
2790bd49f94SRyusuke Konishi 	}
280d4a16d31SVishal Moola (Oracle) 	folio_batch_release(&fbatch);
2810bd49f94SRyusuke Konishi 	cond_resched();
2820bd49f94SRyusuke Konishi 
2830bd49f94SRyusuke Konishi 	if (likely(!err))
2840bd49f94SRyusuke Konishi 		goto repeat;
2850bd49f94SRyusuke Konishi 	return err;
2860bd49f94SRyusuke Konishi }
2870bd49f94SRyusuke Konishi 
2880bd49f94SRyusuke Konishi /**
2897a65004bSRyusuke Konishi  * nilfs_copy_back_pages -- copy back pages to original cache from shadow cache
2900bd49f94SRyusuke Konishi  * @dmap: destination page cache
2910bd49f94SRyusuke Konishi  * @smap: source page cache
2920bd49f94SRyusuke Konishi  *
293f611ff63SMatthew Wilcox  * No pages must be added to the cache during this process.
2940bd49f94SRyusuke Konishi  * This must be ensured by the caller.
2950bd49f94SRyusuke Konishi  */
nilfs_copy_back_pages(struct address_space * dmap,struct address_space * smap)2960bd49f94SRyusuke Konishi void nilfs_copy_back_pages(struct address_space *dmap,
2970bd49f94SRyusuke Konishi 			   struct address_space *smap)
2980bd49f94SRyusuke Konishi {
299f6e0e173SMatthew Wilcox (Oracle) 	struct folio_batch fbatch;
3000bd49f94SRyusuke Konishi 	unsigned int i, n;
301f6e0e173SMatthew Wilcox (Oracle) 	pgoff_t start = 0;
3020bd49f94SRyusuke Konishi 
303f6e0e173SMatthew Wilcox (Oracle) 	folio_batch_init(&fbatch);
3040bd49f94SRyusuke Konishi repeat:
305f6e0e173SMatthew Wilcox (Oracle) 	n = filemap_get_folios(smap, &start, ~0UL, &fbatch);
3060bd49f94SRyusuke Konishi 	if (!n)
3070bd49f94SRyusuke Konishi 		return;
3080bd49f94SRyusuke Konishi 
309f6e0e173SMatthew Wilcox (Oracle) 	for (i = 0; i < folio_batch_count(&fbatch); i++) {
310f6e0e173SMatthew Wilcox (Oracle) 		struct folio *folio = fbatch.folios[i], *dfolio;
311f6e0e173SMatthew Wilcox (Oracle) 		pgoff_t index = folio->index;
3120bd49f94SRyusuke Konishi 
313f6e0e173SMatthew Wilcox (Oracle) 		folio_lock(folio);
314f6e0e173SMatthew Wilcox (Oracle) 		dfolio = filemap_lock_folio(dmap, index);
31566dabbb6SChristoph Hellwig 		if (!IS_ERR(dfolio)) {
316f6e0e173SMatthew Wilcox (Oracle) 			/* overwrite existing folio in the destination cache */
317f6e0e173SMatthew Wilcox (Oracle) 			WARN_ON(folio_test_dirty(dfolio));
318f6e0e173SMatthew Wilcox (Oracle) 			nilfs_copy_page(&dfolio->page, &folio->page, 0);
319f6e0e173SMatthew Wilcox (Oracle) 			folio_unlock(dfolio);
320f6e0e173SMatthew Wilcox (Oracle) 			folio_put(dfolio);
321f6e0e173SMatthew Wilcox (Oracle) 			/* Do we not need to remove folio from smap here? */
3220bd49f94SRyusuke Konishi 		} else {
323f6e0e173SMatthew Wilcox (Oracle) 			struct folio *f;
3240bd49f94SRyusuke Konishi 
325f6e0e173SMatthew Wilcox (Oracle) 			/* move the folio to the destination cache */
326b93b0163SMatthew Wilcox 			xa_lock_irq(&smap->i_pages);
327f6e0e173SMatthew Wilcox (Oracle) 			f = __xa_erase(&smap->i_pages, index);
328f6e0e173SMatthew Wilcox (Oracle) 			WARN_ON(folio != f);
3290bd49f94SRyusuke Konishi 			smap->nrpages--;
330b93b0163SMatthew Wilcox 			xa_unlock_irq(&smap->i_pages);
3310bd49f94SRyusuke Konishi 
332b93b0163SMatthew Wilcox 			xa_lock_irq(&dmap->i_pages);
333f6e0e173SMatthew Wilcox (Oracle) 			f = __xa_store(&dmap->i_pages, index, folio, GFP_NOFS);
334f6e0e173SMatthew Wilcox (Oracle) 			if (unlikely(f)) {
335f611ff63SMatthew Wilcox 				/* Probably -ENOMEM */
336f6e0e173SMatthew Wilcox (Oracle) 				folio->mapping = NULL;
337f6e0e173SMatthew Wilcox (Oracle) 				folio_put(folio);
3380bd49f94SRyusuke Konishi 			} else {
339f6e0e173SMatthew Wilcox (Oracle) 				folio->mapping = dmap;
3400bd49f94SRyusuke Konishi 				dmap->nrpages++;
341f6e0e173SMatthew Wilcox (Oracle) 				if (folio_test_dirty(folio))
342f6e0e173SMatthew Wilcox (Oracle) 					__xa_set_mark(&dmap->i_pages, index,
3430bd49f94SRyusuke Konishi 							PAGECACHE_TAG_DIRTY);
3440bd49f94SRyusuke Konishi 			}
345b93b0163SMatthew Wilcox 			xa_unlock_irq(&dmap->i_pages);
3460bd49f94SRyusuke Konishi 		}
347f6e0e173SMatthew Wilcox (Oracle) 		folio_unlock(folio);
3480bd49f94SRyusuke Konishi 	}
349f6e0e173SMatthew Wilcox (Oracle) 	folio_batch_release(&fbatch);
3500bd49f94SRyusuke Konishi 	cond_resched();
3510bd49f94SRyusuke Konishi 
3520bd49f94SRyusuke Konishi 	goto repeat;
3530bd49f94SRyusuke Konishi }
3540bd49f94SRyusuke Konishi 
3558c26c4e2SVyacheslav Dubeyko /**
3568c26c4e2SVyacheslav Dubeyko  * nilfs_clear_dirty_pages - discard dirty pages in address space
3578c26c4e2SVyacheslav Dubeyko  * @mapping: address space with dirty pages for discarding
3588c26c4e2SVyacheslav Dubeyko  * @silent: suppress [true] or print [false] warning messages
3598c26c4e2SVyacheslav Dubeyko  */
nilfs_clear_dirty_pages(struct address_space * mapping,bool silent)3608c26c4e2SVyacheslav Dubeyko void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
3610bd49f94SRyusuke Konishi {
362243c5ea4SVishal Moola (Oracle) 	struct folio_batch fbatch;
3630bd49f94SRyusuke Konishi 	unsigned int i;
3640bd49f94SRyusuke Konishi 	pgoff_t index = 0;
3650bd49f94SRyusuke Konishi 
366243c5ea4SVishal Moola (Oracle) 	folio_batch_init(&fbatch);
3670bd49f94SRyusuke Konishi 
368243c5ea4SVishal Moola (Oracle) 	while (filemap_get_folios_tag(mapping, &index, (pgoff_t)-1,
369243c5ea4SVishal Moola (Oracle) 				PAGECACHE_TAG_DIRTY, &fbatch)) {
370243c5ea4SVishal Moola (Oracle) 		for (i = 0; i < folio_batch_count(&fbatch); i++) {
371243c5ea4SVishal Moola (Oracle) 			struct folio *folio = fbatch.folios[i];
3720bd49f94SRyusuke Konishi 
373243c5ea4SVishal Moola (Oracle) 			folio_lock(folio);
374782e53d0SRyusuke Konishi 
375782e53d0SRyusuke Konishi 			/*
376782e53d0SRyusuke Konishi 			 * This folio may have been removed from the address
377782e53d0SRyusuke Konishi 			 * space by truncation or invalidation when the lock
378782e53d0SRyusuke Konishi 			 * was acquired.  Skip processing in that case.
379782e53d0SRyusuke Konishi 			 */
380782e53d0SRyusuke Konishi 			if (likely(folio->mapping == mapping))
381243c5ea4SVishal Moola (Oracle) 				nilfs_clear_dirty_page(&folio->page, silent);
382782e53d0SRyusuke Konishi 
383243c5ea4SVishal Moola (Oracle) 			folio_unlock(folio);
3848c26c4e2SVyacheslav Dubeyko 		}
385243c5ea4SVishal Moola (Oracle) 		folio_batch_release(&fbatch);
3868c26c4e2SVyacheslav Dubeyko 		cond_resched();
3878c26c4e2SVyacheslav Dubeyko 	}
3888c26c4e2SVyacheslav Dubeyko }
3898c26c4e2SVyacheslav Dubeyko 
3908c26c4e2SVyacheslav Dubeyko /**
3918c26c4e2SVyacheslav Dubeyko  * nilfs_clear_dirty_page - discard dirty page
3928c26c4e2SVyacheslav Dubeyko  * @page: dirty page that will be discarded
3938c26c4e2SVyacheslav Dubeyko  * @silent: suppress [true] or print [false] warning messages
3948c26c4e2SVyacheslav Dubeyko  */
nilfs_clear_dirty_page(struct page * page,bool silent)3958c26c4e2SVyacheslav Dubeyko void nilfs_clear_dirty_page(struct page *page, bool silent)
3968c26c4e2SVyacheslav Dubeyko {
3978c26c4e2SVyacheslav Dubeyko 	struct inode *inode = page->mapping->host;
3988c26c4e2SVyacheslav Dubeyko 	struct super_block *sb = inode->i_sb;
3998c26c4e2SVyacheslav Dubeyko 
400dc33f5f3SVyacheslav Dubeyko 	BUG_ON(!PageLocked(page));
4018c26c4e2SVyacheslav Dubeyko 
402d6517debSRyusuke Konishi 	if (!silent)
403a1d0747aSJoe Perches 		nilfs_warn(sb, "discard dirty page: offset=%lld, ino=%lu",
4048c26c4e2SVyacheslav Dubeyko 			   page_offset(page), inode->i_ino);
4058c26c4e2SVyacheslav Dubeyko 
4060bd49f94SRyusuke Konishi 	ClearPageUptodate(page);
4070bd49f94SRyusuke Konishi 	ClearPageMappedToDisk(page);
408f2f1fa44SRyusuke Konishi 	ClearPageChecked(page);
4098c26c4e2SVyacheslav Dubeyko 
4108c26c4e2SVyacheslav Dubeyko 	if (page_has_buffers(page)) {
4118c26c4e2SVyacheslav Dubeyko 		struct buffer_head *bh, *head;
412ead8ecffSRyusuke Konishi 		const unsigned long clear_bits =
4134ce5c342SRyusuke Konishi 			(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
4144ce5c342SRyusuke Konishi 			 BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
415743c78d4SRyusuke Konishi 			 BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected) |
416743c78d4SRyusuke Konishi 			 BIT(BH_Delay));
4178c26c4e2SVyacheslav Dubeyko 
4180bd49f94SRyusuke Konishi 		bh = head = page_buffers(page);
4190bd49f94SRyusuke Konishi 		do {
4200bd49f94SRyusuke Konishi 			lock_buffer(bh);
421d6517debSRyusuke Konishi 			if (!silent)
422a1d0747aSJoe Perches 				nilfs_warn(sb,
423d6517debSRyusuke Konishi 					   "discard dirty block: blocknr=%llu, size=%zu",
4248c26c4e2SVyacheslav Dubeyko 					   (u64)bh->b_blocknr, bh->b_size);
425d6517debSRyusuke Konishi 
426ead8ecffSRyusuke Konishi 			set_mask_bits(&bh->b_state, clear_bits, 0);
4270bd49f94SRyusuke Konishi 			unlock_buffer(bh);
4288c26c4e2SVyacheslav Dubeyko 		} while (bh = bh->b_this_page, bh != head);
4298c26c4e2SVyacheslav Dubeyko 	}
4300bd49f94SRyusuke Konishi 
4310bd49f94SRyusuke Konishi 	__nilfs_clear_page_dirty(page);
4320bd49f94SRyusuke Konishi }
4330bd49f94SRyusuke Konishi 
nilfs_page_count_clean_buffers(struct page * page,unsigned int from,unsigned int to)4340c6c44cbSRyusuke Konishi unsigned int nilfs_page_count_clean_buffers(struct page *page,
4350c6c44cbSRyusuke Konishi 					    unsigned int from, unsigned int to)
4360bd49f94SRyusuke Konishi {
4370c6c44cbSRyusuke Konishi 	unsigned int block_start, block_end;
4380bd49f94SRyusuke Konishi 	struct buffer_head *bh, *head;
4390c6c44cbSRyusuke Konishi 	unsigned int nc = 0;
4400bd49f94SRyusuke Konishi 
4410bd49f94SRyusuke Konishi 	for (bh = head = page_buffers(page), block_start = 0;
4420bd49f94SRyusuke Konishi 	     bh != head || !block_start;
4430bd49f94SRyusuke Konishi 	     block_start = block_end, bh = bh->b_this_page) {
4440bd49f94SRyusuke Konishi 		block_end = block_start + bh->b_size;
4450bd49f94SRyusuke Konishi 		if (block_end > from && block_start < to && !buffer_dirty(bh))
4460bd49f94SRyusuke Konishi 			nc++;
4470bd49f94SRyusuke Konishi 	}
4480bd49f94SRyusuke Konishi 	return nc;
4490bd49f94SRyusuke Konishi }
450ebdfed4dSRyusuke Konishi 
4510bd49f94SRyusuke Konishi /*
4520bd49f94SRyusuke Konishi  * NILFS2 needs clear_page_dirty() in the following two cases:
4530bd49f94SRyusuke Konishi  *
454e897be17SRyusuke Konishi  * 1) For B-tree node pages and data pages of DAT file, NILFS2 clears dirty
455e897be17SRyusuke Konishi  *    flag of pages when it copies back pages from shadow cache to the
456e897be17SRyusuke Konishi  *    original cache.
4570bd49f94SRyusuke Konishi  *
4580bd49f94SRyusuke Konishi  * 2) Some B-tree operations like insertion or deletion may dispose buffers
4590bd49f94SRyusuke Konishi  *    in dirty state, and this needs to cancel the dirty state of their pages.
4600bd49f94SRyusuke Konishi  */
__nilfs_clear_page_dirty(struct page * page)4610bd49f94SRyusuke Konishi int __nilfs_clear_page_dirty(struct page *page)
4620bd49f94SRyusuke Konishi {
4630bd49f94SRyusuke Konishi 	struct address_space *mapping = page->mapping;
4640bd49f94SRyusuke Konishi 
4650bd49f94SRyusuke Konishi 	if (mapping) {
466b93b0163SMatthew Wilcox 		xa_lock_irq(&mapping->i_pages);
4670bd49f94SRyusuke Konishi 		if (test_bit(PG_dirty, &page->flags)) {
468f611ff63SMatthew Wilcox 			__xa_clear_mark(&mapping->i_pages, page_index(page),
4690bd49f94SRyusuke Konishi 					     PAGECACHE_TAG_DIRTY);
470b93b0163SMatthew Wilcox 			xa_unlock_irq(&mapping->i_pages);
4710bd49f94SRyusuke Konishi 			return clear_page_dirty_for_io(page);
4720bd49f94SRyusuke Konishi 		}
473b93b0163SMatthew Wilcox 		xa_unlock_irq(&mapping->i_pages);
4740bd49f94SRyusuke Konishi 		return 0;
4750bd49f94SRyusuke Konishi 	}
4760bd49f94SRyusuke Konishi 	return TestClearPageDirty(page);
4770bd49f94SRyusuke Konishi }
478622daaffSRyusuke Konishi 
479622daaffSRyusuke Konishi /**
480622daaffSRyusuke Konishi  * nilfs_find_uncommitted_extent - find extent of uncommitted data
481622daaffSRyusuke Konishi  * @inode: inode
482622daaffSRyusuke Konishi  * @start_blk: start block offset (in)
483622daaffSRyusuke Konishi  * @blkoff: start offset of the found extent (out)
484622daaffSRyusuke Konishi  *
485622daaffSRyusuke Konishi  * This function searches an extent of buffers marked "delayed" which
486622daaffSRyusuke Konishi  * starts from a block offset equal to or larger than @start_blk.  If
487622daaffSRyusuke Konishi  * such an extent was found, this will store the start offset in
488622daaffSRyusuke Konishi  * @blkoff and return its length in blocks.  Otherwise, zero is
489622daaffSRyusuke Konishi  * returned.
490622daaffSRyusuke Konishi  */
nilfs_find_uncommitted_extent(struct inode * inode,sector_t start_blk,sector_t * blkoff)491622daaffSRyusuke Konishi unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
492622daaffSRyusuke Konishi 					    sector_t start_blk,
493622daaffSRyusuke Konishi 					    sector_t *blkoff)
494622daaffSRyusuke Konishi {
49524a1efb4SVishal Moola (Oracle) 	unsigned int i, nr_folios;
496622daaffSRyusuke Konishi 	pgoff_t index;
497622daaffSRyusuke Konishi 	unsigned long length = 0;
49824a1efb4SVishal Moola (Oracle) 	struct folio_batch fbatch;
49924a1efb4SVishal Moola (Oracle) 	struct folio *folio;
500622daaffSRyusuke Konishi 
501622daaffSRyusuke Konishi 	if (inode->i_mapping->nrpages == 0)
502622daaffSRyusuke Konishi 		return 0;
503622daaffSRyusuke Konishi 
50409cbfeafSKirill A. Shutemov 	index = start_blk >> (PAGE_SHIFT - inode->i_blkbits);
505622daaffSRyusuke Konishi 
50624a1efb4SVishal Moola (Oracle) 	folio_batch_init(&fbatch);
507622daaffSRyusuke Konishi 
508622daaffSRyusuke Konishi repeat:
50924a1efb4SVishal Moola (Oracle) 	nr_folios = filemap_get_folios_contig(inode->i_mapping, &index, ULONG_MAX,
51024a1efb4SVishal Moola (Oracle) 			&fbatch);
51124a1efb4SVishal Moola (Oracle) 	if (nr_folios == 0)
512622daaffSRyusuke Konishi 		return length;
513622daaffSRyusuke Konishi 
514622daaffSRyusuke Konishi 	i = 0;
515622daaffSRyusuke Konishi 	do {
51624a1efb4SVishal Moola (Oracle) 		folio = fbatch.folios[i];
517622daaffSRyusuke Konishi 
51824a1efb4SVishal Moola (Oracle) 		folio_lock(folio);
51924a1efb4SVishal Moola (Oracle) 		if (folio_buffers(folio)) {
520622daaffSRyusuke Konishi 			struct buffer_head *bh, *head;
52124a1efb4SVishal Moola (Oracle) 			sector_t b;
522622daaffSRyusuke Konishi 
52324a1efb4SVishal Moola (Oracle) 			b = folio->index << (PAGE_SHIFT - inode->i_blkbits);
52424a1efb4SVishal Moola (Oracle) 			bh = head = folio_buffers(folio);
525622daaffSRyusuke Konishi 			do {
526622daaffSRyusuke Konishi 				if (b < start_blk)
527622daaffSRyusuke Konishi 					continue;
528622daaffSRyusuke Konishi 				if (buffer_delay(bh)) {
529622daaffSRyusuke Konishi 					if (length == 0)
530622daaffSRyusuke Konishi 						*blkoff = b;
531622daaffSRyusuke Konishi 					length++;
532622daaffSRyusuke Konishi 				} else if (length > 0) {
533622daaffSRyusuke Konishi 					goto out_locked;
534622daaffSRyusuke Konishi 				}
535622daaffSRyusuke Konishi 			} while (++b, bh = bh->b_this_page, bh != head);
536622daaffSRyusuke Konishi 		} else {
537622daaffSRyusuke Konishi 			if (length > 0)
538622daaffSRyusuke Konishi 				goto out_locked;
539622daaffSRyusuke Konishi 		}
54024a1efb4SVishal Moola (Oracle) 		folio_unlock(folio);
541622daaffSRyusuke Konishi 
54224a1efb4SVishal Moola (Oracle) 	} while (++i < nr_folios);
543622daaffSRyusuke Konishi 
54424a1efb4SVishal Moola (Oracle) 	folio_batch_release(&fbatch);
545622daaffSRyusuke Konishi 	cond_resched();
546622daaffSRyusuke Konishi 	goto repeat;
547622daaffSRyusuke Konishi 
548622daaffSRyusuke Konishi out_locked:
54924a1efb4SVishal Moola (Oracle) 	folio_unlock(folio);
55024a1efb4SVishal Moola (Oracle) 	folio_batch_release(&fbatch);
551622daaffSRyusuke Konishi 	return length;
552622daaffSRyusuke Konishi }
553