Skip to content

Commit 6e21193

Browse files
konistorvalds
authored andcommitted
nilfs2: fix lockdep warnings during disk space reclamation
During disk space reclamation, nilfs2 still emits the following lockdep warning due to page/folio operations on shadowed page caches that nilfs2 uses to get a snapshot of DAT file in memory: WARNING: CPU: 0 PID: 2643 at include/linux/backing-dev.h:272 __folio_mark_dirty+0x645/0x670 ... RIP: 0010:__folio_mark_dirty+0x645/0x670 ... Call Trace: filemap_dirty_folio+0x74/0xd0 __set_page_dirty_nobuffers+0x85/0xb0 nilfs_copy_dirty_pages+0x288/0x510 [nilfs2] nilfs_mdt_save_to_shadow_map+0x50/0xe0 [nilfs2] nilfs_clean_segments+0xee/0x5d0 [nilfs2] nilfs_ioctl_clean_segments.isra.19+0xb08/0xf40 [nilfs2] nilfs_ioctl+0xc52/0xfb0 [nilfs2] __x64_sys_ioctl+0x11d/0x170 This fixes the remaining warning by using inode objects to hold those page caches. Link: https://lkml.kernel.org/r/1647867427-30498-3-git-send-email-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com> Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: David Hildenbrand <david@redhat.com> Cc: Hao Sun <sunhao.th@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent e897be1 commit 6e21193

5 files changed

Lines changed: 92 additions & 21 deletions

File tree

fs/nilfs2/dat.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,9 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size,
497497
di = NILFS_DAT_I(dat);
498498
lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
499499
nilfs_palloc_setup_cache(dat, &di->palloc_cache);
500-
nilfs_mdt_setup_shadow_map(dat, &di->shadow);
500+
err = nilfs_mdt_setup_shadow_map(dat, &di->shadow);
501+
if (err)
502+
goto failed;
501503

502504
err = nilfs_read_inode_common(dat, raw_inode);
503505
if (err)

fs/nilfs2/inode.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
* @root: pointer on NILFS root object (mounted checkpoint)
3131
* @for_gc: inode for GC flag
3232
* @for_btnc: inode for B-tree node cache flag
33+
* @for_shadow: inode for shadowed page cache flag
3334
*/
3435
struct nilfs_iget_args {
3536
u64 ino;
3637
__u64 cno;
3738
struct nilfs_root *root;
3839
bool for_gc;
3940
bool for_btnc;
41+
bool for_shadow;
4042
};
4143

4244
static int nilfs_iget_test(struct inode *inode, void *opaque);
@@ -315,7 +317,7 @@ static int nilfs_insert_inode_locked(struct inode *inode,
315317
{
316318
struct nilfs_iget_args args = {
317319
.ino = ino, .root = root, .cno = 0, .for_gc = false,
318-
.for_btnc = false
320+
.for_btnc = false, .for_shadow = false
319321
};
320322

321323
return insert_inode_locked4(inode, ino, nilfs_iget_test, &args);
@@ -534,6 +536,12 @@ static int nilfs_iget_test(struct inode *inode, void *opaque)
534536
} else if (args->for_btnc) {
535537
return 0;
536538
}
539+
if (test_bit(NILFS_I_SHADOW, &ii->i_state)) {
540+
if (!args->for_shadow)
541+
return 0;
542+
} else if (args->for_shadow) {
543+
return 0;
544+
}
537545

538546
if (!test_bit(NILFS_I_GCINODE, &ii->i_state))
539547
return !args->for_gc;
@@ -555,6 +563,8 @@ static int nilfs_iget_set(struct inode *inode, void *opaque)
555563
NILFS_I(inode)->i_state = BIT(NILFS_I_GCINODE);
556564
if (args->for_btnc)
557565
NILFS_I(inode)->i_state |= BIT(NILFS_I_BTNC);
566+
if (args->for_shadow)
567+
NILFS_I(inode)->i_state |= BIT(NILFS_I_SHADOW);
558568
return 0;
559569
}
560570

@@ -563,7 +573,7 @@ struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root,
563573
{
564574
struct nilfs_iget_args args = {
565575
.ino = ino, .root = root, .cno = 0, .for_gc = false,
566-
.for_btnc = false
576+
.for_btnc = false, .for_shadow = false
567577
};
568578

569579
return ilookup5(sb, ino, nilfs_iget_test, &args);
@@ -574,7 +584,7 @@ struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
574584
{
575585
struct nilfs_iget_args args = {
576586
.ino = ino, .root = root, .cno = 0, .for_gc = false,
577-
.for_btnc = false
587+
.for_btnc = false, .for_shadow = false
578588
};
579589

580590
return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
@@ -606,7 +616,7 @@ struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino,
606616
{
607617
struct nilfs_iget_args args = {
608618
.ino = ino, .root = NULL, .cno = cno, .for_gc = true,
609-
.for_btnc = false
619+
.for_btnc = false, .for_shadow = false
610620
};
611621
struct inode *inode;
612622
int err;
@@ -653,6 +663,7 @@ int nilfs_attach_btree_node_cache(struct inode *inode)
653663
args.cno = ii->i_cno;
654664
args.for_gc = test_bit(NILFS_I_GCINODE, &ii->i_state) != 0;
655665
args.for_btnc = true;
666+
args.for_shadow = test_bit(NILFS_I_SHADOW, &ii->i_state) != 0;
656667

657668
btnc_inode = iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test,
658669
nilfs_iget_set, &args);
@@ -688,6 +699,50 @@ void nilfs_detach_btree_node_cache(struct inode *inode)
688699
}
689700
}
690701

702+
/**
703+
* nilfs_iget_for_shadow - obtain inode for shadow mapping
704+
* @inode: inode object that uses shadow mapping
705+
*
706+
* nilfs_iget_for_shadow() allocates a pair of inodes that holds page
707+
* caches for shadow mapping. The page cache for data pages is set up
708+
* in one inode and the one for b-tree node pages is set up in the
709+
* other inode, which is attached to the former inode.
710+
*
711+
* Return Value: On success, a pointer to the inode for data pages is
712+
* returned. On errors, one of the following negative error code is returned
713+
* in a pointer type.
714+
*
715+
* %-ENOMEM - Insufficient memory available.
716+
*/
717+
struct inode *nilfs_iget_for_shadow(struct inode *inode)
718+
{
719+
struct nilfs_iget_args args = {
720+
.ino = inode->i_ino, .root = NULL, .cno = 0, .for_gc = false,
721+
.for_btnc = false, .for_shadow = true
722+
};
723+
struct inode *s_inode;
724+
int err;
725+
726+
s_inode = iget5_locked(inode->i_sb, inode->i_ino, nilfs_iget_test,
727+
nilfs_iget_set, &args);
728+
if (unlikely(!s_inode))
729+
return ERR_PTR(-ENOMEM);
730+
if (!(s_inode->i_state & I_NEW))
731+
return inode;
732+
733+
NILFS_I(s_inode)->i_flags = 0;
734+
memset(NILFS_I(s_inode)->i_bmap, 0, sizeof(struct nilfs_bmap));
735+
mapping_set_gfp_mask(s_inode->i_mapping, GFP_NOFS);
736+
737+
err = nilfs_attach_btree_node_cache(s_inode);
738+
if (unlikely(err)) {
739+
iget_failed(s_inode);
740+
return ERR_PTR(err);
741+
}
742+
unlock_new_inode(s_inode);
743+
return s_inode;
744+
}
745+
691746
void nilfs_write_inode_common(struct inode *inode,
692747
struct nilfs_inode *raw_inode, int has_bmap)
693748
{

fs/nilfs2/mdt.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,18 @@ int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz)
471471
void nilfs_mdt_clear(struct inode *inode)
472472
{
473473
struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
474+
struct nilfs_shadow_map *shadow = mdi->mi_shadow;
474475

475476
if (mdi->mi_palloc_cache)
476477
nilfs_palloc_destroy_cache(inode);
478+
479+
if (shadow) {
480+
struct inode *s_inode = shadow->inode;
481+
482+
shadow->inode = NULL;
483+
iput(s_inode);
484+
mdi->mi_shadow = NULL;
485+
}
477486
}
478487

479488
/**
@@ -507,12 +516,15 @@ int nilfs_mdt_setup_shadow_map(struct inode *inode,
507516
struct nilfs_shadow_map *shadow)
508517
{
509518
struct nilfs_mdt_info *mi = NILFS_MDT(inode);
519+
struct inode *s_inode;
510520

511521
INIT_LIST_HEAD(&shadow->frozen_buffers);
512-
address_space_init_once(&shadow->frozen_data);
513-
nilfs_mapping_init(&shadow->frozen_data, inode);
514-
address_space_init_once(&shadow->frozen_btnodes);
515-
nilfs_mapping_init(&shadow->frozen_btnodes, inode);
522+
523+
s_inode = nilfs_iget_for_shadow(inode);
524+
if (IS_ERR(s_inode))
525+
return PTR_ERR(s_inode);
526+
527+
shadow->inode = s_inode;
516528
mi->mi_shadow = shadow;
517529
return 0;
518530
}
@@ -526,13 +538,14 @@ int nilfs_mdt_save_to_shadow_map(struct inode *inode)
526538
struct nilfs_mdt_info *mi = NILFS_MDT(inode);
527539
struct nilfs_inode_info *ii = NILFS_I(inode);
528540
struct nilfs_shadow_map *shadow = mi->mi_shadow;
541+
struct inode *s_inode = shadow->inode;
529542
int ret;
530543

531-
ret = nilfs_copy_dirty_pages(&shadow->frozen_data, inode->i_mapping);
544+
ret = nilfs_copy_dirty_pages(s_inode->i_mapping, inode->i_mapping);
532545
if (ret)
533546
goto out;
534547

535-
ret = nilfs_copy_dirty_pages(&shadow->frozen_btnodes,
548+
ret = nilfs_copy_dirty_pages(NILFS_I(s_inode)->i_assoc_inode->i_mapping,
536549
ii->i_assoc_inode->i_mapping);
537550
if (ret)
538551
goto out;
@@ -549,7 +562,7 @@ int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh)
549562
struct page *page;
550563
int blkbits = inode->i_blkbits;
551564

552-
page = grab_cache_page(&shadow->frozen_data, bh->b_page->index);
565+
page = grab_cache_page(shadow->inode->i_mapping, bh->b_page->index);
553566
if (!page)
554567
return -ENOMEM;
555568

@@ -581,7 +594,7 @@ nilfs_mdt_get_frozen_buffer(struct inode *inode, struct buffer_head *bh)
581594
struct page *page;
582595
int n;
583596

584-
page = find_lock_page(&shadow->frozen_data, bh->b_page->index);
597+
page = find_lock_page(shadow->inode->i_mapping, bh->b_page->index);
585598
if (page) {
586599
if (page_has_buffers(page)) {
587600
n = bh_offset(bh) >> inode->i_blkbits;
@@ -622,11 +635,11 @@ void nilfs_mdt_restore_from_shadow_map(struct inode *inode)
622635
nilfs_palloc_clear_cache(inode);
623636

624637
nilfs_clear_dirty_pages(inode->i_mapping, true);
625-
nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data);
638+
nilfs_copy_back_pages(inode->i_mapping, shadow->inode->i_mapping);
626639

627640
nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping, true);
628641
nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping,
629-
&shadow->frozen_btnodes);
642+
NILFS_I(shadow->inode)->i_assoc_inode->i_mapping);
630643

631644
nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store);
632645

@@ -641,10 +654,11 @@ void nilfs_mdt_clear_shadow_map(struct inode *inode)
641654
{
642655
struct nilfs_mdt_info *mi = NILFS_MDT(inode);
643656
struct nilfs_shadow_map *shadow = mi->mi_shadow;
657+
struct inode *shadow_btnc_inode = NILFS_I(shadow->inode)->i_assoc_inode;
644658

645659
down_write(&mi->mi_sem);
646660
nilfs_release_frozen_buffers(shadow);
647-
truncate_inode_pages(&shadow->frozen_data, 0);
648-
truncate_inode_pages(&shadow->frozen_btnodes, 0);
661+
truncate_inode_pages(shadow->inode->i_mapping, 0);
662+
truncate_inode_pages(shadow_btnc_inode->i_mapping, 0);
649663
up_write(&mi->mi_sem);
650664
}

fs/nilfs2/mdt.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@
1818
/**
1919
* struct nilfs_shadow_map - shadow mapping of meta data file
2020
* @bmap_store: shadow copy of bmap state
21-
* @frozen_data: shadowed dirty data pages
22-
* @frozen_btnodes: shadowed dirty b-tree nodes' pages
21+
* @inode: holder of page caches used in shadow mapping
2322
* @frozen_buffers: list of frozen buffers
2423
*/
2524
struct nilfs_shadow_map {
2625
struct nilfs_bmap_store bmap_store;
27-
struct address_space frozen_data;
28-
struct address_space frozen_btnodes;
26+
struct inode *inode;
2927
struct list_head frozen_buffers;
3028
};
3129

fs/nilfs2/nilfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ enum {
9292
NILFS_I_BMAP, /* has bmap and btnode_cache */
9393
NILFS_I_GCINODE, /* inode for GC, on memory only */
9494
NILFS_I_BTNC, /* inode for btree node cache */
95+
NILFS_I_SHADOW, /* inode for shadowed page cache */
9596
};
9697

9798
/*
@@ -263,6 +264,7 @@ extern struct inode *nilfs_iget_for_gc(struct super_block *sb,
263264
unsigned long ino, __u64 cno);
264265
int nilfs_attach_btree_node_cache(struct inode *inode);
265266
void nilfs_detach_btree_node_cache(struct inode *inode);
267+
struct inode *nilfs_iget_for_shadow(struct inode *inode);
266268
extern void nilfs_update_inode(struct inode *, struct buffer_head *, int);
267269
extern void nilfs_truncate(struct inode *);
268270
extern void nilfs_evict_inode(struct inode *);

0 commit comments

Comments
 (0)