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