Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}