Print this page
Possibility to physically reserve space without writing leaf blocks

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/zfs_vnops.c
          +++ new/usr/src/uts/common/fs/zfs/zfs_vnops.c
↓ open down ↓ 66 lines elided ↑ open up ↑
  67   67  #include <sys/sa.h>
  68   68  #include <sys/dirent.h>
  69   69  #include <sys/policy.h>
  70   70  #include <sys/sunddi.h>
  71   71  #include <sys/filio.h>
  72   72  #include <sys/sid.h>
  73   73  #include "fs/fs_subr.h"
  74   74  #include <sys/zfs_ctldir.h>
  75   75  #include <sys/zfs_fuid.h>
  76   76  #include <sys/zfs_sa.h>
       77 +#include <sys/zfeature.h>
  77   78  #include <sys/dnlc.h>
  78   79  #include <sys/zfs_rlock.h>
  79   80  #include <sys/extdirent.h>
  80   81  #include <sys/kidmap.h>
  81   82  #include <sys/cred.h>
  82   83  #include <sys/attr.h>
  83   84  
  84   85  /*
  85   86   * Programming rules.
  86   87   *
↓ open down ↓ 198 lines elided ↑ open up ↑
 285  286                  ASSERT(hole);
 286  287                  noff = file_sz;
 287  288          }
 288  289  
 289  290          if (noff < *off)
 290  291                  return (error);
 291  292          *off = noff;
 292  293          return (error);
 293  294  }
 294  295  
      296 +
      297 +static int zfs_zero_write(vnode_t *vp, uint64_t size, cred_t *cr,
      298 +    caller_context_t *ct);
      299 +
 295  300  /* ARGSUSED */
 296  301  static int
 297  302  zfs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred,
 298  303      int *rvalp, caller_context_t *ct)
 299  304  {
 300  305          offset_t off;
 301  306          int error;
 302  307          zfsvfs_t *zfsvfs;
 303  308          znode_t *zp;
      309 +        uint64_t size;
 304  310  
 305  311          switch (com) {
 306  312          case _FIOFFS:
 307  313                  return (zfs_sync(vp->v_vfsp, 0, cred));
 308  314  
 309  315                  /*
 310  316                   * The following two ioctls are used by bfu.  Faking out,
 311  317                   * necessary to avoid bfu errors.
 312  318                   */
 313  319          case _FIOGDIO:
↓ open down ↓ 11 lines elided ↑ open up ↑
 325  331                  ZFS_VERIFY_ZP(zp);
 326  332  
 327  333                  /* offset parameter is in/out */
 328  334                  error = zfs_holey(vp, com, &off);
 329  335                  ZFS_EXIT(zfsvfs);
 330  336                  if (error)
 331  337                          return (error);
 332  338                  if (ddi_copyout(&off, (void *)data, sizeof (off), flag))
 333  339                          return (SET_ERROR(EFAULT));
 334  340                  return (0);
      341 +        case _FIO_RESERVE_SPACE:
      342 +                if (ddi_copyin((void *)data, &size, sizeof (size), flag))
      343 +                        return (EFAULT);
      344 +                error = zfs_zero_write(vp, size, cred, ct);
      345 +                return (error);
 335  346          }
 336  347          return (SET_ERROR(ENOTTY));
 337  348  }
 338  349  
 339  350  /*
 340  351   * Utility functions to map and unmap a single physical page.  These
 341  352   * are used to manage the mappable copies of ZFS file data, and therefore
 342  353   * do not update ref/mod bits.
 343  354   */
 344  355  caddr_t
↓ open down ↓ 604 lines elided ↑ open up ↑
 949  960          }
 950  961  
 951  962          if (ioflag & (FSYNC | FDSYNC) ||
 952  963              zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
 953  964                  zil_commit(zilog, zp->z_id);
 954  965  
 955  966          ZFS_EXIT(zfsvfs);
 956  967          return (0);
 957  968  }
 958  969  
      970 +#define ZFS_RESERVE_CHUNK (2 * 1024 * 1024)
      971 +/* ARGSUSED */
      972 +static int
      973 +zfs_zero_write(vnode_t *vp, uint64_t size, cred_t *cr, caller_context_t *ct)
      974 +{
      975 +        znode_t         *zp = VTOZ(vp);
      976 +        zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
      977 +        int             count = 0;
      978 +        sa_bulk_attr_t  bulk[4];
      979 +        uint64_t        mtime[2], ctime[2];
      980 +        rl_t            *rl;
      981 +        int             error = 0;
      982 +        dmu_tx_t        *tx = NULL;
      983 +        uint64_t        end_size;
      984 +        uint64_t        pos = 0;
      985 +
      986 +        if (zp->z_size > 0)
      987 +                return (EFBIG);
      988 +        if (size == 0)
      989 +                return (0);
      990 +
      991 +        ZFS_ENTER(zfsvfs);
      992 +        ZFS_VERIFY_ZP(zp);
      993 +
      994 +        if (!spa_feature_is_enabled(zfsvfs->z_os->os_spa,
      995 +            SPA_FEATURE_SPACE_RESERVATION))
      996 +        {
      997 +                ZFS_EXIT(zfsvfs);
      998 +                return (ENOTSUP);
      999 +        }
     1000 +
     1001 +        SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
     1002 +        SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
     1003 +        SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
     1004 +            &zp->z_size, 8);
     1005 +        SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
     1006 +            &zp->z_pflags, 8);
     1007 +
     1008 +        /*
     1009 +         * If immutable or not appending then return EPERM
     1010 +         */
     1011 +        if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY))) {
     1012 +                ZFS_EXIT(zfsvfs);
     1013 +                return (EPERM);
     1014 +        }
     1015 +
     1016 +        rl = zfs_range_lock(zp, 0, size, RL_WRITER);
     1017 +
     1018 +        if (zfs_owner_overquota(zfsvfs, zp, B_FALSE) ||
     1019 +            zfs_owner_overquota(zfsvfs, zp, B_TRUE)) {
     1020 +                error = EDQUOT;
     1021 +                goto out;
     1022 +        }
     1023 +
     1024 +        while (pos < size) {
     1025 +                uint64_t length = size - pos;
     1026 +                length = MIN(length, ZFS_RESERVE_CHUNK);
     1027 +again:
     1028 +                tx = dmu_tx_create(zfsvfs->z_os);
     1029 +                dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
     1030 +                dmu_tx_hold_write(tx, zp->z_id, pos, length);
     1031 +                zfs_sa_upgrade_txholds(tx, zp);
     1032 +                error = dmu_tx_assign(tx, TXG_NOWAIT);
     1033 +                if (error) {
     1034 +                        if (error == ERESTART) {
     1035 +                                dmu_tx_wait(tx);
     1036 +                                dmu_tx_abort(tx);
     1037 +                                goto again;
     1038 +                        }
     1039 +                        dmu_tx_abort(tx);
     1040 +                        goto out;
     1041 +                }
     1042 +
     1043 +                if (pos == 0)
     1044 +                        zfs_grow_blocksize(zp, MIN(size, zfsvfs->z_max_blksz), tx);
     1045 +                dmu_write_zero(zfsvfs->z_os, zp->z_id, pos, length, tx);
     1046 +
     1047 +                zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE);
     1048 +
     1049 +                pos += length;
     1050 +                while ((end_size = zp->z_size) < pos)
     1051 +                        (void) atomic_cas_64(&zp->z_size, end_size, pos);
     1052 +
     1053 +                error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
     1054 +
     1055 +                dmu_tx_commit(tx);
     1056 +                if (error)
     1057 +                        goto out;
     1058 +        }
     1059 +out:
     1060 +        zfs_range_unlock(rl);
     1061 +        ZFS_EXIT(zfsvfs);
     1062 +
     1063 +        return (error);
     1064 +}
     1065 +
 959 1066  void
 960 1067  zfs_get_done(zgd_t *zgd, int error)
 961 1068  {
 962 1069          znode_t *zp = zgd->zgd_private;
 963 1070          objset_t *os = zp->z_zfsvfs->z_os;
 964 1071  
 965 1072          if (zgd->zgd_db)
 966 1073                  dmu_buf_rele(zgd->zgd_db, zgd);
 967 1074  
 968 1075          zfs_range_unlock(zgd->zgd_rl);
↓ open down ↓ 4338 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX