@@ -588,6 +588,93 @@ int bch2_dev_usage_init(struct bch_dev *ca, bool gc)
588588 return ret ;
589589}
590590
591+ void bch2_verify_accounting_clean (struct bch_fs * c )
592+ {
593+ bool mismatch = false;
594+ struct bch_fs_usage_base base = {}, base_inmem = {};
595+
596+ bch2_trans_run (c ,
597+ for_each_btree_key (trans , iter ,
598+ BTREE_ID_accounting , POS_MIN ,
599+ BTREE_ITER_all_snapshots , k , ({
600+ u64 v [BCH_ACCOUNTING_MAX_COUNTERS ];
601+ struct bkey_s_c_accounting a = bkey_s_c_to_accounting (k );
602+ unsigned nr = bch2_accounting_counters (k .k );
603+
604+ bch2_accounting_mem_read (c , k .k -> p , v , nr );
605+
606+ if (memcmp (a .v -> d , v , nr * sizeof (u64 ))) {
607+ struct printbuf buf = PRINTBUF ;
608+
609+ bch2_bkey_val_to_text (& buf , c , k );
610+ prt_str (& buf , " !=" );
611+ for (unsigned j = 0 ; j < nr ; j ++ )
612+ prt_printf (& buf , " %llu" , v [j ]);
613+
614+ pr_err ("%s" , buf .buf );
615+ printbuf_exit (& buf );
616+ mismatch = true;
617+ }
618+
619+ struct disk_accounting_pos acc_k ;
620+ bpos_to_disk_accounting_pos (& acc_k , a .k -> p );
621+
622+ switch (acc_k .type ) {
623+ case BCH_DISK_ACCOUNTING_persistent_reserved :
624+ base .reserved += acc_k .persistent_reserved .nr_replicas * a .v -> d [0 ];
625+ break ;
626+ case BCH_DISK_ACCOUNTING_replicas :
627+ fs_usage_data_type_to_base (& base , acc_k .replicas .data_type , a .v -> d [0 ]);
628+ break ;
629+ case BCH_DISK_ACCOUNTING_dev_data_type : {
630+ rcu_read_lock ();
631+ struct bch_dev * ca = bch2_dev_rcu (c , acc_k .dev_data_type .dev );
632+ if (!ca ) {
633+ rcu_read_unlock ();
634+ continue ;
635+ }
636+
637+ v [0 ] = percpu_u64_get (& ca -> usage -> d [acc_k .dev_data_type .data_type ].buckets );
638+ v [1 ] = percpu_u64_get (& ca -> usage -> d [acc_k .dev_data_type .data_type ].sectors );
639+ v [2 ] = percpu_u64_get (& ca -> usage -> d [acc_k .dev_data_type .data_type ].fragmented );
640+ rcu_read_unlock ();
641+
642+ if (memcmp (a .v -> d , v , 3 * sizeof (u64 ))) {
643+ struct printbuf buf = PRINTBUF ;
644+
645+ bch2_bkey_val_to_text (& buf , c , k );
646+ prt_str (& buf , " in mem" );
647+ for (unsigned j = 0 ; j < nr ; j ++ )
648+ prt_printf (& buf , " %llu" , v [j ]);
649+
650+ pr_err ("dev accounting mismatch: %s" , buf .buf );
651+ printbuf_exit (& buf );
652+ mismatch = true;
653+ }
654+ }
655+ }
656+
657+ 0 ;
658+ })));
659+
660+ acc_u64s_percpu (& base_inmem .hidden , & c -> usage -> hidden , sizeof (base_inmem ) / sizeof (u64 ));
661+
662+ #define check (x ) \
663+ if (base.x != base_inmem.x) { \
664+ pr_err("fs_usage_base.%s mismatch: %llu != %llu", #x, base.x, base_inmem.x); \
665+ mismatch = true; \
666+ }
667+
668+ //check(hidden);
669+ check (btree );
670+ check (data );
671+ check (cached );
672+ check (reserved );
673+ check (nr_inodes );
674+
675+ WARN_ON (mismatch );
676+ }
677+
591678void bch2_accounting_free (struct bch_accounting_mem * acc )
592679{
593680 darray_exit (& acc -> k );
0 commit comments