@@ -235,9 +235,10 @@ pub(crate) async fn mirror_root_inode(
235
235
needs_license ( & ctx, LicensedFeature :: Mirroring ) ?;
236
236
fail_on_pre_shutdown ( & ctx) ?;
237
237
238
+ let offline_timeout = ctx. info . user_config . node_offline_timeout . as_secs ( ) ;
238
239
let meta_root = ctx
239
240
. db
240
- . read_tx ( |tx| {
241
+ . read_tx ( move |tx| {
241
242
let node_uid = match db:: misc:: get_meta_root ( tx) ? {
242
243
MetaRoot :: Normal ( _, node_uid) => node_uid,
243
244
MetaRoot :: Mirrored ( _) => bail ! ( "Root inode is already mirrored" ) ,
@@ -267,7 +268,33 @@ pub(crate) async fn mirror_root_inode(
267
268
} ) ?;
268
269
269
270
if clients > 0 {
270
- bail ! ( "This operation requires that all clients are disconnected/unmounted, but still has {clients} clients mounted." ) ;
271
+ bail ! (
272
+ "This operation requires that all clients are disconnected/unmounted. \
273
+ {clients} clients are still mounted."
274
+ ) ;
275
+ }
276
+
277
+ let mut server_stmt = tx. prepare ( sql ! (
278
+ "SELECT COUNT(*) FROM nodes
279
+ WHERE node_type = ?1 AND UNIXEPOCH('now') - UNIXEPOCH(last_contact) < ?2
280
+ AND node_uid != ?3"
281
+ ) ) ?;
282
+
283
+ let metas = server_stmt. query_row (
284
+ params ! [ NodeType :: Meta . sql_variant( ) , offline_timeout, node_uid] ,
285
+ |row| row. get :: < _ , i64 > ( 0 ) ,
286
+ ) ?;
287
+ let storages = server_stmt. query_row (
288
+ params ! [ NodeType :: Storage . sql_variant( ) , offline_timeout, node_uid] ,
289
+ |row| row. get :: < _ , i64 > ( 0 ) ,
290
+ ) ?;
291
+
292
+ if metas > 0 || storages > 0 {
293
+ bail ! (
294
+ "This operation requires that all nodes except the root meta node are shut \
295
+ down. {metas} meta nodes (excluding the root meta node) and {storages} storage nodes have \
296
+ communicated during the last {offline_timeout}s."
297
+ ) ;
271
298
}
272
299
273
300
Ok ( node_uid)
0 commit comments