Print this page
FITS: generating send-streams in portable format
This commit adds the command 'zfs fits-send', analogous to zfs send. The
generated send stream is compatible with the stream generated with that
from 'btrfs send' and can in principle easily be received to any filesystem.


3180 
3181                 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3182                 if (zhp != NULL) {
3183                         clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3184                             CL_GATHER_MOUNT_ALWAYS, 0);
3185                         zfs_close(zhp);
3186                         if (clp != NULL) {
3187                                 /* mount and share received datasets */
3188                                 err = changelist_postfix(clp);
3189                                 changelist_free(clp);
3190                         }
3191                 }
3192                 if (zhp == NULL || clp == NULL || err)
3193                         err = -1;
3194         }
3195         if (top_zfs)
3196                 free(top_zfs);
3197 
3198         return (err);
3199 }





































































































3180 
3181                 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3182                 if (zhp != NULL) {
3183                         clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3184                             CL_GATHER_MOUNT_ALWAYS, 0);
3185                         zfs_close(zhp);
3186                         if (clp != NULL) {
3187                                 /* mount and share received datasets */
3188                                 err = changelist_postfix(clp);
3189                                 changelist_free(clp);
3190                         }
3191                 }
3192                 if (zhp == NULL || clp == NULL || err)
3193                         err = -1;
3194         }
3195         if (top_zfs)
3196                 free(top_zfs);
3197 
3198         return (err);
3199 }
3200 
3201 /*
3202  * Generate a fits stream for the dataset identified by the argument zhp.
3203  *
3204  * The content of the send stream is the snapshot identified by
3205  * 'tosnap'.  Incremental streams are requested from the snapshot identified
3206  * by "fromsnap" (if non-null)
3207  * Currently no recursive send is implemented
3208  */
3209 int
3210 zfs_fits_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
3211     sendflags_t *flags, int outfd, snapfilter_cb_t filter_func,
3212     void *cb_arg)
3213 {
3214         char errbuf[1024];
3215         char name[MAXPATHLEN];
3216         zfs_cmd_t zc = { 0 };
3217         libzfs_handle_t *hdl = zhp->zfs_hdl;
3218         zfs_handle_t *thdl;
3219 
3220         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3221             "cannot send '%s'"), zhp->zfs_name);
3222 
3223         if (fromsnap && fromsnap[0] == '\0') {
3224                 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3225                     "zero-length incremental source"));
3226                 return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3227         }
3228 
3229         (void) snprintf(name, sizeof (name), "%s@%s", zhp->zfs_name, tosnap);
3230         if ((thdl = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT)) == NULL) {
3231                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
3232                     "WARNING: could not send %s@%s: does not exist\n"),
3233                     zhp->zfs_name, tosnap);
3234                 return (B_TRUE);
3235         }
3236         zc.zc_sendobj = zfs_prop_get_int(thdl, ZFS_PROP_OBJSETID);
3237         zfs_close(thdl);
3238 
3239         if (fromsnap) {
3240                 (void) snprintf(name, sizeof (name), "%s@%s",
3241                     zhp->zfs_name, fromsnap);
3242                 if ((thdl = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT)) == NULL) {
3243                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
3244                             "WARNING: could not send %s@%s:\n"
3245                             "incremental source (%s@%s) does not exist\n"),
3246                             zhp->zfs_name, tosnap,
3247                             zhp->zfs_name, fromsnap);
3248                         return (B_TRUE);
3249                 }
3250                 zc.zc_fromobj = zfs_prop_get_int(thdl, ZFS_PROP_OBJSETID);
3251                 zfs_close(thdl);
3252         }
3253 
3254         assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
3255 
3256         (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
3257             zhp->zfs_name, tosnap);
3258         zc.zc_cookie = outfd;
3259         zc.zc_obj = 0;
3260 
3261         if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_FITS_SEND, &zc) != 0) {
3262                 char errbuf[1024];
3263                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3264                     "warning: cannot send '%s'"), zhp->zfs_name);
3265 
3266                 switch (errno) {
3267                 case EXDEV:
3268                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3269                             "not an earlier snapshot from the same fs"));
3270                         return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
3271                 case ENOENT:
3272                         if (zfs_dataset_exists(hdl, zc.zc_name,
3273                             ZFS_TYPE_SNAPSHOT)) {
3274                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3275                                     "incremental source (@%s) does not exist"),
3276                                     zc.zc_value);
3277                         }
3278                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
3279                 case EDQUOT:
3280                 case EFBIG:
3281                 case EIO:
3282                 case ENOLINK:
3283                 case ENOSPC:
3284                 case ENOSTR:
3285                 case ENXIO:
3286                 case EPIPE:
3287                 case ERANGE:
3288                 case EFAULT:
3289                 case EROFS:
3290                         zfs_error_aux(hdl, strerror(errno));
3291                         return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
3292                 default:
3293                         return (zfs_standard_error(hdl, errno, errbuf));
3294                 }
3295         }
3296 
3297         return (0);
3298 }