btrfs-progs: Refactor btrfs_map_block and its variants to use btrfs_fs_info
[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 #include "help.h"
35
36 #define FIELD_BUF_LEN 80
37
38 static int debug_corrupt_block(struct extent_buffer *eb,
39                 struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 copy)
40 {
41         int ret;
42         u64 length;
43         struct btrfs_multi_bio *multi = NULL;
44         struct btrfs_device *device;
45         int num_copies;
46         int mirror_num = 1;
47
48         length = blocksize;
49         while (1) {
50                 ret = btrfs_map_block(root->fs_info, READ, eb->start, &length,
51                                       &multi, 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_fs_info *fs_info,
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(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_fs_info *fs_info, u64 bytenr)
168 {
169         struct extent_buffer *eb;
170
171         eb = read_tree_block(fs_info, bytenr, fs_info->nodesize, 0);
172         if (!extent_buffer_uptodate(eb))
173                 return -EIO;;
174
175         corrupt_keys(NULL, fs_info, 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)
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);
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         struct btrfs_fs_info *fs_info = root->fs_info;
281         int i;
282
283         if (!eb)
284                 return;
285
286         if (btrfs_is_leaf(eb)) {
287                 btrfs_corrupt_extent_leaf(trans, root, eb);
288                 return;
289         }
290
291         if (btrfs_header_level(eb) == 1 && eb != root->node) {
292                 if (rand_range(5))
293                         return;
294         }
295
296         for (i = 0; i < btrfs_header_nritems(eb); i++) {
297                 struct extent_buffer *next;
298
299                 next = read_tree_block(fs_info, btrfs_node_blockptr(eb, i),
300                                        fs_info->nodesize,
301                                        btrfs_node_ptr_generation(eb, i));
302                 if (!extent_buffer_uptodate(next))
303                         continue;
304                 btrfs_corrupt_extent_tree(trans, root, next);
305                 free_extent_buffer(next);
306         }
307 }
308
309 enum btrfs_inode_field {
310         BTRFS_INODE_FIELD_ISIZE,
311         BTRFS_INODE_FIELD_NBYTES,
312         BTRFS_INODE_FIELD_NLINK,
313         BTRFS_INODE_FIELD_GENERATION,
314         BTRFS_INODE_FIELD_TRANSID,
315         BTRFS_INODE_FIELD_BLOCK_GROUP,
316         BTRFS_INODE_FIELD_MODE,
317         BTRFS_INODE_FIELD_UID,
318         BTRFS_INODE_FIELD_GID,
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         if (!strncmp(field, "nlink", FIELD_BUF_LEN))
358                 return BTRFS_INODE_FIELD_NLINK;
359         if (!strncmp(field, "generation", FIELD_BUF_LEN))
360                 return BTRFS_INODE_FIELD_GENERATION;
361         if (!strncmp(field, "transid", FIELD_BUF_LEN))
362                 return BTRFS_INODE_FIELD_TRANSID;
363         if (!strncmp(field, "block_group", FIELD_BUF_LEN))
364                 return BTRFS_INODE_FIELD_BLOCK_GROUP;
365         if (!strncmp(field, "mode", FIELD_BUF_LEN))
366                 return BTRFS_INODE_FIELD_MODE;
367         if (!strncmp(field, "uid", FIELD_BUF_LEN))
368                 return BTRFS_INODE_FIELD_UID;
369         if (!strncmp(field, "gid", FIELD_BUF_LEN))
370                 return BTRFS_INODE_FIELD_GID;
371         return BTRFS_INODE_FIELD_BAD;
372 }
373
374 static enum btrfs_file_extent_field convert_file_extent_field(char *field)
375 {
376         if (!strncmp(field, "disk_bytenr", FIELD_BUF_LEN))
377                 return BTRFS_FILE_EXTENT_DISK_BYTENR;
378         return BTRFS_FILE_EXTENT_BAD;
379 }
380
381 static enum btrfs_metadata_block_field
382 convert_metadata_block_field(char *field)
383 {
384         if (!strncmp(field, "generation", FIELD_BUF_LEN))
385                 return BTRFS_METADATA_BLOCK_GENERATION;
386         if (!strncmp(field, "shift_items", FIELD_BUF_LEN))
387                 return BTRFS_METADATA_BLOCK_SHIFT_ITEMS;
388         return BTRFS_METADATA_BLOCK_BAD;
389 }
390
391 static enum btrfs_key_field convert_key_field(char *field)
392 {
393         if (!strncmp(field, "objectid", FIELD_BUF_LEN))
394                 return BTRFS_KEY_OBJECTID;
395         if (!strncmp(field, "type", FIELD_BUF_LEN))
396                 return BTRFS_KEY_TYPE;
397         if (!strncmp(field, "offset", FIELD_BUF_LEN))
398                 return BTRFS_KEY_OFFSET;
399         return BTRFS_KEY_BAD;
400 }
401
402 static enum btrfs_item_field convert_item_field(char *field)
403 {
404         if (!strncmp(field, "offset", FIELD_BUF_LEN))
405                 return BTRFS_ITEM_OFFSET;
406         return BTRFS_ITEM_BAD;
407 }
408
409 static enum btrfs_dir_item_field convert_dir_item_field(char *field)
410 {
411         if (!strncmp(field, "name", FIELD_BUF_LEN))
412                 return BTRFS_DIR_ITEM_NAME;
413         if (!strncmp(field, "location_objectid", FIELD_BUF_LEN))
414                 return BTRFS_DIR_ITEM_LOCATION_OBJECTID;
415         return BTRFS_DIR_ITEM_BAD;
416 }
417
418 static u64 generate_u64(u64 orig)
419 {
420         u64 ret;
421         do {
422                 ret = rand_u64();
423         } while (ret == orig);
424         return ret;
425 }
426
427 static u32 generate_u32(u32 orig)
428 {
429         u32 ret;
430         do {
431                 ret = rand_u32();
432         } while (ret == orig);
433         return ret;
434 }
435
436 static u8 generate_u8(u8 orig)
437 {
438         u8 ret;
439         do {
440                 ret = rand_u8();
441         } while (ret == orig);
442         return ret;
443 }
444
445 static int corrupt_key(struct btrfs_root *root, struct btrfs_key *key,
446                        char *field)
447 {
448         enum btrfs_key_field corrupt_field = convert_key_field(field);
449         struct btrfs_path *path;
450         struct btrfs_trans_handle *trans;
451         int ret;
452
453         root = root->fs_info->fs_root;
454         if (corrupt_field == BTRFS_KEY_BAD) {
455                 fprintf(stderr, "Invalid field %s\n", field);
456                 return -EINVAL;
457         }
458
459         path = btrfs_alloc_path();
460         if (!path)
461                 return -ENOMEM;
462
463         trans = btrfs_start_transaction(root, 1);
464         if (IS_ERR(trans)) {
465                 btrfs_free_path(path);
466                 return PTR_ERR(trans);
467         }
468
469         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
470         if (ret < 0)
471                 goto out;
472         if (ret > 0) {
473                 fprintf(stderr, "Couldn't find the key to corrupt\n");
474                 ret = -ENOENT;
475                 goto out;
476         }
477
478         switch (corrupt_field) {
479         case BTRFS_KEY_OBJECTID:
480                 key->objectid = generate_u64(key->objectid);
481                 break;
482         case BTRFS_KEY_TYPE:
483                 key->type = generate_u8(key->type);
484                 break;
485         case BTRFS_KEY_OFFSET:
486                 key->offset = generate_u64(key->objectid);
487                 break;
488         default:
489                 fprintf(stderr, "Invalid field %s, %d\n", field,
490                         corrupt_field);
491                 ret = -EINVAL;
492                 goto out;
493         }
494
495         btrfs_set_item_key_unsafe(root, path, key);
496 out:
497         btrfs_free_path(path);
498         btrfs_commit_transaction(trans, root);
499         return ret;
500 }
501
502 static int corrupt_dir_item(struct btrfs_root *root, struct btrfs_key *key,
503                             char *field)
504 {
505         struct btrfs_trans_handle *trans;
506         struct btrfs_dir_item *di;
507         struct btrfs_path *path;
508         char name[PATH_MAX];
509         struct btrfs_key location;
510         struct btrfs_disk_key disk_key;
511         unsigned long name_ptr;
512         enum btrfs_dir_item_field corrupt_field =
513                 convert_dir_item_field(field);
514         u64 bogus;
515         u16 name_len;
516         int ret;
517
518         if (corrupt_field == BTRFS_DIR_ITEM_BAD) {
519                 fprintf(stderr, "Invalid field %s\n", field);
520                 return -EINVAL;
521         }
522
523         path = btrfs_alloc_path();
524         if (!path)
525                 return -ENOMEM;
526
527         trans = btrfs_start_transaction(root, 1);
528         if (IS_ERR(trans)) {
529                 btrfs_free_path(path);
530                 return PTR_ERR(trans);
531         }
532
533         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
534         if (ret) {
535                 if (ret > 0)
536                         ret = -ENOENT;
537                 fprintf(stderr, "Error searching for dir item %d\n", ret);
538                 goto out;
539         }
540
541         di = btrfs_item_ptr(path->nodes[0], path->slots[0],
542                             struct btrfs_dir_item);
543
544         switch (corrupt_field) {
545         case BTRFS_DIR_ITEM_NAME:
546                 name_len = btrfs_dir_name_len(path->nodes[0], di);
547                 name_ptr = (unsigned long)(di + 1);
548                 read_extent_buffer(path->nodes[0], name, name_ptr, name_len);
549                 name[0]++;
550                 write_extent_buffer(path->nodes[0], name, name_ptr, name_len);
551                 btrfs_mark_buffer_dirty(path->nodes[0]);
552                 goto out;
553         case BTRFS_DIR_ITEM_LOCATION_OBJECTID:
554                 btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
555                 bogus = generate_u64(location.objectid);
556                 location.objectid = bogus;
557                 btrfs_cpu_key_to_disk(&disk_key, &location);
558                 btrfs_set_dir_item_key(path->nodes[0], di, &disk_key);
559                 btrfs_mark_buffer_dirty(path->nodes[0]);
560                 goto out;
561         default:
562                 ret = -EINVAL;
563                 goto out;
564         }
565 out:
566         btrfs_commit_transaction(trans, root);
567         btrfs_free_path(path);
568         return ret;
569 }
570
571 static int corrupt_inode(struct btrfs_trans_handle *trans,
572                          struct btrfs_root *root, u64 inode, char *field)
573 {
574         struct btrfs_inode_item *ei;
575         struct btrfs_path *path;
576         struct btrfs_key key;
577         enum btrfs_inode_field corrupt_field = convert_inode_field(field);
578         u64 bogus;
579         u64 orig;
580         int ret;
581
582         if (corrupt_field == BTRFS_INODE_FIELD_BAD) {
583                 fprintf(stderr, "Invalid field %s\n", field);
584                 return -EINVAL;
585         }
586
587         key.objectid = inode;
588         key.type = BTRFS_INODE_ITEM_KEY;
589         key.offset = (u64)-1;
590
591         path = btrfs_alloc_path();
592         if (!path)
593                 return -ENOMEM;
594
595         ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
596         if (ret < 0)
597                 goto out;
598         if (ret) {
599                 if (!path->slots[0]) {
600                         fprintf(stderr, "Couldn't find inode %Lu\n", inode);
601                         ret = -ENOENT;
602                         goto out;
603                 }
604                 path->slots[0]--;
605                 ret = 0;
606         }
607
608         btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
609         if (key.objectid != inode) {
610                 fprintf(stderr, "Couldn't find inode %Lu\n", inode);
611                 ret = -ENOENT;
612                 goto out;
613         }
614
615         ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
616                             struct btrfs_inode_item);
617         switch (corrupt_field) {
618         case BTRFS_INODE_FIELD_ISIZE:
619                 orig = btrfs_inode_size(path->nodes[0], ei);
620                 bogus = generate_u64(orig);
621                 btrfs_set_inode_size(path->nodes[0], ei, bogus);
622                 break;
623         case BTRFS_INODE_FIELD_NBYTES:
624                 orig = btrfs_inode_nbytes(path->nodes[0], ei);
625                 bogus = generate_u64(orig);
626                 btrfs_set_inode_nbytes(path->nodes[0], ei, bogus);
627                 break;
628         case BTRFS_INODE_FIELD_NLINK:
629                 orig = btrfs_inode_nlink(path->nodes[0], ei);
630                 bogus = generate_u32(orig);
631                 btrfs_set_inode_nlink(path->nodes[0], ei, bogus);
632                 break;
633         case BTRFS_INODE_FIELD_GENERATION:
634                 orig = btrfs_inode_generation(path->nodes[0], ei);
635                 bogus = generate_u64(orig);
636                 btrfs_set_inode_generation(path->nodes[0], ei, bogus);
637                 break;
638         case BTRFS_INODE_FIELD_TRANSID:
639                 orig = btrfs_inode_transid(path->nodes[0], ei);
640                 bogus = generate_u64(orig);
641                 btrfs_set_inode_transid(path->nodes[0], ei, bogus);
642                 break;
643         case BTRFS_INODE_FIELD_BLOCK_GROUP:
644                 orig = btrfs_inode_block_group(path->nodes[0], ei);
645                 bogus = generate_u64(orig);
646                 btrfs_set_inode_block_group(path->nodes[0], ei, bogus);
647                 break;
648         case BTRFS_INODE_FIELD_MODE:
649                 orig = btrfs_inode_mode(path->nodes[0], ei);
650                 bogus = generate_u32(orig);
651                 btrfs_set_inode_mode(path->nodes[0], ei, bogus);
652                 break;
653         case BTRFS_INODE_FIELD_UID:
654                 orig = btrfs_inode_uid(path->nodes[0], ei);
655                 bogus = generate_u32(orig);
656                 btrfs_set_inode_uid(path->nodes[0], ei, bogus);
657                 break;
658         case BTRFS_INODE_FIELD_GID:
659                 orig = btrfs_inode_gid(path->nodes[0], ei);
660                 bogus = generate_u32(orig);
661                 btrfs_set_inode_gid(path->nodes[0], ei, bogus);
662                 break;
663         default:
664                 ret = -EINVAL;
665                 break;
666         }
667         btrfs_mark_buffer_dirty(path->nodes[0]);
668 out:
669         btrfs_free_path(path);
670         return ret;
671 }
672
673 static int corrupt_file_extent(struct btrfs_trans_handle *trans,
674                                struct btrfs_root *root, u64 inode, u64 extent,
675                                char *field)
676 {
677         struct btrfs_file_extent_item *fi;
678         struct btrfs_path *path;
679         struct btrfs_key key;
680         enum btrfs_file_extent_field corrupt_field;
681         u64 bogus;
682         u64 orig;
683         int ret = 0;
684
685         corrupt_field = convert_file_extent_field(field);
686         if (corrupt_field == BTRFS_FILE_EXTENT_BAD) {
687                 fprintf(stderr, "Invalid field %s\n", field);
688                 return -EINVAL;
689         }
690
691         key.objectid = inode;
692         key.type = BTRFS_EXTENT_DATA_KEY;
693         key.offset = extent;
694
695         path = btrfs_alloc_path();
696         if (!path)
697                 return -ENOMEM;
698
699         ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
700         if (ret < 0)
701                 goto out;
702         if (ret) {
703                 fprintf(stderr, "Couldn't find extent %llu for inode %llu\n",
704                         extent, inode);
705                 ret = -ENOENT;
706                 goto out;
707         }
708
709         fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
710                             struct btrfs_file_extent_item);
711         switch (corrupt_field) {
712         case BTRFS_FILE_EXTENT_DISK_BYTENR:
713                 orig = btrfs_file_extent_disk_bytenr(path->nodes[0], fi);
714                 bogus = generate_u64(orig);
715                 btrfs_set_file_extent_disk_bytenr(path->nodes[0], fi, bogus);
716                 break;
717         default:
718                 ret = -EINVAL;
719                 break;
720         }
721         btrfs_mark_buffer_dirty(path->nodes[0]);
722 out:
723         btrfs_free_path(path);
724         return ret;
725 }
726
727 static void shift_items(struct btrfs_root *root, struct extent_buffer *eb)
728 {
729         int nritems = btrfs_header_nritems(eb);
730         int shift_space = btrfs_leaf_free_space(root, eb) / 2;
731         int slot = nritems / 2;
732         int i = 0;
733         unsigned int data_end = btrfs_item_offset_nr(eb, nritems - 1);
734
735         /* Shift the item data up to and including slot back by shift space */
736         memmove_extent_buffer(eb, btrfs_leaf_data(eb) + data_end - shift_space,
737                               btrfs_leaf_data(eb) + data_end,
738                               btrfs_item_offset_nr(eb, slot - 1) - data_end);
739
740         /* Now update the item pointers. */
741         for (i = nritems - 1; i >= slot; i--) {
742                 u32 offset = btrfs_item_offset_nr(eb, i);
743                 offset -= shift_space;
744                 btrfs_set_item_offset(eb, btrfs_item_nr(i), offset);
745         }
746 }
747
748 static int corrupt_metadata_block(struct btrfs_fs_info *fs_info, u64 block,
749                                   char *field)
750 {
751         struct btrfs_trans_handle *trans;
752         struct btrfs_root *root;
753         struct btrfs_path *path;
754         struct extent_buffer *eb;
755         struct btrfs_key key, root_key;
756         enum btrfs_metadata_block_field corrupt_field;
757         u64 root_objectid;
758         u64 orig, bogus;
759         u8 level;
760         int ret;
761
762         corrupt_field = convert_metadata_block_field(field);
763         if (corrupt_field == BTRFS_METADATA_BLOCK_BAD) {
764                 fprintf(stderr, "Invalid field %s\n", field);
765                 return -EINVAL;
766         }
767
768         eb = read_tree_block(fs_info, block, fs_info->nodesize, 0);
769         if (!extent_buffer_uptodate(eb)) {
770                 fprintf(stderr, "Couldn't read in tree block %s\n", field);
771                 return -EINVAL;
772         }
773         root_objectid = btrfs_header_owner(eb);
774         level = btrfs_header_level(eb);
775         if (level)
776                 btrfs_node_key_to_cpu(eb, &key, 0);
777         else
778                 btrfs_item_key_to_cpu(eb, &key, 0);
779         free_extent_buffer(eb);
780
781         root_key.objectid = root_objectid;
782         root_key.type = BTRFS_ROOT_ITEM_KEY;
783         root_key.offset = (u64)-1;
784
785         root = btrfs_read_fs_root(fs_info, &root_key);
786         if (IS_ERR(root)) {
787                 fprintf(stderr, "Couldn't find owner root %llu\n",
788                         key.objectid);
789                 return PTR_ERR(root);
790         }
791
792         path = btrfs_alloc_path();
793         if (!path)
794                 return -ENOMEM;
795
796         trans = btrfs_start_transaction(root, 1);
797         if (IS_ERR(trans)) {
798                 btrfs_free_path(path);
799                 fprintf(stderr, "Couldn't start transaction %ld\n",
800                         PTR_ERR(trans));
801                 return PTR_ERR(trans);
802         }
803
804         path->lowest_level = level;
805         ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
806         if (ret < 0) {
807                 fprintf(stderr, "Error searching to node %d\n", ret);
808                 goto out;
809         }
810         eb = path->nodes[level];
811
812         ret = 0;
813         switch (corrupt_field) {
814         case BTRFS_METADATA_BLOCK_GENERATION:
815                 orig = btrfs_header_generation(eb);
816                 bogus = generate_u64(orig);
817                 btrfs_set_header_generation(eb, bogus);
818                 break;
819         case BTRFS_METADATA_BLOCK_SHIFT_ITEMS:
820                 shift_items(root, path->nodes[level]);
821                 break;
822         default:
823                 ret = -EINVAL;
824                 break;
825         }
826         btrfs_mark_buffer_dirty(path->nodes[level]);
827 out:
828         btrfs_commit_transaction(trans, root);
829         btrfs_free_path(path);
830         return ret;
831 }
832
833 static int corrupt_btrfs_item(struct btrfs_root *root, struct btrfs_key *key,
834                               char *field)
835 {
836         struct btrfs_trans_handle *trans;
837         struct btrfs_path *path;
838         enum btrfs_item_field corrupt_field;
839         u32 orig, bogus;
840         int ret;
841
842         corrupt_field = convert_item_field(field);
843         if (corrupt_field == BTRFS_ITEM_BAD) {
844                 fprintf(stderr, "Invalid field %s\n", field);
845                 return -EINVAL;
846         }
847
848         path = btrfs_alloc_path();
849         if (!path)
850                 return -ENOMEM;
851
852         trans = btrfs_start_transaction(root, 1);
853         if (IS_ERR(trans)) {
854                 btrfs_free_path(path);
855                 fprintf(stderr, "Couldn't start transaction %ld\n",
856                         PTR_ERR(trans));
857                 return PTR_ERR(trans);
858         }
859
860         ret = btrfs_search_slot(trans, root, key, path, 0, 1);
861         if (ret != 0) {
862                 fprintf(stderr, "Error searching to node %d\n", ret);
863                 goto out;
864         }
865
866         ret = 0;
867         switch (corrupt_field) {
868         case BTRFS_ITEM_OFFSET:
869                 orig = btrfs_item_offset_nr(path->nodes[0], path->slots[0]);
870                 bogus = generate_u32(orig);
871                 btrfs_set_item_offset(path->nodes[0],
872                                       btrfs_item_nr(path->slots[0]), bogus);
873                 break;
874         default:
875                 ret = -EINVAL;
876                 break;
877         }
878         btrfs_mark_buffer_dirty(path->nodes[0]);
879 out:
880         btrfs_commit_transaction(trans, root);
881         btrfs_free_path(path);
882         return ret;
883 }
884
885 static int delete_item(struct btrfs_root *root, struct btrfs_key *key)
886 {
887         struct btrfs_trans_handle *trans;
888         struct btrfs_path *path;
889         int ret;
890
891         path = btrfs_alloc_path();
892         if (!path)
893                 return -ENOMEM;
894
895         trans = btrfs_start_transaction(root, 1);
896         if (IS_ERR(trans)) {
897                 btrfs_free_path(path);
898                 fprintf(stderr, "Couldn't start transaction %ld\n",
899                         PTR_ERR(trans));
900                 return PTR_ERR(trans);
901         }
902
903         ret = btrfs_search_slot(trans, root, key, path, -1, 1);
904         if (ret) {
905                 if (ret > 0)
906                         ret = -ENOENT;
907                 fprintf(stderr, "Error searching to node %d\n", ret);
908                 goto out;
909         }
910         ret = btrfs_del_item(trans, root, path);
911         btrfs_mark_buffer_dirty(path->nodes[0]);
912 out:
913         btrfs_commit_transaction(trans, root);
914         btrfs_free_path(path);
915         return ret;
916 }
917
918 static int delete_csum(struct btrfs_root *root, u64 bytenr, u64 bytes)
919 {
920         struct btrfs_trans_handle *trans;
921         int ret;
922
923         root = root->fs_info->csum_root;
924         trans = btrfs_start_transaction(root, 1);
925         if (IS_ERR(trans)) {
926                 fprintf(stderr, "Couldn't start transaction %ld\n",
927                         PTR_ERR(trans));
928                 return PTR_ERR(trans);
929         }
930
931         ret = btrfs_del_csums(trans, root, bytenr, bytes);
932         if (ret)
933                 fprintf(stderr, "Error deleting csums %d\n", ret);
934         btrfs_commit_transaction(trans, root);
935         return ret;
936 }
937
938 /* corrupt item using NO cow.
939  * Because chunk recover will recover based on whole partition scanning,
940  * If using COW, chunk recover will use the old item to recover,
941  * which is still OK but we want to check the ability to rebuild chunk
942  * not only restore the old ones */
943 static int corrupt_item_nocow(struct btrfs_trans_handle *trans,
944                        struct btrfs_root *root, struct btrfs_path *path,
945                        int del)
946 {
947         int ret = 0;
948         struct btrfs_key key;
949         struct extent_buffer *leaf;
950         unsigned long ptr;
951         int slot;
952         u32 item_size;
953
954         leaf = path->nodes[0];
955         slot = path->slots[0];
956         /* Not deleting the first item of a leaf to keep leaf structure */
957         if (slot == 0)
958                 del = 0;
959         /* Only accept valid eb */
960         if (slot >= btrfs_header_nritems(leaf)) {
961                 error("invalid eb: no data or slot out of range: %d >= %d",
962                                 slot, btrfs_header_nritems(leaf));
963                 return -EINVAL;
964         }
965         btrfs_item_key_to_cpu(leaf, &key, slot);
966         if (del) {
967                 fprintf(stdout, "Deleting key and data [%llu, %u, %llu].\n",
968                         key.objectid, key.type, key.offset);
969                 btrfs_del_item(trans, root, path);
970         } else {
971                 fprintf(stdout, "Corrupting key and data [%llu, %u, %llu].\n",
972                         key.objectid, key.type, key.offset);
973                 ptr = btrfs_item_ptr_offset(leaf, slot);
974                 item_size = btrfs_item_size_nr(leaf, slot);
975                 memset_extent_buffer(leaf, 0, ptr, item_size);
976                 btrfs_mark_buffer_dirty(leaf);
977         }
978         return ret;
979 }
980 static int corrupt_chunk_tree(struct btrfs_trans_handle *trans,
981                        struct btrfs_root *root)
982 {
983         int ret;
984         int del;
985         int slot;
986         struct btrfs_path *path;
987         struct btrfs_key key;
988         struct btrfs_key found_key;
989         struct extent_buffer *leaf;
990
991         path = btrfs_alloc_path();
992         if (!path)
993                 return -ENOMEM;
994
995         key.objectid = (u64)-1;
996         key.offset = (u64)-1;
997         key.type = (u8)-1;
998
999         /* Here, cow and ins_len must equals 0 for the following reasons:
1000          * 1) chunk recover is based on disk scanning, so COW should be
1001          *    disabled in case the original chunk being scanned and
1002          *    recovered using the old chunk.
1003          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON will be
1004          *    triggered.
1005          */
1006         ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
1007         BUG_ON(ret == 0);
1008         if (ret < 0) {
1009                 fprintf(stderr, "Error searching tree\n");
1010                 goto free_out;
1011         }
1012         /* corrupt/del dev_item first */
1013         while (!btrfs_previous_item(root, path, 0, BTRFS_DEV_ITEM_KEY)) {
1014                 slot = path->slots[0];
1015                 leaf = path->nodes[0];
1016                 del = rand_range(3);
1017                 /* Never delete the first item to keep the leaf structure */
1018                 if (path->slots[0] == 0)
1019                         del = 0;
1020                 ret = corrupt_item_nocow(trans, root, path, del);
1021                 if (ret)
1022                         goto free_out;
1023         }
1024         btrfs_release_path(path);
1025
1026         /* Here, cow and ins_len must equals 0 for the following reasons:
1027          * 1) chunk recover is based on disk scanning, so COW should be
1028          *    disabled in case the original chunk being scanned and
1029          *    recovered using the old chunk.
1030          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON will be
1031          *    triggered.
1032          */
1033         ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
1034         BUG_ON(ret == 0);
1035         if (ret < 0) {
1036                 fprintf(stderr, "Error searching tree\n");
1037                 goto free_out;
1038         }
1039         /* corrupt/del chunk then*/
1040         while (!btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY)) {
1041                 slot = path->slots[0];
1042                 leaf = path->nodes[0];
1043                 del = rand_range(3);
1044                 btrfs_item_key_to_cpu(leaf, &found_key, slot);
1045                 ret = corrupt_item_nocow(trans, root, path, del);
1046                 if (ret)
1047                         goto free_out;
1048         }
1049 free_out:
1050         btrfs_free_path(path);
1051         return ret;
1052 }
1053 static int find_chunk_offset(struct btrfs_root *root,
1054                       struct btrfs_path *path, u64 offset)
1055 {
1056         struct btrfs_key key;
1057         int ret;
1058
1059         key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
1060         key.type = BTRFS_CHUNK_ITEM_KEY;
1061         key.offset = offset;
1062
1063         /* Here, cow and ins_len must equals 0 for following reasons:
1064          * 1) chunk recover is based on disk scanning, so COW should
1065          *    be disabled in case the original chunk being scanned
1066          *    and recovered using the old chunk.
1067          * 2) if cow = 0, ins_len must also be set to 0, or BUG_ON
1068          *    will be triggered.
1069          */
1070         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1071         if (ret > 0) {
1072                 fprintf(stderr, "Can't find chunk with given offset %llu\n",
1073                         offset);
1074                 goto out;
1075         }
1076         if (ret < 0) {
1077                 fprintf(stderr, "Error searching chunk\n");
1078                 goto out;
1079         }
1080 out:
1081         return ret;
1082
1083 }
1084 int main(int argc, char **argv)
1085 {
1086         struct cache_tree root_cache;
1087         struct btrfs_key key;
1088         struct btrfs_root *root;
1089         char *dev;
1090         /* chunk offset can be 0,so change to (u64)-1 */
1091         u64 logical = (u64)-1;
1092         int ret = 0;
1093         u64 copy = 0;
1094         u64 bytes = 4096;
1095         int extent_rec = 0;
1096         int extent_tree = 0;
1097         int corrupt_block_keys = 0;
1098         int chunk_rec = 0;
1099         int chunk_tree = 0;
1100         int corrupt_item = 0;
1101         int corrupt_di = 0;
1102         int delete = 0;
1103         u64 metadata_block = 0;
1104         u64 inode = 0;
1105         u64 file_extent = (u64)-1;
1106         u64 root_objectid = 0;
1107         u64 csum_bytenr = 0;
1108         char field[FIELD_BUF_LEN];
1109
1110         field[0] = '\0';
1111         memset(&key, 0, sizeof(key));
1112
1113         while(1) {
1114                 int c;
1115                 static const struct option long_options[] = {
1116                         /* { "byte-count", 1, NULL, 'b' }, */
1117                         { "logical", required_argument, NULL, 'l' },
1118                         { "copy", required_argument, NULL, 'c' },
1119                         { "bytes", required_argument, NULL, 'b' },
1120                         { "extent-record", no_argument, NULL, 'e' },
1121                         { "extent-tree", no_argument, NULL, 'E' },
1122                         { "keys", no_argument, NULL, 'k' },
1123                         { "chunk-record", no_argument, NULL, 'u' },
1124                         { "chunk-tree", no_argument, NULL, 'U' },
1125                         { "inode", required_argument, NULL, 'i'},
1126                         { "file-extent", required_argument, NULL, 'x'},
1127                         { "metadata-block", required_argument, NULL, 'm'},
1128                         { "field", required_argument, NULL, 'f'},
1129                         { "key", required_argument, NULL, 'K'},
1130                         { "item", no_argument, NULL, 'I'},
1131                         { "dir-item", no_argument, NULL, 'D'},
1132                         { "delete", no_argument, NULL, 'd'},
1133                         { "root", no_argument, NULL, 'r'},
1134                         { "csum", required_argument, NULL, 'C'},
1135                         { "help", no_argument, NULL, GETOPT_VAL_HELP},
1136                         { NULL, 0, NULL, 0 }
1137                 };
1138
1139                 c = getopt_long(argc, argv, "l:c:b:eEkuUi:f:x:m:K:IDdr:C:",
1140                                 long_options, NULL);
1141                 if (c < 0)
1142                         break;
1143                 switch(c) {
1144                         case 'l':
1145                                 logical = arg_strtou64(optarg);
1146                                 break;
1147                         case 'c':
1148                                 copy = arg_strtou64(optarg);
1149                                 break;
1150                         case 'b':
1151                                 bytes = arg_strtou64(optarg);
1152                                 break;
1153                         case 'e':
1154                                 extent_rec = 1;
1155                                 break;
1156                         case 'E':
1157                                 extent_tree = 1;
1158                                 break;
1159                         case 'k':
1160                                 corrupt_block_keys = 1;
1161                                 break;
1162                         case 'u':
1163                                 chunk_rec = 1;
1164                                 break;
1165                         case 'U':
1166                                 chunk_tree = 1;
1167                                 break;
1168                         case 'i':
1169                                 inode = arg_strtou64(optarg);
1170                                 break;
1171                         case 'f':
1172                                 strncpy(field, optarg, FIELD_BUF_LEN);
1173                                 break;
1174                         case 'x':
1175                                 file_extent = arg_strtou64(optarg);
1176                                 break;
1177                         case 'm':
1178                                 metadata_block = arg_strtou64(optarg);
1179                                 break;
1180                         case 'K':
1181                                 ret = sscanf(optarg, "%llu,%u,%llu",
1182                                              &key.objectid,
1183                                              (unsigned int *)&key.type,
1184                                              &key.offset);
1185                                 if (ret != 3) {
1186                                         fprintf(stderr, "error reading key "
1187                                                 "%d\n", errno);
1188                                         print_usage(1);
1189                                 }
1190                                 break;
1191                         case 'D':
1192                                 corrupt_di = 1;
1193                                 break;
1194                         case 'I':
1195                                 corrupt_item = 1;
1196                                 break;
1197                         case 'd':
1198                                 delete = 1;
1199                                 break;
1200                         case 'r':
1201                                 root_objectid = arg_strtou64(optarg);
1202                                 break;
1203                         case 'C':
1204                                 csum_bytenr = arg_strtou64(optarg);
1205                                 break;
1206                         case GETOPT_VAL_HELP:
1207                         default:
1208                                 print_usage(c != GETOPT_VAL_HELP);
1209                 }
1210         }
1211         set_argv0(argv);
1212         if (check_argc_min(argc - optind, 1))
1213                 print_usage(1);
1214         dev = argv[optind];
1215
1216         radix_tree_init();
1217         cache_tree_init(&root_cache);
1218
1219         root = open_ctree(dev, 0, OPEN_CTREE_WRITES);
1220         if (!root) {
1221                 fprintf(stderr, "Open ctree failed\n");
1222                 exit(1);
1223         }
1224         if (extent_rec) {
1225                 struct btrfs_trans_handle *trans;
1226
1227                 if (logical == (u64)-1)
1228                         print_usage(1);
1229                 trans = btrfs_start_transaction(root, 1);
1230                 ret = corrupt_extent(trans, root, logical);
1231                 btrfs_commit_transaction(trans, root);
1232                 goto out_close;
1233         }
1234         if (extent_tree) {
1235                 struct btrfs_trans_handle *trans;
1236                 trans = btrfs_start_transaction(root, 1);
1237                 btrfs_corrupt_extent_tree(trans, root->fs_info->extent_root,
1238                                           root->fs_info->extent_root->node);
1239                 btrfs_commit_transaction(trans, root);
1240                 goto out_close;
1241         }
1242         if (chunk_rec) {
1243                 struct btrfs_trans_handle *trans;
1244                 struct btrfs_path *path;
1245                 int del;
1246
1247                 if (logical == (u64)-1)
1248                         print_usage(1);
1249                 del = rand_range(3);
1250                 path = btrfs_alloc_path();
1251                 if (!path) {
1252                         fprintf(stderr, "path allocation failed\n");
1253                         goto out_close;
1254                 }
1255
1256                 if (find_chunk_offset(root->fs_info->chunk_root, path,
1257                                       logical) != 0) {
1258                         btrfs_free_path(path);
1259                         goto out_close;
1260                 }
1261                 trans = btrfs_start_transaction(root, 1);
1262                 ret = corrupt_item_nocow(trans, root->fs_info->chunk_root,
1263                                          path, del);
1264                 if (ret < 0)
1265                         fprintf(stderr, "Failed to corrupt chunk record\n");
1266                 btrfs_commit_transaction(trans, root);
1267                 goto out_close;
1268         }
1269         if (chunk_tree) {
1270                 struct btrfs_trans_handle *trans;
1271                 trans = btrfs_start_transaction(root, 1);
1272                 ret = corrupt_chunk_tree(trans, root->fs_info->chunk_root);
1273                 if (ret < 0)
1274                         fprintf(stderr, "Failed to corrupt chunk tree\n");
1275                 btrfs_commit_transaction(trans, root);
1276                 goto out_close;
1277         }
1278         if (inode) {
1279                 struct btrfs_trans_handle *trans;
1280
1281                 if (*field == 0)
1282                         print_usage(1);
1283
1284                 trans = btrfs_start_transaction(root, 1);
1285                 if (file_extent == (u64)-1) {
1286                         printf("corrupting inode\n");
1287                         ret = corrupt_inode(trans, root, inode, field);
1288                 } else {
1289                         printf("corrupting file extent\n");
1290                         ret = corrupt_file_extent(trans, root, inode,
1291                                                   file_extent, field);
1292                 }
1293                 btrfs_commit_transaction(trans, root);
1294                 goto out_close;
1295         }
1296         if (metadata_block) {
1297                 if (*field == 0)
1298                         print_usage(1);
1299                 ret = corrupt_metadata_block(root->fs_info, metadata_block,
1300                                              field);
1301                 goto out_close;
1302         }
1303         if (corrupt_di) {
1304                 if (!key.objectid || *field == 0)
1305                         print_usage(1);
1306                 ret = corrupt_dir_item(root, &key, field);
1307                 goto out_close;
1308         }
1309         if (csum_bytenr) {
1310                 ret = delete_csum(root, csum_bytenr, bytes);
1311                 goto out_close;
1312         }
1313         if (corrupt_item) {
1314                 if (!key.objectid)
1315                         print_usage(1);
1316                 ret = corrupt_btrfs_item(root, &key, field);
1317         }
1318         if (delete) {
1319                 struct btrfs_root *target = root;
1320
1321                 if (!key.objectid)
1322                         print_usage(1);
1323                 if (root_objectid) {
1324                         struct btrfs_key root_key;
1325
1326                         root_key.objectid = root_objectid;
1327                         root_key.type = BTRFS_ROOT_ITEM_KEY;
1328                         root_key.offset = (u64)-1;
1329
1330                         target = btrfs_read_fs_root(root->fs_info, &root_key);
1331                         if (IS_ERR(target)) {
1332                                 fprintf(stderr, "Couldn't find root %llu\n",
1333                                         (unsigned long long)root_objectid);
1334                                 print_usage(1);
1335                         }
1336                 }
1337                 ret = delete_item(target, &key);
1338                 goto out_close;
1339         }
1340         if (key.objectid || key.offset || key.type) {
1341                 if (*field == 0)
1342                         print_usage(1);
1343                 ret = corrupt_key(root, &key, field);
1344                 goto out_close;
1345         }
1346         /*
1347          * If we made it here and we have extent set then we didn't specify
1348          * inode and we're screwed.
1349          */
1350         if (file_extent != (u64)-1)
1351                 print_usage(1);
1352
1353         if (logical == (u64)-1)
1354                 print_usage(1);
1355
1356         if (bytes == 0)
1357                 bytes = root->fs_info->sectorsize;
1358
1359         bytes = round_up(bytes, root->fs_info->sectorsize);
1360
1361         while (bytes > 0) {
1362                 if (corrupt_block_keys) {
1363                         corrupt_keys_in_block(root->fs_info, logical);
1364                 } else {
1365                         struct extent_buffer *eb;
1366
1367                         eb = btrfs_find_create_tree_block(root->fs_info,
1368                                         logical, root->fs_info->sectorsize);
1369                         if (!eb) {
1370                                 error(
1371                 "not enough memory to allocate extent buffer for bytenr %llu",
1372                                         (unsigned long long)logical);
1373                                 ret = 1;
1374                                 goto out_close;
1375                         }
1376
1377                         debug_corrupt_block(eb, root, logical,
1378                                             root->fs_info->sectorsize, copy);
1379                         free_extent_buffer(eb);
1380                 }
1381                 logical += root->fs_info->sectorsize;
1382                 bytes -= root->fs_info->sectorsize;
1383         }
1384         return ret;
1385 out_close:
1386         close_ctree(root);
1387         return ret;
1388 }