From d973736c404a5d15ed0a3710da6297fd2b703424 Mon Sep 17 00:00:00 2001 From: Ted Schundler Date: Tue, 28 Jul 2015 15:06:21 -0700 Subject: [PATCH 1/2] Updates to work on alternate partition layout and to work past errors --- zfs.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++------- zfsimpl.c | 4 ++-- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/zfs.c b/zfs.c index e08ea80..cd219ad 100644 --- a/zfs.c +++ b/zfs.c @@ -437,14 +437,15 @@ zfs_probe_partition(void *arg, const char *partname, int ret; /* Probe only freebsd-zfs and freebsd partitions */ - if (part->type != PART_FREEBSD && - part->type != PART_FREEBSD_ZFS) - return; + //if (part->type != PART_FREEBSD && + // part->type != PART_FREEBSD_ZFS) + // return; ppa = (struct zfs_probe_args *)arg; strncpy(devname, ppa->devname, strlen(ppa->devname) - 1); devname[strlen(ppa->devname) - 1] = '\0'; sprintf(devname, "%s%s:", devname, partname); + printf("dn: %s\n", devname); pa.fd = open(devname, O_RDONLY); if (pa.fd == -1) return; @@ -473,7 +474,7 @@ zfs_probe_dev(const char *devname, uint64_t *pool_guid) struct zfs_probe_args pa; off_t mediasz; int ret; - +printf("zppd: %s\n", devname); pa.fd = open(devname, O_RDONLY); if (pa.fd == -1) return (ENXIO); @@ -730,6 +731,17 @@ i386_zfs_probe(void) sprintf(devname, "/dev/ada%d", unit); if (zfs_probe_dev(devname, NULL) != 0) break; + sprintf(devname, "/dev/ada%dp1", unit); + zfs_probe_dev(devname, NULL); + sprintf(devname, "/dev/ada%dp2", unit); + zfs_probe_dev(devname, NULL); + sprintf(devname, "/dev/ada%dp3", unit); + zfs_probe_dev(devname, NULL); + sprintf(devname, "/dev/ada%dp4", unit); + zfs_probe_dev(devname, NULL); + sprintf(devname, "/dev/ada%dp5", unit); + zfs_probe_dev(devname, NULL); + } for (unit = 0; unit < MAXBDDEV; unit++) { sprintf(devname, "/dev/da%d", unit); @@ -1008,15 +1020,48 @@ build(char *path, mode_t omode) char *dirname(const char *); char *fname = NULL; const char *destfolder = NULL; -int opt_copy = 0; -int opt_recursive = 0; +int opt_copy = 0; +int opt_recursive = 0; +int opt_ignore_errors = 0; +char **exclude_list = NULL; +int exclude_list_size = 0; +int exclude_list_count = 0; + +void +add_exclude(char *prefix) +{ + int newsize; + printf("exclude: %s\n", prefix); + + if (exclude_list_size == exclude_list_count) { + if (exclude_list_size) { + newsize = exclude_list_size << 1; + } else { + newsize = 8; + } + printf("resize: %d -> %d\n", newsize, sizeof(char*) * newsize); + exclude_list = realloc(exclude_list, sizeof(char*) * newsize); + exclude_list_size = newsize; + } + exclude_list[exclude_list_count++] = prefix; +} + int zfs_recover(const char *file, struct open_file *f) { int ret = 0; - //printf("zfs_recover file=%s\n", file); + printf("zfs_recover file=%s\n", file); + int flen=strlen(file); int xlen; + for (int xi=0; xi < exclude_list_count; xi++) { + xlen=strlen(exclude_list[xi]); + if (xlen > flen) continue; + if (!memcmp(file, exclude_list[xi], xlen)) { + printf("matches exclude rule %s\n", exclude_list[xi]); + return ret; + } + } ret = zfs_open(file, f); if (ret != 0) { printf("zfs_open failed: %s\n", strerror(ret)); @@ -1117,7 +1162,8 @@ zfs_recover(const char *file, struct open_file *f) ret = zfs_recover(d_name, f); free(n1->file); free(n1); - } + if (opt_recursive && ret != 0 && opt_ignore_errors == 0) + return ret; } } else if (S_ISREG(sb.st_mode)) { //printf("file size=%d\n", (int)sb.st_size); if (!opt_copy) { @@ -1215,7 +1261,7 @@ main(int argc, char **argv) int ret, ch, opt_devprint = 0; const char * opt_zfs_list = NULL; - while ((ch = getopt(argc, argv, "df:rc:l:")) != -1) { + while ((ch = getopt(argc, argv, "df:rc:l:x:i")) != -1) { switch (ch) { case 'd': opt_devprint = 1; @@ -1235,6 +1281,12 @@ main(int argc, char **argv) case 'l': opt_zfs_list = optarg; break; + case 'i': + opt_ignore_errors = 1; + break; + case 'x': + add_exclude(optarg); + break; default: usage(); } diff --git a/zfsimpl.c b/zfsimpl.c index 2e0cb45..d073237 100644 --- a/zfsimpl.c +++ b/zfsimpl.c @@ -1178,8 +1178,8 @@ zio_read(const spa_t *spa, const blkptr_t *bp, void *buf) break; } if (error != 0) - printf("ZFS: i/o error - all block copies unavailable\n"); - return (error); + printf("ZFS: i/o error !!!- all block copies unavailable\n"); + return (0); /* error); */ } static int From 5b183591000d25f61bae7a2b0011aa9042c05e3f Mon Sep 17 00:00:00 2001 From: Ted Schundler Date: Sat, 3 Sep 2016 23:07:01 -0700 Subject: [PATCH 2/2] More updates to work on alternate partition layout and to work past errors --- zfs.c | 110 ++++++++++++++++++++++++++++++++++++------------------ zfsimpl.c | 13 +++++-- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/zfs.c b/zfs.c index cd219ad..a8013f4 100644 --- a/zfs.c +++ b/zfs.c @@ -47,6 +47,20 @@ __FBSDID("$FreeBSD: stable/9/sys/boot/zfs/zfs.c 243243 2012-11-18 17:09:29Z ae $ #include "libzfs.h" +#define READ_BL_SIZE 32*1024 +char *dirname(const char *); +char *fname = NULL; +const char *destfolder = NULL; +int opt_copy = 0; +int opt_recursive = 0; +int opt_ignore_errors = 0; +char **exclude_list = NULL; +int exclude_list_size = 0; +int exclude_list_count = 0; +char **device_list = NULL; +int device_list_size = 0; +int device_list_count = 0; + #include "zfsimpl.c" #undef SOPEN_RASIZE @@ -433,7 +447,7 @@ zfs_probe_partition(void *arg, const char *partname, { struct zfs_probe_args *ppa, pa; struct ptable *table; - char devname[32]; + char devname[64]; int ret; /* Probe only freebsd-zfs and freebsd partitions */ @@ -445,7 +459,7 @@ zfs_probe_partition(void *arg, const char *partname, strncpy(devname, ppa->devname, strlen(ppa->devname) - 1); devname[strlen(ppa->devname) - 1] = '\0'; sprintf(devname, "%s%s:", devname, partname); - printf("dn: %s\n", devname); + printf("dn: %s\n", devname); pa.fd = open(devname, O_RDONLY); if (pa.fd == -1) return; @@ -458,7 +472,7 @@ zfs_probe_partition(void *arg, const char *partname, pa.pool_guid = ppa->pool_guid; pa.secsz = ppa->secsz; table = ptable_open(&pa, part->end - part->start + 1, - ppa->secsz, zfs_diskread); + ppa->secsz, zfs_diskread); if (table != NULL) { ptable_iterate(table, &pa, zfs_probe_partition); ptable_close(table); @@ -474,7 +488,7 @@ zfs_probe_dev(const char *devname, uint64_t *pool_guid) struct zfs_probe_args pa; off_t mediasz; int ret; -printf("zppd: %s\n", devname); + printf("Probe Dev: %s\n", devname); pa.fd = open(devname, O_RDONLY); if (pa.fd == -1) return (ENXIO); @@ -715,9 +729,23 @@ zfs_list(const char *name) static void i386_zfs_probe(void) { - char devname[32]; + char devname[64]; int unit; - + int part; + + /* User specified devices to probe */ + if (device_list_count) { + for (int di=0; di < device_list_count; di++) { + if (zfs_probe_dev(device_list[di], NULL) != 0) { + /* try with /dev prefix */ + sprintf(devname, "/dev/%s", device_list[di]); + zfs_probe_dev(devname, NULL); + } + } + return; + + } + /* * Open all the disks we can find and see if we can reconstruct * ZFS pools from them. @@ -731,19 +759,12 @@ i386_zfs_probe(void) sprintf(devname, "/dev/ada%d", unit); if (zfs_probe_dev(devname, NULL) != 0) break; - sprintf(devname, "/dev/ada%dp1", unit); - zfs_probe_dev(devname, NULL); - sprintf(devname, "/dev/ada%dp2", unit); - zfs_probe_dev(devname, NULL); - sprintf(devname, "/dev/ada%dp3", unit); - zfs_probe_dev(devname, NULL); - sprintf(devname, "/dev/ada%dp4", unit); - zfs_probe_dev(devname, NULL); - sprintf(devname, "/dev/ada%dp5", unit); - zfs_probe_dev(devname, NULL); - - } - for (unit = 0; unit < MAXBDDEV; unit++) { + for (part = 1; part < 9; part++) { + sprintf(devname, "/dev/ada%dp%d", unit, part); + zfs_probe_dev(devname, NULL); + } + } + for (unit = 0; unit < MAXBDDEV; unit++) { sprintf(devname, "/dev/da%d", unit); if (zfs_probe_dev(devname, NULL) != 0) break; @@ -935,7 +956,7 @@ myread(struct open_file *f, void *dest, size_t bcount) /* no more data, return what we had */ if (f->f_ralen == 0) return(bcount - resid); - } + } } /* @@ -1016,17 +1037,6 @@ build(char *path, mode_t omode) return (retval); } -#define READ_BL_SIZE 32*1024 -char *dirname(const char *); -char *fname = NULL; -const char *destfolder = NULL; -int opt_copy = 0; -int opt_recursive = 0; -int opt_ignore_errors = 0; -char **exclude_list = NULL; -int exclude_list_size = 0; -int exclude_list_count = 0; - void add_exclude(char *prefix) { @@ -1039,7 +1049,7 @@ add_exclude(char *prefix) } else { newsize = 8; } - printf("resize: %d -> %d\n", newsize, sizeof(char*) * newsize); + //printf("resize: %d -> %d\n", newsize, sizeof(char*) * newsize); exclude_list = realloc(exclude_list, sizeof(char*) * newsize); exclude_list_size = newsize; } @@ -1047,6 +1057,26 @@ add_exclude(char *prefix) } +void +add_device(char *devname) +{ + int newsize; + printf("Scan device: %s\n", devname); + + if (device_list_size == device_list_count) { + if (device_list_size) { + newsize = device_list_size << 1; + } else { + newsize = 8; + } + //printf("resize: %d -> %d\n", newsize, sizeof(char*) * newsize); + device_list = realloc(device_list, sizeof(char*) * newsize); + device_list_size = newsize; + } + device_list[device_list_count++] = devname; +} + + int zfs_recover(const char *file, struct open_file *f) { @@ -1242,15 +1272,18 @@ usage(void) { printf("%s\n%s\n%s\n\n", - "usage: zfs_read -d", - " zfs_read -l ", - " zfs_read [-c ] [-r] -f "); + "usage: zfs_read [-n device] [-i] -d", + " zfs_read [-n device] [-i] -l ", + " zfs_read [-n device] [-i [-i]] [-c ] [-x prefix ] [-r] -f "); printf("OPTIONS\n"); printf("\t%-18s%s\n", "-d", "look for pool in device /dev/da* and /dev/ada*"); + printf("\t%-18s%s\n", "-n device", "look for pool in device or file - repeat for multiple devices"); printf("\t%-18s%s\n", "-l pool_name", "list dataset for pool_name"); printf("\t%-18s%s\n", "-f dataset:folder", "working folder, example: mypool/Pictures:/"); printf("\t%-18s%s\n", "-c destfolder", "restore a copie of all files in destfolder"); printf("\t%-18s%s\n", "-r", "recursive list or copie"); + printf("\t%-18s%s\n", "-i [-i]", "ignore errors (-i again to ignore more)"); + printf("\t%-18s%s\n", "-x path_prefix", "exclude paths beginning with this prefix"); exit(EX_USAGE); } @@ -1261,7 +1294,7 @@ main(int argc, char **argv) int ret, ch, opt_devprint = 0; const char * opt_zfs_list = NULL; - while ((ch = getopt(argc, argv, "df:rc:l:x:i")) != -1) { + while ((ch = getopt(argc, argv, "df:rc:l:x:in:")) != -1) { switch (ch) { case 'd': opt_devprint = 1; @@ -1282,11 +1315,14 @@ main(int argc, char **argv) opt_zfs_list = optarg; break; case 'i': - opt_ignore_errors = 1; + opt_ignore_errors++; break; case 'x': add_exclude(optarg); break; + case 'n': + add_device(optarg); + break; default: usage(); } diff --git a/zfsimpl.c b/zfsimpl.c index d073237..e206a62 100644 --- a/zfsimpl.c +++ b/zfsimpl.c @@ -930,8 +930,13 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap) if (nvlist_find(nvlist, ZPOOL_CONFIG_FEATURES_FOR_READ, DATA_TYPE_NVLIST, 0, &features) == 0 - && nvlist_check_features_for_read(features) != 0) - return (EIO); + && nvlist_check_features_for_read(features) != 0) { + + //unsupported flags are maybe not too bad + if (opt_ignore_errors == 0) { + return (EIO); + } +} if (nvlist_find(nvlist, ZPOOL_CONFIG_POOL_STATE, @@ -1179,7 +1184,9 @@ zio_read(const spa_t *spa, const blkptr_t *bp, void *buf) } if (error != 0) printf("ZFS: i/o error !!!- all block copies unavailable\n"); - return (0); /* error); */ + if (opt_ignore_errors > 1) + return 0; + return (error); } static int