@@ -319,7 +319,6 @@ static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid,
319319 mutex_init (& fs_devs -> device_list_mutex );
320320
321321 INIT_LIST_HEAD (& fs_devs -> devices );
322- INIT_LIST_HEAD (& fs_devs -> resized_devices );
323322 INIT_LIST_HEAD (& fs_devs -> alloc_list );
324323 INIT_LIST_HEAD (& fs_devs -> fs_list );
325324 if (fsid )
@@ -335,6 +334,7 @@ static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid,
335334
336335void btrfs_free_device (struct btrfs_device * device )
337336{
337+ WARN_ON (!list_empty (& device -> post_commit_list ));
338338 rcu_string_free (device -> name );
339339 bio_put (device -> flush_bio );
340340 kfree (device );
@@ -403,7 +403,7 @@ static struct btrfs_device *__alloc_device(void)
403403
404404 INIT_LIST_HEAD (& dev -> dev_list );
405405 INIT_LIST_HEAD (& dev -> dev_alloc_list );
406- INIT_LIST_HEAD (& dev -> resized_list );
406+ INIT_LIST_HEAD (& dev -> post_commit_list );
407407
408408 spin_lock_init (& dev -> io_lock );
409409
@@ -2853,7 +2853,6 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
28532853{
28542854 struct btrfs_fs_info * fs_info = device -> fs_info ;
28552855 struct btrfs_super_block * super_copy = fs_info -> super_copy ;
2856- struct btrfs_fs_devices * fs_devices ;
28572856 u64 old_total ;
28582857 u64 diff ;
28592858
@@ -2872,18 +2871,16 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
28722871 return - EINVAL ;
28732872 }
28742873
2875- fs_devices = fs_info -> fs_devices ;
2876-
28772874 btrfs_set_super_total_bytes (super_copy ,
28782875 round_down (old_total + diff , fs_info -> sectorsize ));
28792876 device -> fs_devices -> total_rw_bytes += diff ;
28802877
28812878 btrfs_device_set_total_bytes (device , new_size );
28822879 btrfs_device_set_disk_total_bytes (device , new_size );
28832880 btrfs_clear_space_info_full (device -> fs_info );
2884- if (list_empty (& device -> resized_list ))
2885- list_add_tail (& device -> resized_list ,
2886- & fs_devices -> resized_devices );
2881+ if (list_empty (& device -> post_commit_list ))
2882+ list_add_tail (& device -> post_commit_list ,
2883+ & trans -> transaction -> dev_update_list );
28872884 mutex_unlock (& fs_info -> chunk_mutex );
28882885
28892886 return btrfs_update_device (trans , device );
@@ -4872,9 +4869,9 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
48724869 }
48734870
48744871 btrfs_device_set_disk_total_bytes (device , new_size );
4875- if (list_empty (& device -> resized_list ))
4876- list_add_tail (& device -> resized_list ,
4877- & fs_info -> fs_devices -> resized_devices );
4872+ if (list_empty (& device -> post_commit_list ))
4873+ list_add_tail (& device -> post_commit_list ,
4874+ & trans -> transaction -> dev_update_list );
48784875
48794876 WARN_ON (diff > old_total );
48804877 btrfs_set_super_total_bytes (super_copy ,
@@ -5214,9 +5211,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
52145211 if (ret )
52155212 goto error_del_extent ;
52165213
5217- for (i = 0 ; i < map -> num_stripes ; i ++ )
5218- btrfs_device_set_bytes_used (map -> stripes [i ].dev ,
5219- map -> stripes [i ].dev -> bytes_used + stripe_size );
5214+ for (i = 0 ; i < map -> num_stripes ; i ++ ) {
5215+ struct btrfs_device * dev = map -> stripes [i ].dev ;
5216+
5217+ btrfs_device_set_bytes_used (dev , dev -> bytes_used + stripe_size );
5218+ if (list_empty (& dev -> post_commit_list ))
5219+ list_add_tail (& dev -> post_commit_list ,
5220+ & trans -> transaction -> dev_update_list );
5221+ }
52205222
52215223 atomic64_sub (stripe_size * map -> num_stripes , & info -> free_chunk_space );
52225224
@@ -7579,51 +7581,34 @@ void btrfs_scratch_superblocks(struct block_device *bdev, const char *device_pat
75797581}
75807582
75817583/*
7582- * Update the size of all devices, which is used for writing out the
7583- * super blocks.
7584+ * Update the size and bytes used for each device where it changed. This is
7585+ * delayed since we would otherwise get errors while writing out the
7586+ * superblocks.
7587+ *
7588+ * Must be invoked during transaction commit.
75847589 */
7585- void btrfs_update_commit_device_size (struct btrfs_fs_info * fs_info )
7590+ void btrfs_commit_device_sizes (struct btrfs_transaction * trans )
75867591{
7587- struct btrfs_fs_devices * fs_devices = fs_info -> fs_devices ;
75887592 struct btrfs_device * curr , * next ;
75897593
7590- if (list_empty (& fs_devices -> resized_devices ))
7591- return ;
7592-
7593- mutex_lock (& fs_devices -> device_list_mutex );
7594- mutex_lock (& fs_info -> chunk_mutex );
7595- list_for_each_entry_safe (curr , next , & fs_devices -> resized_devices ,
7596- resized_list ) {
7597- list_del_init (& curr -> resized_list );
7598- curr -> commit_total_bytes = curr -> disk_total_bytes ;
7599- }
7600- mutex_unlock (& fs_info -> chunk_mutex );
7601- mutex_unlock (& fs_devices -> device_list_mutex );
7602- }
7603-
7604- /* Must be invoked during the transaction commit */
7605- void btrfs_update_commit_device_bytes_used (struct btrfs_transaction * trans )
7606- {
7607- struct btrfs_fs_info * fs_info = trans -> fs_info ;
7608- struct extent_map * em ;
7609- struct map_lookup * map ;
7610- struct btrfs_device * dev ;
7611- int i ;
7594+ ASSERT (trans -> state == TRANS_STATE_COMMIT_DOING );
76127595
7613- if (list_empty (& trans -> pending_chunks ))
7596+ if (list_empty (& trans -> dev_update_list ))
76147597 return ;
76157598
7616- /* In order to kick the device replace finish process */
7617- mutex_lock (& fs_info -> chunk_mutex );
7618- list_for_each_entry (em , & trans -> pending_chunks , list ) {
7619- map = em -> map_lookup ;
7620-
7621- for (i = 0 ; i < map -> num_stripes ; i ++ ) {
7622- dev = map -> stripes [i ].dev ;
7623- dev -> commit_bytes_used = dev -> bytes_used ;
7624- }
7599+ /*
7600+ * We don't need the device_list_mutex here. This list is owned by the
7601+ * transaction and the transaction must complete before the device is
7602+ * released.
7603+ */
7604+ mutex_lock (& trans -> fs_info -> chunk_mutex );
7605+ list_for_each_entry_safe (curr , next , & trans -> dev_update_list ,
7606+ post_commit_list ) {
7607+ list_del_init (& curr -> post_commit_list );
7608+ curr -> commit_total_bytes = curr -> disk_total_bytes ;
7609+ curr -> commit_bytes_used = curr -> bytes_used ;
76257610 }
7626- mutex_unlock (& fs_info -> chunk_mutex );
7611+ mutex_unlock (& trans -> fs_info -> chunk_mutex );
76277612}
76287613
76297614void btrfs_set_fs_info_ptr (struct btrfs_fs_info * fs_info )
0 commit comments