2017-03-17 09:18:50 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* Code for moving data off a device .
*/
# include "bcachefs.h"
2020-12-17 23:08:58 +03:00
# include "bkey_buf.h"
2017-03-17 09:18:50 +03:00
# include "btree_update.h"
2019-01-21 23:32:13 +03:00
# include "btree_update_interior.h"
2017-03-17 09:18:50 +03:00
# include "buckets.h"
2022-07-19 02:42:58 +03:00
# include "errcode.h"
2017-03-17 09:18:50 +03:00
# include "extents.h"
2023-09-11 01:05:17 +03:00
# include "io_write.h"
2017-03-17 09:18:50 +03:00
# include "journal.h"
# include "keylist.h"
# include "migrate.h"
# include "move.h"
# include "replicas.h"
# include "super-io.h"
2018-11-01 22:10:01 +03:00
static int drop_dev_ptrs ( struct bch_fs * c , struct bkey_s k ,
2017-03-17 09:18:50 +03:00
unsigned dev_idx , int flags , bool metadata )
{
unsigned replicas = metadata ? c - > opts . metadata_replicas : c - > opts . data_replicas ;
unsigned lost = metadata ? BCH_FORCE_IF_METADATA_LOST : BCH_FORCE_IF_DATA_LOST ;
unsigned degraded = metadata ? BCH_FORCE_IF_METADATA_DEGRADED : BCH_FORCE_IF_DATA_DEGRADED ;
unsigned nr_good ;
2018-11-01 22:10:01 +03:00
bch2_bkey_drop_device ( k , dev_idx ) ;
2017-03-17 09:18:50 +03:00
2018-11-01 22:10:01 +03:00
nr_good = bch2_bkey_durability ( c , k . s_c ) ;
2017-03-17 09:18:50 +03:00
if ( ( ! nr_good & & ! ( flags & lost ) ) | |
( nr_good < replicas & & ! ( flags & degraded ) ) )
2024-02-06 05:44:23 +03:00
return - BCH_ERR_remove_would_lose_data ;
2017-03-17 09:18:50 +03:00
return 0 ;
}
2022-07-17 07:31:40 +03:00
static int bch2_dev_usrdata_drop_key ( struct btree_trans * trans ,
struct btree_iter * iter ,
struct bkey_s_c k ,
unsigned dev_idx ,
int flags )
{
struct bch_fs * c = trans - > c ;
struct bkey_i * n ;
int ret ;
2023-03-11 00:28:37 +03:00
if ( ! bch2_bkey_has_device_c ( k , dev_idx ) )
2022-07-17 07:31:40 +03:00
return 0 ;
2023-06-27 01:36:24 +03:00
n = bch2_bkey_make_mut ( trans , iter , & k , BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE ) ;
2022-07-17 07:31:40 +03:00
ret = PTR_ERR_OR_ZERO ( n ) ;
if ( ret )
return ret ;
ret = drop_dev_ptrs ( c , bkey_i_to_s ( n ) , dev_idx , flags , false ) ;
if ( ret )
return ret ;
/*
* If the new extent no longer has any pointers , bch2_extent_normalize ( )
* will do the appropriate thing with it ( turning it into a
* KEY_TYPE_error key , or just a discard if it was a cached extent )
*/
bch2_extent_normalize ( c , bkey_i_to_s ( n ) ) ;
/*
* Since we ' re not inserting through an extent iterator
* ( BTREE_ITER_ALL_SNAPSHOTS iterators aren ' t extent iterators ) ,
* we aren ' t using the extent overwrite path to delete , we ' re
* just using the normal key deletion path :
*/
if ( bkey_deleted ( & n - > k ) )
n - > k . size = 0 ;
2023-05-01 02:21:06 +03:00
return 0 ;
2022-07-17 07:31:40 +03:00
}
static int bch2_dev_usrdata_drop ( struct bch_fs * c , unsigned dev_idx , int flags )
2017-03-17 09:18:50 +03:00
{
2023-09-13 00:16:02 +03:00
struct btree_trans * trans = bch2_trans_get ( c ) ;
2022-07-17 07:31:40 +03:00
enum btree_id id ;
2017-03-17 09:18:50 +03:00
int ret = 0 ;
2022-07-17 07:31:40 +03:00
for ( id = 0 ; id < BTREE_ID_NR ; id + + ) {
if ( ! btree_type_has_ptrs ( id ) )
2017-03-17 09:18:50 +03:00
continue ;
2023-09-13 00:16:02 +03:00
ret = for_each_btree_key_commit ( trans , iter , id , POS_MIN ,
2022-07-17 07:31:40 +03:00
BTREE_ITER_PREFETCH | BTREE_ITER_ALL_SNAPSHOTS , k ,
2023-11-12 00:31:50 +03:00
NULL , NULL , BCH_TRANS_COMMIT_no_enospc ,
2023-09-13 00:16:02 +03:00
bch2_dev_usrdata_drop_key ( trans , & iter , k , dev_idx , flags ) ) ;
2017-03-17 09:18:50 +03:00
if ( ret )
break ;
}
2023-09-13 00:16:02 +03:00
bch2_trans_put ( trans ) ;
2017-03-17 09:18:50 +03:00
return ret ;
}
static int bch2_dev_metadata_drop ( struct bch_fs * c , unsigned dev_idx , int flags )
{
2023-09-13 00:16:02 +03:00
struct btree_trans * trans ;
2021-08-30 22:18:31 +03:00
struct btree_iter iter ;
2017-03-17 09:18:50 +03:00
struct closure cl ;
struct btree * b ;
2020-12-17 23:08:58 +03:00
struct bkey_buf k ;
2017-03-17 09:18:50 +03:00
unsigned id ;
int ret ;
/* don't handle this yet: */
if ( flags & BCH_FORCE_IF_METADATA_LOST )
2024-02-06 05:44:23 +03:00
return - BCH_ERR_remove_with_metadata_missing_unimplemented ;
2017-03-17 09:18:50 +03:00
2023-09-13 00:16:02 +03:00
trans = bch2_trans_get ( c ) ;
2020-12-17 23:08:58 +03:00
bch2_bkey_buf_init ( & k ) ;
2017-03-17 09:18:50 +03:00
closure_init_stack ( & cl ) ;
for ( id = 0 ; id < BTREE_ID_NR ; id + + ) {
2023-09-13 00:16:02 +03:00
bch2_trans_node_iter_init ( trans , & iter , id , POS_MIN , 0 , 0 ,
2021-10-07 21:59:00 +03:00
BTREE_ITER_PREFETCH ) ;
2021-10-19 21:20:50 +03:00
retry :
2021-10-19 22:11:45 +03:00
ret = 0 ;
2023-09-13 00:16:02 +03:00
while ( bch2_trans_begin ( trans ) ,
2021-10-19 21:20:50 +03:00
( b = bch2_btree_iter_peek_node ( & iter ) ) & &
! ( ret = PTR_ERR_OR_ZERO ( b ) ) ) {
2023-03-11 00:28:37 +03:00
if ( ! bch2_bkey_has_device_c ( bkey_i_to_s_c ( & b - > key ) , dev_idx ) )
2021-10-07 21:59:00 +03:00
goto next ;
2020-01-04 06:38:14 +03:00
2020-12-17 23:08:58 +03:00
bch2_bkey_buf_copy ( & k , c , & b - > key ) ;
2020-01-04 06:38:14 +03:00
2020-12-17 23:08:58 +03:00
ret = drop_dev_ptrs ( c , bkey_i_to_s ( k . k ) ,
2020-01-04 06:38:14 +03:00
dev_idx , flags , true ) ;
2024-02-06 05:44:23 +03:00
if ( ret )
2021-03-20 03:29:11 +03:00
break ;
2020-01-04 06:38:14 +03:00
2023-09-13 00:16:02 +03:00
ret = bch2_btree_node_update_key ( trans , & iter , b , k . k , 0 , false ) ;
2022-07-18 06:06:38 +03:00
if ( bch2_err_matches ( ret , BCH_ERR_transaction_restart ) ) {
2021-03-20 03:29:11 +03:00
ret = 0 ;
2021-10-07 21:59:00 +03:00
continue ;
2020-01-04 06:38:14 +03:00
}
2021-10-07 21:59:00 +03:00
2023-12-17 06:43:41 +03:00
bch_err_msg ( c , ret , " updating btree node key " ) ;
if ( ret )
2021-03-20 03:29:11 +03:00
break ;
2021-10-07 21:59:00 +03:00
next :
bch2_btree_iter_next_node ( & iter ) ;
2017-03-17 09:18:50 +03:00
}
2022-07-18 06:06:38 +03:00
if ( bch2_err_matches ( ret , BCH_ERR_transaction_restart ) )
2021-10-19 21:20:50 +03:00
goto retry ;
2023-09-13 00:16:02 +03:00
bch2_trans_iter_exit ( trans , & iter ) ;
2021-03-20 03:29:11 +03:00
if ( ret )
goto err ;
2017-03-17 09:18:50 +03:00
}
2022-04-18 00:30:49 +03:00
bch2_btree_interior_updates_flush ( c ) ;
2017-03-17 09:18:50 +03:00
ret = 0 ;
2019-03-25 22:10:15 +03:00
err :
2020-12-17 23:08:58 +03:00
bch2_bkey_buf_exit ( & k , c ) ;
2023-09-13 00:16:02 +03:00
bch2_trans_put ( trans ) ;
2019-03-25 22:10:15 +03:00
2022-07-18 06:06:38 +03:00
BUG_ON ( bch2_err_matches ( ret , BCH_ERR_transaction_restart ) ) ;
2017-03-17 09:18:50 +03:00
return ret ;
}
int bch2_dev_data_drop ( struct bch_fs * c , unsigned dev_idx , int flags )
{
return bch2_dev_usrdata_drop ( c , dev_idx , flags ) ? :
2020-01-04 06:38:14 +03:00
bch2_dev_metadata_drop ( c , dev_idx , flags ) ;
2017-03-17 09:18:50 +03:00
}