/* Prepare request iterator and buffer for each replica */ static struct req_iter *prepare_requests(struct request *req, int *nr) { if (is_erasure_oid(req->rq.obj.oid)) return prepare_erasure_requests(req, nr); else return prepare_replication_requests(req, nr); }
size_t get_store_objsize(uint64_t oid) { if (is_erasure_oid(oid)) { uint8_t policy = get_vdi_copy_policy(oid_to_vid(oid)); int d; ec_policy_to_dp(policy, &d, NULL); return SD_DATA_OBJ_SIZE / d; } return get_objsize(oid); }
static int get_store_tmp_path(uint64_t oid, uint8_t ec_index, char *path) { if (is_erasure_oid(oid)) { if (unlikely(ec_index >= SD_MAX_COPIES)) panic("invalid ec_index %d", ec_index); return snprintf(path, PATH_MAX, "%s/%016"PRIx64"_%d.tmp", md_get_object_dir(oid), oid, ec_index); } return snprintf(path, PATH_MAX, "%s/%016" PRIx64".tmp", md_get_object_dir(oid), oid); }
static void finish_requests(struct request *req, struct req_iter *reqs, int nr_to_send) { uint64_t oid = req->rq.obj.oid; uint32_t len = req->rq.data_length; uint64_t off = req->rq.obj.offset; int opcode = req->rq.opcode; int start = off / SD_EC_DATA_STRIPE_SIZE; int end = DIV_ROUND_UP(off + len, SD_EC_DATA_STRIPE_SIZE), i, j; int nr_stripe = end - start; if (!is_erasure_oid(oid)) goto out; sd_debug("start %d, end %d, send %d, off %"PRIu64 ", len %"PRIu32, start, end, nr_to_send, off, len); /* We need to assemble the data strips into the req buffer for read */ if (opcode == SD_OP_READ_OBJ) { char *p, *buf; uint8_t policy = req->rq.obj.copy_policy ?: get_vdi_copy_policy(oid_to_vid(req->rq.obj.oid)); int ed = 0, strip_size; buf = malloc(SD_EC_DATA_STRIPE_SIZE * nr_stripe); if(unlikely(!buf)) { goto out; } ec_policy_to_dp(policy, &ed, NULL); strip_size = SD_EC_DATA_STRIPE_SIZE / ed; p = buf; for (i = 0; i < nr_stripe; i++) { for (j = 0; j < nr_to_send; j++) { memcpy(p, reqs[j].buf + strip_size * i, strip_size); p += strip_size; } } memcpy(req->data, buf + off % SD_EC_DATA_STRIPE_SIZE, len); req->rp.data_length = req->rq.data_length; free(buf); }
static int default_read_from_path(uint64_t oid, const char *path, const struct siocb *iocb) { int flags = prepare_iocb(oid, iocb, false), fd, ret = SD_RES_SUCCESS; ssize_t size; fd = open(path, flags); if (fd < 0) return err_to_sderr(path, oid, errno); if (is_erasure_oid(oid) && iocb->ec_index <= SD_MAX_COPIES) { uint8_t idx; if (get_erasure_index(path, &idx) < 0) { close(fd); return err_to_sderr(path, oid, errno); } /* We pretend NO-OBJ to read old object in the stale dir */ if (idx != iocb->ec_index) { sd_debug("ec_index %d != %d", iocb->ec_index, idx); close(fd); return SD_RES_NO_OBJ; } } size = xpread(fd, iocb->buf, iocb->length, iocb->offset); if (unlikely(size != iocb->length)) { sd_err("failed to read object %"PRIx64", path=%s, offset=%" PRId32", size=%"PRId32", result=%zd, %m", oid, path, iocb->offset, iocb->length, size); ret = err_to_sderr(path, oid, errno); } close(fd); return ret; }