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.

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/fits.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 ↓ 4939 lines elided ↑ open up ↑
5124 5125          if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
5125 5126                  fp->f_offset = off;
5126 5127          releasef(fd);
5127 5128          if (fromsnap != NULL)
5128 5129                  dmu_objset_rele(fromsnap, FTAG);
5129 5130          dmu_objset_rele(tosnap, FTAG);
5130 5131          return (error);
5131 5132  }
5132 5133  
5133 5134  /*
     5135 + * inputs:
     5136 + * zc_name      name of snapshot to send
     5137 + * zc_cookie    file descriptor to send stream to
     5138 + * zc_obj       fromorigin flag (mutually exclusive with zc_fromobj)
     5139 + * zc_sendobj   objsetid of snapshot to send
     5140 + * zc_fromobj   objsetid of incremental fromsnap (may be zero)
     5141 + * zc_guid      if set, estimate size of stream only.  zc_cookie is ignored.
     5142 + *              output size in zc_objset_type.
     5143 + *
     5144 + * outputs: none
     5145 + */
     5146 +static int
     5147 +zfs_ioc_fits_send(zfs_cmd_t *zc)
     5148 +{
     5149 +        objset_t *fromsnap = NULL;
     5150 +        objset_t *tosnap;
     5151 +        int error;
     5152 +        offset_t off;
     5153 +        dsl_dataset_t *ds;
     5154 +        dsl_dataset_t *dsfrom = NULL;
     5155 +        spa_t *spa;
     5156 +        file_t *fp;
     5157 +        dsl_pool_t *dp;
     5158 +        boolean_t estimate = (zc->zc_guid != 0);
     5159 +
     5160 +        error = spa_open(zc->zc_name, &spa, FTAG);
     5161 +        if (error)
     5162 +                return (error);
     5163 +
     5164 +        dp = spa_get_dsl(spa);
     5165 +        rw_enter(&dp->dp_config_rwlock, RW_READER);
     5166 +        error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &ds);
     5167 +        rw_exit(&dp->dp_config_rwlock);
     5168 +        spa_close(spa, FTAG);
     5169 +        if (error)
     5170 +                return (error);
     5171 +
     5172 +        error = dmu_objset_from_ds(ds, &tosnap);
     5173 +        if (error) {
     5174 +                dsl_dataset_rele(ds, FTAG);
     5175 +                return (error);
     5176 +        }
     5177 +
     5178 +        if (zc->zc_fromobj != 0) {
     5179 +                rw_enter(&dp->dp_config_rwlock, RW_READER);
     5180 +                error = dsl_dataset_hold_obj(dp, zc->zc_fromobj, FTAG, &dsfrom);
     5181 +                rw_exit(&dp->dp_config_rwlock);
     5182 +                if (error) {
     5183 +                        dsl_dataset_rele(ds, FTAG);
     5184 +                        return (error);
     5185 +                }
     5186 +                error = dmu_objset_from_ds(dsfrom, &fromsnap);
     5187 +                if (error) {
     5188 +                        dsl_dataset_rele(dsfrom, FTAG);
     5189 +                        dsl_dataset_rele(ds, FTAG);
     5190 +                        return (error);
     5191 +                }
     5192 +        }
     5193 +
     5194 +        if (zc->zc_obj) {
     5195 +                dsl_pool_t *dp = ds->ds_dir->dd_pool;
     5196 +
     5197 +                if (fromsnap != NULL) {
     5198 +                        dsl_dataset_rele(dsfrom, FTAG);
     5199 +                        dsl_dataset_rele(ds, FTAG);
     5200 +                        return (EINVAL);
     5201 +                }
     5202 +
     5203 +                if (dsl_dir_is_clone(ds->ds_dir)) {
     5204 +                        rw_enter(&dp->dp_config_rwlock, RW_READER);
     5205 +                        error = dsl_dataset_hold_obj(dp,
     5206 +                            ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &dsfrom);
     5207 +                        rw_exit(&dp->dp_config_rwlock);
     5208 +                        if (error) {
     5209 +                                dsl_dataset_rele(ds, FTAG);
     5210 +                                return (error);
     5211 +                        }
     5212 +                        error = dmu_objset_from_ds(dsfrom, &fromsnap);
     5213 +                        if (error) {
     5214 +                                dsl_dataset_rele(dsfrom, FTAG);
     5215 +                                dsl_dataset_rele(ds, FTAG);
     5216 +                                return (error);
     5217 +                        }
     5218 +                }
     5219 +        }
     5220 +
     5221 +        fp = getf(zc->zc_cookie);
     5222 +        if (fp == NULL) {
     5223 +                dsl_dataset_rele(ds, FTAG);
     5224 +                if (dsfrom)
     5225 +                        dsl_dataset_rele(dsfrom, FTAG);
     5226 +                return (EBADF);
     5227 +        }
     5228 +
     5229 +        off = fp->f_offset;
     5230 +        error = fits_send(tosnap, fromsnap, zc->zc_cookie, fp->f_vnode, &off);
     5231 +
     5232 +        if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
     5233 +                fp->f_offset = off;
     5234 +        releasef(zc->zc_cookie);
     5235 +
     5236 +        if (dsfrom)
     5237 +                dsl_dataset_rele(dsfrom, FTAG);
     5238 +        dsl_dataset_rele(ds, FTAG);
     5239 +        return (error);
     5240 +}
     5241 +
     5242 +/*
5134 5243   * Determine approximately how large a zfs send stream will be -- the number
5135 5244   * of bytes that will be written to the fd supplied to zfs_ioc_send_new().
5136 5245   *
5137 5246   * innvl: {
5138 5247   *     (optional) "fromsnap" -> full snap name to send an incremental from
5139 5248   * }
5140 5249   *
5141 5250   * outnvl: {
5142 5251   *     "space" -> bytes of space (uint64)
5143 5252   * }
↓ open down ↓ 271 lines elided ↑ open up ↑
5415 5524          zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_OBJ_TO_STATS,
5416 5525              zfs_ioc_obj_to_stats, zfs_secpolicy_diff);
5417 5526          zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_OBJ_TO_PATH,
5418 5527              zfs_ioc_obj_to_path, zfs_secpolicy_diff);
5419 5528          zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_USERSPACE_ONE,
5420 5529              zfs_ioc_userspace_one, zfs_secpolicy_userspace_one);
5421 5530          zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_USERSPACE_MANY,
5422 5531              zfs_ioc_userspace_many, zfs_secpolicy_userspace_many);
5423 5532          zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_SEND,
5424 5533              zfs_ioc_send, zfs_secpolicy_send);
     5534 +        zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_FITS_SEND,
     5535 +            zfs_ioc_fits_send, zfs_secpolicy_send);
5425 5536  
5426 5537          zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_PROP, zfs_ioc_set_prop,
5427 5538              zfs_secpolicy_none);
5428 5539          zfs_ioctl_register_dataset_modify(ZFS_IOC_DESTROY, zfs_ioc_destroy,
5429 5540              zfs_secpolicy_destroy);
5430 5541          zfs_ioctl_register_dataset_modify(ZFS_IOC_ROLLBACK, zfs_ioc_rollback,
5431 5542              zfs_secpolicy_rollback);
5432 5543          zfs_ioctl_register_dataset_modify(ZFS_IOC_RENAME, zfs_ioc_rename,
5433 5544              zfs_secpolicy_rename);
5434 5545          zfs_ioctl_register_dataset_modify(ZFS_IOC_RECV, zfs_ioc_recv,
↓ open down ↓ 482 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX