@@ -126,6 +126,49 @@ static const char * const tune_usage[] = {
126
126
NULL
127
127
};
128
128
129
+ enum btrfstune_group_enum {
130
+ /* Extent/block group tree feature. */
131
+ EXTENT_TREE ,
132
+
133
+ /* V1/v2 free space cache. */
134
+ SPACE_CACHE ,
135
+
136
+ /* Metadata UUID. */
137
+ METADATA_UUID ,
138
+
139
+ /* FSID change. */
140
+ FSID_CHANGE ,
141
+
142
+ /* Seed device. */
143
+ SEED ,
144
+
145
+ /* Csum conversion */
146
+ CSUM_CHANGE ,
147
+
148
+ /*
149
+ * Legacy features (which later become default), including:
150
+ * - no-holes
151
+ * - extref
152
+ * - skinny-metadata
153
+ */
154
+ LEGACY ,
155
+
156
+ BTRFSTUNE_NR_GROUPS ,
157
+ };
158
+
159
+ static bool btrfstune_cmd_groups [BTRFSTUNE_NR_GROUPS ] = { 0 };
160
+
161
+ static unsigned int btrfstune_count_set_groups ()
162
+ {
163
+ int ret = 0 ;
164
+
165
+ for (int i = 0 ; i < BTRFSTUNE_NR_GROUPS ; i ++ ) {
166
+ if (btrfstune_cmd_groups [i ])
167
+ ret ++ ;
168
+ }
169
+ return ret ;
170
+ }
171
+
129
172
static const struct cmd_struct tune_cmd = {
130
173
.usagestr = tune_usage
131
174
};
@@ -135,8 +178,6 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
135
178
struct btrfs_root * root ;
136
179
struct btrfs_fs_info * fs_info ;
137
180
unsigned ctree_flags = OPEN_CTREE_WRITES ;
138
- int success = 0 ;
139
- int total = 0 ;
140
181
int seeding_flag = 0 ;
141
182
u64 seeding_value = 0 ;
142
183
int random_fsid = 0 ;
@@ -178,51 +219,63 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
178
219
case 'S' :
179
220
seeding_flag = 1 ;
180
221
seeding_value = arg_strtou64 (optarg );
222
+ btrfstune_cmd_groups [SEED ] = true;
181
223
break ;
182
224
case 'r' :
183
225
super_flags |= BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF ;
226
+ btrfstune_cmd_groups [LEGACY ] = true;
184
227
break ;
185
228
case 'x' :
186
229
super_flags |= BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA ;
230
+ btrfstune_cmd_groups [LEGACY ] = true;
187
231
break ;
188
232
case 'n' :
189
233
super_flags |= BTRFS_FEATURE_INCOMPAT_NO_HOLES ;
234
+ btrfstune_cmd_groups [LEGACY ] = true;
190
235
break ;
191
236
case 'f' :
192
237
force = 1 ;
193
238
break ;
194
239
case 'U' :
195
240
ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH ;
196
241
new_fsid_str = optarg ;
242
+ btrfstune_cmd_groups [FSID_CHANGE ] = true;
197
243
break ;
198
244
case 'u' :
199
245
ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH ;
200
246
random_fsid = 1 ;
247
+ btrfstune_cmd_groups [FSID_CHANGE ] = true;
201
248
break ;
202
249
case 'M' :
203
250
ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH ;
204
251
change_metadata_uuid = 1 ;
205
252
new_fsid_str = optarg ;
253
+ btrfstune_cmd_groups [METADATA_UUID ] = true;
206
254
break ;
207
255
case 'm' :
208
256
ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH ;
209
257
change_metadata_uuid = 1 ;
258
+ btrfstune_cmd_groups [METADATA_UUID ] = true;
210
259
break ;
211
260
case GETOPT_VAL_ENABLE_BLOCK_GROUP_TREE :
212
261
to_bg_tree = true;
262
+ btrfstune_cmd_groups [EXTENT_TREE ] = true;
213
263
break ;
214
264
case GETOPT_VAL_DISABLE_BLOCK_GROUP_TREE :
215
265
to_extent_tree = true;
266
+ btrfstune_cmd_groups [EXTENT_TREE ] = true;
216
267
break ;
217
268
case GETOPT_VAL_ENABLE_FREE_SPACE_TREE :
218
269
to_fst = true;
270
+ btrfstune_cmd_groups [SPACE_CACHE ] = true;
219
271
break ;
220
272
#if EXPERIMENTAL
221
273
case GETOPT_VAL_CSUM :
222
274
btrfs_warn_experimental (
223
275
"Switching checksums is experimental, do not use for valuable data!" );
224
276
ctree_flags |= OPEN_CTREE_SKIP_CSUM_CHECK ;
225
277
csum_type = parse_csum_type (optarg );
278
+ btrfstune_cmd_groups [CSUM_CHANGE ] = true;
226
279
break ;
227
280
#endif
228
281
case GETOPT_VAL_HELP :
@@ -238,20 +291,23 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
238
291
goto free_out ;
239
292
}
240
293
241
- if (random_fsid && new_fsid_str ) {
242
- error ("random fsid can't be used with specified fsid" );
294
+ if (btrfstune_count_set_groups () == 0 ) {
295
+ error ("at least one option should be specified" );
296
+ usage (& tune_cmd , 1 );
243
297
ret = 1 ;
244
298
goto free_out ;
245
299
}
246
- if (!super_flags && !seeding_flag && !(random_fsid || new_fsid_str ) &&
247
- !change_metadata_uuid && csum_type == -1 && !to_bg_tree &&
248
- !to_extent_tree && !to_fst ) {
249
- error ("at least one option should be specified" );
300
+ if (btrfstune_count_set_groups () > 1 ) {
301
+ error ("too many conflicting options specified" );
250
302
usage (& tune_cmd , 1 );
251
303
ret = 1 ;
252
304
goto free_out ;
253
305
}
254
-
306
+ if (random_fsid && new_fsid_str ) {
307
+ error ("random fsid can't be used with specified fsid" );
308
+ ret = 1 ;
309
+ goto free_out ;
310
+ }
255
311
if (new_fsid_str ) {
256
312
uuid_t tmp ;
257
313
@@ -321,17 +377,17 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
321
377
if (to_bg_tree ) {
322
378
if (to_extent_tree ) {
323
379
error ("option --convert-to-block-group-tree conflicts with --convert-from-block-group-tree" );
324
- ret = 1 ;
380
+ ret = - EINVAL ;
325
381
goto out ;
326
382
}
327
383
if (btrfs_fs_compat_ro (fs_info , BLOCK_GROUP_TREE )) {
328
384
error ("the filesystem already has block group tree feature" );
329
- ret = 1 ;
385
+ ret = - EINVAL ;
330
386
goto out ;
331
387
}
332
388
if (!btrfs_fs_compat_ro (fs_info , FREE_SPACE_TREE_VALID )) {
333
389
error ("the filesystem doesn't have space cache v2, needs to be mounted with \"-o space_cache=v2\" first" );
334
- ret = 1 ;
390
+ ret = - EINVAL ;
335
391
goto out ;
336
392
}
337
393
ret = convert_to_bg_tree (fs_info );
@@ -344,7 +400,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
344
400
if (to_fst ) {
345
401
if (btrfs_fs_compat_ro (fs_info , FREE_SPACE_TREE_VALID )) {
346
402
error ("filesystem already has free-space-tree feature" );
347
- ret = 1 ;
403
+ ret = - EINVAL ;
348
404
goto out ;
349
405
}
350
406
ret = convert_to_fst (fs_info );
@@ -355,12 +411,12 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
355
411
if (to_extent_tree ) {
356
412
if (to_bg_tree ) {
357
413
error ("option --convert-to-block-group-tree conflicts with --convert-from-block-group-tree" );
358
- ret = 1 ;
414
+ ret = - EINVAL ;
359
415
goto out ;
360
416
}
361
417
if (!btrfs_fs_compat_ro (fs_info , BLOCK_GROUP_TREE )) {
362
418
error ("filesystem doesn't have block-group-tree feature" );
363
- ret = 1 ;
419
+ ret = - EINVAL ;
364
420
goto out ;
365
421
}
366
422
ret = convert_to_extent_tree (fs_info );
@@ -373,7 +429,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
373
429
if (seeding_flag ) {
374
430
if (btrfs_fs_incompat (fs_info , METADATA_UUID )) {
375
431
error ("SEED flag cannot be changed on a metadata-uuid changed fs" );
376
- ret = 1 ;
432
+ ret = - EINVAL ;
377
433
goto out ;
378
434
}
379
435
@@ -383,34 +439,30 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
383
439
ret = ask_user ("We are going to clear the seeding flag, are you sure?" );
384
440
if (!ret ) {
385
441
error ("clear seeding flag canceled" );
386
- ret = 1 ;
442
+ ret = - EINVAL ;
387
443
goto out ;
388
444
}
389
445
}
390
446
391
447
ret = update_seeding_flag (root , device , seeding_value , force );
392
- if (!ret )
393
- success ++ ;
394
- total ++ ;
448
+ goto out ;
395
449
}
396
450
397
451
if (super_flags ) {
398
452
ret = set_super_incompat_flags (root , super_flags );
399
- if (!ret )
400
- success ++ ;
401
- total ++ ;
453
+ goto out ;
402
454
}
403
455
404
456
if (csum_type != -1 ) {
405
- /* TODO: check conflicting flags */
406
457
pr_verbose (LOG_DEFAULT , "Proceed to switch checksums\n" );
407
458
ret = btrfs_change_csum_type (fs_info , csum_type );
459
+ goto out ;
408
460
}
409
461
410
462
if (change_metadata_uuid ) {
411
463
if (seeding_flag ) {
412
464
error ("not allowed to set both seeding flag and uuid metadata" );
413
- ret = 1 ;
465
+ ret = - EINVAL ;
414
466
goto out ;
415
467
}
416
468
@@ -419,18 +471,16 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
419
471
else
420
472
ret = set_metadata_uuid (root , NULL );
421
473
422
- if (!ret )
423
- success ++ ;
424
- total ++ ;
425
474
btrfs_register_all_devices ();
475
+ goto out ;
426
476
}
427
477
428
478
if (random_fsid || (new_fsid_str && !change_metadata_uuid )) {
429
479
if (fs_info -> fs_devices -> active_metadata_uuid ) {
430
480
error (
431
481
"Cannot rewrite fsid while METADATA_UUID flag is active. \n"
432
482
"Ensure fsid and metadata_uuid match before retrying." );
433
- ret = 1 ;
483
+ ret = - EINVAL ;
434
484
goto out ;
435
485
}
436
486
@@ -442,24 +492,19 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
442
492
ret = ask_user ("We are going to change UUID, are your sure?" );
443
493
if (!ret ) {
444
494
error ("UUID change canceled" );
445
- ret = 1 ;
495
+ ret = - EINVAL ;
446
496
goto out ;
447
497
}
448
498
}
449
499
ret = change_uuid (fs_info , new_fsid_str );
450
- if (!ret )
451
- success ++ ;
452
- total ++ ;
500
+ goto out ;
453
501
}
454
-
455
- if (success == total ) {
456
- ret = 0 ;
457
- } else {
502
+ out :
503
+ if (ret < 0 ) {
458
504
fs_info -> readonly = 1 ;
459
505
ret = 1 ;
460
506
error ("btrfstune failed" );
461
507
}
462
- out :
463
508
close_ctree (root );
464
509
btrfs_close_all_devices ();
465
510
0 commit comments