if (!is_power_of_2(dev->zone_size)) {
pr_err("zone_size must be power-of-two\n"); return -EINVAL;
} if (dev->zone_size > dev->size) {
pr_err("Zone size larger than device capacity\n"); return -EINVAL;
}
if (!dev->zone_capacity)
dev->zone_capacity = dev->zone_size;
if (dev->zone_capacity > dev->zone_size) {
pr_err("zone capacity (%lu MB) larger than zone size (%lu MB)\n",
dev->zone_capacity, dev->zone_size); return -EINVAL;
}
/* *Ifasmallerzonecapacitywasrequested,donotallowasmallerlast *zoneatthesametimeassuchzoneconfigurationdoesnotcorrespond *toanyrealzoneddevice.
*/ if (dev->zone_capacity != dev->zone_size &&
dev->size & (dev->zone_size - 1)) {
pr_err("A smaller last zone is not allowed with zone capacity smaller than zone size.\n"); return -EINVAL;
}
if (dev->zone_nr_conv >= dev->nr_zones) {
dev->zone_nr_conv = dev->nr_zones - 1;
pr_info("changed the number of conventional zones to %u",
dev->zone_nr_conv);
}
/* Max active zones has to be < nbr of seq zones in order to be enforceable */ if (dev->zone_max_active >= dev->nr_zones - dev->zone_nr_conv) {
dev->zone_max_active = 0;
pr_info("zone_max_active limit disabled, limit >= zone count\n");
}
/* Max open zones has to be <= max active zones */ if (dev->zone_max_active && dev->zone_max_open > dev->zone_max_active) {
dev->zone_max_open = dev->zone_max_active;
pr_info("changed the maximum number of open zones to %u\n",
dev->zone_max_open);
} elseif (dev->zone_max_open >= dev->nr_zones - dev->zone_nr_conv) {
dev->zone_max_open = 0;
pr_info("zone_max_open limit disabled, limit >= zone count\n");
}
dev->need_zone_res_mgmt = dev->zone_max_active || dev->zone_max_open;
dev->imp_close_zone_no = dev->zone_nr_conv;
for (i = 0; i < dev->zone_nr_conv; i++) {
zone = &dev->zones[i];
switch (zone->cond) { case BLK_ZONE_COND_EMPTY:
ret = null_check_active(dev); if (ret != BLK_STS_OK) return ret;
fallthrough; case BLK_ZONE_COND_CLOSED: return null_check_open(dev); default: /* Should never be called for other states */
WARN_ON(1); return BLK_STS_IOERR;
}
}
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) return BLK_STS_IOERR;
switch (zone->cond) { case BLK_ZONE_COND_EXP_OPEN: /* Open operation on exp open is not an error */ return BLK_STS_OK; case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_IMP_OPEN: case BLK_ZONE_COND_CLOSED: break; case BLK_ZONE_COND_FULL: default: return BLK_STS_IOERR;
}
if (dev->need_zone_res_mgmt) {
spin_lock(&dev->zone_res_lock);
switch (zone->cond) { case BLK_ZONE_COND_EMPTY:
ret = null_check_zone_resources(dev, zone); if (ret != BLK_STS_OK) {
spin_unlock(&dev->zone_res_lock); return ret;
} break; case BLK_ZONE_COND_IMP_OPEN:
dev->nr_zones_imp_open--; break; case BLK_ZONE_COND_CLOSED:
ret = null_check_zone_resources(dev, zone); if (ret != BLK_STS_OK) {
spin_unlock(&dev->zone_res_lock); return ret;
}
dev->nr_zones_closed--; break; default: break;
}
switch (zone->cond) { case BLK_ZONE_COND_CLOSED: /* close operation on closed is not an error */ return BLK_STS_OK; case BLK_ZONE_COND_IMP_OPEN: case BLK_ZONE_COND_EXP_OPEN: break; case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_FULL: default: return BLK_STS_IOERR;
}
if (dev->need_zone_res_mgmt) {
spin_lock(&dev->zone_res_lock);
switch (zone->cond) { case BLK_ZONE_COND_IMP_OPEN:
dev->nr_zones_imp_open--; break; case BLK_ZONE_COND_EXP_OPEN:
dev->nr_zones_exp_open--; break; default: break;
}
if (zone->wp > zone->start)
dev->nr_zones_closed++;
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) return BLK_STS_IOERR;
if (dev->need_zone_res_mgmt) {
spin_lock(&dev->zone_res_lock);
switch (zone->cond) { case BLK_ZONE_COND_FULL: /* Finish operation on full is not an error */
spin_unlock(&dev->zone_res_lock); return BLK_STS_OK; case BLK_ZONE_COND_EMPTY:
ret = null_check_zone_resources(dev, zone); if (ret != BLK_STS_OK) {
spin_unlock(&dev->zone_res_lock); return ret;
} break; case BLK_ZONE_COND_IMP_OPEN:
dev->nr_zones_imp_open--; break; case BLK_ZONE_COND_EXP_OPEN:
dev->nr_zones_exp_open--; break; case BLK_ZONE_COND_CLOSED:
ret = null_check_zone_resources(dev, zone); if (ret != BLK_STS_OK) {
spin_unlock(&dev->zone_res_lock); return ret;
}
dev->nr_zones_closed--; break; default:
spin_unlock(&dev->zone_res_lock); return BLK_STS_IOERR;
}
if (dev->need_zone_res_mgmt) {
spin_lock(&dev->zone_res_lock);
switch (zone->cond) { case BLK_ZONE_COND_IMP_OPEN:
dev->nr_zones_imp_open--; break; case BLK_ZONE_COND_EXP_OPEN:
dev->nr_zones_exp_open--; break; case BLK_ZONE_COND_CLOSED:
dev->nr_zones_closed--; break; case BLK_ZONE_COND_EMPTY: case BLK_ZONE_COND_FULL: break; default:
spin_unlock(&dev->zone_res_lock); return BLK_STS_IOERR;
}
if (op == REQ_OP_ZONE_RESET_ALL) { for (i = dev->zone_nr_conv; i < dev->nr_zones; i++) {
zone = &dev->zones[i];
null_lock_zone(dev, zone); if (zone->cond != BLK_ZONE_COND_EMPTY &&
zone->cond != BLK_ZONE_COND_READONLY &&
zone->cond != BLK_ZONE_COND_OFFLINE) {
null_reset_zone(dev, zone);
trace_nullb_zone_op(cmd, i, zone->cond);
}
null_unlock_zone(dev, zone);
} return BLK_STS_OK;
}
zone_no = null_zone_no(dev, sector);
zone = &dev->zones[zone_no];
null_lock_zone(dev, zone);
if (zone->cond == BLK_ZONE_COND_READONLY ||
zone->cond == BLK_ZONE_COND_OFFLINE) {
ret = BLK_STS_IOERR; goto unlock;
}
switch (op) { case REQ_OP_ZONE_RESET:
ret = null_reset_zone(dev, zone); break; case REQ_OP_ZONE_OPEN:
ret = null_open_zone(dev, zone); break; case REQ_OP_ZONE_CLOSE:
ret = null_close_zone(dev, zone); break; case REQ_OP_ZONE_FINISH:
ret = null_finish_zone(dev, zone); break; default:
ret = BLK_STS_NOTSUPP; break;
}
if (ret == BLK_STS_OK)
trace_nullb_zone_op(cmd, zone_no, zone->cond);
switch (op) { case REQ_OP_WRITE: return null_zone_write(cmd, sector, nr_sectors, false); case REQ_OP_ZONE_APPEND: return null_zone_write(cmd, sector, nr_sectors, true); case REQ_OP_ZONE_RESET: case REQ_OP_ZONE_RESET_ALL: case REQ_OP_ZONE_OPEN: case REQ_OP_ZONE_CLOSE: case REQ_OP_ZONE_FINISH: return null_zone_mgmt(cmd, op, sector); default:
dev = cmd->nq->dev;
zone = &dev->zones[null_zone_no(dev, sector)]; if (zone->cond == BLK_ZONE_COND_OFFLINE) return BLK_STS_IOERR;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.