xref: /openbmc/linux/fs/nilfs2/page.c (revision 24a1efb4a91283c853a31fa4775d5c10c09129a4)
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 *
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 	touch_buffer(bh);
430bd49f94SRyusuke Konishi 	wait_on_buffer(bh);
440bd49f94SRyusuke Konishi 	return bh;
450bd49f94SRyusuke Konishi }
460bd49f94SRyusuke Konishi 
470bd49f94SRyusuke Konishi struct buffer_head *nilfs_grab_buffer(struct inode *inode,
480bd49f94SRyusuke Konishi 				      struct address_space *mapping,
490bd49f94SRyusuke Konishi 				      unsigned long blkoff,
500bd49f94SRyusuke Konishi 				      unsigned long b_state)
510bd49f94SRyusuke Konishi {
520bd49f94SRyusuke Konishi 	int blkbits = inode->i_blkbits;
5309cbfeafSKirill A. Shutemov 	pgoff_t index = blkoff >> (PAGE_SHIFT - blkbits);
54c1c1d709SRyusuke Konishi 	struct page *page;
55c1c1d709SRyusuke Konishi 	struct buffer_head *bh;
560bd49f94SRyusuke Konishi 
570bd49f94SRyusuke Konishi 	page = grab_cache_page(mapping, index);
580bd49f94SRyusuke Konishi 	if (unlikely(!page))
590bd49f94SRyusuke Konishi 		return NULL;
600bd49f94SRyusuke Konishi 
610bd49f94SRyusuke Konishi 	bh = __nilfs_get_page_block(page, blkoff, index, blkbits, b_state);
620bd49f94SRyusuke Konishi 	if (unlikely(!bh)) {
630bd49f94SRyusuke Konishi 		unlock_page(page);
6409cbfeafSKirill A. Shutemov 		put_page(page);
650bd49f94SRyusuke Konishi 		return NULL;
660bd49f94SRyusuke Konishi 	}
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  */
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) |
804ce5c342SRyusuke Konishi 		 BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected));
810bd49f94SRyusuke Konishi 
820bd49f94SRyusuke Konishi 	lock_buffer(bh);
83ead8ecffSRyusuke Konishi 	set_mask_bits(&bh->b_state, clear_bits, 0);
8484338237SRyusuke Konishi 	if (nilfs_page_buffers_clean(page))
850bd49f94SRyusuke Konishi 		__nilfs_clear_page_dirty(page);
860bd49f94SRyusuke Konishi 
870bd49f94SRyusuke Konishi 	bh->b_blocknr = -1;
880bd49f94SRyusuke Konishi 	ClearPageUptodate(page);
890bd49f94SRyusuke Konishi 	ClearPageMappedToDisk(page);
900bd49f94SRyusuke Konishi 	unlock_buffer(bh);
910bd49f94SRyusuke Konishi 	brelse(bh);
920bd49f94SRyusuke Konishi }
930bd49f94SRyusuke Konishi 
940bd49f94SRyusuke Konishi /**
950bd49f94SRyusuke Konishi  * nilfs_copy_buffer -- copy buffer data and flags
960bd49f94SRyusuke Konishi  * @dbh: destination buffer
970bd49f94SRyusuke Konishi  * @sbh: source buffer
980bd49f94SRyusuke Konishi  */
990bd49f94SRyusuke Konishi void nilfs_copy_buffer(struct buffer_head *dbh, struct buffer_head *sbh)
1000bd49f94SRyusuke Konishi {
1010bd49f94SRyusuke Konishi 	void *kaddr0, *kaddr1;
1020bd49f94SRyusuke Konishi 	unsigned long bits;
1030bd49f94SRyusuke Konishi 	struct page *spage = sbh->b_page, *dpage = dbh->b_page;
1040bd49f94SRyusuke Konishi 	struct buffer_head *bh;
1050bd49f94SRyusuke Konishi 
1067b9c0976SCong Wang 	kaddr0 = kmap_atomic(spage);
1077b9c0976SCong Wang 	kaddr1 = kmap_atomic(dpage);
1080bd49f94SRyusuke Konishi 	memcpy(kaddr1 + bh_offset(dbh), kaddr0 + bh_offset(sbh), sbh->b_size);
1097b9c0976SCong Wang 	kunmap_atomic(kaddr1);
1107b9c0976SCong Wang 	kunmap_atomic(kaddr0);
1110bd49f94SRyusuke Konishi 
1120bd49f94SRyusuke Konishi 	dbh->b_state = sbh->b_state & NILFS_BUFFER_INHERENT_BITS;
1130bd49f94SRyusuke Konishi 	dbh->b_blocknr = sbh->b_blocknr;
1140bd49f94SRyusuke Konishi 	dbh->b_bdev = sbh->b_bdev;
1150bd49f94SRyusuke Konishi 
1160bd49f94SRyusuke Konishi 	bh = dbh;
1174ce5c342SRyusuke Konishi 	bits = sbh->b_state & (BIT(BH_Uptodate) | BIT(BH_Mapped));
1180bd49f94SRyusuke Konishi 	while ((bh = bh->b_this_page) != dbh) {
1190bd49f94SRyusuke Konishi 		lock_buffer(bh);
1200bd49f94SRyusuke Konishi 		bits &= bh->b_state;
1210bd49f94SRyusuke Konishi 		unlock_buffer(bh);
1220bd49f94SRyusuke Konishi 	}
1234ce5c342SRyusuke Konishi 	if (bits & BIT(BH_Uptodate))
1240bd49f94SRyusuke Konishi 		SetPageUptodate(dpage);
1250bd49f94SRyusuke Konishi 	else
1260bd49f94SRyusuke Konishi 		ClearPageUptodate(dpage);
1274ce5c342SRyusuke Konishi 	if (bits & BIT(BH_Mapped))
1280bd49f94SRyusuke Konishi 		SetPageMappedToDisk(dpage);
1290bd49f94SRyusuke Konishi 	else
1300bd49f94SRyusuke Konishi 		ClearPageMappedToDisk(dpage);
1310bd49f94SRyusuke Konishi }
1320bd49f94SRyusuke Konishi 
1330bd49f94SRyusuke Konishi /**
1340bd49f94SRyusuke Konishi  * nilfs_page_buffers_clean - check if a page has dirty buffers or not.
1350bd49f94SRyusuke Konishi  * @page: page to be checked
1360bd49f94SRyusuke Konishi  *
1370bd49f94SRyusuke Konishi  * nilfs_page_buffers_clean() returns zero if the page has dirty buffers.
1380bd49f94SRyusuke Konishi  * Otherwise, it returns non-zero value.
1390bd49f94SRyusuke Konishi  */
1400bd49f94SRyusuke Konishi int nilfs_page_buffers_clean(struct page *page)
1410bd49f94SRyusuke Konishi {
1420bd49f94SRyusuke Konishi 	struct buffer_head *bh, *head;
1430bd49f94SRyusuke Konishi 
1440bd49f94SRyusuke Konishi 	bh = head = page_buffers(page);
1450bd49f94SRyusuke Konishi 	do {
1460bd49f94SRyusuke Konishi 		if (buffer_dirty(bh))
1470bd49f94SRyusuke Konishi 			return 0;
1480bd49f94SRyusuke Konishi 		bh = bh->b_this_page;
1490bd49f94SRyusuke Konishi 	} while (bh != head);
1500bd49f94SRyusuke Konishi 	return 1;
1510bd49f94SRyusuke Konishi }
1520bd49f94SRyusuke Konishi 
1530bd49f94SRyusuke Konishi void nilfs_page_bug(struct page *page)
1540bd49f94SRyusuke Konishi {
1550bd49f94SRyusuke Konishi 	struct address_space *m;
156aa405b1fSRyusuke Konishi 	unsigned long ino;
1570bd49f94SRyusuke Konishi 
1580bd49f94SRyusuke Konishi 	if (unlikely(!page)) {
1590bd49f94SRyusuke Konishi 		printk(KERN_CRIT "NILFS_PAGE_BUG(NULL)\n");
1600bd49f94SRyusuke Konishi 		return;
1610bd49f94SRyusuke Konishi 	}
1620bd49f94SRyusuke Konishi 
1630bd49f94SRyusuke Konishi 	m = page->mapping;
164aa405b1fSRyusuke Konishi 	ino = m ? m->host->i_ino : 0;
165aa405b1fSRyusuke Konishi 
1660bd49f94SRyusuke Konishi 	printk(KERN_CRIT "NILFS_PAGE_BUG(%p): cnt=%d index#=%llu flags=0x%lx "
1670bd49f94SRyusuke Konishi 	       "mapping=%p ino=%lu\n",
168fe896d18SJoonsoo Kim 	       page, page_ref_count(page),
1690bd49f94SRyusuke Konishi 	       (unsigned long long)page->index, page->flags, m, ino);
1700bd49f94SRyusuke Konishi 
1710bd49f94SRyusuke Konishi 	if (page_has_buffers(page)) {
1720bd49f94SRyusuke Konishi 		struct buffer_head *bh, *head;
1730bd49f94SRyusuke Konishi 		int i = 0;
1740bd49f94SRyusuke Konishi 
1750bd49f94SRyusuke Konishi 		bh = head = page_buffers(page);
1760bd49f94SRyusuke Konishi 		do {
1770bd49f94SRyusuke Konishi 			printk(KERN_CRIT
1780bd49f94SRyusuke Konishi 			       " BH[%d] %p: cnt=%d block#=%llu state=0x%lx\n",
1790bd49f94SRyusuke Konishi 			       i++, bh, atomic_read(&bh->b_count),
1800bd49f94SRyusuke Konishi 			       (unsigned long long)bh->b_blocknr, bh->b_state);
1810bd49f94SRyusuke Konishi 			bh = bh->b_this_page;
1820bd49f94SRyusuke Konishi 		} while (bh != head);
1830bd49f94SRyusuke Konishi 	}
1840bd49f94SRyusuke Konishi }
1850bd49f94SRyusuke Konishi 
1860bd49f94SRyusuke Konishi /**
1870bd49f94SRyusuke Konishi  * nilfs_copy_page -- copy the page with buffers
1880bd49f94SRyusuke Konishi  * @dst: destination page
1890bd49f94SRyusuke Konishi  * @src: source page
1900bd49f94SRyusuke Konishi  * @copy_dirty: flag whether to copy dirty states on the page's buffer heads.
1910bd49f94SRyusuke Konishi  *
1927a65004bSRyusuke Konishi  * This function is for both data pages and btnode pages.  The dirty flag
1930bd49f94SRyusuke Konishi  * should be treated by caller.  The page must not be under i/o.
1940bd49f94SRyusuke Konishi  * Both src and dst page must be locked
1950bd49f94SRyusuke Konishi  */
1960bd49f94SRyusuke Konishi static void nilfs_copy_page(struct page *dst, struct page *src, int copy_dirty)
1970bd49f94SRyusuke Konishi {
198e1ce8a97SColin Ian King 	struct buffer_head *dbh, *dbufs, *sbh;
1990bd49f94SRyusuke Konishi 	unsigned long mask = NILFS_BUFFER_INHERENT_BITS;
2000bd49f94SRyusuke Konishi 
2010bd49f94SRyusuke Konishi 	BUG_ON(PageWriteback(dst));
2020bd49f94SRyusuke Konishi 
203e1ce8a97SColin Ian King 	sbh = page_buffers(src);
2040bd49f94SRyusuke Konishi 	if (!page_has_buffers(dst))
2050bd49f94SRyusuke Konishi 		create_empty_buffers(dst, sbh->b_size, 0);
2060bd49f94SRyusuke Konishi 
2070bd49f94SRyusuke Konishi 	if (copy_dirty)
2084ce5c342SRyusuke Konishi 		mask |= BIT(BH_Dirty);
2090bd49f94SRyusuke Konishi 
2100bd49f94SRyusuke Konishi 	dbh = dbufs = page_buffers(dst);
2110bd49f94SRyusuke Konishi 	do {
2120bd49f94SRyusuke Konishi 		lock_buffer(sbh);
2130bd49f94SRyusuke Konishi 		lock_buffer(dbh);
2140bd49f94SRyusuke Konishi 		dbh->b_state = sbh->b_state & mask;
2150bd49f94SRyusuke Konishi 		dbh->b_blocknr = sbh->b_blocknr;
2160bd49f94SRyusuke Konishi 		dbh->b_bdev = sbh->b_bdev;
2170bd49f94SRyusuke Konishi 		sbh = sbh->b_this_page;
2180bd49f94SRyusuke Konishi 		dbh = dbh->b_this_page;
2190bd49f94SRyusuke Konishi 	} while (dbh != dbufs);
2200bd49f94SRyusuke Konishi 
2210bd49f94SRyusuke Konishi 	copy_highpage(dst, src);
2220bd49f94SRyusuke Konishi 
2230bd49f94SRyusuke Konishi 	if (PageUptodate(src) && !PageUptodate(dst))
2240bd49f94SRyusuke Konishi 		SetPageUptodate(dst);
2250bd49f94SRyusuke Konishi 	else if (!PageUptodate(src) && PageUptodate(dst))
2260bd49f94SRyusuke Konishi 		ClearPageUptodate(dst);
2270bd49f94SRyusuke Konishi 	if (PageMappedToDisk(src) && !PageMappedToDisk(dst))
2280bd49f94SRyusuke Konishi 		SetPageMappedToDisk(dst);
2290bd49f94SRyusuke Konishi 	else if (!PageMappedToDisk(src) && PageMappedToDisk(dst))
2300bd49f94SRyusuke Konishi 		ClearPageMappedToDisk(dst);
2310bd49f94SRyusuke Konishi 
2320bd49f94SRyusuke Konishi 	do {
2330bd49f94SRyusuke Konishi 		unlock_buffer(sbh);
2340bd49f94SRyusuke Konishi 		unlock_buffer(dbh);
2350bd49f94SRyusuke Konishi 		sbh = sbh->b_this_page;
2360bd49f94SRyusuke Konishi 		dbh = dbh->b_this_page;
2370bd49f94SRyusuke Konishi 	} while (dbh != dbufs);
2380bd49f94SRyusuke Konishi }
2390bd49f94SRyusuke Konishi 
2400bd49f94SRyusuke Konishi int nilfs_copy_dirty_pages(struct address_space *dmap,
2410bd49f94SRyusuke Konishi 			   struct address_space *smap)
2420bd49f94SRyusuke Konishi {
2430bd49f94SRyusuke Konishi 	struct pagevec pvec;
2440bd49f94SRyusuke Konishi 	unsigned int i;
2450bd49f94SRyusuke Konishi 	pgoff_t index = 0;
2460bd49f94SRyusuke Konishi 	int err = 0;
2470bd49f94SRyusuke Konishi 
24886679820SMel Gorman 	pagevec_init(&pvec);
2490bd49f94SRyusuke Konishi repeat:
25067fd707fSJan Kara 	if (!pagevec_lookup_tag(&pvec, smap, &index, PAGECACHE_TAG_DIRTY))
2510bd49f94SRyusuke Konishi 		return 0;
2520bd49f94SRyusuke Konishi 
2530bd49f94SRyusuke Konishi 	for (i = 0; i < pagevec_count(&pvec); i++) {
2540bd49f94SRyusuke Konishi 		struct page *page = pvec.pages[i], *dpage;
2550bd49f94SRyusuke Konishi 
2560bd49f94SRyusuke Konishi 		lock_page(page);
2570bd49f94SRyusuke Konishi 		if (unlikely(!PageDirty(page)))
2580bd49f94SRyusuke Konishi 			NILFS_PAGE_BUG(page, "inconsistent dirty state");
2590bd49f94SRyusuke Konishi 
2600bd49f94SRyusuke Konishi 		dpage = grab_cache_page(dmap, page->index);
2610bd49f94SRyusuke Konishi 		if (unlikely(!dpage)) {
2620bd49f94SRyusuke Konishi 			/* No empty page is added to the page cache */
2630bd49f94SRyusuke Konishi 			err = -ENOMEM;
2640bd49f94SRyusuke Konishi 			unlock_page(page);
2650bd49f94SRyusuke Konishi 			break;
2660bd49f94SRyusuke Konishi 		}
2670bd49f94SRyusuke Konishi 		if (unlikely(!page_has_buffers(page)))
2680bd49f94SRyusuke Konishi 			NILFS_PAGE_BUG(page,
2690bd49f94SRyusuke Konishi 				       "found empty page in dat page cache");
2700bd49f94SRyusuke Konishi 
2710bd49f94SRyusuke Konishi 		nilfs_copy_page(dpage, page, 1);
2720bd49f94SRyusuke Konishi 		__set_page_dirty_nobuffers(dpage);
2730bd49f94SRyusuke Konishi 
2740bd49f94SRyusuke Konishi 		unlock_page(dpage);
27509cbfeafSKirill A. Shutemov 		put_page(dpage);
2760bd49f94SRyusuke Konishi 		unlock_page(page);
2770bd49f94SRyusuke Konishi 	}
2780bd49f94SRyusuke Konishi 	pagevec_release(&pvec);
2790bd49f94SRyusuke Konishi 	cond_resched();
2800bd49f94SRyusuke Konishi 
2810bd49f94SRyusuke Konishi 	if (likely(!err))
2820bd49f94SRyusuke Konishi 		goto repeat;
2830bd49f94SRyusuke Konishi 	return err;
2840bd49f94SRyusuke Konishi }
2850bd49f94SRyusuke Konishi 
2860bd49f94SRyusuke Konishi /**
2877a65004bSRyusuke Konishi  * nilfs_copy_back_pages -- copy back pages to original cache from shadow cache
2880bd49f94SRyusuke Konishi  * @dmap: destination page cache
2890bd49f94SRyusuke Konishi  * @smap: source page cache
2900bd49f94SRyusuke Konishi  *
291f611ff63SMatthew Wilcox  * No pages must be added to the cache during this process.
2920bd49f94SRyusuke Konishi  * This must be ensured by the caller.
2930bd49f94SRyusuke Konishi  */
2940bd49f94SRyusuke Konishi void nilfs_copy_back_pages(struct address_space *dmap,
2950bd49f94SRyusuke Konishi 			   struct address_space *smap)
2960bd49f94SRyusuke Konishi {
297f6e0e173SMatthew Wilcox (Oracle) 	struct folio_batch fbatch;
2980bd49f94SRyusuke Konishi 	unsigned int i, n;
299f6e0e173SMatthew Wilcox (Oracle) 	pgoff_t start = 0;
3000bd49f94SRyusuke Konishi 
301f6e0e173SMatthew Wilcox (Oracle) 	folio_batch_init(&fbatch);
3020bd49f94SRyusuke Konishi repeat:
303f6e0e173SMatthew Wilcox (Oracle) 	n = filemap_get_folios(smap, &start, ~0UL, &fbatch);
3040bd49f94SRyusuke Konishi 	if (!n)
3050bd49f94SRyusuke Konishi 		return;
3060bd49f94SRyusuke Konishi 
307f6e0e173SMatthew Wilcox (Oracle) 	for (i = 0; i < folio_batch_count(&fbatch); i++) {
308f6e0e173SMatthew Wilcox (Oracle) 		struct folio *folio = fbatch.folios[i], *dfolio;
309f6e0e173SMatthew Wilcox (Oracle) 		pgoff_t index = folio->index;
3100bd49f94SRyusuke Konishi 
311f6e0e173SMatthew Wilcox (Oracle) 		folio_lock(folio);
312f6e0e173SMatthew Wilcox (Oracle) 		dfolio = filemap_lock_folio(dmap, index);
313f6e0e173SMatthew Wilcox (Oracle) 		if (dfolio) {
314f6e0e173SMatthew Wilcox (Oracle) 			/* overwrite existing folio in the destination cache */
315f6e0e173SMatthew Wilcox (Oracle) 			WARN_ON(folio_test_dirty(dfolio));
316f6e0e173SMatthew Wilcox (Oracle) 			nilfs_copy_page(&dfolio->page, &folio->page, 0);
317f6e0e173SMatthew Wilcox (Oracle) 			folio_unlock(dfolio);
318f6e0e173SMatthew Wilcox (Oracle) 			folio_put(dfolio);
319f6e0e173SMatthew Wilcox (Oracle) 			/* Do we not need to remove folio from smap here? */
3200bd49f94SRyusuke Konishi 		} else {
321f6e0e173SMatthew Wilcox (Oracle) 			struct folio *f;
3220bd49f94SRyusuke Konishi 
323f6e0e173SMatthew Wilcox (Oracle) 			/* move the folio to the destination cache */
324b93b0163SMatthew Wilcox 			xa_lock_irq(&smap->i_pages);
325f6e0e173SMatthew Wilcox (Oracle) 			f = __xa_erase(&smap->i_pages, index);
326f6e0e173SMatthew Wilcox (Oracle) 			WARN_ON(folio != f);
3270bd49f94SRyusuke Konishi 			smap->nrpages--;
328b93b0163SMatthew Wilcox 			xa_unlock_irq(&smap->i_pages);
3290bd49f94SRyusuke Konishi 
330b93b0163SMatthew Wilcox 			xa_lock_irq(&dmap->i_pages);
331f6e0e173SMatthew Wilcox (Oracle) 			f = __xa_store(&dmap->i_pages, index, folio, GFP_NOFS);
332f6e0e173SMatthew Wilcox (Oracle) 			if (unlikely(f)) {
333f611ff63SMatthew Wilcox 				/* Probably -ENOMEM */
334f6e0e173SMatthew Wilcox (Oracle) 				folio->mapping = NULL;
335f6e0e173SMatthew Wilcox (Oracle) 				folio_put(folio);
3360bd49f94SRyusuke Konishi 			} else {
337f6e0e173SMatthew Wilcox (Oracle) 				folio->mapping = dmap;
3380bd49f94SRyusuke Konishi 				dmap->nrpages++;
339f6e0e173SMatthew Wilcox (Oracle) 				if (folio_test_dirty(folio))
340f6e0e173SMatthew Wilcox (Oracle) 					__xa_set_mark(&dmap->i_pages, index,
3410bd49f94SRyusuke Konishi 							PAGECACHE_TAG_DIRTY);
3420bd49f94SRyusuke Konishi 			}
343b93b0163SMatthew Wilcox 			xa_unlock_irq(&dmap->i_pages);
3440bd49f94SRyusuke Konishi 		}
345f6e0e173SMatthew Wilcox (Oracle) 		folio_unlock(folio);
3460bd49f94SRyusuke Konishi 	}
347f6e0e173SMatthew Wilcox (Oracle) 	folio_batch_release(&fbatch);
3480bd49f94SRyusuke Konishi 	cond_resched();
3490bd49f94SRyusuke Konishi 
3500bd49f94SRyusuke Konishi 	goto repeat;
3510bd49f94SRyusuke Konishi }
3520bd49f94SRyusuke Konishi 
3538c26c4e2SVyacheslav Dubeyko /**
3548c26c4e2SVyacheslav Dubeyko  * nilfs_clear_dirty_pages - discard dirty pages in address space
3558c26c4e2SVyacheslav Dubeyko  * @mapping: address space with dirty pages for discarding
3568c26c4e2SVyacheslav Dubeyko  * @silent: suppress [true] or print [false] warning messages
3578c26c4e2SVyacheslav Dubeyko  */
3588c26c4e2SVyacheslav Dubeyko void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
3590bd49f94SRyusuke Konishi {
3600bd49f94SRyusuke Konishi 	struct pagevec pvec;
3610bd49f94SRyusuke Konishi 	unsigned int i;
3620bd49f94SRyusuke Konishi 	pgoff_t index = 0;
3630bd49f94SRyusuke Konishi 
36486679820SMel Gorman 	pagevec_init(&pvec);
3650bd49f94SRyusuke Konishi 
36667fd707fSJan Kara 	while (pagevec_lookup_tag(&pvec, mapping, &index,
36767fd707fSJan Kara 					PAGECACHE_TAG_DIRTY)) {
3680bd49f94SRyusuke Konishi 		for (i = 0; i < pagevec_count(&pvec); i++) {
3690bd49f94SRyusuke Konishi 			struct page *page = pvec.pages[i];
3700bd49f94SRyusuke Konishi 
3710bd49f94SRyusuke Konishi 			lock_page(page);
3728c26c4e2SVyacheslav Dubeyko 			nilfs_clear_dirty_page(page, silent);
3738c26c4e2SVyacheslav Dubeyko 			unlock_page(page);
3748c26c4e2SVyacheslav Dubeyko 		}
3758c26c4e2SVyacheslav Dubeyko 		pagevec_release(&pvec);
3768c26c4e2SVyacheslav Dubeyko 		cond_resched();
3778c26c4e2SVyacheslav Dubeyko 	}
3788c26c4e2SVyacheslav Dubeyko }
3798c26c4e2SVyacheslav Dubeyko 
3808c26c4e2SVyacheslav Dubeyko /**
3818c26c4e2SVyacheslav Dubeyko  * nilfs_clear_dirty_page - discard dirty page
3828c26c4e2SVyacheslav Dubeyko  * @page: dirty page that will be discarded
3838c26c4e2SVyacheslav Dubeyko  * @silent: suppress [true] or print [false] warning messages
3848c26c4e2SVyacheslav Dubeyko  */
3858c26c4e2SVyacheslav Dubeyko void nilfs_clear_dirty_page(struct page *page, bool silent)
3868c26c4e2SVyacheslav Dubeyko {
3878c26c4e2SVyacheslav Dubeyko 	struct inode *inode = page->mapping->host;
3888c26c4e2SVyacheslav Dubeyko 	struct super_block *sb = inode->i_sb;
3898c26c4e2SVyacheslav Dubeyko 
390dc33f5f3SVyacheslav Dubeyko 	BUG_ON(!PageLocked(page));
3918c26c4e2SVyacheslav Dubeyko 
392d6517debSRyusuke Konishi 	if (!silent)
393a1d0747aSJoe Perches 		nilfs_warn(sb, "discard dirty page: offset=%lld, ino=%lu",
3948c26c4e2SVyacheslav Dubeyko 			   page_offset(page), inode->i_ino);
3958c26c4e2SVyacheslav Dubeyko 
3960bd49f94SRyusuke Konishi 	ClearPageUptodate(page);
3970bd49f94SRyusuke Konishi 	ClearPageMappedToDisk(page);
3988c26c4e2SVyacheslav Dubeyko 
3998c26c4e2SVyacheslav Dubeyko 	if (page_has_buffers(page)) {
4008c26c4e2SVyacheslav Dubeyko 		struct buffer_head *bh, *head;
401ead8ecffSRyusuke Konishi 		const unsigned long clear_bits =
4024ce5c342SRyusuke Konishi 			(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
4034ce5c342SRyusuke Konishi 			 BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
4044ce5c342SRyusuke Konishi 			 BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected));
4058c26c4e2SVyacheslav Dubeyko 
4060bd49f94SRyusuke Konishi 		bh = head = page_buffers(page);
4070bd49f94SRyusuke Konishi 		do {
4080bd49f94SRyusuke Konishi 			lock_buffer(bh);
409d6517debSRyusuke Konishi 			if (!silent)
410a1d0747aSJoe Perches 				nilfs_warn(sb,
411d6517debSRyusuke Konishi 					   "discard dirty block: blocknr=%llu, size=%zu",
4128c26c4e2SVyacheslav Dubeyko 					   (u64)bh->b_blocknr, bh->b_size);
413d6517debSRyusuke Konishi 
414ead8ecffSRyusuke Konishi 			set_mask_bits(&bh->b_state, clear_bits, 0);
4150bd49f94SRyusuke Konishi 			unlock_buffer(bh);
4168c26c4e2SVyacheslav Dubeyko 		} while (bh = bh->b_this_page, bh != head);
4178c26c4e2SVyacheslav Dubeyko 	}
4180bd49f94SRyusuke Konishi 
4190bd49f94SRyusuke Konishi 	__nilfs_clear_page_dirty(page);
4200bd49f94SRyusuke Konishi }
4210bd49f94SRyusuke Konishi 
4220c6c44cbSRyusuke Konishi unsigned int nilfs_page_count_clean_buffers(struct page *page,
4230c6c44cbSRyusuke Konishi 					    unsigned int from, unsigned int to)
4240bd49f94SRyusuke Konishi {
4250c6c44cbSRyusuke Konishi 	unsigned int block_start, block_end;
4260bd49f94SRyusuke Konishi 	struct buffer_head *bh, *head;
4270c6c44cbSRyusuke Konishi 	unsigned int nc = 0;
4280bd49f94SRyusuke Konishi 
4290bd49f94SRyusuke Konishi 	for (bh = head = page_buffers(page), block_start = 0;
4300bd49f94SRyusuke Konishi 	     bh != head || !block_start;
4310bd49f94SRyusuke Konishi 	     block_start = block_end, bh = bh->b_this_page) {
4320bd49f94SRyusuke Konishi 		block_end = block_start + bh->b_size;
4330bd49f94SRyusuke Konishi 		if (block_end > from && block_start < to && !buffer_dirty(bh))
4340bd49f94SRyusuke Konishi 			nc++;
4350bd49f94SRyusuke Konishi 	}
4360bd49f94SRyusuke Konishi 	return nc;
4370bd49f94SRyusuke Konishi }
438ebdfed4dSRyusuke Konishi 
4390bd49f94SRyusuke Konishi /*
4400bd49f94SRyusuke Konishi  * NILFS2 needs clear_page_dirty() in the following two cases:
4410bd49f94SRyusuke Konishi  *
442e897be17SRyusuke Konishi  * 1) For B-tree node pages and data pages of DAT file, NILFS2 clears dirty
443e897be17SRyusuke Konishi  *    flag of pages when it copies back pages from shadow cache to the
444e897be17SRyusuke Konishi  *    original cache.
4450bd49f94SRyusuke Konishi  *
4460bd49f94SRyusuke Konishi  * 2) Some B-tree operations like insertion or deletion may dispose buffers
4470bd49f94SRyusuke Konishi  *    in dirty state, and this needs to cancel the dirty state of their pages.
4480bd49f94SRyusuke Konishi  */
4490bd49f94SRyusuke Konishi int __nilfs_clear_page_dirty(struct page *page)
4500bd49f94SRyusuke Konishi {
4510bd49f94SRyusuke Konishi 	struct address_space *mapping = page->mapping;
4520bd49f94SRyusuke Konishi 
4530bd49f94SRyusuke Konishi 	if (mapping) {
454b93b0163SMatthew Wilcox 		xa_lock_irq(&mapping->i_pages);
4550bd49f94SRyusuke Konishi 		if (test_bit(PG_dirty, &page->flags)) {
456f611ff63SMatthew Wilcox 			__xa_clear_mark(&mapping->i_pages, page_index(page),
4570bd49f94SRyusuke Konishi 					     PAGECACHE_TAG_DIRTY);
458b93b0163SMatthew Wilcox 			xa_unlock_irq(&mapping->i_pages);
4590bd49f94SRyusuke Konishi 			return clear_page_dirty_for_io(page);
4600bd49f94SRyusuke Konishi 		}
461b93b0163SMatthew Wilcox 		xa_unlock_irq(&mapping->i_pages);
4620bd49f94SRyusuke Konishi 		return 0;
4630bd49f94SRyusuke Konishi 	}
4640bd49f94SRyusuke Konishi 	return TestClearPageDirty(page);
4650bd49f94SRyusuke Konishi }
466622daaffSRyusuke Konishi 
467622daaffSRyusuke Konishi /**
468622daaffSRyusuke Konishi  * nilfs_find_uncommitted_extent - find extent of uncommitted data
469622daaffSRyusuke Konishi  * @inode: inode
470622daaffSRyusuke Konishi  * @start_blk: start block offset (in)
471622daaffSRyusuke Konishi  * @blkoff: start offset of the found extent (out)
472622daaffSRyusuke Konishi  *
473622daaffSRyusuke Konishi  * This function searches an extent of buffers marked "delayed" which
474622daaffSRyusuke Konishi  * starts from a block offset equal to or larger than @start_blk.  If
475622daaffSRyusuke Konishi  * such an extent was found, this will store the start offset in
476622daaffSRyusuke Konishi  * @blkoff and return its length in blocks.  Otherwise, zero is
477622daaffSRyusuke Konishi  * returned.
478622daaffSRyusuke Konishi  */
479622daaffSRyusuke Konishi unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
480622daaffSRyusuke Konishi 					    sector_t start_blk,
481622daaffSRyusuke Konishi 					    sector_t *blkoff)
482622daaffSRyusuke Konishi {
483*24a1efb4SVishal Moola (Oracle) 	unsigned int i, nr_folios;
484622daaffSRyusuke Konishi 	pgoff_t index;
485622daaffSRyusuke Konishi 	unsigned long length = 0;
486*24a1efb4SVishal Moola (Oracle) 	struct folio_batch fbatch;
487*24a1efb4SVishal Moola (Oracle) 	struct folio *folio;
488622daaffSRyusuke Konishi 
489622daaffSRyusuke Konishi 	if (inode->i_mapping->nrpages == 0)
490622daaffSRyusuke Konishi 		return 0;
491622daaffSRyusuke Konishi 
49209cbfeafSKirill A. Shutemov 	index = start_blk >> (PAGE_SHIFT - inode->i_blkbits);
493622daaffSRyusuke Konishi 
494*24a1efb4SVishal Moola (Oracle) 	folio_batch_init(&fbatch);
495622daaffSRyusuke Konishi 
496622daaffSRyusuke Konishi repeat:
497*24a1efb4SVishal Moola (Oracle) 	nr_folios = filemap_get_folios_contig(inode->i_mapping, &index, ULONG_MAX,
498*24a1efb4SVishal Moola (Oracle) 			&fbatch);
499*24a1efb4SVishal Moola (Oracle) 	if (nr_folios == 0)
500622daaffSRyusuke Konishi 		return length;
501622daaffSRyusuke Konishi 
502622daaffSRyusuke Konishi 	i = 0;
503622daaffSRyusuke Konishi 	do {
504*24a1efb4SVishal Moola (Oracle) 		folio = fbatch.folios[i];
505622daaffSRyusuke Konishi 
506*24a1efb4SVishal Moola (Oracle) 		folio_lock(folio);
507*24a1efb4SVishal Moola (Oracle) 		if (folio_buffers(folio)) {
508622daaffSRyusuke Konishi 			struct buffer_head *bh, *head;
509*24a1efb4SVishal Moola (Oracle) 			sector_t b;
510622daaffSRyusuke Konishi 
511*24a1efb4SVishal Moola (Oracle) 			b = folio->index << (PAGE_SHIFT - inode->i_blkbits);
512*24a1efb4SVishal Moola (Oracle) 			bh = head = folio_buffers(folio);
513622daaffSRyusuke Konishi 			do {
514622daaffSRyusuke Konishi 				if (b < start_blk)
515622daaffSRyusuke Konishi 					continue;
516622daaffSRyusuke Konishi 				if (buffer_delay(bh)) {
517622daaffSRyusuke Konishi 					if (length == 0)
518622daaffSRyusuke Konishi 						*blkoff = b;
519622daaffSRyusuke Konishi 					length++;
520622daaffSRyusuke Konishi 				} else if (length > 0) {
521622daaffSRyusuke Konishi 					goto out_locked;
522622daaffSRyusuke Konishi 				}
523622daaffSRyusuke Konishi 			} while (++b, bh = bh->b_this_page, bh != head);
524622daaffSRyusuke Konishi 		} else {
525622daaffSRyusuke Konishi 			if (length > 0)
526622daaffSRyusuke Konishi 				goto out_locked;
527622daaffSRyusuke Konishi 		}
528*24a1efb4SVishal Moola (Oracle) 		folio_unlock(folio);
529622daaffSRyusuke Konishi 
530*24a1efb4SVishal Moola (Oracle) 	} while (++i < nr_folios);
531622daaffSRyusuke Konishi 
532*24a1efb4SVishal Moola (Oracle) 	folio_batch_release(&fbatch);
533622daaffSRyusuke Konishi 	cond_resched();
534622daaffSRyusuke Konishi 	goto repeat;
535622daaffSRyusuke Konishi 
536622daaffSRyusuke Konishi out_locked:
537*24a1efb4SVishal Moola (Oracle) 	folio_unlock(folio);
538*24a1efb4SVishal Moola (Oracle) 	folio_batch_release(&fbatch);
539622daaffSRyusuke Konishi 	return length;
540622daaffSRyusuke Konishi }
541