Print this page
3740 Poor ZFS send / receive performance due to snapshot hold / release processing
Submitted by: Steven Hartland <steven.hartland@multiplay.co.uk>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libzfs/common/libzfs_dataset.c
          +++ new/usr/src/lib/libzfs/common/libzfs_dataset.c
↓ open down ↓ 4073 lines elided ↑ open up ↑
4074 4074          nvlist_t *nvl;
4075 4075          const char *snapname;
4076 4076          const char *tag;
4077 4077          boolean_t recursive;
4078 4078  };
4079 4079  
4080 4080  static int
4081 4081  zfs_hold_one(zfs_handle_t *zhp, void *arg)
4082 4082  {
4083 4083          struct holdarg *ha = arg;
4084      -        zfs_handle_t *szhp;
4085 4084          char name[ZFS_MAXNAMELEN];
4086 4085          int rv = 0;
4087 4086  
4088 4087          (void) snprintf(name, sizeof (name),
4089 4088              "%s@%s", zhp->zfs_name, ha->snapname);
4090 4089  
4091      -        szhp = make_dataset_handle(zhp->zfs_hdl, name);
4092      -        if (szhp) {
     4090 +        if (lzc_exists(name))
4093 4091                  fnvlist_add_string(ha->nvl, name, ha->tag);
4094      -                zfs_close(szhp);
4095      -        }
4096 4092  
4097 4093          if (ha->recursive)
4098 4094                  rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha);
4099 4095          zfs_close(zhp);
4100 4096          return (rv);
4101 4097  }
4102 4098  
4103 4099  int
4104 4100  zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4105      -    boolean_t recursive, boolean_t enoent_ok, int cleanup_fd)
     4101 +    boolean_t recursive, int cleanup_fd)
4106 4102  {
4107 4103          int ret;
4108 4104          struct holdarg ha;
4109      -        nvlist_t *errors;
4110      -        libzfs_handle_t *hdl = zhp->zfs_hdl;
4111      -        char errbuf[1024];
4112      -        nvpair_t *elem;
4113 4105  
4114 4106          ha.nvl = fnvlist_alloc();
4115 4107          ha.snapname = snapname;
4116 4108          ha.tag = tag;
4117 4109          ha.recursive = recursive;
4118 4110          (void) zfs_hold_one(zfs_handle_dup(zhp), &ha);
4119      -        ret = lzc_hold(ha.nvl, cleanup_fd, &errors);
     4111 +        ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl);
4120 4112          fnvlist_free(ha.nvl);
4121 4113  
     4114 +        return (ret);
     4115 +}
     4116 +
     4117 +int
     4118 +zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds)
     4119 +{
     4120 +        int ret;
     4121 +        nvlist_t *errors;
     4122 +        libzfs_handle_t *hdl = zhp->zfs_hdl;
     4123 +        char errbuf[1024];
     4124 +        nvpair_t *elem;
     4125 + 
     4126 +        ret = lzc_hold(holds, cleanup_fd, &errors);
     4127 + 
4122 4128          if (ret == 0)
4123 4129                  return (0);
4124 4130  
4125 4131          if (nvlist_next_nvpair(errors, NULL) == NULL) {
4126 4132                  /* no hold-specific errors */
4127 4133                  (void) snprintf(errbuf, sizeof (errbuf),
4128 4134                      dgettext(TEXT_DOMAIN, "cannot hold"));
4129 4135                  switch (ret) {
4130 4136                  case ENOTSUP:
4131 4137                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
↓ open down ↓ 23 lines elided ↑ open up ↑
4155 4161                           * up being slightly too long.
4156 4162                           */
4157 4163                          (void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf);
4158 4164                          break;
4159 4165                  case EINVAL:
4160 4166                          (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4161 4167                          break;
4162 4168                  case EEXIST:
4163 4169                          (void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf);
4164 4170                          break;
4165      -                case ENOENT:
4166      -                        if (enoent_ok)
4167      -                                return (ENOENT);
4168      -                        /* FALLTHROUGH */
4169 4171                  default:
4170 4172                          (void) zfs_standard_error(hdl,
4171 4173                              fnvpair_value_int32(elem), errbuf);
4172 4174                  }
4173 4175          }
4174 4176  
4175 4177          fnvlist_free(errors);
4176 4178          return (ret);
4177 4179  }
4178 4180  
4179      -struct releasearg {
4180      -        nvlist_t *nvl;
4181      -        const char *snapname;
4182      -        const char *tag;
4183      -        boolean_t recursive;
4184      -};
4185      -
4186 4181  static int
4187 4182  zfs_release_one(zfs_handle_t *zhp, void *arg)
4188 4183  {
4189 4184          struct holdarg *ha = arg;
4190      -        zfs_handle_t *szhp;
4191 4185          char name[ZFS_MAXNAMELEN];
4192 4186          int rv = 0;
4193 4187  
4194 4188          (void) snprintf(name, sizeof (name),
4195 4189              "%s@%s", zhp->zfs_name, ha->snapname);
4196 4190  
4197      -        szhp = make_dataset_handle(zhp->zfs_hdl, name);
4198      -        if (szhp) {
     4191 +        if (lzc_exists(name)) {
4199 4192                  nvlist_t *holds = fnvlist_alloc();
4200 4193                  fnvlist_add_boolean(holds, ha->tag);
4201 4194                  fnvlist_add_nvlist(ha->nvl, name, holds);
4202      -                zfs_close(szhp);
     4195 +                fnvlist_free(holds);
4203 4196          }
4204 4197  
4205 4198          if (ha->recursive)
4206 4199                  rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
4207 4200          zfs_close(zhp);
4208 4201          return (rv);
4209 4202  }
4210 4203  
4211 4204  int
4212 4205  zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
↓ open down ↓ 255 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX