int default_write(uint64_t oid, struct siocb *iocb) { int flags = get_open_flags(oid, false), fd, ret = SD_RES_SUCCESS; char path[PATH_MAX]; ssize_t size; if (iocb->epoch < sys_epoch()) { dprintf("%"PRIu32" sys %"PRIu32"\n", iocb->epoch, sys_epoch()); return SD_RES_OLD_NODE_VER; } get_obj_path(oid, path); if (iocb->flags & SD_FLAG_CMD_CACHE && is_disk_cache_enabled()) flags &= ~O_DSYNC; fd = open(path, flags, def_fmode); if (fd < 0) return err_to_sderr(oid, errno); size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset); if (size != iocb->length) { eprintf("failed to write object %"PRIx64", path=%s, offset=%" PRId64", size=%"PRId32", result=%zd, %m\n", oid, path, iocb->offset, iocb->length, size); ret = err_to_sderr(oid, errno); goto out; } out: close(fd); return ret; }
int default_create_and_write(uint64_t oid, struct siocb *iocb) { char path[PATH_MAX], tmp_path[PATH_MAX]; int flags = get_open_flags(oid, true); int ret, fd; uint32_t len = iocb->length; get_obj_path(oid, path); get_tmp_obj_path(oid, tmp_path); fd = open(tmp_path, flags, def_fmode); if (fd < 0) { if (errno == EEXIST) /* This happens if node membership changes during object * creation; while gateway retries a CREATE request, * recovery process could also recover the object at the * same time. They should try to write the same date, * so it is okay to simply return success here. */ dprintf("%s exists\n", tmp_path); return SD_RES_SUCCESS; eprintf("failed to open %s: %m\n", tmp_path); return err_to_sderr(oid, errno); } if (iocb->offset != 0 || iocb->length != get_objsize(oid)) { ret = prealloc(fd, get_objsize(oid)); if (ret != SD_RES_SUCCESS) goto out; } ret = xpwrite(fd, iocb->buf, len, iocb->offset); if (ret != len) { eprintf("failed to write object. %m\n"); ret = err_to_sderr(oid, errno); goto out; } ret = rename(tmp_path, path); if (ret < 0) { eprintf("failed to rename %s to %s: %m\n", tmp_path, path); ret = err_to_sderr(oid, errno); goto out; } dprintf("%"PRIx64"\n", oid); ret = SD_RES_SUCCESS; out: if (ret != SD_RES_SUCCESS) unlink(tmp_path); close(fd); return ret; }
int default_exist(uint64_t oid) { char path[PATH_MAX]; get_obj_path(oid, path); if (access(path, R_OK | W_OK) < 0) { if (errno != ENOENT) eprintf("failed to check object %"PRIx64", %m\n", oid); return 0; } return 1; }
int default_create_and_write(uint64_t oid, const struct siocb *iocb) { char path[PATH_MAX], tmp_path[PATH_MAX]; int flags = prepare_iocb(oid, iocb, true); int ret, fd; uint32_t len = iocb->length; bool ec = is_erasure_obj(oid, iocb->copy_policy); size_t obj_size; sd_debug("%"PRIx64, oid); get_obj_path(oid, path, sizeof(path)); get_tmp_obj_path(oid, tmp_path, sizeof(tmp_path)); if (uatomic_is_true(&sys->use_journal) && journal_write_store(oid, iocb->buf, iocb->length, iocb->offset, true) != SD_RES_SUCCESS) { sd_err("turn off journaling"); uatomic_set_false(&sys->use_journal); flags |= O_DSYNC; sync(); } fd = open(tmp_path, flags, sd_def_fmode); if (fd < 0) { if (errno == EEXIST) { /* * This happens if node membership changes during object * creation; while gateway retries a CREATE request, * recovery process could also recover the object at the * same time. They should try to write the same date, * so it is okay to simply return success here. */ sd_debug("%s exists", tmp_path); return SD_RES_SUCCESS; } sd_err("failed to open %s: %m", tmp_path); return err_to_sderr(path, oid, errno); } if (ec) { uint8_t policy = iocb->copy_policy ?: get_vdi_copy_policy(oid_to_vid(oid)); int d; ec_policy_to_dp(policy, &d, NULL); obj_size = SD_DATA_OBJ_SIZE / d; } else
static int get_object_path(uint64_t oid, uint32_t epoch, char *path) { if (default_exist(oid)) { get_obj_path(oid, path); } else { get_stale_obj_path(oid, epoch, path); if (access(path, F_OK) < 0) { if (errno == ENOENT) return SD_RES_NO_OBJ; return SD_RES_EIO; } } return SD_RES_SUCCESS; }
int default_remove_object(uint64_t oid) { char path[PATH_MAX]; get_obj_path(oid, path); if (unlink(path) < 0) { if (errno == ENOENT) return SD_RES_NO_OBJ; eprintf("failed to remove object %"PRIx64", %m\n", oid); return SD_RES_EIO; } return SD_RES_SUCCESS; }
static int move_object_to_stale_dir(uint64_t oid, void *arg) { char path[PATH_MAX], stale_path[PATH_MAX]; uint32_t tgt_epoch = *(int *)arg; get_obj_path(oid, path); get_stale_obj_path(oid, tgt_epoch, stale_path); if (rename(path, stale_path) < 0) { eprintf("failed to move stale object %"PRIX64" to %s, %m\n", oid, path); return SD_RES_EIO; } dprintf("moved object %"PRIx64"\n", oid); return SD_RES_SUCCESS; }
int default_link(uint64_t oid, struct siocb *iocb, uint32_t tgt_epoch) { char path[PATH_MAX], stale_path[PATH_MAX]; dprintf("try link %"PRIx64" from snapshot with epoch %d\n", oid, tgt_epoch); get_obj_path(oid, path); get_stale_obj_path(oid, tgt_epoch, stale_path); if (link(stale_path, path) < 0) { eprintf("failed to link from %s to %s, %m\n", stale_path, path); return err_to_sderr(oid, errno); } return SD_RES_SUCCESS; }
int default_remove_object(uint64_t oid) { char path[PATH_MAX]; if (uatomic_is_true(&sys->use_journal)) journal_remove_object(oid); get_obj_path(oid, path); if (unlink(path) < 0) { if (errno == ENOENT) return SD_RES_NO_OBJ; sd_err("failed to remove object %"PRIx64", %m", oid); return SD_RES_EIO; } return SD_RES_SUCCESS; }
int default_read(uint64_t oid, struct siocb *iocb) { int ret; char path[PATH_MAX]; uint32_t epoch = sys_epoch(); get_obj_path(oid, path); ret = default_read_from_path(oid, path, iocb); /* If the request is againt the older epoch, try to read from * the stale directory */ while (ret == SD_RES_NO_OBJ && iocb->epoch < epoch) { epoch--; get_stale_obj_path(oid, epoch, path); ret = default_read_from_path(oid, path, iocb); } return ret; }
int default_read(uint64_t oid, const struct siocb *iocb) { int ret; char path[PATH_MAX]; get_obj_path(oid, path); ret = default_read_from_path(oid, path, iocb); /* * If the request is againt the older epoch, try to read from * the stale directory */ if (ret == SD_RES_NO_OBJ && iocb->epoch > 0 && iocb->epoch < sys_epoch()) { get_stale_obj_path(oid, iocb->epoch, path); ret = default_read_from_path(oid, path, iocb); } return ret; }
int default_write(uint64_t oid, const struct siocb *iocb) { int flags = get_open_flags(oid, false, iocb->flags), fd, ret = SD_RES_SUCCESS; char path[PATH_MAX]; ssize_t size; if (iocb->epoch < sys_epoch()) { sd_dprintf("%"PRIu32" sys %"PRIu32"\n", iocb->epoch, sys_epoch()); return SD_RES_OLD_NODE_VER; } get_obj_path(oid, path); if (uatomic_is_true(&sys->use_journal) && journal_file_write(oid, iocb->buf, iocb->length, iocb->offset, false) != SD_RES_SUCCESS) { sd_eprintf("turn off journaling\n"); uatomic_set_false(&sys->use_journal); flags |= O_DSYNC; sync(); } fd = open(path, flags, def_fmode); if (fd < 0) return err_to_sderr(oid, errno); size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset); if (size != iocb->length) { sd_eprintf("failed to write object %"PRIx64", path=%s, offset=%" PRId64", size=%"PRId32", result=%zd, %m\n", oid, path, iocb->offset, iocb->length, size); ret = err_to_sderr(oid, errno); goto out; } out: close(fd); return ret; }
int default_write(uint64_t oid, const struct siocb *iocb) { int flags = prepare_iocb(oid, iocb, false), fd, ret = SD_RES_SUCCESS; char path[PATH_MAX]; ssize_t size; if (iocb->epoch < sys_epoch()) { sd_debug("%"PRIu32" sys %"PRIu32, iocb->epoch, sys_epoch()); return SD_RES_OLD_NODE_VER; } if (uatomic_is_true(&sys->use_journal) && unlikely(journal_write_store(oid, iocb->buf, iocb->length, iocb->offset, false)) != SD_RES_SUCCESS) { sd_err("turn off journaling"); uatomic_set_false(&sys->use_journal); flags |= O_DSYNC; sync(); } get_obj_path(oid, path); fd = open(path, flags, sd_def_fmode); if (unlikely(fd < 0)) return err_to_sderr(path, oid, errno); size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset); if (unlikely(size != iocb->length)) { sd_err("failed to write object %"PRIx64", path=%s, offset=%" PRId64", size=%"PRId32", result=%zd, %m", oid, path, iocb->offset, iocb->length, size); ret = err_to_sderr(path, oid, errno); goto out; } out: close(fd); return ret; }
int default_link(uint64_t oid, uint32_t tgt_epoch) { char path[PATH_MAX], stale_path[PATH_MAX]; sd_debug("try link %"PRIx64" from snapshot with epoch %d", oid, tgt_epoch); get_obj_path(oid, path); get_stale_obj_path(oid, tgt_epoch, stale_path); if (link(stale_path, path) < 0) { /* * Recovery thread and main thread might try to recover the * same object and we might get EEXIST in such case. */ if (errno == EEXIST) goto out; sd_debug("failed to link from %s to %s, %m", stale_path, path); return err_to_sderr(path, oid, errno); } out: return SD_RES_SUCCESS; }
int default_create_and_write(uint64_t oid, const struct siocb *iocb) { char path[PATH_MAX], tmp_path[PATH_MAX]; int flags = prepare_iocb(oid, iocb, true); int ret, fd; uint32_t len = iocb->length; get_obj_path(oid, path); get_tmp_obj_path(oid, tmp_path); if (uatomic_is_true(&sys->use_journal) && journal_write_store(oid, iocb->buf, iocb->length, iocb->offset, true) != SD_RES_SUCCESS) { sd_err("turn off journaling"); uatomic_set_false(&sys->use_journal); flags |= O_DSYNC; sync(); } fd = open(tmp_path, flags, sd_def_fmode); if (fd < 0) { if (errno == EEXIST) { /* * This happens if node membership changes during object * creation; while gateway retries a CREATE request, * recovery process could also recover the object at the * same time. They should try to write the same date, * so it is okay to simply return success here. */ sd_debug("%s exists", tmp_path); return SD_RES_SUCCESS; } sd_err("failed to open %s: %m", tmp_path); return err_to_sderr(path, oid, errno); } if (iocb->offset != 0 || iocb->length != get_objsize(oid)) { ret = prealloc(fd, get_objsize(oid)); if (ret < 0) { ret = err_to_sderr(path, oid, errno); goto out; } } ret = xpwrite(fd, iocb->buf, len, iocb->offset); if (ret != len) { sd_err("failed to write object. %m"); ret = err_to_sderr(path, oid, errno); goto out; } ret = rename(tmp_path, path); if (ret < 0) { sd_err("failed to rename %s to %s: %m", tmp_path, path); ret = err_to_sderr(path, oid, errno); goto out; } sd_debug("%"PRIx64, oid); ret = SD_RES_SUCCESS; out: if (ret != SD_RES_SUCCESS) unlink(tmp_path); close(fd); return ret; }