Mercurial > illumos > illumos-gate
changeset 868:09ef7c98db8f
6344651 LZ, 'zfs restore', internal error: unexpected error 1 ...
6344659 'zfs restore -d <filesytem>' not create ancestor fs as designed
6344695 'zfs restore' return 0 while "Most recent snapshot does not match ...
6345773 error messages from 'zfs restore' should say "cannot"
6345826 must run 'zfs volfini' to 'zfs restore' incremental backup of zvol
author | ahrens |
---|---|
date | Tue, 08 Nov 2005 23:13:25 -0800 |
parents | 1d5e94400592 |
children | dc133b87dfb3 |
files | usr/src/lib/libzfs/common/libzfs_dataset.c |
diffstat | 1 files changed, 86 insertions(+), 76 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c Tue Nov 08 02:22:36 2005 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c Tue Nov 08 23:13:25 2005 -0800 @@ -2270,7 +2270,7 @@ { zfs_cmd_t zc = { 0 }; time_t begin_time; - int err, bytes; + int ioctl_err, err, bytes, size; char *cp; dmu_replay_record_t drr; struct drr_begin *drrb = &zc.zc_begin_record; @@ -2287,14 +2287,14 @@ cp = (char *)&drr; bytes = 0; do { - err = read(STDIN_FILENO, cp, sizeof (drr) - bytes); - cp += err; - bytes += err; - } while (err > 0); - - if (err < 0 || bytes != sizeof (drr)) { + size = read(STDIN_FILENO, cp, sizeof (drr) - bytes); + cp += size; + bytes += size; + } while (size > 0); + + if (size < 0 || bytes != sizeof (drr)) { zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: invalid backup stream " + "cannot restore: invalid backup stream " "(couldn't read first record)")); return (-1); } @@ -2304,7 +2304,7 @@ if (drrb->drr_magic != DMU_BACKUP_MAGIC && drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) { zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: invalid backup stream " + "cannot restore: invalid backup stream " "(invalid magic number)")); return (-1); } @@ -2314,7 +2314,7 @@ if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) drrb->drr_version = BSWAP_64(drrb->drr_version); zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: only backup version 0x%llx is supported, " + "cannot restore: only backup version 0x%llx is supported, " "stream is version %llx."), DMU_BACKUP_VERSION, drrb->drr_version); return (-1); @@ -2327,7 +2327,7 @@ if (isprefix) { if (strchr(tosnap, '@') != NULL) { zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " + "cannot restore: " "argument to -d must be a filesystem")); return (-1); } @@ -2348,7 +2348,7 @@ cp = strchr(drr.drr_u.drr_begin.drr_toname, '@'); if (cp == NULL || strlen(tosnap) + strlen(cp) >= MAXNAMELEN) { zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: invalid backup stream " + "cannot restore: invalid backup stream " "(invalid snapshot name)")); return (-1); } @@ -2368,65 +2368,86 @@ h = zfs_open(zc.zc_name, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); if (h == NULL) { zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore incrememtal backup: destination\n" + "cannot restore incrememtal backup: destination\n" "filesystem %s does not exist"), zc.zc_name); return (-1); } - /* unmount destination fs */ - if (!dryrun) - (void) zfs_unmount(h, NULL, 0); + if (!dryrun) { + /* unmount destination fs or remove device link. */ + if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { + (void) zfs_unmount(h, NULL, 0); + } else { + (void) zvol_remove_link(h->zfs_name); + } + } zfs_close(h); - - } else { /* full backup stream */ - /* do the ioctl to the containing fs's parent */ (void) strcpy(zc.zc_name, drrb->drr_toname); - cp = strrchr(zc.zc_name, '/'); - if (cp == NULL) { + + /* make sure they aren't trying to restore into the root */ + if (strchr(zc.zc_name, '/') == NULL) { cp = strchr(zc.zc_name, '@'); if (cp) *cp = '\0'; zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: destination fs %s already exists"), + "cannot restore: destination fs %s already exists"), zc.zc_name); return (-1); } - *cp = '\0'; - - /* make sure destination fs exists */ if (isprefix) { + zfs_handle_t *h; + /* make sure prefix exists */ - zfs_handle_t *h; - - /* make sure destination fs exists */ h = zfs_open(tosnap, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); if (h == NULL) { zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore:" + "cannot restore: " "filesystem %s does not exist"), tosnap); return (-1); } /* create any necessary ancestors up to prefix */ + zc.zc_objset_type = DMU_OST_ZFS; + /* + * zc.zc_name is now the full name of the snap + * we're restoring into + */ cp = zc.zc_name + strlen(tosnap) + 1; while (cp = strchr(cp, '/')) { *cp = '\0'; err = ioctl(zfs_fd, ZFS_IOC_CREATE, &zc); - if (err && err != ENOENT && err != EEXIST) { + if (err && errno != ENOENT && errno != EEXIST) { zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore:" + "cannot restore: " "couldn't create ancestor %s"), zc.zc_name); return (-1); } + *cp = '/'; + cp++; } } + + /* Make sure destination fs does not exist */ + cp = strchr(zc.zc_name, '@'); + *cp = '\0'; + if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) { + zfs_error(dgettext(TEXT_DOMAIN, + "cannot restore full backup: " + "destination filesystem %s already exists"), + zc.zc_name); + return (-1); + } + + /* Do the recvbackup ioctl to the fs's parent. */ + cp = strrchr(zc.zc_name, '/'); + *cp = '\0'; } (void) strcpy(zc.zc_prop_value, tosnap); @@ -2442,21 +2463,21 @@ } if (dryrun) return (0); - err = ioctl(zfs_fd, ZFS_IOC_RECVBACKUP, &zc); - if (err != 0) { + err = ioctl_err = ioctl(zfs_fd, ZFS_IOC_RECVBACKUP, &zc); + if (ioctl_err != 0) { switch (errno) { case ENODEV: zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " - "Most recent snapshot does not " + "cannot restore: " + "most recent snapshot does not " "match incremental backup source")); break; case ETXTBSY: zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " - "Destination has been modified since " - "most recent snapshot.\n" - "Use 'zfs rollback' to discard changes.")); + "cannot restore: " + "destination has been modified since " + "most recent snapshot --\n" + "use 'zfs rollback' to discard changes")); break; case EEXIST: if (drrb->drr_fromguid == 0) { @@ -2465,37 +2486,36 @@ *cp = '\0'; } zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore to %s: Destination already exists"), + "cannot restore to %s: destination already exists"), drrb->drr_toname); break; case ENOENT: zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " - "Destination does not exist")); + "cannot restore: destination does not exist")); break; case EBUSY: zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " - "Destination is in use")); + "cannot restore: destination is in use")); break; case ENOSPC: zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " - "Out of space")); + "cannot restore: out of space")); break; case EDQUOT: zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " - "Quota exceeded")); + "cannot restore: quota exceeded")); break; case EINTR: zfs_error(dgettext(TEXT_DOMAIN, - "Restore failed: signal recieved")); + "restore failed: signal recieved")); break; case EINVAL: zfs_error(dgettext(TEXT_DOMAIN, - "Can't restore: " - "invalid backup stream")); + "cannot restore: invalid backup stream")); + break; + case EPERM: + zfs_error(dgettext(TEXT_DOMAIN, + "cannot restore: permission denied")); break; default: zfs_baderror(errno); @@ -2503,45 +2523,35 @@ } /* - * Mount or recreate the /dev links for the target filesystem. + * Mount or recreate the /dev links for the target filesystem + * (if created, or if we tore them down to do an incremental + * restore), and the /dev links for the new snapshot (if + * created). */ cp = strchr(drrb->drr_toname, '@'); - if (cp && (err == 0 || drrb->drr_fromguid)) { + if (cp && (ioctl_err == 0 || drrb->drr_fromguid)) { zfs_handle_t *h; *cp = '\0'; h = zfs_open(drrb->drr_toname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); + *cp = '@'; if (h) { - if (h->zfs_type == ZFS_TYPE_FILESYSTEM) + if (h->zfs_type == ZFS_TYPE_FILESYSTEM) { err = zfs_mount(h, NULL, 0); - else + } else { err = zvol_create_link(h->zfs_name); + if (err == 0 && ioctl_err == 0) { + err = + zvol_create_link(drrb->drr_toname); + } + } zfs_close(h); } } - /* - * If the destination snapshot was also specified, and it was a volume, - * make sure that the appropriate /dev link was created as well. - */ - if (err == 0) { - zfs_handle_t *h; - - if (cp) - *cp = '@'; - - h = zfs_open(drrb->drr_toname, ZFS_TYPE_SNAPSHOT | - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (h) { - if (h->zfs_volblocksize) - err = zvol_create_link(h->zfs_name); - zfs_close(h); - } - } - - if (err) - return (err); + if (err || ioctl_err) + return (-1); if (verbose) { char buf1[64];