static int farm_write(uint64_t oid, struct siocb *iocb, int create) { int flags = def_open_flags, 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; } if (!is_data_obj(oid)) flags &= ~O_DIRECT; if (create) flags |= O_CREAT | O_TRUNC; sprintf(path, "%s%016"PRIx64, obj_path, oid); fd = open(path, flags, def_fmode); if (fd < 0) return err_to_sderr(oid, errno); if (flock(fd, LOCK_EX) < 0) { ret = SD_RES_EIO; eprintf("%m\n"); goto out; } if (create && !(iocb->flags & SD_FLAG_CMD_COW)) { ret = prealloc(fd, get_objsize(oid)); if (ret != SD_RES_SUCCESS) { if (flock(fd, LOCK_UN) < 0) { ret = SD_RES_EIO; eprintf("%m\n"); goto out; } goto out; } } size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset); if (flock(fd, LOCK_UN) < 0) { ret = SD_RES_EIO; eprintf("%m\n"); goto out; } if (size != iocb->length) { eprintf("%m\n"); ret = SD_RES_EIO; goto out; } trunk_update_entry(oid); out: close(fd); return ret; }
static int get_open_flags(uint64_t oid, bool create) { int flags = O_DSYNC | O_RDWR; if (is_data_obj(oid)) flags |= O_DIRECT; if (create) flags |= O_CREAT | O_EXCL; return flags; }
static void *read_working_object(uint64_t oid, uint64_t offset, uint32_t length) { void *buf = NULL; char path[PATH_MAX]; int fd, flags = def_open_flags; size_t size; snprintf(path, sizeof(path), "%s%016" PRIx64, obj_path, oid); if (!is_data_obj(oid)) flags &= ~O_DIRECT; fd = open(path, flags); if (fd < 0) { dprintf("object %"PRIx64" not found\n", oid); goto out; } buf = valloc(length); if (!buf) { eprintf("no memory to allocate buffer.\n"); goto out; } if (flock(fd, LOCK_SH) < 0) { eprintf("%m\n"); goto err; } size = xpread(fd, buf, length, offset); if (flock(fd, LOCK_UN) < 0) { eprintf("%m\n"); goto err; } if (length != size) { eprintf("size %zu len %"PRIu32" off %"PRIu64" %m\n", size, length, offset); goto err; } out: if (fd > 0) close(fd); return buf; err: free(buf); close(fd); return NULL; }
static int get_open_flags(uint64_t oid, bool create, int fl) { int flags = O_DSYNC | O_RDWR; if (uatomic_is_true(&sys->use_journal) || sys->nosync == true) flags &= ~O_DSYNC; /* We can not use DIO for inode object because it is not 512B aligned */ if (sys->backend_dio && is_data_obj(oid)) flags |= O_DIRECT; if (create) flags |= O_CREAT | O_EXCL; return flags; }
static int farm_atomic_put(uint64_t oid, struct siocb *iocb) { char path[PATH_MAX], tmp_path[PATH_MAX]; int flags = def_open_flags | O_CREAT; int ret = SD_RES_EIO, fd; uint32_t len = iocb->length; snprintf(path, sizeof(path), "%s%016" PRIx64, obj_path, oid); snprintf(tmp_path, sizeof(tmp_path), "%s%016" PRIx64 ".tmp", obj_path, oid); if (!is_data_obj(oid)) flags &= ~O_DIRECT; fd = open(tmp_path, flags, def_fmode); if (fd < 0) { eprintf("failed to open %s: %m\n", tmp_path); goto out; } ret = xwrite(fd, iocb->buf, len); if (ret != len) { eprintf("failed to write object. %m\n"); ret = SD_RES_EIO; goto out_close; } ret = rename(tmp_path, path); if (ret < 0) { eprintf("failed to rename %s to %s: %m\n", tmp_path, path); ret = SD_RES_EIO; goto out_close; } dprintf("%"PRIx64"\n", oid); trunk_get_entry(oid); ret = SD_RES_SUCCESS; out_close: close(fd); out: return ret; }
static int get_open_flags(uint64_t oid, bool create, int fl) { int flags = O_RDWR; if (!sys->no_sync) flags |= O_DSYNC; if ((fl & SD_FLAG_CMD_CACHE && is_disk_cache_enabled()) || uatomic_is_true(&sys->use_journal)) flags &= ~O_DSYNC; /* * We can not use DIO for inode object because it is not 512B aligned. */ if (sys->backend_dio && is_data_obj(oid)) flags |= O_DIRECT; if (create) flags |= O_CREAT | O_EXCL; return flags; }
static int farm_read(uint64_t oid, struct siocb *iocb) { int flags = def_open_flags, fd, ret = SD_RES_SUCCESS; uint32_t epoch = sys_epoch(); char path[PATH_MAX]; ssize_t size; int i; void *buffer; if (iocb->epoch < epoch) { buffer = read_working_object(oid, iocb->offset, iocb->length); if (!buffer) { /* Here if read the object from the targeted epoch failed, * we need to read from the later epoch, because at some epoch * we doesn't write the object to the snapshot, we assume * it in the current local object directory, but maybe * in the next epoch we removed it from the local directory. * in this case, we should try to retrieve object upwards, since. * when the object is to be removed, it will get written to the * snapshot at later epoch. */ for (i = iocb->epoch; i < epoch; i++) { buffer = retrieve_object_from_snap(oid, i); if (buffer) break; } } if (!buffer) return SD_RES_NO_OBJ; memcpy(iocb->buf, buffer, iocb->length); free(buffer); return SD_RES_SUCCESS; } if (!is_data_obj(oid)) flags &= ~O_DIRECT; sprintf(path, "%s%016"PRIx64, obj_path, oid); fd = open(path, flags); if (fd < 0) return err_to_sderr(oid, errno); if (flock(fd, LOCK_SH) < 0) { ret = SD_RES_EIO; eprintf("%m\n"); goto out; } size = xpread(fd, iocb->buf, iocb->length, iocb->offset); if (flock(fd, LOCK_UN) < 0) { ret = SD_RES_EIO; eprintf("%m\n"); goto out; } if (size != iocb->length) { ret = SD_RES_EIO; goto out; } out: close(fd); return ret; }