diff options
Diffstat (limited to 'fs/nilfs2')
| -rw-r--r-- | fs/nilfs2/inode.c | 17 | ||||
| -rw-r--r-- | fs/nilfs2/mdt.c | 19 | ||||
| -rw-r--r-- | fs/nilfs2/page.c | 70 | ||||
| -rw-r--r-- | fs/nilfs2/page.h | 3 |
4 files changed, 86 insertions, 23 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 6b49f14eac8c..ba7a1da7634b 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
| @@ -175,6 +175,11 @@ static int nilfs_writepages(struct address_space *mapping, | |||
| 175 | struct inode *inode = mapping->host; | 175 | struct inode *inode = mapping->host; |
| 176 | int err = 0; | 176 | int err = 0; |
| 177 | 177 | ||
| 178 | if (inode->i_sb->s_flags & MS_RDONLY) { | ||
| 179 | nilfs_clear_dirty_pages(mapping, false); | ||
| 180 | return -EROFS; | ||
| 181 | } | ||
| 182 | |||
| 178 | if (wbc->sync_mode == WB_SYNC_ALL) | 183 | if (wbc->sync_mode == WB_SYNC_ALL) |
| 179 | err = nilfs_construct_dsync_segment(inode->i_sb, inode, | 184 | err = nilfs_construct_dsync_segment(inode->i_sb, inode, |
| 180 | wbc->range_start, | 185 | wbc->range_start, |
| @@ -187,6 +192,18 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc) | |||
| 187 | struct inode *inode = page->mapping->host; | 192 | struct inode *inode = page->mapping->host; |
| 188 | int err; | 193 | int err; |
| 189 | 194 | ||
| 195 | if (inode && (inode->i_sb->s_flags & MS_RDONLY)) { | ||
| 196 | /* | ||
| 197 | * It means that filesystem was remounted in read-only | ||
| 198 | * mode because of error or metadata corruption. But we | ||
| 199 | * have dirty pages that try to be flushed in background. | ||
| 200 | * So, here we simply discard this dirty page. | ||
| 201 | */ | ||
| 202 | nilfs_clear_dirty_page(page, false); | ||
| 203 | unlock_page(page); | ||
| 204 | return -EROFS; | ||
| 205 | } | ||
| 206 | |||
| 190 | redirty_page_for_writepage(wbc, page); | 207 | redirty_page_for_writepage(wbc, page); |
| 191 | unlock_page(page); | 208 | unlock_page(page); |
| 192 | 209 | ||
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index f9897d09c693..c4dcd1db57ee 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
| @@ -375,14 +375,25 @@ int nilfs_mdt_fetch_dirty(struct inode *inode) | |||
| 375 | static int | 375 | static int |
| 376 | nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | 376 | nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) |
| 377 | { | 377 | { |
| 378 | struct inode *inode; | 378 | struct inode *inode = page->mapping->host; |
| 379 | struct super_block *sb; | 379 | struct super_block *sb; |
| 380 | int err = 0; | 380 | int err = 0; |
| 381 | 381 | ||
| 382 | if (inode && (inode->i_sb->s_flags & MS_RDONLY)) { | ||
| 383 | /* | ||
| 384 | * It means that filesystem was remounted in read-only | ||
| 385 | * mode because of error or metadata corruption. But we | ||
| 386 | * have dirty pages that try to be flushed in background. | ||
| 387 | * So, here we simply discard this dirty page. | ||
| 388 | */ | ||
| 389 | nilfs_clear_dirty_page(page, false); | ||
| 390 | unlock_page(page); | ||
| 391 | return -EROFS; | ||
| 392 | } | ||
| 393 | |||
| 382 | redirty_page_for_writepage(wbc, page); | 394 | redirty_page_for_writepage(wbc, page); |
| 383 | unlock_page(page); | 395 | unlock_page(page); |
| 384 | 396 | ||
| 385 | inode = page->mapping->host; | ||
| 386 | if (!inode) | 397 | if (!inode) |
| 387 | return 0; | 398 | return 0; |
| 388 | 399 | ||
| @@ -561,10 +572,10 @@ void nilfs_mdt_restore_from_shadow_map(struct inode *inode) | |||
| 561 | if (mi->mi_palloc_cache) | 572 | if (mi->mi_palloc_cache) |
| 562 | nilfs_palloc_clear_cache(inode); | 573 | nilfs_palloc_clear_cache(inode); |
| 563 | 574 | ||
| 564 | nilfs_clear_dirty_pages(inode->i_mapping); | 575 | nilfs_clear_dirty_pages(inode->i_mapping, true); |
| 565 | nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data); | 576 | nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data); |
| 566 | 577 | ||
| 567 | nilfs_clear_dirty_pages(&ii->i_btnode_cache); | 578 | nilfs_clear_dirty_pages(&ii->i_btnode_cache, true); |
| 568 | nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes); | 579 | nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes); |
| 569 | 580 | ||
| 570 | nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store); | 581 | nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store); |
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 07f76db04ec7..131a5841a070 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c | |||
| @@ -370,7 +370,12 @@ repeat: | |||
| 370 | goto repeat; | 370 | goto repeat; |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | void nilfs_clear_dirty_pages(struct address_space *mapping) | 373 | /** |
| 374 | * nilfs_clear_dirty_pages - discard dirty pages in address space | ||
| 375 | * @mapping: address space with dirty pages for discarding | ||
| 376 | * @silent: suppress [true] or print [false] warning messages | ||
| 377 | */ | ||
| 378 | void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent) | ||
| 374 | { | 379 | { |
| 375 | struct pagevec pvec; | 380 | struct pagevec pvec; |
| 376 | unsigned int i; | 381 | unsigned int i; |
| @@ -382,25 +387,9 @@ void nilfs_clear_dirty_pages(struct address_space *mapping) | |||
| 382 | PAGEVEC_SIZE)) { | 387 | PAGEVEC_SIZE)) { |
| 383 | for (i = 0; i < pagevec_count(&pvec); i++) { | 388 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 384 | struct page *page = pvec.pages[i]; | 389 | struct page *page = pvec.pages[i]; |
| 385 | struct buffer_head *bh, *head; | ||
| 386 | 390 | ||
| 387 | lock_page(page); | 391 | lock_page(page); |
| 388 | ClearPageUptodate(page); | 392 | nilfs_clear_dirty_page(page, silent); |
| 389 | ClearPageMappedToDisk(page); | ||
| 390 | bh = head = page_buffers(page); | ||
| 391 | do { | ||
| 392 | lock_buffer(bh); | ||
| 393 | clear_buffer_dirty(bh); | ||
| 394 | clear_buffer_nilfs_volatile(bh); | ||
| 395 | clear_buffer_nilfs_checked(bh); | ||
| 396 | clear_buffer_nilfs_redirected(bh); | ||
| 397 | clear_buffer_uptodate(bh); | ||
| 398 | clear_buffer_mapped(bh); | ||
| 399 | unlock_buffer(bh); | ||
| 400 | bh = bh->b_this_page; | ||
| 401 | } while (bh != head); | ||
| 402 | |||
| 403 | __nilfs_clear_page_dirty(page); | ||
| 404 | unlock_page(page); | 393 | unlock_page(page); |
| 405 | } | 394 | } |
| 406 | pagevec_release(&pvec); | 395 | pagevec_release(&pvec); |
| @@ -408,6 +397,51 @@ void nilfs_clear_dirty_pages(struct address_space *mapping) | |||
| 408 | } | 397 | } |
| 409 | } | 398 | } |
| 410 | 399 | ||
| 400 | /** | ||
| 401 | * nilfs_clear_dirty_page - discard dirty page | ||
| 402 | * @page: dirty page that will be discarded | ||
| 403 | * @silent: suppress [true] or print [false] warning messages | ||
| 404 | */ | ||
| 405 | void nilfs_clear_dirty_page(struct page *page, bool silent) | ||
| 406 | { | ||
| 407 | struct inode *inode = page->mapping->host; | ||
| 408 | struct super_block *sb = inode->i_sb; | ||
| 409 | |||
| 410 | BUG_ON(!test_bit(PG_locked, &page->flags)); | ||
| 411 | |||
| 412 | if (!silent) { | ||
| 413 | nilfs_warning(sb, __func__, | ||
| 414 | "discard page: offset %lld, ino %lu", | ||
| 415 | page_offset(page), inode->i_ino); | ||
| 416 | } | ||
| 417 | |||
| 418 | ClearPageUptodate(page); | ||
| 419 | ClearPageMappedToDisk(page); | ||
| 420 | |||
| 421 | if (page_has_buffers(page)) { | ||
| 422 | struct buffer_head *bh, *head; | ||
| 423 | |||
| 424 | bh = head = page_buffers(page); | ||
| 425 | do { | ||
| 426 | lock_buffer(bh); | ||
| 427 | if (!silent) { | ||
| 428 | nilfs_warning(sb, __func__, | ||
| 429 | "discard block %llu, size %zu", | ||
| 430 | (u64)bh->b_blocknr, bh->b_size); | ||
| 431 | } | ||
| 432 | clear_buffer_dirty(bh); | ||
| 433 | clear_buffer_nilfs_volatile(bh); | ||
| 434 | clear_buffer_nilfs_checked(bh); | ||
| 435 | clear_buffer_nilfs_redirected(bh); | ||
| 436 | clear_buffer_uptodate(bh); | ||
| 437 | clear_buffer_mapped(bh); | ||
| 438 | unlock_buffer(bh); | ||
| 439 | } while (bh = bh->b_this_page, bh != head); | ||
| 440 | } | ||
| 441 | |||
| 442 | __nilfs_clear_page_dirty(page); | ||
| 443 | } | ||
| 444 | |||
| 411 | unsigned nilfs_page_count_clean_buffers(struct page *page, | 445 | unsigned nilfs_page_count_clean_buffers(struct page *page, |
| 412 | unsigned from, unsigned to) | 446 | unsigned from, unsigned to) |
| 413 | { | 447 | { |
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h index fb7de71605a0..ef30c5c2426f 100644 --- a/fs/nilfs2/page.h +++ b/fs/nilfs2/page.h | |||
| @@ -55,7 +55,8 @@ void nilfs_page_bug(struct page *); | |||
| 55 | 55 | ||
| 56 | int nilfs_copy_dirty_pages(struct address_space *, struct address_space *); | 56 | int nilfs_copy_dirty_pages(struct address_space *, struct address_space *); |
| 57 | void nilfs_copy_back_pages(struct address_space *, struct address_space *); | 57 | void nilfs_copy_back_pages(struct address_space *, struct address_space *); |
| 58 | void nilfs_clear_dirty_pages(struct address_space *); | 58 | void nilfs_clear_dirty_page(struct page *, bool); |
| 59 | void nilfs_clear_dirty_pages(struct address_space *, bool); | ||
| 59 | void nilfs_mapping_init(struct address_space *mapping, struct inode *inode, | 60 | void nilfs_mapping_init(struct address_space *mapping, struct inode *inode, |
| 60 | struct backing_dev_info *bdi); | 61 | struct backing_dev_info *bdi); |
| 61 | unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned); | 62 | unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned); |
