a2f35abc58ee49ea4770fd687b95e152c57d16d7
[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_NLINK,
312         BTRFS_INODE_FIELD_BAD,
313 };
314
315 enum btrfs_file_extent_field {
316         BTRFS_FILE_EXTENT_DISK_BYTENR,
317         BTRFS_FILE_EXTENT_BAD,
318 };
319
320 enum btrfs_dir_item_field {
321         BTRFS_DIR_ITEM_NAME,
322         BTRFS_DIR_ITEM_LOCATION_OBJECTID,
323         BTRFS_DIR_ITEM_BAD,
324 };
325
326 enum btrfs_metadata_block_field {
327         BTRFS_METADATA_BLOCK_GENERATION,
328         BTRFS_METADATA_BLOCK_SHIFT_ITEMS,
329         BTRFS_METADATA_BLOCK_BAD,
330 };
331
332 enum btrfs_item_field {
333         BTRFS_ITEM_OFFSET,
334         BTRFS_ITEM_BAD,
335 };
336
337 enum btrfs_key_field {
338         BTRFS_KEY_OBJECTID,
339         BTRFS_KEY_TYPE,
340         BTRFS_KEY_OFFSET,
341         BTRFS_KEY_BAD,
342 };
343
344 static enum btrfs_inode_field convert_inode_field(char *field)
345 {
346         if (!strncmp(field, "isize", FIELD_BUF_LEN))
347                 return BTRFS_INODE_FIELD_ISIZE;
348         if (!strncmp(field, "nbytes", FIELD_BUF_LEN))
349                 return BTRFS_INODE_FIELD_NBYTES;
350         if (!strncmp(field, "nlink", FIELD_BUF_LEN))
351                 return BTRFS_INODE_FIELD_NLINK;
352         return BTRFS_INODE_FIELD_BAD;
353 }
354
355 static enum btrfs_file_extent_field convert_file_extent_field(char *field)
356 {
357         if (!strncmp(field, "disk_bytenr", FIELD_BUF_LEN))
358                 return BTRFS_FILE_EXTENT_DISK_BYTENR;
359         return BTRFS_FILE_EXTENT_BAD;
360 }
361
362 static enum btrfs_metadata_block_field
363 convert_metadata_block_field(char *field)
364 {
365         if (!strncmp(field, "generation", FIELD_BUF_LEN))
366                 return BTRFS_METADATA_BLOCK_GENERATION;
367         if (!strncmp(field, "shift_items", FIELD_BUF_LEN))
368                 return BTRFS_METADATA_BLOCK_SHIFT_ITEMS;
369         return BTRFS_METADATA_BLOCK_BAD;
370 }
371
372 static enum btrfs_key_field convert_key_field(char *field)
373 {
374         if (!strncmp(field, "objectid", FIELD_BUF_LEN))
375                 return BTRFS_KEY_OBJECTID;
376         if (!strncmp(field, "type", FIELD_BUF_LEN))
377                 return BTRFS_KEY_TYPE;
378         if (!strncmp(field, "offset", FIELD_BUF_LEN))
379                 return BTRFS_KEY_OFFSET;
380         return BTRFS_KEY_BAD;
381 }
382
383 static enum btrfs_item_field convert_item_field(char *field)
384 {
385         if (!strncmp(field, "offset", FIELD_BUF_LEN))
386                 return BTRFS_ITEM_OFFSET;
387         return BTRFS_ITEM_BAD;
388 }
389
390 static enum btrfs_dir_item_field convert_dir_item_field(char *field)
391 {
392         if (!strncmp(field, "name", FIELD_BUF_LEN))
393                 return BTRFS_DIR_ITEM_NAME;
394         if (!strncmp(field, "location_objectid", FIELD_BUF_LEN))
395                 return BTRFS_DIR_ITEM_LOCATION_OBJECTID;
396         return BTRFS_DIR_ITEM_BAD;
397 }
398
399 static u64 generate_u64(u64 orig)
400 {
401         u64 ret;
402         do {
403                 ret = rand_u64();
404         } while (ret == orig);
405         return ret;
406 }
407
408 static u32 generate_u32(u32 orig)
409 {
410         u32 ret;
411         do {
412                 ret = rand_u32();
413         } while (ret == orig);
414         return ret;
415 }
416
417 static u8 generate_u8(u8 orig)
418 {
419         u8 ret;
420         do {
421                 ret = rand_u8();
422         } while (ret == orig);
423         return ret;
424 }
425
426 static int corrupt_key(struct btrfs_root *root, struct btrfs_key *key,
427                        char *field)
428 {
429         enum btrfs_key_field corrupt_field = convert_key_field(field);
430         struct btrfs_path *path;
431         struct btrfs_trans_handle *trans;
432         int ret;
433
434         root = root->fs_info->fs_root;
435         if (corrupt_field == BTRFS_KEY_BAD) {
436                 fprintf(stderr, "Invalid field %s\n", field);
437                 return -EINVAL;
438         }
439
440         path = btrfs_alloc_path();
441         if (!path)
442                 return -ENOMEM;
443
444         trans = btrfs_start_transaction(root, 1);
445         if (IS_ERR(trans)) {
446                 btrfs_free_path(path);
447                 return PTR_ERR(trans);
448         }
449
450         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
451         if (ret < 0)
452                 goto out;
453         if (ret > 0) {
454                 fprintf(stderr, "Couldn't find the key to corrupt\n");
455                 ret = -ENOENT;
456                 goto out;
457         }
458
459         switch (corrupt_field) {
460         case BTRFS_KEY_OBJECTID:
461                 key->objectid = generate_u64(key->objectid);
462                 break;
463         case BTRFS_KEY_TYPE:
464                 key->type = generate_u8(key->type);
465                 break;
466         case BTRFS_KEY_OFFSET:
467                 key->offset = generate_u64(key->objectid);
468                 break;
469         default:
470                 fprintf(stderr, "Invalid field %s, %d\n", field,
471                         corrupt_field);
472                 ret = -EINVAL;
473                 goto out;
474         }
475
476         btrfs_set_item_key_unsafe(root, path, key);
477 out:
478         btrfs_free_path(path);
479         btrfs_commit_transaction(trans, root);
480         return ret;
481 }
482
483 static int corrupt_dir_item(struct btrfs_root *root, struct btrfs_key *key,
484                             char *field)
485 {
486         struct btrfs_trans_handle *trans;
487         struct btrfs_dir_item *di;
488         struct btrfs_path *path;
489         char name[PATH_MAX];
490         struct btrfs_key location;
491         struct btrfs_disk_key disk_key;
492         unsigned long name_ptr;
493         enum btrfs_dir_item_field corrupt_field =
494                 convert_dir_item_field(field);
495         u64 bogus;
496         u16 name_len;
497         int ret;
498
499         if (corrupt_field == BTRFS_DIR_ITEM_BAD) {
500                 fprintf(stderr, "Invalid field %s\n", field);
501                 return -EINVAL;
502         }
503
504         path = btrfs_alloc_path();
505         if (!path)
506                 return -ENOMEM;
507
508         trans = btrfs_start_transaction(root, 1);
509         if (IS_ERR(trans)) {
510                 btrfs_free_path(path);
511                 return PTR_ERR(trans);
512         }
513
514         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
515         if (ret) {
516                 if (ret > 0)
517                         ret = -ENOENT;
518                 fprintf(stderr, "Error searching for dir item %d\n", ret);
519                 goto out;
520         }
521
522         di = btrfs_item_ptr(path->nodes[0], path->slots[0],
523                             struct btrfs_dir_item);
524
525         switch (corrupt_field) {
526         case BTRFS_DIR_ITEM_NAME:
527                 name_len = btrfs_dir_name_len(path->nodes[0], di);
528                 name_ptr = (unsigned long)(di + 1);
529                 read_extent_buffer(path->nodes[0], name, name_ptr, name_len);
530                 name[0]++;
531                 write_extent_buffer(path->nodes[0], name, name_ptr, name_len);
532                 btrfs_mark_buffer_dirty(path->nodes[0]);
533                 goto out;
534         case BTRFS_DIR_ITEM_LOCATION_OBJECTID:
535                 btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
536                 bogus = generate_u64(location.objectid);
537                 location.objectid = bogus;
538                 btrfs_cpu_key_to_disk(&disk_key, &location);
539                 btrfs_set_dir_item_key(path->nodes[0], di, &disk_key);
540                 btrfs_mark_buffer_dirty(path->nodes[0]);
541                 goto out;
542         default:
543                 ret = -EINVAL;
544                 goto out;
545         }
546 out:
547         btrfs_commit_transaction(trans, root);
548         btrfs_free_path(path);
549         return ret;
550 }
551
552 static int corrupt_inode(struct btrfs_trans_handle *trans,
553                          struct btrfs_root *root, u64 inode, char *field)
554 {
555         struct btrfs_inode_item *ei;
556         struct btrfs_path *path;
557         struct btrfs_key key;
558         enum btrfs_inode_field corrupt_field = convert_inode_field(field);
559         u64 bogus;
560         u64 orig;
561         int ret;
562
563         if (corrupt_field == BTRFS_INODE_FIELD_BAD) {
564                 fprintf(stderr, "Invalid field %s\n", field);
565                 return -EINVAL;
566         }
567
568         key.objectid = inode;
569         key.type = BTRFS_INODE_ITEM_KEY;
570         key.offset = (u64)-1;
571
572         path = btrfs_alloc_path();
573         if (!path)
574                 return -ENOMEM;
575
576         ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
577         if (ret < 0)
578                 goto out;
579         if (ret) {
580                 if (!path->slots[0]) {
581                         fprintf(stderr, "Couldn't find inode %Lu\n", inode);
582                         ret = -ENOENT;
583                         goto out;
584                 }
585                 path->slots[0]--;
586                 ret = 0;
587         }
588
589         btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
590         if (key.objectid != inode) {
591                 fprintf(stderr, "Couldn't find inode %Lu\n", inode);
592                 ret = -ENOENT;
593                 goto out;
594         }
595
596         ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
597                             struct btrfs_inode_item);
598         switch (corrupt_field) {
599         case BTRFS_INODE_FIELD_ISIZE:
600                 orig = btrfs_inode_size(path->nodes[0], ei);
601                 bogus = generate_u64(orig);
602                 btrfs_set_inode_size(path->nodes[0], ei, bogus);
603                 break;
604         case BTRFS_INODE_FIELD_NBYTES:
605                 orig = btrfs_inode_nbytes(path->nodes[0], ei);
606                 bogus = generate_u64(orig);
607                 btrfs_set_inode_nbytes(path->nodes[0], ei, bogus);
608                 break;
609         case BTRFS_INODE_FIELD_NLINK:
610                 orig = btrfs_inode_nlink(path->nodes[0], ei);
611                 bogus = generate_u32(orig);
612                 btrfs_set_inode_nlink(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         if (slot >= btrfs_header_nritems(leaf)) {
911                 error("invalid eb: no data or slot out of range: %d >= %d",
912                                 slot, btrfs_header_nritems(leaf));
913                 return -EINVAL;
914         }
915         btrfs_item_key_to_cpu(leaf, &key, slot);
916         if (del) {
917                 fprintf(stdout, "Deleting key and data [%llu, %u, %llu].\n",
918                         key.objectid, key.type, key.offset);
919                 btrfs_del_item(trans, root, path);
920         } else {
921                 fprintf(stdout, "Corrupting key and data [%llu, %u, %llu].\n",
922                         key.objectid, key.type, key.offset);
923                 ptr = btrfs_item_ptr_offset(leaf, slot);
924                 item_size = btrfs_item_size_nr(leaf, slot);
925                 memset_extent_buffer(leaf, 0, ptr, item_size);
926                 btrfs_mark_buffer_dirty(leaf);
927         }
928         return ret;
929 }
930 static int corrupt_chunk_tree(struct btrfs_trans_handle *trans,
931                        struct btrfs_root *root)
932 {
933         int ret;
934         int del;
935         int slot;
936         struct btrfs_path *path;
937         struct btrfs_key key;
938         struct btrfs_key found_key;
939         struct extent_buffer *leaf;
940
941         path = btrfs_alloc_path();
942         if (!path)
943                 return -ENOMEM;
944
945         key.objectid = (u64)-1;
946         key.offset = (u64)-1;
947         key.type = (u8)-1;
948
949         /* Here, cow and ins_len must equals 0 for the following reasons:
950          * 1) chunk recover is based on disk scanning, so COW should be
951          *    disabled in case the original chunk being scanned and
952          *    recovered using the old chunk.
953          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON will be
954          *    triggered.
955          */
956         ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
957         BUG_ON(ret == 0);
958         if (ret < 0) {
959                 fprintf(stderr, "Error searching tree\n");
960                 goto free_out;
961         }
962         /* corrupt/del dev_item first */
963         while (!btrfs_previous_item(root, path, 0, BTRFS_DEV_ITEM_KEY)) {
964                 slot = path->slots[0];
965                 leaf = path->nodes[0];
966                 del = rand_range(3);
967                 /* Never delete the first item to keep the leaf structure */
968                 if (path->slots[0] == 0)
969                         del = 0;
970                 ret = corrupt_item_nocow(trans, root, path, del);
971                 if (ret)
972                         goto free_out;
973         }
974         btrfs_release_path(path);
975
976         /* Here, cow and ins_len must equals 0 for the following reasons:
977          * 1) chunk recover is based on disk scanning, so COW should be
978          *    disabled in case the original chunk being scanned and
979          *    recovered using the old chunk.
980          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON will be
981          *    triggered.
982          */
983         ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
984         BUG_ON(ret == 0);
985         if (ret < 0) {
986                 fprintf(stderr, "Error searching tree\n");
987                 goto free_out;
988         }
989         /* corrupt/del chunk then*/
990         while (!btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY)) {
991                 slot = path->slots[0];
992                 leaf = path->nodes[0];
993                 del = rand_range(3);
994                 btrfs_item_key_to_cpu(leaf, &found_key, slot);
995                 ret = corrupt_item_nocow(trans, root, path, del);
996                 if (ret)
997                         goto free_out;
998         }
999 free_out:
1000         btrfs_free_path(path);
1001         return ret;
1002 }
1003 static int find_chunk_offset(struct btrfs_root *root,
1004                       struct btrfs_path *path, u64 offset)
1005 {
1006         struct btrfs_key key;
1007         int ret;
1008
1009         key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
1010         key.type = BTRFS_CHUNK_ITEM_KEY;
1011         key.offset = offset;
1012
1013         /* Here, cow and ins_len must equals 0 for following reasons:
1014          * 1) chunk recover is based on disk scanning, so COW should
1015          *    be disabled in case the original chunk being scanned
1016          *    and recovered using the old chunk.
1017          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON
1018          *    will be triggered.
1019          */
1020         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1021         if (ret > 0) {
1022                 fprintf(stderr, "Can't find chunk with given offset %llu\n",
1023                         offset);
1024                 goto out;
1025         }
1026         if (ret < 0) {
1027                 fprintf(stderr, "Error searching chunk\n");
1028                 goto out;
1029         }
1030 out:
1031         return ret;
1032
1033 }
1034 int main(int argc, char **argv)
1035 {
1036         struct cache_tree root_cache;
1037         struct btrfs_key key;
1038         struct btrfs_root *root;
1039         char *dev;
1040         /* chunk offset can be 0,so change to (u64)-1 */
1041         u64 logical = (u64)-1;
1042         int ret = 0;
1043         u64 copy = 0;
1044         u64 bytes = 4096;
1045         int extent_rec = 0;
1046         int extent_tree = 0;
1047         int corrupt_block_keys = 0;
1048         int chunk_rec = 0;
1049         int chunk_tree = 0;
1050         int corrupt_item = 0;
1051         int corrupt_di = 0;
1052         int delete = 0;
1053         u64 metadata_block = 0;
1054         u64 inode = 0;
1055         u64 file_extent = (u64)-1;
1056         u64 root_objectid = 0;
1057         u64 csum_bytenr = 0;
1058         char field[FIELD_BUF_LEN];
1059
1060         field[0] = '\0';
1061         memset(&key, 0, sizeof(key));
1062
1063         while(1) {
1064                 int c;
1065                 static const struct option long_options[] = {
1066                         /* { "byte-count", 1, NULL, 'b' }, */
1067                         { "logical", required_argument, NULL, 'l' },
1068                         { "copy", required_argument, NULL, 'c' },
1069                         { "bytes", required_argument, NULL, 'b' },
1070                         { "extent-record", no_argument, NULL, 'e' },
1071                         { "extent-tree", no_argument, NULL, 'E' },
1072                         { "keys", no_argument, NULL, 'k' },
1073                         { "chunk-record", no_argument, NULL, 'u' },
1074                         { "chunk-tree", no_argument, NULL, 'U' },
1075                         { "inode", required_argument, NULL, 'i'},
1076                         { "file-extent", required_argument, NULL, 'x'},
1077                         { "metadata-block", required_argument, NULL, 'm'},
1078                         { "field", required_argument, NULL, 'f'},
1079                         { "key", required_argument, NULL, 'K'},
1080                         { "item", no_argument, NULL, 'I'},
1081                         { "dir-item", no_argument, NULL, 'D'},
1082                         { "delete", no_argument, NULL, 'd'},
1083                         { "root", no_argument, NULL, 'r'},
1084                         { "csum", required_argument, NULL, 'C'},
1085                         { "help", no_argument, NULL, GETOPT_VAL_HELP},
1086                         { NULL, 0, NULL, 0 }
1087                 };
1088
1089                 c = getopt_long(argc, argv, "l:c:b:eEkuUi:f:x:m:K:IDdr:C:",
1090                                 long_options, NULL);
1091                 if (c < 0)
1092                         break;
1093                 switch(c) {
1094                         case 'l':
1095                                 logical = arg_strtou64(optarg);
1096                                 break;
1097                         case 'c':
1098                                 copy = arg_strtou64(optarg);
1099                                 break;
1100                         case 'b':
1101                                 bytes = arg_strtou64(optarg);
1102                                 break;
1103                         case 'e':
1104                                 extent_rec = 1;
1105                                 break;
1106                         case 'E':
1107                                 extent_tree = 1;
1108                                 break;
1109                         case 'k':
1110                                 corrupt_block_keys = 1;
1111                                 break;
1112                         case 'u':
1113                                 chunk_rec = 1;
1114                                 break;
1115                         case 'U':
1116                                 chunk_tree = 1;
1117                                 break;
1118                         case 'i':
1119                                 inode = arg_strtou64(optarg);
1120                                 break;
1121                         case 'f':
1122                                 strncpy(field, optarg, FIELD_BUF_LEN);
1123                                 break;
1124                         case 'x':
1125                                 file_extent = arg_strtou64(optarg);
1126                                 break;
1127                         case 'm':
1128                                 metadata_block = arg_strtou64(optarg);
1129                                 break;
1130                         case 'K':
1131                                 ret = sscanf(optarg, "%llu,%u,%llu",
1132                                              &key.objectid,
1133                                              (unsigned int *)&key.type,
1134                                              &key.offset);
1135                                 if (ret != 3) {
1136                                         fprintf(stderr, "error reading key "
1137                                                 "%d\n", errno);
1138                                         print_usage(1);
1139                                 }
1140                                 break;
1141                         case 'D':
1142                                 corrupt_di = 1;
1143                                 break;
1144                         case 'I':
1145                                 corrupt_item = 1;
1146                                 break;
1147                         case 'd':
1148                                 delete = 1;
1149                                 break;
1150                         case 'r':
1151                                 root_objectid = arg_strtou64(optarg);
1152                                 break;
1153                         case 'C':
1154                                 csum_bytenr = arg_strtou64(optarg);
1155                                 break;
1156                         case GETOPT_VAL_HELP:
1157                         default:
1158                                 print_usage(c != GETOPT_VAL_HELP);
1159                 }
1160         }
1161         set_argv0(argv);
1162         if (check_argc_min(argc - optind, 1))
1163                 print_usage(1);
1164         dev = argv[optind];
1165
1166         radix_tree_init();
1167         cache_tree_init(&root_cache);
1168
1169         root = open_ctree(dev, 0, OPEN_CTREE_WRITES);
1170         if (!root) {
1171                 fprintf(stderr, "Open ctree failed\n");
1172                 exit(1);
1173         }
1174         if (extent_rec) {
1175                 struct btrfs_trans_handle *trans;
1176
1177                 if (logical == (u64)-1)
1178                         print_usage(1);
1179                 trans = btrfs_start_transaction(root, 1);
1180                 ret = corrupt_extent (trans, root, logical, 0);
1181                 btrfs_commit_transaction(trans, root);
1182                 goto out_close;
1183         }
1184         if (extent_tree) {
1185                 struct btrfs_trans_handle *trans;
1186                 trans = btrfs_start_transaction(root, 1);
1187                 btrfs_corrupt_extent_tree(trans, root->fs_info->extent_root,
1188                                           root->fs_info->extent_root->node);
1189                 btrfs_commit_transaction(trans, root);
1190                 goto out_close;
1191         }
1192         if (chunk_rec) {
1193                 struct btrfs_trans_handle *trans;
1194                 struct btrfs_path *path;
1195                 int del;
1196
1197                 if (logical == (u64)-1)
1198                         print_usage(1);
1199                 del = rand_range(3);
1200                 path = btrfs_alloc_path();
1201                 if (!path) {
1202                         fprintf(stderr, "path allocation failed\n");
1203                         goto out_close;
1204                 }
1205
1206                 if (find_chunk_offset(root->fs_info->chunk_root, path,
1207                                       logical) != 0) {
1208                         btrfs_free_path(path);
1209                         goto out_close;
1210                 }
1211                 trans = btrfs_start_transaction(root, 1);
1212                 ret = corrupt_item_nocow(trans, root->fs_info->chunk_root,
1213                                          path, del);
1214                 if (ret < 0)
1215                         fprintf(stderr, "Failed to corrupt chunk record\n");
1216                 btrfs_commit_transaction(trans, root);
1217                 goto out_close;
1218         }
1219         if (chunk_tree) {
1220                 struct btrfs_trans_handle *trans;
1221                 trans = btrfs_start_transaction(root, 1);
1222                 ret = corrupt_chunk_tree(trans, root->fs_info->chunk_root);
1223                 if (ret < 0)
1224                         fprintf(stderr, "Failed to corrupt chunk tree\n");
1225                 btrfs_commit_transaction(trans, root);
1226                 goto out_close;
1227         }
1228         if (inode) {
1229                 struct btrfs_trans_handle *trans;
1230
1231                 if (*field == 0)
1232                         print_usage(1);
1233
1234                 trans = btrfs_start_transaction(root, 1);
1235                 if (file_extent == (u64)-1) {
1236                         printf("corrupting inode\n");
1237                         ret = corrupt_inode(trans, root, inode, field);
1238                 } else {
1239                         printf("corrupting file extent\n");
1240                         ret = corrupt_file_extent(trans, root, inode,
1241                                                   file_extent, field);
1242                 }
1243                 btrfs_commit_transaction(trans, root);
1244                 goto out_close;
1245         }
1246         if (metadata_block) {
1247                 if (*field == 0)
1248                         print_usage(1);
1249                 ret = corrupt_metadata_block(root, metadata_block, field);
1250                 goto out_close;
1251         }
1252         if (corrupt_di) {
1253                 if (!key.objectid || *field == 0)
1254                         print_usage(1);
1255                 ret = corrupt_dir_item(root, &key, field);
1256                 goto out_close;
1257         }
1258         if (csum_bytenr) {
1259                 ret = delete_csum(root, csum_bytenr, bytes);
1260                 goto out_close;
1261         }
1262         if (corrupt_item) {
1263                 if (!key.objectid)
1264                         print_usage(1);
1265                 ret = corrupt_btrfs_item(root, &key, field);
1266         }
1267         if (delete) {
1268                 struct btrfs_root *target = root;
1269
1270                 if (!key.objectid)
1271                         print_usage(1);
1272                 if (root_objectid) {
1273                         struct btrfs_key root_key;
1274
1275                         root_key.objectid = root_objectid;
1276                         root_key.type = BTRFS_ROOT_ITEM_KEY;
1277                         root_key.offset = (u64)-1;
1278
1279                         target = btrfs_read_fs_root(root->fs_info, &root_key);
1280                         if (IS_ERR(target)) {
1281                                 fprintf(stderr, "Couldn't find root %llu\n",
1282                                         (unsigned long long)root_objectid);
1283                                 print_usage(1);
1284                         }
1285                 }
1286                 ret = delete_item(target, &key);
1287                 goto out_close;
1288         }
1289         if (key.objectid || key.offset || key.type) {
1290                 if (*field == 0)
1291                         print_usage(1);
1292                 ret = corrupt_key(root, &key, field);
1293                 goto out_close;
1294         }
1295         /*
1296          * If we made it here and we have extent set then we didn't specify
1297          * inode and we're screwed.
1298          */
1299         if (file_extent != (u64)-1)
1300                 print_usage(1);
1301
1302         if (logical == (u64)-1)
1303                 print_usage(1);
1304
1305         if (bytes == 0)
1306                 bytes = root->sectorsize;
1307
1308         bytes = (bytes + root->sectorsize - 1) / root->sectorsize;
1309         bytes *= root->sectorsize;
1310
1311         while (bytes > 0) {
1312                 if (corrupt_block_keys) {
1313                         corrupt_keys_in_block(root, logical);
1314                 } else {
1315                         struct extent_buffer *eb;
1316
1317                         eb = btrfs_find_create_tree_block(root->fs_info,
1318                                         logical, root->sectorsize);
1319                         if (!eb) {
1320                                 error(
1321                 "not enough memory to allocate extent buffer for bytenr %llu",
1322                                         (unsigned long long)logical);
1323                                 ret = 1;
1324                                 goto out_close;
1325                         }
1326
1327                         debug_corrupt_block(eb, root, logical, root->sectorsize,
1328                                         copy);
1329                         free_extent_buffer(eb);
1330                 }
1331                 logical += root->sectorsize;
1332                 bytes -= root->sectorsize;
1333         }
1334         return ret;
1335 out_close:
1336         close_ctree(root);
1337         return ret;
1338 }