108
108
fprintf(stderr, "\t-K The key to corrupt in the format "
109
109
"<num>,<num>,<num> (must also specify -f for the field)\n");
110
110
fprintf(stderr, "\t-f The field in the item to corrupt\n");
111
fprintf(stderr, "\t-I An item to corrupt (must also specify the field "
112
"to corrupt and a root+key for the item)\n");
113
fprintf(stderr, "\t-D Corrupt a dir item, must specify key and field\n");
301
304
BTRFS_FILE_EXTENT_BAD,
307
enum btrfs_dir_item_field {
309
BTRFS_DIR_ITEM_LOCATION_OBJECTID,
304
313
enum btrfs_metadata_block_field {
305
314
BTRFS_METADATA_BLOCK_GENERATION,
315
BTRFS_METADATA_BLOCK_SHIFT_ITEMS,
306
316
BTRFS_METADATA_BLOCK_BAD,
319
enum btrfs_item_field {
309
324
enum btrfs_key_field {
310
325
BTRFS_KEY_OBJECTID,
333
348
if (!strncmp(field, "generation", FIELD_BUF_LEN))
334
349
return BTRFS_METADATA_BLOCK_GENERATION;
350
if (!strncmp(field, "shift_items", FIELD_BUF_LEN))
351
return BTRFS_METADATA_BLOCK_SHIFT_ITEMS;
335
352
return BTRFS_METADATA_BLOCK_BAD;
346
363
return BTRFS_KEY_BAD;
366
static enum btrfs_item_field convert_item_field(char *field)
368
if (!strncmp(field, "offset", FIELD_BUF_LEN))
369
return BTRFS_ITEM_OFFSET;
370
return BTRFS_ITEM_BAD;
373
static enum btrfs_dir_item_field convert_dir_item_field(char *field)
375
if (!strncmp(field, "name", FIELD_BUF_LEN))
376
return BTRFS_DIR_ITEM_NAME;
377
if (!strncmp(field, "location_objectid", FIELD_BUF_LEN))
378
return BTRFS_DIR_ITEM_LOCATION_OBJECTID;
379
return BTRFS_DIR_ITEM_BAD;
349
382
static u64 generate_u64(u64 orig)
466
static int corrupt_dir_item(struct btrfs_root *root, struct btrfs_key *key,
469
struct btrfs_trans_handle *trans;
470
struct btrfs_dir_item *di;
471
struct btrfs_path *path;
473
struct btrfs_key location;
474
struct btrfs_disk_key disk_key;
475
unsigned long name_ptr;
476
enum btrfs_dir_item_field corrupt_field =
477
convert_dir_item_field(field);
482
if (corrupt_field == BTRFS_DIR_ITEM_BAD) {
483
fprintf(stderr, "Invalid field %s\n", field);
487
path = btrfs_alloc_path();
491
trans = btrfs_start_transaction(root, 1);
493
btrfs_free_path(path);
494
return PTR_ERR(trans);
497
ret = btrfs_search_slot(trans, root, key, path, 0, 1);
501
fprintf(stderr, "Error searching for dir item %d\n", ret);
505
di = btrfs_item_ptr(path->nodes[0], path->slots[0],
506
struct btrfs_dir_item);
508
switch (corrupt_field) {
509
case BTRFS_DIR_ITEM_NAME:
510
name_len = btrfs_dir_name_len(path->nodes[0], di);
511
name = malloc(name_len);
516
name_ptr = (unsigned long)(di + 1);
517
read_extent_buffer(path->nodes[0], name, name_ptr, name_len);
519
write_extent_buffer(path->nodes[0], name, name_ptr, name_len);
520
btrfs_mark_buffer_dirty(path->nodes[0]);
523
case BTRFS_DIR_ITEM_LOCATION_OBJECTID:
524
btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
525
bogus = generate_u64(location.objectid);
526
location.objectid = bogus;
527
btrfs_cpu_key_to_disk(&disk_key, &location);
528
btrfs_set_dir_item_key(path->nodes[0], di, &disk_key);
529
btrfs_mark_buffer_dirty(path->nodes[0]);
536
btrfs_commit_transaction(trans, root);
537
btrfs_free_path(path);
425
541
static int corrupt_inode(struct btrfs_trans_handle *trans,
426
542
struct btrfs_root *root, u64 inode, char *field)
657
static void shift_items(struct btrfs_root *root, struct extent_buffer *eb)
659
int nritems = btrfs_header_nritems(eb);
660
int shift_space = btrfs_leaf_free_space(root, eb) / 2;
661
int slot = nritems / 2;
663
unsigned int data_end = btrfs_item_offset_nr(eb, nritems - 1);
665
/* Shift the item data up to and including slot back by shift space */
666
memmove_extent_buffer(eb, btrfs_leaf_data(eb) + data_end - shift_space,
667
btrfs_leaf_data(eb) + data_end,
668
btrfs_item_offset_nr(eb, slot - 1) - data_end);
670
/* Now update the item pointers. */
671
for (i = nritems - 1; i >= slot; i--) {
672
u32 offset = btrfs_item_offset_nr(eb, i);
673
offset -= shift_space;
674
btrfs_set_item_offset(eb, btrfs_item_nr(i), offset);
541
678
static int corrupt_metadata_block(struct btrfs_root *root, u64 block,
762
static int corrupt_btrfs_item(struct btrfs_root *root, struct btrfs_key *key,
765
struct btrfs_trans_handle *trans;
766
struct btrfs_path *path;
767
enum btrfs_item_field corrupt_field;
771
corrupt_field = convert_item_field(field);
772
if (corrupt_field == BTRFS_ITEM_BAD) {
773
fprintf(stderr, "Invalid field %s\n", field);
777
path = btrfs_alloc_path();
781
trans = btrfs_start_transaction(root, 1);
783
btrfs_free_path(path);
784
fprintf(stderr, "Couldn't start transaction %ld\n",
786
return PTR_ERR(trans);
789
ret = btrfs_search_slot(trans, root, key, path, 0, 1);
791
fprintf(stderr, "Error searching to node %d\n", ret);
796
switch (corrupt_field) {
797
case BTRFS_ITEM_OFFSET:
798
orig = btrfs_item_offset_nr(path->nodes[0], path->slots[0]);
799
bogus = generate_u32(orig);
800
btrfs_set_item_offset(path->nodes[0],
801
btrfs_item_nr(path->slots[0]), bogus);
807
btrfs_mark_buffer_dirty(path->nodes[0]);
809
btrfs_commit_transaction(trans, root);
810
btrfs_free_path(path);
622
814
static struct option long_options[] = {
623
815
/* { "byte-count", 1, NULL, 'b' }, */
624
816
{ "logical", 1, NULL, 'l' },
634
826
{ "metadata-block", 1, NULL, 'm'},
635
827
{ "field", 1, NULL, 'f'},
636
828
{ "key", 1, NULL, 'K'},
829
{ "item", 0, NULL, 'I'},
830
{ "dir-item", 0, NULL, 'D'},
811
c = getopt_long(ac, av, "l:c:b:eEkuUi:f:x:m:K:", long_options,
1007
c = getopt_long(ac, av, "l:c:b:eEkuUi:f:x:m:K:ID", long_options,
955
1157
ret = corrupt_metadata_block(root, metadata_block, field);
1161
if (!key.objectid || !strlen(field))
1163
ret = corrupt_dir_item(root, &key, field);
1169
ret = corrupt_btrfs_item(root, &key, field);
958
1172
if (key.objectid || key.offset || key.type) {
959
1173
if (!strlen(field))