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