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) }