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.

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/zfs_ioctl.c
          +++ new/usr/src/uts/common/fs/zfs/zfs_ioctl.c
↓ open down ↓ 164 lines elided ↑ open up ↑
 165  165  #include <sys/mount.h>
 166  166  #include <sys/sdt.h>
 167  167  #include <sys/fs/zfs.h>
 168  168  #include <sys/zfs_ctldir.h>
 169  169  #include <sys/zfs_dir.h>
 170  170  #include <sys/zfs_onexit.h>
 171  171  #include <sys/zvol.h>
 172  172  #include <sys/dsl_scan.h>
 173  173  #include <sharefs/share.h>
 174  174  #include <sys/dmu_objset.h>
      175 +#include <sys/far.h>
 175  176  
 176  177  #include "zfs_namecheck.h"
 177  178  #include "zfs_prop.h"
 178  179  #include "zfs_deleg.h"
 179  180  #include "zfs_comutil.h"
 180  181  
 181  182  extern struct modlfs zfs_modlfs;
 182  183  
 183  184  extern void zfs_init(void);
 184  185  extern void zfs_fini(void);
↓ open down ↓ 3850 lines elided ↑ open up ↑
4035 4036          return (error);
4036 4037  }
4037 4038  
4038 4039  /*
4039 4040   * inputs:
4040 4041   * zc_name      name of snapshot to send
4041 4042   * zc_cookie    file descriptor to send stream to
4042 4043   * zc_obj       fromorigin flag (mutually exclusive with zc_fromobj)
4043 4044   * zc_sendobj   objsetid of snapshot to send
4044 4045   * zc_fromobj   objsetid of incremental fromsnap (may be zero)
4045      - * zc_guid      if set, estimate size of stream only.  zc_cookie is ignored.
4046      - *              output size in zc_objset_type.
     4046 + * zc_guid      bit 0: if set, estimate size of stream only. zc_cookie is
     4047 + *              ignored. output size in zc_objset_type.
     4048 + * zc_guid      bit 1: if set, send output in FAR-format
4047 4049   *
4048 4050   * outputs: none
4049 4051   */
4050 4052  static int
4051 4053  zfs_ioc_send(zfs_cmd_t *zc)
4052 4054  {
4053 4055          objset_t *fromsnap = NULL;
4054 4056          objset_t *tosnap;
4055 4057          int error;
4056 4058          offset_t off;
4057 4059          dsl_dataset_t *ds;
4058 4060          dsl_dataset_t *dsfrom = NULL;
4059 4061          spa_t *spa;
4060 4062          dsl_pool_t *dp;
4061      -        boolean_t estimate = (zc->zc_guid != 0);
     4063 +        boolean_t estimate = ((zc->zc_guid & 1) != 0);
     4064 +        boolean_t far = ((zc->zc_guid & 2) != 0);
4062 4065  
4063 4066          error = spa_open(zc->zc_name, &spa, FTAG);
4064 4067          if (error)
4065 4068                  return (error);
4066 4069  
4067 4070          dp = spa_get_dsl(spa);
4068 4071          rw_enter(&dp->dp_config_rwlock, RW_READER);
4069 4072          error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &ds);
4070 4073          rw_exit(&dp->dp_config_rwlock);
4071 4074          spa_close(spa, FTAG);
↓ open down ↓ 55 lines elided ↑ open up ↑
4127 4130          } else {
4128 4131                  file_t *fp = getf(zc->zc_cookie);
4129 4132                  if (fp == NULL) {
4130 4133                          dsl_dataset_rele(ds, FTAG);
4131 4134                          if (dsfrom)
4132 4135                                  dsl_dataset_rele(dsfrom, FTAG);
4133 4136                          return (EBADF);
4134 4137                  }
4135 4138  
4136 4139                  off = fp->f_offset;
4137      -                error = dmu_send(tosnap, fromsnap,
4138      -                    zc->zc_cookie, fp->f_vnode, &off);
     4140 +                if (!far)
     4141 +                        error = dmu_send(tosnap, fromsnap,
     4142 +                            zc->zc_cookie, fp->f_vnode, &off);
     4143 +                else
     4144 +                        error = far_send(tosnap, fromsnap,
     4145 +                            zc->zc_cookie, fp->f_vnode, &off);
4139 4146  
4140 4147                  if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
4141 4148                          fp->f_offset = off;
4142 4149                  releasef(zc->zc_cookie);
4143 4150          }
4144 4151          if (dsfrom)
4145 4152                  dsl_dataset_rele(dsfrom, FTAG);
4146 4153          dsl_dataset_rele(ds, FTAG);
4147 4154          return (error);
4148 4155  }
↓ open down ↓ 936 lines elided ↑ open up ↑
5085 5092  /* ARGSUSED */
5086 5093  static int
5087 5094  zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
5088 5095  {
5089 5096          objset_t *fromsnap = NULL;
5090 5097          objset_t *tosnap;
5091 5098          int error;
5092 5099          offset_t off;
5093 5100          char *fromname;
5094 5101          int fd;
     5102 +        int far;
5095 5103  
5096 5104          error = nvlist_lookup_int32(innvl, "fd", &fd);
5097 5105          if (error != 0)
5098 5106                  return (EINVAL);
5099 5107  
     5108 +        error = nvlist_lookup_int32(innvl, "far", &far);
     5109 +        if (error != 0 && error != ENOENT)
     5110 +                return (EINVAL);
     5111 +
5100 5112          error = dmu_objset_hold(snapname, FTAG, &tosnap);
5101 5113          if (error)
5102 5114                  return (error);
5103 5115  
5104 5116          error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
5105 5117          if (error == 0) {
5106 5118                  error = dmu_objset_hold(fromname, FTAG, &fromsnap);
5107 5119                  if (error) {
5108 5120                          dmu_objset_rele(tosnap, FTAG);
5109 5121                          return (error);
↓ open down ↓ 2 lines elided ↑ open up ↑
5112 5124  
5113 5125          file_t *fp = getf(fd);
5114 5126          if (fp == NULL) {
5115 5127                  dmu_objset_rele(tosnap, FTAG);
5116 5128                  if (fromsnap != NULL)
5117 5129                          dmu_objset_rele(fromsnap, FTAG);
5118 5130                  return (EBADF);
5119 5131          }
5120 5132  
5121 5133          off = fp->f_offset;
5122      -        error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
     5134 +        if (!far)
     5135 +                error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
     5136 +        else
     5137 +                error = far_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
5123 5138  
5124 5139          if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
5125 5140                  fp->f_offset = off;
5126 5141          releasef(fd);
5127 5142          if (fromsnap != NULL)
5128 5143                  dmu_objset_rele(fromsnap, FTAG);
5129 5144          dmu_objset_rele(tosnap, FTAG);
5130 5145          return (error);
5131 5146  }
5132 5147  
↓ open down ↓ 784 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX