Print this page
Matt's code review fixes

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 ↓ 4085 lines elided ↑ open up ↑
4086 4086                  /* don't bother receiving the property */
4087 4087                  (void) nvlist_remove_nvpair(props, pair);
4088 4088  next:
4089 4089                  pair = next_pair;
4090 4090          }
4091 4091  }
4092 4092  
4093 4093  /*
4094 4094   * Extract properties that cannot be set PRIOR to the receipt of a dataset.
4095 4095   * For example, refquota cannot be set until after the receipt of a dataset,
4096      - * because a prior snapshot may exceed the refquota, and refquotas only apply
4097      - * to the current dataset.  The caller (libzfs) will manage these properties
4098      - * somewhat as well to make sure they only come down with the last dataset in
4099      - * a replication stream, but we still need to be safe about it here in
4100      - * kernel-land.
     4096 + * because in replication streams, an older/earlier snapshot may exceed the
     4097 + * refquota.  We want to receive the older/earlier snapshot, but setting
     4098 + * refquota pre-receipt will set the dsl's ACTUAL quota, which will prevent
     4099 + * the older/earlier snapshot from being received (with EDQUOT).
     4100 + *
     4101 + * The ZFS test "zfs_receive_011_pos" demonstrates such a scenario.
     4102 + *
     4103 + * libzfs will need to be judicious handling errors encountered by props
     4104 + * extracted by this function.
4101 4105   */
4102 4106  static nvlist_t *
4103 4107  extract_delay_props(nvlist_t *props)
4104 4108  {
4105 4109          nvlist_t *delayprops;
4106 4110          nvpair_t *nvp, *tmp;
4107 4111          static const zfs_prop_t delayable[] = { ZFS_PROP_REFQUOTA, 0 };
4108      -        boolean_t dontbother = B_TRUE;
4109 4112          int i;
4110 4113  
4111 4114          VERIFY(nvlist_alloc(&delayprops, NV_UNIQUE_NAME, KM_SLEEP) == 0);
4112 4115  
4113 4116          for (nvp = nvlist_next_nvpair(props, NULL); nvp != NULL;
4114 4117              nvp = nvlist_next_nvpair(props, nvp)) {
4115 4118                  /*
4116 4119                   * strcmp() is safe because zfs_prop_to_name() always returns
4117 4120                   * a bounded string.
4118 4121                   */
↓ open down ↓ 1 lines elided ↑ open up ↑
4120 4123                          if (strcmp(zfs_prop_to_name(delayable[i]),
4121 4124                              nvpair_name(nvp)) == 0) {
4122 4125                                  break;
4123 4126                          }
4124 4127                  }
4125 4128                  if (delayable[i] != 0) {
4126 4129                          tmp = nvlist_prev_nvpair(props, nvp);
4127 4130                          VERIFY(nvlist_add_nvpair(delayprops, nvp) == 0);
4128 4131                          VERIFY(nvlist_remove_nvpair(props, nvp) == 0);
4129 4132                          nvp = tmp;
4130      -                        dontbother = B_FALSE;  /* Actually, do bother! */
4131 4133                  }
4132 4134          }
4133 4135  
4134      -        if (dontbother) {
     4136 +        if (nvlist_empty(delayprops)) {
4135 4137                  nvlist_free(delayprops);
4136 4138                  delayprops = NULL;
4137 4139          }
4138 4140          return (delayprops);
4139 4141  }
4140 4142  
4141 4143  #ifdef  DEBUG
4142 4144  static boolean_t zfs_ioc_recv_inject_err;
4143 4145  #endif
4144 4146  
↓ open down ↓ 141 lines elided ↑ open up ↑
4286 4288                          error = dmu_recv_end(&drc, NULL);
4287 4289                  }
4288 4290  
4289 4291                  /* Set delayed properties now, after we're done receiving. */
4290 4292                  if (delayprops != NULL) {
4291 4293                          (void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,
4292 4294                              delayprops, errors);
4293 4295                  }
4294 4296          }
4295 4297  
4296      -        /* Merge delayprops back in with regular props, in case of errors. */
     4298 +        /*
     4299 +         * Merge delayed props back in with initial props, so errors (which is
     4300 +         * one list) can match up with the order in which props were set.
     4301 +         * Also, the error cleanup code only deals with the unsplit props
     4302 +         * list.
     4303 +         */
4297 4304          if (delayprops != NULL) {
4298 4305                  VERIFY(nvlist_merge(props, delayprops, 0) == 0);
4299 4306                  nvlist_free(delayprops);
4300 4307          }
4301 4308  
4302      -        /* Put the props error list into zc AFTER the delayprops. */
     4309 +        /*
     4310 +         * Now that all props, initial and delayed, are set, report the prop
     4311 +         * errors to the caller.
     4312 +         */
4303 4313          if (zc->zc_nvlist_dst_size != 0 &&
4304 4314              (nvlist_smush(errors, zc->zc_nvlist_dst_size) != 0 ||
4305 4315              put_nvlist(zc, errors) != 0)) {
4306 4316                  /*
4307 4317                   * Caller made zc->zc_nvlist_dst less than the minimum expected
4308 4318                   * size or supplied an invalid address.
4309 4319                   */
4310 4320                  props_error = SET_ERROR(EINVAL);
4311 4321          }
4312 4322  
↓ open down ↓ 1958 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX