Print this page
FAR: generating send-streams in portable format
This commit adds a switch '-F' to zfs send. This set, zfs send generates
a stream in FAR-format instead of the traditional zfs stream format. The
generated send stream is compatible with the stream generated from 'btrfs send'
and can in principle easily be received to any filesystem.
@@ -170,10 +170,11 @@
#include <sys/zfs_onexit.h>
#include <sys/zvol.h>
#include <sys/dsl_scan.h>
#include <sharefs/share.h>
#include <sys/dmu_objset.h>
+#include <sys/far.h>
#include "zfs_namecheck.h"
#include "zfs_prop.h"
#include "zfs_deleg.h"
#include "zfs_comutil.h"
@@ -4040,12 +4041,13 @@
* zc_name name of snapshot to send
* zc_cookie file descriptor to send stream to
* zc_obj fromorigin flag (mutually exclusive with zc_fromobj)
* zc_sendobj objsetid of snapshot to send
* zc_fromobj objsetid of incremental fromsnap (may be zero)
- * zc_guid if set, estimate size of stream only. zc_cookie is ignored.
- * output size in zc_objset_type.
+ * zc_guid bit 0: if set, estimate size of stream only. zc_cookie is
+ * ignored. output size in zc_objset_type.
+ * zc_guid bit 1: if set, send output in FAR-format
*
* outputs: none
*/
static int
zfs_ioc_send(zfs_cmd_t *zc)
@@ -4056,11 +4058,12 @@
offset_t off;
dsl_dataset_t *ds;
dsl_dataset_t *dsfrom = NULL;
spa_t *spa;
dsl_pool_t *dp;
- boolean_t estimate = (zc->zc_guid != 0);
+ boolean_t estimate = ((zc->zc_guid & 1) != 0);
+ boolean_t far = ((zc->zc_guid & 2) != 0);
error = spa_open(zc->zc_name, &spa, FTAG);
if (error)
return (error);
@@ -4132,12 +4135,16 @@
dsl_dataset_rele(dsfrom, FTAG);
return (EBADF);
}
off = fp->f_offset;
+ if (!far)
error = dmu_send(tosnap, fromsnap,
zc->zc_cookie, fp->f_vnode, &off);
+ else
+ error = far_send(tosnap, fromsnap,
+ zc->zc_cookie, fp->f_vnode, &off);
if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
fp->f_offset = off;
releasef(zc->zc_cookie);
}
@@ -5090,15 +5097,20 @@
objset_t *tosnap;
int error;
offset_t off;
char *fromname;
int fd;
+ int far;
error = nvlist_lookup_int32(innvl, "fd", &fd);
if (error != 0)
return (EINVAL);
+ error = nvlist_lookup_int32(innvl, "far", &far);
+ if (error != 0 && error != ENOENT)
+ return (EINVAL);
+
error = dmu_objset_hold(snapname, FTAG, &tosnap);
if (error)
return (error);
error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
@@ -5117,11 +5129,14 @@
dmu_objset_rele(fromsnap, FTAG);
return (EBADF);
}
off = fp->f_offset;
+ if (!far)
error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
+ else
+ error = far_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
fp->f_offset = off;
releasef(fd);
if (fromsnap != NULL)