Example #1
0
int osd_submit_and_wait(int fd, struct osd_command *command)
{
	int ret;

	ret = osd_submit_command(fd, command);
	if (ret) {
		osd_error("%s: submit failed", __func__);
		return ret;
	}

	ret = osd_wait_this_response(fd, command);
	if (ret) {
		osd_error("%s: wait_response failed", __func__);
		return ret;
	}
	return 0;
}
Example #2
0
/*
 * osd_wait_response, plus verify that the command retrieved was the
 * one we expected, or error.
 */
int osd_wait_this_response(int fd, struct osd_command *command)
{
	int ret;
	struct osd_command *cmp;

	ret = osd_wait_response(fd, &cmp);
	if (ret == 0) {
		if (cmp != command) {
			osd_error("%s: wrong command returned", __func__);
			ret = -EIO;
		}
	}
	return ret;
}
Example #3
0
int db_begin_txn(struct db_context *dbc)
{
    int ret = 0;
    char *err = NULL;

    assert(dbc && dbc->db);

    ret = sqlite3_exec(dbc->db, "BEGIN TRANSACTION;", NULL, NULL, &err);
    if (ret != SQLITE_OK) {
        osd_error("pragma failed: %s", err);
        sqlite3_free(err);
        return OSD_ERROR;
    }

    return OSD_OK;
}
Example #4
0
int db_end_txn(struct db_context *dbc)
{
    int ret = 0;
    char *err = NULL;

    TICK_TRACE(db_end_txn);
    assert(dbc && dbc->db);

    ret = sqlite3_exec(dbc->db, "END TRANSACTION;", NULL, NULL, &err);
    if (ret != SQLITE_OK) {
        osd_error("pragma failed: %s", err);
        return OSD_ERROR;
    }

    TICK_TRACE(db_end_txn);
    return OSD_OK;
}
Example #5
0
/*
 * returns:
 * OSD_ERROR: in case no table is found
 * OSD_OK: when all tables exist
 */
static int db_check_tables(struct db_context *dbc)
{
    int i = 0;
    int ret = 0;
    char SQL[MAXSQLEN];
    char *err = NULL;
    const char *tables[] = {"attr", "obj", "coll"};
    struct array arr = {ARRAY_SIZE(tables), tables};

    sprintf(SQL, "SELECT name FROM sqlite_master WHERE type='table' "
            " ORDER BY name;");
    ret = sqlite3_exec(dbc->db, SQL, check_membership, &arr, &err);
    if (ret != SQLITE_OK) {
        osd_error("%s: query %s failed: %s", __func__, SQL, err);
        sqlite3_free(err);
        return OSD_ERROR;
    }

    return OSD_OK;
}
Example #6
0
int osd_wait_response(int fd, struct osd_command **out_command)
{
	struct sg_io_v4 sg;
	struct osd_command *command;
	int ret;

	ret = read(fd, &sg, sizeof(sg));
	if (ret < 0) {
		osd_error_errno("%s: read", __func__);
		return -errno;
	}
	if (ret != sizeof(sg)) {
		osd_error("%s: short read, %d not %zu", __func__, ret,
		          sizeof(sg));
		return -EPIPE;
	}

	command = (void *)(uintptr_t) sg.usr_ptr;
	if (command->inlen_alloc)
		command->inlen = command->inlen_alloc - sg.din_resid;
	command->status = sg.device_status;
	command->sense_len = sg.response_len;

#ifndef KERNEL_SUPPORTS_BSG_IOVEC
	// copy from buffer to iovecs
	if (command->inlen_alloc && command->iov_inlen > 1) {
		sg_iovec_t *iov = (sg_iovec_t *) command->indata;
		uint8_t *buff = (uint8_t *) (uintptr_t) sg.din_xferp;
		int i;
		for (i=0; i<command->iov_inlen; i++) {
			memcpy(iov[i].iov_base, buff, iov[i].iov_len);
			buff += iov[i].iov_len;
		}
		free((void *) (uintptr_t) sg.din_xferp);
	}
#endif

	*out_command = command;

	return 0;
}
Example #7
0
int db_print_pragma(struct db_context *dbc)
{
    int ret = 0;
    char *err = NULL;
    char SQL[MAXSQLEN];

    assert(dbc && dbc->db);

    sprintf(SQL,
            " PRAGMA synchronous;"
            " PRAGMA auto_vacuum;"
            " PRAGMA auto_vacuum;"
            " PRAGMA temp_store;"
           );
    ret = sqlite3_exec(dbc->db, SQL, callback, NULL, &err);
    if (ret != SQLITE_OK) {
        osd_error("pragma failed: %s", err);
        sqlite3_free(err);
        return OSD_ERROR;
    }

    return OSD_OK;
}
Example #8
0
int db_exec_pragma(struct db_context *dbc)
{
    int ret = 0;
    char *err = NULL;
    char SQL[MAXSQLEN];

    assert(dbc && dbc->db);

    sprintf(SQL,
            "PRAGMA synchronous = OFF; " /* sync off */
            "PRAGMA auto_vacuum = 1; "   /* reduce db size on delete */
            "PRAGMA count_changes = 0; " /* ignore count changes */
            "PRAGMA temp_store = 0; "    /* memory as scratchpad */
           );
    ret = sqlite3_exec(dbc->db, SQL, NULL, NULL, &err);
    if (ret != SQLITE_OK) {
        osd_error("pragma failed: %s", err);
        sqlite3_free(err);
        return OSD_ERROR;
    }

    return OSD_OK;
}
Example #9
0
static void init(void)
{
	int ret;
	struct osd_drive_description *drive_list;
	int num_drives;

	printf("Initialization\n");
	ret = osd_get_drive_list(&drive_list, &num_drives);
	if (ret < 0) {
		osd_error_errno("%s: get drive list", __func__);
		exit(1);
	}
	if (num_drives == 0) {
		osd_error("%s: No drives found: %d", __func__, num_drives);
		exit(1);
	}

	printf("Found %d Drives Now open drive #0\n", num_drives);
	fd = open(drive_list[0].chardev, O_RDWR);
	if (fd < 0) {
		osd_error_errno("%s: open %s", __func__, drive_list[0].chardev);
		exit(1);
	}
}
Example #10
0
File: sgio.c Project: snsl/osc-osd
static int bidi_test(int fd, uint64_t pid, uint64_t oid)
{
	int ret;
	struct osd_command command;
	struct attribute_list *attr, attr_proto = {
	    .page = 0x1,
	    .number = 0x82,  /* logical length (not used capacity) */
	    .len = sizeof(uint64_t),
	};

	osd_info(__func__);
	ret = osd_command_set_get_attributes(&command, pid, oid);
	if (ret) {
		osd_error_xerrno(ret, "%s: get_attributes failed", __func__);
		printf("\n");
		return 1;
	}
	ret = osd_command_attr_build(&command, &attr_proto, 1);
	if (ret) {
		osd_error_xerrno(ret, "%s: attr_build failed", __func__);
		printf("\n");
		return 1;
	}
	memset(command.indata, 0xaa, command.inlen_alloc);
	ret = osd_submit_and_wait(fd, &command);
	if (ret) {
		osd_error_xerrno(ret, "%s: submit failed", __func__);
		printf("\n");
		return 1;
	}
	printf("%s: status %u sense len %u inlen %zu\n", __func__,
	       command.status, command.sense_len, command.inlen);

	/* verify retrieved list */
	osd_hexdump(command.indata, command.inlen_alloc);
	ret = osd_command_attr_resolve(&command);
	if (ret) {
		osd_error("%s: attr_resolve failed", __func__);
		printf("\n");
		exit(1);
	}
	attr = command.attr;

	if (attr->outlen != attr->len) {
		osd_error("%s: short attr outlen %d", __func__,
		          attr->outlen);
		exit(1);
	}

	printf("%s: logical length 0x%016llx\n\n", __func__,
	       llu(get_ntohll(attr->val)));

	osd_command_attr_free(&command);
	return 0;
}

static void iovec_write_test(int fd, uint64_t pid, uint64_t oid)
{
	struct osd_command command;
	const char buf1[] = "If iovec_write_test works,";
	const char buf2[] = " you will see this sentence.";
	char bufout[200];
	struct bsg_iovec vec[2];
	size_t tot_len;
	int ret;

	osd_info(__func__);
	vec[0].iov_base = (iov_base_t)(uintptr_t) buf1;
	vec[0].iov_len = sizeof(buf1)-1;
	vec[1].iov_base = (iov_base_t)(uintptr_t) buf2;
	vec[1].iov_len = sizeof(buf2);
	tot_len = sizeof(buf1)-1 + sizeof(buf2);
	memset(&command, 0, sizeof(command));
	osd_command_set_write(&command, pid, oid, tot_len, 0);
	command.cdb_len = OSD_CDB_SIZE;
	command.outlen = tot_len;
	command.outdata = vec;
	command.iov_outlen = 2;

	ret = osd_submit_and_wait(fd, &command);
	if (ret) {
		osd_error("%s: submit_and_wait failed", __func__);
		return;
	}
	printf("%s: seemed to work\n", __func__);

	/* read it back, non-iov */
	memset(&command, 0, sizeof(command));
	memset(bufout, 0, sizeof(bufout));
	osd_command_set_read(&command, pid, oid, sizeof(bufout), 0);
	command.cdb_len = OSD_CDB_SIZE;
	command.inlen_alloc = sizeof(bufout);
	command.indata = bufout;

	ret = osd_submit_and_wait(fd, &command);
	if (ret)
		osd_error("%s: submit_and_wait failed", __func__);
	printf("%s: read some bytes (%zu): %s\n\n", __func__,
	       command.inlen, bufout);
}

static void iovec_read_test(int fd, uint64_t pid, uint64_t oid)
{
	struct osd_command command;
	const char bufout[] = "A big line of data for iovec_read_test to get.";
	char buf1[21];
	char buf2[100];
	struct bsg_iovec vec[2];
	size_t tot_len;
	int ret;

	/* write it, non-iov */
	osd_info(__func__);
	memset(&command, 0, sizeof(command));
	osd_command_set_write(&command, pid, oid, sizeof(bufout), 0);
	command.cdb_len = OSD_CDB_SIZE;
	command.outlen = sizeof(bufout);
	command.outdata = bufout;
	ret = osd_submit_and_wait(fd, &command);
	if (ret) {
		osd_error("%s: submit_and_wait failed", __func__);
		return;
	}

	memset(buf1, 0, sizeof(buf1));
	memset(buf2, 0, sizeof(buf2));
	vec[0].iov_base = (iov_base_t)(uintptr_t) buf1;
	vec[0].iov_len = sizeof(buf1)-1;
	vec[1].iov_base = (iov_base_t)(uintptr_t) buf2;
	vec[1].iov_len = sizeof(buf2);
	tot_len = sizeof(buf1)-1 + sizeof(buf2);
	memset(&command, 0, sizeof(command));
	osd_command_set_read(&command, pid, oid, tot_len, 0);
	command.cdb_len = OSD_CDB_SIZE;
	command.inlen_alloc = tot_len;
	command.indata = vec;
	command.iov_inlen = 2;

	ret = osd_submit_and_wait(fd, &command);
	if (ret) {
		osd_error("%s: submit_and_wait failed", __func__);
		return;
	}

	buf1[sizeof(buf1)-1] = '\0';  /* terminate partial string */
	printf("%s: read some bytes (%zu): %s + %s\n\n", __func__,
	       command.inlen, buf1, buf2);
}

static void attr_test(int fd, uint64_t pid, uint64_t oid)
{
	int i, ret;
	uint64_t len;
	uint8_t *ts;  /* odd 6-byte timestamp */
	const uint8_t data[] = "Some data.";
	/* const char attr_data[] = "An attribute.\n"; */
	struct osd_command command;

	struct attribute_list *attr, attr_proto[] = {
		{
			.type = ATTR_GET,
			.page = 0x1,  /* user info page */
			.number = 0x82,  /* logical length */
			.len = sizeof(uint64_t),
		},
		{
			.type = ATTR_GET,
Example #11
0
/*
 *  <0: error
 * ==0: success
 * ==1: new db opened, caller must initialize tables
 */
int osd_db_open(const char *path, struct osd_device *osd)
{
    int ret;
    struct stat sb;
    char SQL[MAXSQLEN];
    char *err = NULL;
    int is_new_db = 0;

    ret = stat(path, &sb);
    if (ret == 0) {
        if (!S_ISREG(sb.st_mode)) {
            osd_error("%s: path %s not a regular file %d",
                      __func__, path, sb.st_mode);
            ret = 1;
            goto out;
        }
    } else {
        if (errno != ENOENT) {
            osd_error("%s: stat path %s", __func__, path);
            goto out;
        }

        /* sqlite3 will create it for us */
        is_new_db = 1;
    }

    osd->handle->dbc = Calloc(1, sizeof(*osd->handle->dbc));
    if (!osd->handle->dbc) {
        ret = -ENOMEM;
        goto out;
    }

    ret = sqlite3_open(path, &(osd->handle->dbc->db));
    if (ret != SQLITE_OK) {
        osd_error("%s: open db %s", __func__, path);
        ret = OSD_ERROR;
        goto out_free_dbc;
    }

    if (is_new_db) {
        /* build tables from schema file */
        ret = sqlite3_exec(osd->handle->dbc->db, osd_schema, NULL, NULL, &err);
        if (ret != SQLITE_OK) {
            sqlite3_free(err);
            ret = OSD_ERROR;
            goto out_close_db;
        }
    } else {
        /* existing db, check for tables */
        ret = db_check_tables(osd->handle->dbc);
        if (ret != OSD_OK)
            goto out_close_db;
    }

    /* initialize dbc fields */
    ret = db_initialize(osd->handle->dbc);
    if (ret != OSD_OK) {
        ret = OSD_ERROR;
        goto out_close_db;
    }

    if (is_new_db)
        ret = 1;
    goto out;

out_close_db:
    sqlite3_close(osd->handle->dbc->db);
out_free_dbc:
    free(osd->handle->dbc);
    osd->handle->dbc = NULL;
out:
    return ret;
}
Example #12
0
int osd_submit_command(int fd, struct osd_command *command)
{
	int ret;
	struct sg_io_v4 sg;

	memset(&sg, 0, sizeof(sg));
	sg.guard = 'Q';
	sg.request_len = command->cdb_len;
	sg.request = (uint64_t) (uintptr_t) command->cdb;
	sg.max_response_len = sizeof(command->sense);
	sg.response = (uint64_t) (uintptr_t) command->sense;

	if (command->outlen) {
#ifdef KERNEL_SUPPORTS_BSG_IOVEC
		sg.dout_xfer_len = command->outlen;
		sg.dout_xferp = (uint64_t) (uintptr_t) command->outdata;
		sg.dout_iovec_count = command->iov_outlen;
#else
		// The kernel doesn't support BSG iovecs mainly because
		// of a problem going from 32-bit user iovecs to a 64-bit kernel
		// So, just copy the iovecs into a new buffer and use that
		sg_iovec_t *iov = (sg_iovec_t *)(uintptr_t)command->outdata;
		if (command->iov_outlen == 0) {
			sg.dout_xfer_len = command->outlen;
			sg.dout_xferp = (uint64_t) (uintptr_t) command->outdata;
		} else if (command->iov_outlen == 1) {
			sg.dout_xfer_len = iov->iov_len;
			sg.dout_xferp = (uint64_t) (uintptr_t) iov->iov_base;
		} else {
			int i;
			uint8_t *buff = Malloc(command->outlen);
			sg.dout_xferp = (uint64_t) (uintptr_t) buff;
			for (i=0; i<command->iov_outlen; i++) {
				memcpy(buff, iov[i].iov_base, iov[i].iov_len);
				buff += iov[i].iov_len;
			}
			sg.dout_xfer_len = command->outlen;
		}
		sg.dout_iovec_count = 0;
#endif
	}
	if (command->inlen_alloc) {
#ifdef KERNEL_SUPPORTS_BSG_IOVEC
		sg.din_xfer_len = command->inlen_alloc;
		sg.din_xferp = (uint64_t) (uintptr_t) command->indata;
		sg.din_iovec_count = command->iov_inlen;
#else
		if (command->iov_inlen == 0) {
			sg.din_xfer_len = command->inlen_alloc;
			sg.din_xferp = (uint64_t) (uintptr_t) command->indata;
			sg.din_iovec_count = command->iov_inlen;
		} else if (command->iov_inlen == 1) {
			sg_iovec_t *iov = (sg_iovec_t *)command->indata;
			sg.din_xfer_len = iov->iov_len;
			sg.din_xferp = (uint64_t) (uintptr_t) iov->iov_base;
		} else {
			sg.din_xfer_len = command->inlen_alloc;
			sg.din_xferp = (uint64_t) (uintptr_t) (uint8_t*) Malloc(command->inlen_alloc);
		}
		sg.din_iovec_count = 0;
#endif
	}

	/*
	 * Allow 30 sec for entire command.  Some can be
	 * slow, especially with debugging messages on.
	 */
	sg.timeout = 30000;
	sg.usr_ptr = (uint64_t) (uintptr_t) command;
	ret = write(fd, &sg, sizeof(sg));
#ifndef KERNEL_SUPPORTS_BSG_IOVEC
	if (command->outlen && command->iov_outlen > 1) {
		free((void *) (uintptr_t) sg.dout_xferp);
	}
#endif
	if (ret < 0) {
		osd_error_errno("%s: write", __func__);
		return -errno;
	}
	if (ret != sizeof(sg)) {
		osd_error("%s: short write, %d not %zu", __func__, ret,
			  sizeof(sg));
		return -EIO;
	}
	return 0;
}