btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag
[platform/upstream/btrfs-progs.git] / btrfs-corrupt-block.c
1 /*
2  * Copyright (C) 2009 Oracle.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <getopt.h>
24 #include <limits.h>
25
26 #include "kerncompat.h"
27 #include "ctree.h"
28 #include "volumes.h"
29 #include "disk-io.h"
30 #include "print-tree.h"
31 #include "transaction.h"
32 #include "list.h"
33 #include "utils.h"
34
35 #define FIELD_BUF_LEN 80
36
37 static int debug_corrupt_block(struct extent_buffer *eb,
38                 struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 copy)
39 {
40         int ret;
41         u64 length;
42         struct btrfs_multi_bio *multi = NULL;
43         struct btrfs_device *device;
44         int num_copies;
45         int mirror_num = 1;
46
47         length = blocksize;
48         while (1) {
49                 ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
50                                       eb->start, &length, &multi,
51                                       mirror_num, NULL);
52                 if (ret) {
53                         error("cannot map block %llu length %llu mirror %d: %d",
54                                         (unsigned long long)eb->start,
55                                         (unsigned long long)length,
56                                         mirror_num, ret);
57                         return ret;
58                 }
59                 device = multi->stripes[0].dev;
60                 eb->fd = device->fd;
61                 device->total_ios++;
62                 eb->dev_bytenr = multi->stripes[0].physical;
63
64                 fprintf(stdout,
65                         "mirror %d logical %llu physical %llu device %s\n",
66                         mirror_num, (unsigned long long)bytenr,
67                         (unsigned long long)eb->dev_bytenr, device->name);
68                 free(multi);
69
70                 if (!copy || mirror_num == copy) {
71                         ret = read_extent_from_disk(eb, 0, eb->len);
72                         if (ret < 0) {
73                                 error("cannot read eb bytenr %llu: %s",
74                                                 (unsigned long long)eb->dev_bytenr,
75                                                 strerror(-ret));
76                                 return ret;
77                         }
78                         printf("corrupting %llu copy %d\n", eb->start,
79                                mirror_num);
80                         memset(eb->data, 0, eb->len);
81                         ret = write_extent_to_disk(eb);
82                         if (ret < 0) {
83                                 error("cannot write eb bytenr %llu: %s",
84                                                 (unsigned long long)eb->dev_bytenr,
85                                                 strerror(-ret));
86                                 return ret;
87                         }
88                         fsync(eb->fd);
89                 }
90
91                 num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
92                                               eb->start, eb->len);
93                 if (num_copies == 1)
94                         break;
95
96                 mirror_num++;
97                 if (mirror_num > num_copies)
98                         break;
99         }
100
101         return 0;
102 }
103
104 static void print_usage(int ret)
105 {
106         printf("usage: btrfs-corrupt-block [options] device\n");
107         printf("\t-l   Logical extent to be corrupted\n");
108         printf("\t-c   Copy of the extent to be corrupted (usually 1 or 2, default: 0)\n");
109         printf("\t-b   Number of bytes to be corrupted\n");
110         printf("\t-e   Extent to be corrupted\n");
111         printf("\t-E   The whole extent tree to be corrupted\n");
112         printf("\t-u   Given chunk item to be corrupted\n");
113         printf("\t-U   The whole chunk tree to be corrupted\n");
114         printf("\t-i   The inode item to corrupt (must also specify the field to corrupt)\n");
115         printf("\t-x   The file extent item to corrupt (must also specify -i for the inode and -f for the field to corrupt)\n");
116         printf("\t-m   The metadata block to corrupt (must also specify -f for the field to corrupt)\n");
117         printf("\t-K   The key to corrupt in the format <num>,<num>,<num> (must also specify -f for the field)\n");
118         printf("\t-f   The field in the item to corrupt\n");
119         printf("\t-I   An item to corrupt (must also specify the field to corrupt and a root+key for the item)\n");
120         printf("\t-D   Corrupt a dir item, must specify key and field\n");
121         printf("\t-d   Delete this item (must specify -K)\n");
122         printf("\t-r   Operate on this root (only works with -d)\n");
123         printf("\t-C   Delete a csum for the specified bytenr.  When used with -b it'll delete that many bytes, otherwise it's just sectorsize\n");
124         exit(ret);
125 }
126
127 static void corrupt_keys(struct btrfs_trans_handle *trans,
128                          struct btrfs_root *root,
129                          struct extent_buffer *eb)
130 {
131         int slot;
132         int bad_slot;
133         int nr;
134         struct btrfs_disk_key bad_key;;
135
136         nr = btrfs_header_nritems(eb);
137         if (nr == 0)
138                 return;
139
140         slot = rand_range(nr);
141         bad_slot = rand_range(nr);
142
143         if (bad_slot == slot)
144                 return;
145
146         fprintf(stderr,
147                 "corrupting keys in block %llu slot %d swapping with %d\n",
148                 (unsigned long long)eb->start, slot, bad_slot);
149
150         if (btrfs_header_level(eb) == 0) {
151                 btrfs_item_key(eb, &bad_key, bad_slot);
152                 btrfs_set_item_key(eb, &bad_key, slot);
153         } else {
154                 btrfs_node_key(eb, &bad_key, bad_slot);
155                 btrfs_set_node_key(eb, &bad_key, slot);
156         }
157         btrfs_mark_buffer_dirty(eb);
158         if (!trans) {
159                 u16 csum_size =
160                         btrfs_super_csum_size(root->fs_info->super_copy);
161                 csum_tree_block_size(eb, csum_size, 0);
162                 write_extent_to_disk(eb);
163         }
164 }
165
166
167 static int corrupt_keys_in_block(struct btrfs_root *root, u64 bytenr)
168 {
169         struct extent_buffer *eb;
170
171         eb = read_tree_block(root, bytenr, root->nodesize, 0);
172         if (!extent_buffer_uptodate(eb))
173                 return -EIO;;
174
175         corrupt_keys(NULL, root, eb);
176         free_extent_buffer(eb);
177         return 0;
178 }
179
180 static int corrupt_extent(struct btrfs_trans_handle *trans,
181                           struct btrfs_root *root, u64 bytenr, u64 copy)
182 {
183         struct btrfs_key key;
184         struct extent_buffer *leaf;
185         u32 item_size;
186         unsigned long ptr;
187         struct btrfs_path *path;
188         int ret;
189         int slot;
190         int should_del = rand_range(3);
191
192         path = btrfs_alloc_path();
193         if (!path)
194                 return -ENOMEM;
195
196         key.objectid = bytenr;
197         key.type = (u8)-1;
198         key.offset = (u64)-1;
199
200         while(1) {
201                 ret = btrfs_search_slot(trans, root->fs_info->extent_root,
202                                         &key, path, -1, 1);
203                 if (ret < 0)
204                         break;
205
206                 if (ret > 0) {
207                         if (path->slots[0] == 0)
208                                 break;
209                         path->slots[0]--;
210                         ret = 0;
211                 }
212                 leaf = path->nodes[0];
213                 slot = path->slots[0];
214                 btrfs_item_key_to_cpu(leaf, &key, slot);
215                 if (key.objectid != bytenr)
216                         break;
217
218                 if (key.type != BTRFS_EXTENT_ITEM_KEY &&
219                     key.type != BTRFS_METADATA_ITEM_KEY &&
220                     key.type != BTRFS_TREE_BLOCK_REF_KEY &&
221                     key.type != BTRFS_EXTENT_DATA_REF_KEY &&
222                     key.type != BTRFS_EXTENT_REF_V0_KEY &&
223                     key.type != BTRFS_SHARED_BLOCK_REF_KEY &&
224                     key.type != BTRFS_SHARED_DATA_REF_KEY)
225                         goto next;
226
227                 if (should_del) {
228                         fprintf(stderr,
229                                 "deleting extent record: key %llu %u %llu\n",
230                                 key.objectid, key.type, key.offset);
231
232                         if (key.type == BTRFS_EXTENT_ITEM_KEY) {
233                                 /* make sure this extent doesn't get
234                                  * reused for other purposes */
235                                 btrfs_pin_extent(root->fs_info,
236                                                  key.objectid, key.offset);
237                         }
238
239                         btrfs_del_item(trans, root, path);
240                 } else {
241                         fprintf(stderr,
242                                 "corrupting extent record: key %llu %u %llu\n",
243                                 key.objectid, key.type, key.offset);
244                         ptr = btrfs_item_ptr_offset(leaf, slot);
245                         item_size = btrfs_item_size_nr(leaf, slot);
246                         memset_extent_buffer(leaf, 0, ptr, item_size);
247                         btrfs_mark_buffer_dirty(leaf);
248                 }
249 next:
250                 btrfs_release_path(path);
251
252                 if (key.offset > 0)
253                         key.offset--;
254                 if (key.offset == 0)
255                         break;
256         }
257
258         btrfs_free_path(path);
259         return 0;
260 }
261
262 static void btrfs_corrupt_extent_leaf(struct btrfs_trans_handle *trans,
263                                       struct btrfs_root *root,
264                                       struct extent_buffer *eb)
265 {
266         u32 nr = btrfs_header_nritems(eb);
267         u32 victim = rand_range(nr);
268         u64 objectid;
269         struct btrfs_key key;
270
271         btrfs_item_key_to_cpu(eb, &key, victim);
272         objectid = key.objectid;
273         corrupt_extent(trans, root, objectid, 1);
274 }
275
276 static void btrfs_corrupt_extent_tree(struct btrfs_trans_handle *trans,
277                                       struct btrfs_root *root,
278                                       struct extent_buffer *eb)
279 {
280         int i;
281
282         if (!eb)
283                 return;
284
285         if (btrfs_is_leaf(eb)) {
286                 btrfs_corrupt_extent_leaf(trans, root, eb);
287                 return;
288         }
289
290         if (btrfs_header_level(eb) == 1 && eb != root->node) {
291                 if (rand_range(5))
292                         return;
293         }
294
295         for (i = 0; i < btrfs_header_nritems(eb); i++) {
296                 struct extent_buffer *next;
297
298                 next = read_tree_block(root, btrfs_node_blockptr(eb, i),
299                                        root->nodesize,
300                                        btrfs_node_ptr_generation(eb, i));
301                 if (!extent_buffer_uptodate(next))
302                         continue;
303                 btrfs_corrupt_extent_tree(trans, root, next);
304                 free_extent_buffer(next);
305         }
306 }
307
308 enum btrfs_inode_field {
309         BTRFS_INODE_FIELD_ISIZE,
310         BTRFS_INODE_FIELD_NBYTES,
311         BTRFS_INODE_FIELD_BAD,
312 };
313
314 enum btrfs_file_extent_field {
315         BTRFS_FILE_EXTENT_DISK_BYTENR,
316         BTRFS_FILE_EXTENT_BAD,
317 };
318
319 enum btrfs_dir_item_field {
320         BTRFS_DIR_ITEM_NAME,
321         BTRFS_DIR_ITEM_LOCATION_OBJECTID,
322         BTRFS_DIR_ITEM_BAD,
323 };
324
325 enum btrfs_metadata_block_field {
326         BTRFS_METADATA_BLOCK_GENERATION,
327         BTRFS_METADATA_BLOCK_SHIFT_ITEMS,
328         BTRFS_METADATA_BLOCK_BAD,
329 };
330
331 enum btrfs_item_field {
332         BTRFS_ITEM_OFFSET,
333         BTRFS_ITEM_BAD,
334 };
335
336 enum btrfs_key_field {
337         BTRFS_KEY_OBJECTID,
338         BTRFS_KEY_TYPE,
339         BTRFS_KEY_OFFSET,
340         BTRFS_KEY_BAD,
341 };
342
343 static enum btrfs_inode_field convert_inode_field(char *field)
344 {
345         if (!strncmp(field, "isize", FIELD_BUF_LEN))
346                 return BTRFS_INODE_FIELD_ISIZE;
347         if (!strncmp(field, "nbytes", FIELD_BUF_LEN))
348                 return BTRFS_INODE_FIELD_NBYTES;
349         return BTRFS_INODE_FIELD_BAD;
350 }
351
352 static enum btrfs_file_extent_field convert_file_extent_field(char *field)
353 {
354         if (!strncmp(field, "disk_bytenr", FIELD_BUF_LEN))
355                 return BTRFS_FILE_EXTENT_DISK_BYTENR;
356         return BTRFS_FILE_EXTENT_BAD;
357 }
358
359 static enum btrfs_metadata_block_field
360 convert_metadata_block_field(char *field)
361 {
362         if (!strncmp(field, "generation", FIELD_BUF_LEN))
363                 return BTRFS_METADATA_BLOCK_GENERATION;
364         if (!strncmp(field, "shift_items", FIELD_BUF_LEN))
365                 return BTRFS_METADATA_BLOCK_SHIFT_ITEMS;
366         return BTRFS_METADATA_BLOCK_BAD;
367 }
368
369 static enum btrfs_key_field convert_key_field(char *field)
370 {
371         if (!strncmp(field, "objectid", FIELD_BUF_LEN))
372                 return BTRFS_KEY_OBJECTID;
373         if (!strncmp(field, "type", FIELD_BUF_LEN))
374                 return BTRFS_KEY_TYPE;
375         if (!strncmp(field, "offset", FIELD_BUF_LEN))
376                 return BTRFS_KEY_OFFSET;
377         return BTRFS_KEY_BAD;
378 }
379
380 static enum btrfs_item_field convert_item_field(char *field)
381 {
382         if (!strncmp(field, "offset", FIELD_BUF_LEN))
383                 return BTRFS_ITEM_OFFSET;
384         return BTRFS_ITEM_BAD;
385 }
386
387 static enum btrfs_dir_item_field convert_dir_item_field(char *field)
388 {
389         if (!strncmp(field, "name", FIELD_BUF_LEN))
390                 return BTRFS_DIR_ITEM_NAME;
391         if (!strncmp(field, "location_objectid", FIELD_BUF_LEN))
392                 return BTRFS_DIR_ITEM_LOCATION_OBJECTID;
393         return BTRFS_DIR_ITEM_BAD;
394 }
395
396 static u64 generate_u64(u64 orig)
397 {
398         u64 ret;
399         do {
400                 ret = rand_u64();
401         } while (ret == orig);
402         return ret;
403 }
404
405 static u32 generate_u32(u32 orig)
406 {
407         u32 ret;
408         do {
409                 ret = rand_u32();
410         } while (ret == orig);
411         return ret;
412 }
413
414 static u8 generate_u8(u8 orig)
415 {
416         u8 ret;
417         do {
418                 ret = rand_u8();
419         } while (ret == orig);
420         return ret;
421 }
422
423 static int corrupt_key(struct btrfs_root *root, struct btrfs_key *key,
424                        char *field)
425 {
426         enum btrfs_key_field corrupt_field = convert_key_field(field);
427         struct btrfs_path *path;
428         struct btrfs_trans_handle *trans;
429         int ret;
430
431         root = root->fs_info->fs_root;
432         if (corrupt_field == BTRFS_KEY_BAD) {
433                 fprintf(stderr, "Invalid field %s\n", field);
434                 return -EINVAL;
435         }
436
437         path = btrfs_alloc_path();
438         if (!path)
439                 return -ENOMEM;
440
441         trans = btrfs_start_transaction(root, 1);
442         if (IS_ERR(trans)) {
443                 btrfs_free_path(path);
444                 return PTR_ERR(trans);
445         }
446
447         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
448         if (ret < 0)
449                 goto out;
450         if (ret > 0) {
451                 fprintf(stderr, "Couldn't find the key to corrupt\n");
452                 ret = -ENOENT;
453                 goto out;
454         }
455
456         switch (corrupt_field) {
457         case BTRFS_KEY_OBJECTID:
458                 key->objectid = generate_u64(key->objectid);
459                 break;
460         case BTRFS_KEY_TYPE:
461                 key->type = generate_u8(key->type);
462                 break;
463         case BTRFS_KEY_OFFSET:
464                 key->offset = generate_u64(key->objectid);
465                 break;
466         default:
467                 fprintf(stderr, "Invalid field %s, %d\n", field,
468                         corrupt_field);
469                 ret = -EINVAL;
470                 goto out;
471         }
472
473         btrfs_set_item_key_unsafe(root, path, key);
474 out:
475         btrfs_free_path(path);
476         btrfs_commit_transaction(trans, root);
477         return ret;
478 }
479
480 static int corrupt_dir_item(struct btrfs_root *root, struct btrfs_key *key,
481                             char *field)
482 {
483         struct btrfs_trans_handle *trans;
484         struct btrfs_dir_item *di;
485         struct btrfs_path *path;
486         char name[PATH_MAX];
487         struct btrfs_key location;
488         struct btrfs_disk_key disk_key;
489         unsigned long name_ptr;
490         enum btrfs_dir_item_field corrupt_field =
491                 convert_dir_item_field(field);
492         u64 bogus;
493         u16 name_len;
494         int ret;
495
496         if (corrupt_field == BTRFS_DIR_ITEM_BAD) {
497                 fprintf(stderr, "Invalid field %s\n", field);
498                 return -EINVAL;
499         }
500
501         path = btrfs_alloc_path();
502         if (!path)
503                 return -ENOMEM;
504
505         trans = btrfs_start_transaction(root, 1);
506         if (IS_ERR(trans)) {
507                 btrfs_free_path(path);
508                 return PTR_ERR(trans);
509         }
510
511         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
512         if (ret) {
513                 if (ret > 0)
514                         ret = -ENOENT;
515                 fprintf(stderr, "Error searching for dir item %d\n", ret);
516                 goto out;
517         }
518
519         di = btrfs_item_ptr(path->nodes[0], path->slots[0],
520                             struct btrfs_dir_item);
521
522         switch (corrupt_field) {
523         case BTRFS_DIR_ITEM_NAME:
524                 name_len = btrfs_dir_name_len(path->nodes[0], di);
525                 name_ptr = (unsigned long)(di + 1);
526                 read_extent_buffer(path->nodes[0], name, name_ptr, name_len);
527                 name[0]++;
528                 write_extent_buffer(path->nodes[0], name, name_ptr, name_len);
529                 btrfs_mark_buffer_dirty(path->nodes[0]);
530                 goto out;
531         case BTRFS_DIR_ITEM_LOCATION_OBJECTID:
532                 btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
533                 bogus = generate_u64(location.objectid);
534                 location.objectid = bogus;
535                 btrfs_cpu_key_to_disk(&disk_key, &location);
536                 btrfs_set_dir_item_key(path->nodes[0], di, &disk_key);
537                 btrfs_mark_buffer_dirty(path->nodes[0]);
538                 goto out;
539         default:
540                 ret = -EINVAL;
541                 goto out;
542         }
543 out:
544         btrfs_commit_transaction(trans, root);
545         btrfs_free_path(path);
546         return ret;
547 }
548
549 static int corrupt_inode(struct btrfs_trans_handle *trans,
550                          struct btrfs_root *root, u64 inode, char *field)
551 {
552         struct btrfs_inode_item *ei;
553         struct btrfs_path *path;
554         struct btrfs_key key;
555         enum btrfs_inode_field corrupt_field = convert_inode_field(field);
556         u64 bogus;
557         u64 orig;
558         int ret;
559
560         if (corrupt_field == BTRFS_INODE_FIELD_BAD) {
561                 fprintf(stderr, "Invalid field %s\n", field);
562                 return -EINVAL;
563         }
564
565         key.objectid = inode;
566         key.type = BTRFS_INODE_ITEM_KEY;
567         key.offset = (u64)-1;
568
569         path = btrfs_alloc_path();
570         if (!path)
571                 return -ENOMEM;
572
573         ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
574         if (ret < 0)
575                 goto out;
576         if (ret) {
577                 if (!path->slots[0]) {
578                         fprintf(stderr, "Couldn't find inode %Lu\n", inode);
579                         ret = -ENOENT;
580                         goto out;
581                 }
582                 path->slots[0]--;
583                 ret = 0;
584         }
585
586         btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
587         if (key.objectid != inode) {
588                 fprintf(stderr, "Couldn't find inode %Lu\n", inode);
589                 ret = -ENOENT;
590                 goto out;
591         }
592
593         ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
594                             struct btrfs_inode_item);
595         switch (corrupt_field) {
596         case BTRFS_INODE_FIELD_ISIZE:
597                 orig = btrfs_inode_size(path->nodes[0], ei);
598                 bogus = generate_u64(orig);
599                 btrfs_set_inode_size(path->nodes[0], ei, bogus);
600                 break;
601         case BTRFS_INODE_FIELD_NBYTES:
602                 orig = btrfs_inode_nbytes(path->nodes[0], ei);
603                 bogus = generate_u64(orig);
604                 btrfs_set_inode_nbytes(path->nodes[0], ei, bogus);
605                 break;
606         default:
607                 ret = -EINVAL;
608                 break;
609         }
610         btrfs_mark_buffer_dirty(path->nodes[0]);
611 out:
612         btrfs_free_path(path);
613         return ret;
614 }
615
616 static int corrupt_file_extent(struct btrfs_trans_handle *trans,
617                                struct btrfs_root *root, u64 inode, u64 extent,
618                                char *field)
619 {
620         struct btrfs_file_extent_item *fi;
621         struct btrfs_path *path;
622         struct btrfs_key key;
623         enum btrfs_file_extent_field corrupt_field;
624         u64 bogus;
625         u64 orig;
626         int ret = 0;
627
628         corrupt_field = convert_file_extent_field(field);
629         if (corrupt_field == BTRFS_FILE_EXTENT_BAD) {
630                 fprintf(stderr, "Invalid field %s\n", field);
631                 return -EINVAL;
632         }
633
634         key.objectid = inode;
635         key.type = BTRFS_EXTENT_DATA_KEY;
636         key.offset = extent;
637
638         path = btrfs_alloc_path();
639         if (!path)
640                 return -ENOMEM;
641
642         ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
643         if (ret < 0)
644                 goto out;
645         if (ret) {
646                 fprintf(stderr, "Couldn't find extent %llu for inode %llu\n",
647                         extent, inode);
648                 ret = -ENOENT;
649                 goto out;
650         }
651
652         fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
653                             struct btrfs_file_extent_item);
654         switch (corrupt_field) {
655         case BTRFS_FILE_EXTENT_DISK_BYTENR:
656                 orig = btrfs_file_extent_disk_bytenr(path->nodes[0], fi);
657                 bogus = generate_u64(orig);
658                 btrfs_set_file_extent_disk_bytenr(path->nodes[0], fi, bogus);
659                 break;
660         default:
661                 ret = -EINVAL;
662                 break;
663         }
664         btrfs_mark_buffer_dirty(path->nodes[0]);
665 out:
666         btrfs_free_path(path);
667         return ret;
668 }
669
670 static void shift_items(struct btrfs_root *root, struct extent_buffer *eb)
671 {
672         int nritems = btrfs_header_nritems(eb);
673         int shift_space = btrfs_leaf_free_space(root, eb) / 2;
674         int slot = nritems / 2;
675         int i = 0;
676         unsigned int data_end = btrfs_item_offset_nr(eb, nritems - 1);
677
678         /* Shift the item data up to and including slot back by shift space */
679         memmove_extent_buffer(eb, btrfs_leaf_data(eb) + data_end - shift_space,
680                               btrfs_leaf_data(eb) + data_end,
681                               btrfs_item_offset_nr(eb, slot - 1) - data_end);
682
683         /* Now update the item pointers. */
684         for (i = nritems - 1; i >= slot; i--) {
685                 u32 offset = btrfs_item_offset_nr(eb, i);
686                 offset -= shift_space;
687                 btrfs_set_item_offset(eb, btrfs_item_nr(i), offset);
688         }
689 }
690
691 static int corrupt_metadata_block(struct btrfs_root *root, u64 block,
692                                   char *field)
693 {
694         struct btrfs_trans_handle *trans;
695         struct btrfs_path *path;
696         struct extent_buffer *eb;
697         struct btrfs_key key, root_key;
698         enum btrfs_metadata_block_field corrupt_field;
699         u64 root_objectid;
700         u64 orig, bogus;
701         u8 level;
702         int ret;
703
704         corrupt_field = convert_metadata_block_field(field);
705         if (corrupt_field == BTRFS_METADATA_BLOCK_BAD) {
706                 fprintf(stderr, "Invalid field %s\n", field);
707                 return -EINVAL;
708         }
709
710         eb = read_tree_block(root, block, root->nodesize, 0);
711         if (!extent_buffer_uptodate(eb)) {
712                 fprintf(stderr, "Couldn't read in tree block %s\n", field);
713                 return -EINVAL;
714         }
715         root_objectid = btrfs_header_owner(eb);
716         level = btrfs_header_level(eb);
717         if (level)
718                 btrfs_node_key_to_cpu(eb, &key, 0);
719         else
720                 btrfs_item_key_to_cpu(eb, &key, 0);
721         free_extent_buffer(eb);
722
723         root_key.objectid = root_objectid;
724         root_key.type = BTRFS_ROOT_ITEM_KEY;
725         root_key.offset = (u64)-1;
726
727         root = btrfs_read_fs_root(root->fs_info, &root_key);
728         if (IS_ERR(root)) {
729                 fprintf(stderr, "Couldn't find owner root %llu\n",
730                         key.objectid);
731                 return PTR_ERR(root);
732         }
733
734         path = btrfs_alloc_path();
735         if (!path)
736                 return -ENOMEM;
737
738         trans = btrfs_start_transaction(root, 1);
739         if (IS_ERR(trans)) {
740                 btrfs_free_path(path);
741                 fprintf(stderr, "Couldn't start transaction %ld\n",
742                         PTR_ERR(trans));
743                 return PTR_ERR(trans);
744         }
745
746         path->lowest_level = level;
747         ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
748         if (ret < 0) {
749                 fprintf(stderr, "Error searching to node %d\n", ret);
750                 goto out;
751         }
752         eb = path->nodes[level];
753
754         ret = 0;
755         switch (corrupt_field) {
756         case BTRFS_METADATA_BLOCK_GENERATION:
757                 orig = btrfs_header_generation(eb);
758                 bogus = generate_u64(orig);
759                 btrfs_set_header_generation(eb, bogus);
760                 break;
761         case BTRFS_METADATA_BLOCK_SHIFT_ITEMS:
762                 shift_items(root, path->nodes[level]);
763                 break;
764         default:
765                 ret = -EINVAL;
766                 break;
767         }
768         btrfs_mark_buffer_dirty(path->nodes[level]);
769 out:
770         btrfs_commit_transaction(trans, root);
771         btrfs_free_path(path);
772         return ret;
773 }
774
775 static int corrupt_btrfs_item(struct btrfs_root *root, struct btrfs_key *key,
776                               char *field)
777 {
778         struct btrfs_trans_handle *trans;
779         struct btrfs_path *path;
780         enum btrfs_item_field corrupt_field;
781         u32 orig, bogus;
782         int ret;
783
784         corrupt_field = convert_item_field(field);
785         if (corrupt_field == BTRFS_ITEM_BAD) {
786                 fprintf(stderr, "Invalid field %s\n", field);
787                 return -EINVAL;
788         }
789
790         path = btrfs_alloc_path();
791         if (!path)
792                 return -ENOMEM;
793
794         trans = btrfs_start_transaction(root, 1);
795         if (IS_ERR(trans)) {
796                 btrfs_free_path(path);
797                 fprintf(stderr, "Couldn't start transaction %ld\n",
798                         PTR_ERR(trans));
799                 return PTR_ERR(trans);
800         }
801
802         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
803         if (ret != 0) {
804                 fprintf(stderr, "Error searching to node %d\n", ret);
805                 goto out;
806         }
807
808         ret = 0;
809         switch (corrupt_field) {
810         case BTRFS_ITEM_OFFSET:
811                 orig = btrfs_item_offset_nr(path->nodes[0], path->slots[0]);
812                 bogus = generate_u32(orig);
813                 btrfs_set_item_offset(path->nodes[0],
814                                       btrfs_item_nr(path->slots[0]), bogus);
815                 break;
816         default:
817                 ret = -EINVAL;
818                 break;
819         }
820         btrfs_mark_buffer_dirty(path->nodes[0]);
821 out:
822         btrfs_commit_transaction(trans, root);
823         btrfs_free_path(path);
824         return ret;
825 }
826
827 static int delete_item(struct btrfs_root *root, struct btrfs_key *key)
828 {
829         struct btrfs_trans_handle *trans;
830         struct btrfs_path *path;
831         int ret;
832
833         path = btrfs_alloc_path();
834         if (!path)
835                 return -ENOMEM;
836
837         trans = btrfs_start_transaction(root, 1);
838         if (IS_ERR(trans)) {
839                 btrfs_free_path(path);
840                 fprintf(stderr, "Couldn't start transaction %ld\n",
841                         PTR_ERR(trans));
842                 return PTR_ERR(trans);
843         }
844
845         ret = btrfs_search_slot(trans, root, key, path, -1, 1);
846         if (ret) {
847                 if (ret > 0)
848                         ret = -ENOENT;
849                 fprintf(stderr, "Error searching to node %d\n", ret);
850                 goto out;
851         }
852         ret = btrfs_del_item(trans, root, path);
853         btrfs_mark_buffer_dirty(path->nodes[0]);
854 out:
855         btrfs_commit_transaction(trans, root);
856         btrfs_free_path(path);
857         return ret;
858 }
859
860 static int delete_csum(struct btrfs_root *root, u64 bytenr, u64 bytes)
861 {
862         struct btrfs_trans_handle *trans;
863         int ret;
864
865         root = root->fs_info->csum_root;
866         trans = btrfs_start_transaction(root, 1);
867         if (IS_ERR(trans)) {
868                 fprintf(stderr, "Couldn't start transaction %ld\n",
869                         PTR_ERR(trans));
870                 return PTR_ERR(trans);
871         }
872
873         ret = btrfs_del_csums(trans, root, bytenr, bytes);
874         if (ret)
875                 fprintf(stderr, "Error deleting csums %d\n", ret);
876         btrfs_commit_transaction(trans, root);
877         return ret;
878 }
879
880 /* corrupt item using NO cow.
881  * Because chunk recover will recover based on whole partition scanning,
882  * If using COW, chunk recover will use the old item to recover,
883  * which is still OK but we want to check the ability to rebuild chunk
884  * not only restore the old ones */
885 static int corrupt_item_nocow(struct btrfs_trans_handle *trans,
886                        struct btrfs_root *root, struct btrfs_path *path,
887                        int del)
888 {
889         int ret = 0;
890         struct btrfs_key key;
891         struct extent_buffer *leaf;
892         unsigned long ptr;
893         int slot;
894         u32 item_size;
895
896         leaf = path->nodes[0];
897         slot = path->slots[0];
898         /* Not deleting the first item of a leaf to keep leaf structure */
899         if (slot == 0)
900                 del = 0;
901         /* Only accept valid eb */
902         if (slot >= btrfs_header_nritems(leaf)) {
903                 error("invalid eb: no data or slot out of range: %d >= %d",
904                                 slot, btrfs_header_nritems(leaf));
905                 return -EINVAL;
906         }
907         btrfs_item_key_to_cpu(leaf, &key, slot);
908         if (del) {
909                 fprintf(stdout, "Deleting key and data [%llu, %u, %llu].\n",
910                         key.objectid, key.type, key.offset);
911                 btrfs_del_item(trans, root, path);
912         } else {
913                 fprintf(stdout, "Corrupting key and data [%llu, %u, %llu].\n",
914                         key.objectid, key.type, key.offset);
915                 ptr = btrfs_item_ptr_offset(leaf, slot);
916                 item_size = btrfs_item_size_nr(leaf, slot);
917                 memset_extent_buffer(leaf, 0, ptr, item_size);
918                 btrfs_mark_buffer_dirty(leaf);
919         }
920         return ret;
921 }
922 static int corrupt_chunk_tree(struct btrfs_trans_handle *trans,
923                        struct btrfs_root *root)
924 {
925         int ret;
926         int del;
927         int slot;
928         struct btrfs_path *path;
929         struct btrfs_key key;
930         struct btrfs_key found_key;
931         struct extent_buffer *leaf;
932
933         path = btrfs_alloc_path();
934         if (!path)
935                 return -ENOMEM;
936
937         key.objectid = (u64)-1;
938         key.offset = (u64)-1;
939         key.type = (u8)-1;
940
941         /* Here, cow and ins_len must equals 0 for the following reasons:
942          * 1) chunk recover is based on disk scanning, so COW should be
943          *    disabled in case the original chunk being scanned and
944          *    recovered using the old chunk.
945          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON will be
946          *    triggered.
947          */
948         ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
949         BUG_ON(ret == 0);
950         if (ret < 0) {
951                 fprintf(stderr, "Error searching tree\n");
952                 goto free_out;
953         }
954         /* corrupt/del dev_item first */
955         while (!btrfs_previous_item(root, path, 0, BTRFS_DEV_ITEM_KEY)) {
956                 slot = path->slots[0];
957                 leaf = path->nodes[0];
958                 del = rand_range(3);
959                 /* Never delete the first item to keep the leaf structure */
960                 if (path->slots[0] == 0)
961                         del = 0;
962                 ret = corrupt_item_nocow(trans, root, path, del);
963                 if (ret)
964                         goto free_out;
965         }
966         btrfs_release_path(path);
967
968         /* Here, cow and ins_len must equals 0 for the following reasons:
969          * 1) chunk recover is based on disk scanning, so COW should be
970          *    disabled in case the original chunk being scanned and
971          *    recovered using the old chunk.
972          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON will be
973          *    triggered.
974          */
975         ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
976         BUG_ON(ret == 0);
977         if (ret < 0) {
978                 fprintf(stderr, "Error searching tree\n");
979                 goto free_out;
980         }
981         /* corrupt/del chunk then*/
982         while (!btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY)) {
983                 slot = path->slots[0];
984                 leaf = path->nodes[0];
985                 del = rand_range(3);
986                 btrfs_item_key_to_cpu(leaf, &found_key, slot);
987                 ret = corrupt_item_nocow(trans, root, path, del);
988                 if (ret)
989                         goto free_out;
990         }
991 free_out:
992         btrfs_free_path(path);
993         return ret;
994 }
995 static int find_chunk_offset(struct btrfs_root *root,
996                       struct btrfs_path *path, u64 offset)
997 {
998         struct btrfs_key key;
999         int ret;
1000
1001         key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
1002         key.type = BTRFS_CHUNK_ITEM_KEY;
1003         key.offset = offset;
1004
1005         /* Here, cow and ins_len must equals 0 for following reasons:
1006          * 1) chunk recover is based on disk scanning, so COW should
1007          *    be disabled in case the original chunk being scanned
1008          *    and recovered using the old chunk.
1009          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON
1010          *    will be triggered.
1011          */
1012         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1013         if (ret > 0) {
1014                 fprintf(stderr, "Can't find chunk with given offset %llu\n",
1015                         offset);
1016                 goto out;
1017         }
1018         if (ret < 0) {
1019                 fprintf(stderr, "Error searching chunk\n");
1020                 goto out;
1021         }
1022 out:
1023         return ret;
1024
1025 }
1026 int main(int argc, char **argv)
1027 {
1028         struct cache_tree root_cache;
1029         struct btrfs_key key;
1030         struct btrfs_root *root;
1031         char *dev;
1032         /* chunk offset can be 0,so change to (u64)-1 */
1033         u64 logical = (u64)-1;
1034         int ret = 0;
1035         u64 copy = 0;
1036         u64 bytes = 4096;
1037         int extent_rec = 0;
1038         int extent_tree = 0;
1039         int corrupt_block_keys = 0;
1040         int chunk_rec = 0;
1041         int chunk_tree = 0;
1042         int corrupt_item = 0;
1043         int corrupt_di = 0;
1044         int delete = 0;
1045         u64 metadata_block = 0;
1046         u64 inode = 0;
1047         u64 file_extent = (u64)-1;
1048         u64 root_objectid = 0;
1049         u64 csum_bytenr = 0;
1050         char field[FIELD_BUF_LEN];
1051
1052         field[0] = '\0';
1053         memset(&key, 0, sizeof(key));
1054
1055         while(1) {
1056                 int c;
1057                 static const struct option long_options[] = {
1058                         /* { "byte-count", 1, NULL, 'b' }, */
1059                         { "logical", required_argument, NULL, 'l' },
1060                         { "copy", required_argument, NULL, 'c' },
1061                         { "bytes", required_argument, NULL, 'b' },
1062                         { "extent-record", no_argument, NULL, 'e' },
1063                         { "extent-tree", no_argument, NULL, 'E' },
1064                         { "keys", no_argument, NULL, 'k' },
1065                         { "chunk-record", no_argument, NULL, 'u' },
1066                         { "chunk-tree", no_argument, NULL, 'U' },
1067                         { "inode", required_argument, NULL, 'i'},
1068                         { "file-extent", required_argument, NULL, 'x'},
1069                         { "metadata-block", required_argument, NULL, 'm'},
1070                         { "field", required_argument, NULL, 'f'},
1071                         { "key", required_argument, NULL, 'K'},
1072                         { "item", no_argument, NULL, 'I'},
1073                         { "dir-item", no_argument, NULL, 'D'},
1074                         { "delete", no_argument, NULL, 'd'},
1075                         { "root", no_argument, NULL, 'r'},
1076                         { "csum", required_argument, NULL, 'C'},
1077                         { "help", no_argument, NULL, GETOPT_VAL_HELP},
1078                         { NULL, 0, NULL, 0 }
1079                 };
1080
1081                 c = getopt_long(argc, argv, "l:c:b:eEkuUi:f:x:m:K:IDdr:C:",
1082                                 long_options, NULL);
1083                 if (c < 0)
1084                         break;
1085                 switch(c) {
1086                         case 'l':
1087                                 logical = arg_strtou64(optarg);
1088                                 break;
1089                         case 'c':
1090                                 copy = arg_strtou64(optarg);
1091                                 break;
1092                         case 'b':
1093                                 bytes = arg_strtou64(optarg);
1094                                 break;
1095                         case 'e':
1096                                 extent_rec = 1;
1097                                 break;
1098                         case 'E':
1099                                 extent_tree = 1;
1100                                 break;
1101                         case 'k':
1102                                 corrupt_block_keys = 1;
1103                                 break;
1104                         case 'u':
1105                                 chunk_rec = 1;
1106                                 break;
1107                         case 'U':
1108                                 chunk_tree = 1;
1109                                 break;
1110                         case 'i':
1111                                 inode = arg_strtou64(optarg);
1112                                 break;
1113                         case 'f':
1114                                 strncpy(field, optarg, FIELD_BUF_LEN);
1115                                 break;
1116                         case 'x':
1117                                 file_extent = arg_strtou64(optarg);
1118                                 break;
1119                         case 'm':
1120                                 metadata_block = arg_strtou64(optarg);
1121                                 break;
1122                         case 'K':
1123                                 ret = sscanf(optarg, "%llu,%u,%llu",
1124                                              &key.objectid,
1125                                              (unsigned int *)&key.type,
1126                                              &key.offset);
1127                                 if (ret != 3) {
1128                                         fprintf(stderr, "error reading key "
1129                                                 "%d\n", errno);
1130                                         print_usage(1);
1131                                 }
1132                                 break;
1133                         case 'D':
1134                                 corrupt_di = 1;
1135                                 break;
1136                         case 'I':
1137                                 corrupt_item = 1;
1138                                 break;
1139                         case 'd':
1140                                 delete = 1;
1141                                 break;
1142                         case 'r':
1143                                 root_objectid = arg_strtou64(optarg);
1144                                 break;
1145                         case 'C':
1146                                 csum_bytenr = arg_strtou64(optarg);
1147                                 break;
1148                         case GETOPT_VAL_HELP:
1149                         default:
1150                                 print_usage(c != GETOPT_VAL_HELP);
1151                 }
1152         }
1153         set_argv0(argv);
1154         if (check_argc_min(argc - optind, 1))
1155                 print_usage(1);
1156         dev = argv[optind];
1157
1158         radix_tree_init();
1159         cache_tree_init(&root_cache);
1160
1161         root = open_ctree(dev, 0, OPEN_CTREE_WRITES);
1162         if (!root) {
1163                 fprintf(stderr, "Open ctree failed\n");
1164                 exit(1);
1165         }
1166         if (extent_rec) {
1167                 struct btrfs_trans_handle *trans;
1168
1169                 if (logical == (u64)-1)
1170                         print_usage(1);
1171                 trans = btrfs_start_transaction(root, 1);
1172                 ret = corrupt_extent (trans, root, logical, 0);
1173                 btrfs_commit_transaction(trans, root);
1174                 goto out_close;
1175         }
1176         if (extent_tree) {
1177                 struct btrfs_trans_handle *trans;
1178                 trans = btrfs_start_transaction(root, 1);
1179                 btrfs_corrupt_extent_tree(trans, root->fs_info->extent_root,
1180                                           root->fs_info->extent_root->node);
1181                 btrfs_commit_transaction(trans, root);
1182                 goto out_close;
1183         }
1184         if (chunk_rec) {
1185                 struct btrfs_trans_handle *trans;
1186                 struct btrfs_path *path;
1187                 int del;
1188
1189                 if (logical == (u64)-1)
1190                         print_usage(1);
1191                 del = rand_range(3);
1192                 path = btrfs_alloc_path();
1193                 if (!path) {
1194                         fprintf(stderr, "path allocation failed\n");
1195                         goto out_close;
1196                 }
1197
1198                 if (find_chunk_offset(root->fs_info->chunk_root, path,
1199                                       logical) != 0) {
1200                         btrfs_free_path(path);
1201                         goto out_close;
1202                 }
1203                 trans = btrfs_start_transaction(root, 1);
1204                 ret = corrupt_item_nocow(trans, root->fs_info->chunk_root,
1205                                          path, del);
1206                 if (ret < 0)
1207                         fprintf(stderr, "Failed to corrupt chunk record\n");
1208                 btrfs_commit_transaction(trans, root);
1209                 goto out_close;
1210         }
1211         if (chunk_tree) {
1212                 struct btrfs_trans_handle *trans;
1213                 trans = btrfs_start_transaction(root, 1);
1214                 ret = corrupt_chunk_tree(trans, root->fs_info->chunk_root);
1215                 if (ret < 0)
1216                         fprintf(stderr, "Failed to corrupt chunk tree\n");
1217                 btrfs_commit_transaction(trans, root);
1218                 goto out_close;
1219         }
1220         if (inode) {
1221                 struct btrfs_trans_handle *trans;
1222
1223                 if (*field == 0)
1224                         print_usage(1);
1225
1226                 trans = btrfs_start_transaction(root, 1);
1227                 if (file_extent == (u64)-1) {
1228                         printf("corrupting inode\n");
1229                         ret = corrupt_inode(trans, root, inode, field);
1230                 } else {
1231                         printf("corrupting file extent\n");
1232                         ret = corrupt_file_extent(trans, root, inode,
1233                                                   file_extent, field);
1234                 }
1235                 btrfs_commit_transaction(trans, root);
1236                 goto out_close;
1237         }
1238         if (metadata_block) {
1239                 if (*field == 0)
1240                         print_usage(1);
1241                 ret = corrupt_metadata_block(root, metadata_block, field);
1242                 goto out_close;
1243         }
1244         if (corrupt_di) {
1245                 if (!key.objectid || *field == 0)
1246                         print_usage(1);
1247                 ret = corrupt_dir_item(root, &key, field);
1248                 goto out_close;
1249         }
1250         if (csum_bytenr) {
1251                 ret = delete_csum(root, csum_bytenr, bytes);
1252                 goto out_close;
1253         }
1254         if (corrupt_item) {
1255                 if (!key.objectid)
1256                         print_usage(1);
1257                 ret = corrupt_btrfs_item(root, &key, field);
1258         }
1259         if (delete) {
1260                 struct btrfs_root *target = root;
1261
1262                 if (!key.objectid)
1263                         print_usage(1);
1264                 if (root_objectid) {
1265                         struct btrfs_key root_key;
1266
1267                         root_key.objectid = root_objectid;
1268                         root_key.type = BTRFS_ROOT_ITEM_KEY;
1269                         root_key.offset = (u64)-1;
1270
1271                         target = btrfs_read_fs_root(root->fs_info, &root_key);
1272                         if (IS_ERR(target)) {
1273                                 fprintf(stderr, "Couldn't find root %llu\n",
1274                                         (unsigned long long)root_objectid);
1275                                 print_usage(1);
1276                         }
1277                 }
1278                 ret = delete_item(target, &key);
1279                 goto out_close;
1280         }
1281         if (key.objectid || key.offset || key.type) {
1282                 if (*field == 0)
1283                         print_usage(1);
1284                 ret = corrupt_key(root, &key, field);
1285                 goto out_close;
1286         }
1287         /*
1288          * If we made it here and we have extent set then we didn't specify
1289          * inode and we're screwed.
1290          */
1291         if (file_extent != (u64)-1)
1292                 print_usage(1);
1293
1294         if (logical == (u64)-1)
1295                 print_usage(1);
1296
1297         if (bytes == 0)
1298                 bytes = root->sectorsize;
1299
1300         bytes = (bytes + root->sectorsize - 1) / root->sectorsize;
1301         bytes *= root->sectorsize;
1302
1303         while (bytes > 0) {
1304                 if (corrupt_block_keys) {
1305                         corrupt_keys_in_block(root, logical);
1306                 } else {
1307                         struct extent_buffer *eb;
1308
1309                         eb = btrfs_find_create_tree_block(root->fs_info,
1310                                         logical, root->sectorsize);
1311                         if (!eb) {
1312                                 error(
1313                 "not enough memory to allocate extent buffer for bytenr %llu",
1314                                         (unsigned long long)logical);
1315                                 ret = 1;
1316                                 goto out_close;
1317                         }
1318
1319                         debug_corrupt_block(eb, root, logical, root->sectorsize,
1320                                         copy);
1321                         free_extent_buffer(eb);
1322                 }
1323                 logical += root->sectorsize;
1324                 bytes -= root->sectorsize;
1325         }
1326         return ret;
1327 out_close:
1328         close_ctree(root);
1329         return ret;
1330 }