Beispiel #1
0
static int init_vdi_copy_number(uint64_t oid)
{
	char path[PATH_MAX];
	int fd, flags = get_open_flags(oid, false), ret;
	struct sheepdog_inode *inode = xzalloc(sizeof(*inode));

	snprintf(path, sizeof(path), "%s%016" PRIx64, obj_path, oid);

	fd = open(path, flags);
	if (fd < 0) {
		eprintf("failed to open %s, %m\n", path);
		ret = SD_RES_EIO;
		goto out;
	}

	ret = xpread(fd, inode, SD_INODE_HEADER_SIZE, 0);
	if (ret != SD_INODE_HEADER_SIZE) {
		eprintf("failed to read inode header, path=%s, %m\n", path);
		ret = SD_RES_EIO;
		goto out;
	}

	add_vdi_copy_number(oid_to_vid(oid), inode->nr_copies);

	ret = SD_RES_SUCCESS;
out:
	free(inode);
	return SD_RES_SUCCESS;
}
Beispiel #2
0
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;
}
Beispiel #3
0
void DistributedLock::do_open()
{
	/* If there is no persistence, then there is no contention for distributed locks
	   and we can just return immediately. */
	if (!object_.get_persistence_enabled())
		return;


#ifdef P4P_CLUSTER
	std::string lockfile = object_.get_file().string() + ".lock";

	/* open the file */
	fd_ = open(lockfile.c_str(), get_open_flags(), 0600);
	if (fd_ < 0)
		throw bfs::filesystem_error("open failed", lockfile, bs::error_code(errno, boost::system::posix_category));

	/* acquire the lock */
	struct flock lock;
	memset(&lock, 0, sizeof(lock));
	lock.l_type = get_lock_type();
	lock.l_whence = SEEK_SET;
	if (fcntl(fd_, F_SETLKW, &lock) < 0)
		throw bfs::filesystem_error("lock failed", lockfile, bs::error_code(errno, boost::system::posix_category));

	/* ensure the local object is up to date */
	try
	{
		UpgradableReadLock local_lock(object_);
		object_.update(*this, local_lock);
	}
	catch (distributed_object_error& e) { /* ignore exceptions */ }
#else
	throw std::runtime_error("Persistence support not enabled");
#endif
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
static int default_read_from_path(uint64_t oid, char *path,
				       struct siocb *iocb)
{
	int flags = get_open_flags(oid, false), fd, ret = SD_RES_SUCCESS;
	ssize_t size;

	fd = open(path, flags);

	if (fd < 0)
		return err_to_sderr(oid, errno);

	size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
	if (size != iocb->length) {
		eprintf("failed to read 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);
	}

	close(fd);

	return ret;
}
Beispiel #7
0
CAMLprim value caml_sqlite3_open(
  value v_mode, value v_mutex, value v_cache, value v_vfs_opt, value v_file)
{
  sqlite3 *db;
  int res;
#ifdef SQLITE_HAS_OPEN_V2
  int flags = get_open_flags(v_mode, v_mutex, v_cache);
  char *vfs;
#endif
  int file_len = caml_string_length(v_file) + 1;
  char *file;

#ifdef SQLITE_HAS_OPEN_V2
  if (v_vfs_opt == Val_None) vfs = NULL;
  else {
    value v_vfs = Field(v_vfs_opt, 0);
    int vfs_len = caml_string_length(v_vfs) + 1;
    vfs = caml_stat_alloc(vfs_len);
    memcpy(vfs, String_val(v_vfs), vfs_len);
  }
#else
  if (Int_val(v_mode) || Int_val(v_mutex) || Int_val(v_cache))
    caml_failwith("SQlite3 version < 3.5 does not support open flags");
  if (v_vfs_opt != Val_None)
    caml_failwith("SQLite3 version < 3.5 does not support VFS modules");
#endif

  file = caml_stat_alloc(file_len);
  memcpy(file, String_val(v_file), file_len);

  caml_enter_blocking_section();
#ifdef SQLITE_HAS_OPEN_V2
    res = sqlite3_open_v2(file, &db, flags, vfs);
    free(vfs);
#else
    res = sqlite3_open(file, &db);
#endif
    free(file);
  caml_leave_blocking_section();

  if (res) {
    const char *msg;
    if (db) {
      msg = sqlite3_errmsg(db);
      sqlite3_close(db);
    }
    else msg = "<unknown_error>";
    raise_sqlite3_Error("error opening database: %s", msg);
  } else if (db == NULL)
    raise_sqlite3_InternalError(
      "open returned neither a database nor an error");
  /* "open" succeded */
  {
    db_wrap *dbw;
    value v_res = caml_alloc_final(2, dbw_finalize_gc, 1, 100);
    Sqlite3_val(v_res) = NULL;
    dbw = caml_stat_alloc(sizeof(db_wrap));
    dbw->db = db;
    dbw->rc = SQLITE_OK;
    dbw->ref_count = 1;
    dbw->user_functions = NULL;
    Sqlite3_val(v_res) = dbw;
    return v_res;
  }
}
Beispiel #8
0
int default_create_and_write(uint64_t oid, const struct siocb *iocb)
{
	char path[PATH_MAX], tmp_path[PATH_MAX];
	int flags = get_open_flags(oid, true, iocb->flags);
	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_file_write(oid, iocb->buf, iocb->length, iocb->offset, true)
	    != SD_RES_SUCCESS) {
		sd_eprintf("turn off journaling");
		uatomic_set_false(&sys->use_journal);
		flags |= O_DSYNC;
		sync();
	}

	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.
			 */
			sd_dprintf("%s exists", tmp_path);
			return SD_RES_SUCCESS;
		}

		sd_eprintf("failed to open %s: %m", 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 < 0) {
			ret = err_to_sderr(oid, errno);
			goto out;
		}
	}

	ret = xpwrite(fd, iocb->buf, len, iocb->offset);
	if (ret != len) {
		sd_eprintf("failed to write object. %m");
		ret = err_to_sderr(oid, errno);
		goto out;
	}

	ret = rename(tmp_path, path);
	if (ret < 0) {
		sd_eprintf("failed to rename %s to %s: %m", tmp_path, path);
		ret = err_to_sderr(oid, errno);
		goto out;
	}
	sd_dprintf("%"PRIx64, oid);
	ret = SD_RES_SUCCESS;
out:
	if (ret != SD_RES_SUCCESS)
		unlink(tmp_path);
	close(fd);
	return ret;
}