@@ -2455,6 +2455,122 @@ static int btrfs_qgroup_account(struct btrfs_trans_handle *trans,
2455
2455
return ret ;
2456
2456
}
2457
2457
2458
+ static int
2459
+ btrfs_qgroup_account_extent (struct btrfs_trans_handle * trans ,
2460
+ struct btrfs_fs_info * fs_info ,
2461
+ u64 bytenr , u64 num_bytes ,
2462
+ struct ulist * old_roots , struct ulist * new_roots )
2463
+ {
2464
+ struct ulist * qgroups = NULL ;
2465
+ struct ulist * tmp = NULL ;
2466
+ u64 seq ;
2467
+ u64 nr_new_roots = 0 ;
2468
+ u64 nr_old_roots = 0 ;
2469
+ int ret = 0 ;
2470
+
2471
+ if (new_roots )
2472
+ nr_new_roots = new_roots -> nnodes ;
2473
+ if (old_roots )
2474
+ nr_old_roots = old_roots -> nnodes ;
2475
+
2476
+ if (!fs_info -> quota_enabled )
2477
+ goto out_free ;
2478
+ BUG_ON (!fs_info -> quota_root );
2479
+
2480
+ qgroups = ulist_alloc (GFP_NOFS );
2481
+ if (!qgroups ) {
2482
+ ret = - ENOMEM ;
2483
+ goto out_free ;
2484
+ }
2485
+ tmp = ulist_alloc (GFP_NOFS );
2486
+ if (!tmp ) {
2487
+ ret = - ENOMEM ;
2488
+ goto out_free ;
2489
+ }
2490
+
2491
+ mutex_lock (& fs_info -> qgroup_rescan_lock );
2492
+ if (fs_info -> qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN ) {
2493
+ if (fs_info -> qgroup_rescan_progress .objectid <= bytenr ) {
2494
+ mutex_unlock (& fs_info -> qgroup_rescan_lock );
2495
+ ret = 0 ;
2496
+ goto out_free ;
2497
+ }
2498
+ }
2499
+ mutex_unlock (& fs_info -> qgroup_rescan_lock );
2500
+
2501
+ spin_lock (& fs_info -> qgroup_lock );
2502
+ seq = fs_info -> qgroup_seq ;
2503
+
2504
+ /* Update old refcnts using old_roots */
2505
+ ret = qgroup_update_refcnt (fs_info , old_roots , tmp , qgroups , seq ,
2506
+ UPDATE_OLD );
2507
+ if (ret < 0 )
2508
+ goto out ;
2509
+
2510
+ /* Update new refcnts using new_roots */
2511
+ ret = qgroup_update_refcnt (fs_info , new_roots , tmp , qgroups , seq ,
2512
+ UPDATE_NEW );
2513
+ if (ret < 0 )
2514
+ goto out ;
2515
+
2516
+ qgroup_update_counters (fs_info , qgroups , nr_old_roots , nr_new_roots ,
2517
+ num_bytes , seq );
2518
+
2519
+ /*
2520
+ * Bump qgroup_seq to avoid seq overlap
2521
+ */
2522
+ fs_info -> qgroup_seq += max (nr_old_roots , nr_new_roots ) + 1 ;
2523
+ out :
2524
+ spin_unlock (& fs_info -> qgroup_lock );
2525
+ out_free :
2526
+ ulist_free (tmp );
2527
+ ulist_free (qgroups );
2528
+ ulist_free (old_roots );
2529
+ ulist_free (new_roots );
2530
+ return ret ;
2531
+ }
2532
+
2533
+ int btrfs_qgroup_account_extents (struct btrfs_trans_handle * trans ,
2534
+ struct btrfs_fs_info * fs_info )
2535
+ {
2536
+ struct btrfs_qgroup_extent_record * record ;
2537
+ struct btrfs_delayed_ref_root * delayed_refs ;
2538
+ struct ulist * new_roots = NULL ;
2539
+ struct rb_node * node ;
2540
+ int ret = 0 ;
2541
+
2542
+ delayed_refs = & trans -> transaction -> delayed_refs ;
2543
+ while ((node = rb_first (& delayed_refs -> dirty_extent_root ))) {
2544
+ record = rb_entry (node , struct btrfs_qgroup_extent_record ,
2545
+ node );
2546
+
2547
+ if (!ret ) {
2548
+ /*
2549
+ * Use (u64)-1 as time_seq to do special search, which
2550
+ * doesn't lock tree or delayed_refs and search current
2551
+ * root. It's safe inside commit_transaction().
2552
+ */
2553
+ ret = btrfs_find_all_roots (trans , fs_info ,
2554
+ record -> bytenr , (u64 )- 1 , & new_roots );
2555
+ if (ret < 0 )
2556
+ goto cleanup ;
2557
+ ret = btrfs_qgroup_account_extent (trans , fs_info ,
2558
+ record -> bytenr , record -> num_bytes ,
2559
+ record -> old_roots , new_roots );
2560
+ record -> old_roots = NULL ;
2561
+ new_roots = NULL ;
2562
+ }
2563
+ cleanup :
2564
+ ulist_free (record -> old_roots );
2565
+ ulist_free (new_roots );
2566
+ new_roots = NULL ;
2567
+ rb_erase (node , & delayed_refs -> dirty_extent_root );
2568
+ kfree (record );
2569
+
2570
+ }
2571
+ return ret ;
2572
+ }
2573
+
2458
2574
/*
2459
2575
* Needs to be called everytime we run delayed refs, even if there is an error
2460
2576
* in order to cleanup outstanding operations.
0 commit comments