Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
version.h
man/*.gz
btrfs
btrfs-corrupt-block
btrfs-debug-tree
btrfs-dump-super
btrfs-map-logical
btrfs-select-super
btrfs-show
btrfs-vol
btrfsck
btrfsctl
calc-size
find-root
mkfs.btrfs
repair
Expand Down
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ LIBS=-luuid
RESTORE_LIBS=-lz

progs = btrfsctl mkfs.btrfs btrfs-debug-tree btrfs-show btrfs-vol btrfsck \
btrfs btrfs-map-logical restore find-root calc-size btrfs-corrupt-block
btrfs btrfs-map-logical restore find-root calc-size btrfs-corrupt-block \
btrfs-dump-super

# make C=1 to enable sparse
ifdef C
Expand Down Expand Up @@ -73,6 +74,9 @@ btrfs-zero-log: $(objects) btrfs-zero-log.o
btrfs-select-super: $(objects) btrfs-select-super.o
$(CC) $(CFLAGS) -o btrfs-select-super $(objects) btrfs-select-super.o $(LDFLAGS) $(LIBS)

btrfs-dump-super: $(objects) btrfs-dump-super.o
$(CC) $(CFLAGS) -o btrfs-dump-super $(objects) btrfs-dump-super.o $(LDFLAGS) $(LIBS)

btrfstune: $(objects) btrfstune.o
$(CC) $(CFLAGS) -o btrfstune $(objects) btrfstune.o $(LDFLAGS) $(LIBS)

Expand Down Expand Up @@ -105,7 +109,8 @@ install-man:

clean :
rm -f $(progs) cscope.out *.o .*.d btrfs-convert btrfs-image btrfs-select-super \
btrfs-zero-log btrfstune dir-test ioctl-test quick-test version.h
btrfs-dump-super btrfs-zero-log btrfstune dir-test ioctl-test quick-test \
version.h
cd man; make clean

install: $(progs) install-man
Expand Down
87 changes: 87 additions & 0 deletions btrfs-dump-super.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (C) 2011 Google. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/

#define _XOPEN_SOURCE 500
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "kerncompat.h"
#include "ctree.h"
#include "disk-io.h"
#include "version.h"

static void print_usage(void)
{
fprintf(stderr, "usage: btrfs-dump-super dev\n");
fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION);
exit(1);
}

static int read_block(const char* filename, u64 bytenr, struct btrfs_super_block* sb) {
int fd = open(filename, O_RDONLY, 0600);
int block_size = sizeof(struct btrfs_super_block);
int bytes_read = 0;

if (fd < 0) {
fprintf(stderr, "Could not open %s\n", filename);
return -1;
}

bytes_read = pread(fd, sb, block_size, bytenr);
if (bytes_read < block_size) {
fprintf(stderr, "Only read %d bytes of %d.\n", bytes_read, block_size);
}

close(fd);
return bytes_read;
}

int main(int ac, char **av)
{
int i;

if (ac != 2)
print_usage();

for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
u64 bytenr = btrfs_sb_offset(i);
int fd;
struct btrfs_super_block sb;
int block_size = sizeof(struct btrfs_super_block);
char filename[1024];
int bytes_read = read_block(av[optind], bytenr, &sb);
if (bytes_read < block_size)
continue;

sprintf(filename, "/tmp/block.%s.%llu",
strrchr(av[optind], '/') + 1, bytenr);
fd = open(filename, O_CREAT|O_WRONLY, 0644);
if (block_size != pwrite(fd, &sb, block_size, 0)) {
fprintf(stderr, "Failed to dump superblock %d", i);
continue;
}
fprintf(stderr, "Dumped superblock %s:%d, gen %llu to %s.\n",
av[optind], i, sb.generation, filename);
close(fd);
}

return 0;
}
38 changes: 30 additions & 8 deletions btrfs-select-super.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@

static void print_usage(void)
{
fprintf(stderr, "usage: btrfs-select-super -s number dev\n");
fprintf(stderr, "usage: btrfs-select-super [-c] [-e] -s number dev\n");
fprintf(stderr, " -c Commit changes to disk [IRREVERSIBLE]\n");
fprintf(stderr, " -e Use the earliest super found, may help recover transid verify problems\n");
fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION);
exit(1);
}
Expand All @@ -45,10 +47,13 @@ int main(int ac, char **av)
int ret;
int num;
u64 bytenr = 0;
int commit = 0;
int use_lowest_bdev = 0;
int fp;

while(1) {
int c;
c = getopt(ac, av, "s:");
c = getopt(ac, av, "s:ce");
if (c < 0)
break;
switch(c) {
Expand All @@ -58,6 +63,12 @@ int main(int ac, char **av)
printf("using SB copy %d, bytenr %llu\n", num,
(unsigned long long)bytenr);
break;
case 'c':
commit = 1;
break;
case 'e':
use_earliest_bdev = 1;
break;
default:
print_usage();
}
Expand All @@ -74,22 +85,33 @@ int main(int ac, char **av)

radix_tree_init();

if((ret = check_mounted(av[optind])) < 0) {
if ((ret = check_mounted(av[optind])) < 0) {
fprintf(stderr, "Could not check mount status: %s\n", strerror(-ret));
return ret;
} else if(ret) {
} else if (ret) {
fprintf(stderr, "%s is currently mounted. Aborting.\n", av[optind]);
return -EBUSY;
}

root = open_ctree(av[optind], bytenr, 1);
fp = open(av[optind], O_CREAT|O_RDRW, 0600);
if (fp < 0) {
fprintf(stderr, "Could not open %s\n", av[optind]);
return 1;
}
root = open_ctree_fd(fp, av[optind], bytenr, 1, use_earliest_bdev);

if (root == NULL)
return 1;

/* make the super writing code think we've read the first super */
root->fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET;
ret = write_all_supers(root);
fprintf(stderr, "Found superblock with generation %llu.\n", root->fs_info->super_copy.generation);

if (commit) {
fprintf(stderr, "Committing...\n");

/* make the super writing code think we've read the first super */
root->fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET;
ret = write_all_supers(root);
}

/* we don't close the ctree or anything, because we don't want a real
* transaction commit. We just want the super copy we pulled off the
Expand Down
6 changes: 3 additions & 3 deletions convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -2386,7 +2386,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
fprintf(stderr, "unable to update system chunk\n");
goto fail;
}
root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR);
root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR, 0);
if (!root) {
fprintf(stderr, "unable to open ctree\n");
goto fail;
Expand Down Expand Up @@ -2447,7 +2447,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
goto fail;
}

root = open_ctree_fd(fd, devname, 0, O_RDWR);
root = open_ctree_fd(fd, devname, 0, O_RDWR, 0);
if (!root) {
fprintf(stderr, "unable to open ctree\n");
goto fail;
Expand Down Expand Up @@ -2546,7 +2546,7 @@ int do_rollback(const char *devname, int force)
fprintf(stderr, "unable to open %s\n", devname);
goto fail;
}
root = open_ctree_fd(fd, devname, 0, O_RDWR);
root = open_ctree_fd(fd, devname, 0, O_RDWR, 0);
if (!root) {
fprintf(stderr, "unable to open ctree\n");
goto fail;
Expand Down
23 changes: 15 additions & 8 deletions disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
return fs_info->dev_root;
if (location->objectid == BTRFS_CSUM_TREE_OBJECTID)
return fs_info->csum_root;

BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID ||
location->offset != (u64)-1);

Expand All @@ -602,7 +602,8 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
}

struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
u64 root_tree_bytenr, int writes)
u64 root_tree_bytenr, int writes,
int use_earliest_bdev)
{
u32 sectorsize;
u32 nodesize;
Expand Down Expand Up @@ -677,8 +678,14 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,

fs_info->super_bytenr = sb_bytenr;
disk_super = &fs_info->super_copy;
ret = btrfs_read_dev_super(fs_devices->latest_bdev,
disk_super, sb_bytenr);
if (use_earliest_bdev) {
ret = btrfs_read_dev_super(fs_devices->earliest_bdev,
disk_super, sb_bytenr);
} else {
ret = btrfs_read_dev_super(fs_devices->latest_bdev,
disk_super, sb_bytenr);
}

if (ret) {
printk("No valid btrfs found\n");
goto out_devices;
Expand Down Expand Up @@ -847,7 +854,7 @@ struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes)
fprintf (stderr, "Could not open %s\n", filename);
return NULL;
}
root = __open_ctree_fd(fp, filename, sb_bytenr, 0, writes);
root = __open_ctree_fd(fp, filename, sb_bytenr, 0, writes, 0);
close(fp);

return root;
Expand All @@ -864,16 +871,16 @@ struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
fprintf (stderr, "Could not open %s\n", filename);
return NULL;
}
root = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0);
root = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0, 0);
close(fp);

return root;
}

struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
int writes)
int writes, int use_earliest_bdev)
{
return __open_ctree_fd(fp, path, sb_bytenr, 0, writes);
return __open_ctree_fd(fp, path, sb_bytenr, 0, writes, use_earliest_bdev);
}

int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
Expand Down
2 changes: 1 addition & 1 deletion disk-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf);
struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes);
struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
int writes);
int writes, int use_earliest_bdev);
struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
u64 root_tree_bytenr);
int close_ctree(struct btrfs_root *root);
Expand Down
9 changes: 8 additions & 1 deletion volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ static int device_list_add(const char *path,
memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
fs_devices->latest_devid = devid;
fs_devices->latest_trans = found_transid;
fs_devices->earliest_devid = devid;
fs_devices->earliest_trans = found_transid;
fs_devices->lowest_devid = (u64)-1;
device = NULL;
} else {
Expand Down Expand Up @@ -133,8 +135,11 @@ static int device_list_add(const char *path,
if (found_transid > fs_devices->latest_trans) {
fs_devices->latest_devid = devid;
fs_devices->latest_trans = found_transid;
} else if (found_transid < fs_devices->earliest_trans) {
fs_devices->earliest_devid = devid;
fs_devices->earliest_trans = found_transid;
}
if (fs_devices->lowest_devid > devid) {
if (devid < fs_devices->lowest_devid) {
fs_devices->lowest_devid = devid;
}
*fs_devices_ret = fs_devices;
Expand Down Expand Up @@ -183,6 +188,8 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int flags)

if (device->devid == fs_devices->latest_devid)
fs_devices->latest_bdev = fd;
if (device->devid == fs_devices->earliest_devid)
fs_devices->earliest_bdev = fd;
if (device->devid == fs_devices->lowest_devid)
fs_devices->lowest_bdev = fd;
device->fd = fd;
Expand Down
6 changes: 5 additions & 1 deletion volumes.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,15 @@ struct btrfs_device {
struct btrfs_fs_devices {
u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */

/* the device with this id has the most recent coyp of the super */
/* the device with this id has the most recent copy of the super */
u64 latest_devid;
u64 latest_trans;
/* the device with this id has the least recent copy of the super */
u64 earliest_devid;
u64 earliest_trans;
u64 lowest_devid;
int latest_bdev;
int earliest_bdev;
int lowest_bdev;
struct list_head devices;
struct list_head list;
Expand Down