From 6235eac00c79d771f73ff808c6cf0cdc967eed9b Mon Sep 17 00:00:00 2001 From: cengizk Date: Fri, 20 Jun 2014 09:42:51 -0400 Subject: [PATCH] Changes done within pvfs_on_osd repository --- Makedefs | 4 +- osd-initiator/drivelist.c | 7 +- osd-initiator/python/pvfs-init.py | 11 +- osd-target/db.c | 6 +- osd-target/tests/command.c | 1526 ++++++++++++++++++++++++++++- osd-target/tests/command.h | 203 +++- osd-target/tests/db-test.c | 4 +- osd-util/initiator | 54 +- osd-util/perf.py | 32 +- up | 6 +- 10 files changed, 1777 insertions(+), 76 deletions(-) mode change 120000 => 100644 osd-target/tests/command.c mode change 120000 => 100644 osd-target/tests/command.h diff --git a/Makedefs b/Makedefs index f9ef3aa..6aeaa21 100644 --- a/Makedefs +++ b/Makedefs @@ -3,8 +3,8 @@ # debugging and optimization for everything. # # OPT := -g -OPT := -O3 -DNDEBUG -# OPT := -O3 +# OPT := -O3 -DNDEBUG +OPT := -O3 # Backend configuration flags # PANASAS_OSD=1 diff --git a/osd-initiator/drivelist.c b/osd-initiator/drivelist.c index 8a15a69..f9865a3 100644 --- a/osd-initiator/drivelist.c +++ b/osd-initiator/drivelist.c @@ -158,7 +158,11 @@ int osd_get_drive_list(struct osd_drive_description **drives, int *num_drives) char *string[200]; char *line; FILE *file; - file = fopen("/usr/src/fs.conf", "r"); + char conf_path[200] = {'\0'}; + char *home_path = getenv("HOME"); + strcat(conf_path, home_path); + strcat(conf_path, "/pvfs_on_osd/fs.conf"); + file = fopen(conf_path, "r"); line = (char *) malloc(120); while(condition != EOF) @@ -170,7 +174,6 @@ int osd_get_drive_list(struct osd_drive_description **drives, int *num_drives) strcpy(string[i], line); if(!strncmp(string[i], "osd://", 5)) { - for(j = 0; j < count; j++) { if(!strcmp(&(line[6]), ret[j].targetname)) ret[j].hostname = strdup(string[i-1]); diff --git a/osd-initiator/python/pvfs-init.py b/osd-initiator/python/pvfs-init.py index 88d47aa..de8cc1a 100755 --- a/osd-initiator/python/pvfs-init.py +++ b/osd-initiator/python/pvfs-init.py @@ -135,19 +135,18 @@ run(OSDCommand().set_format_osd(1<<30)) # allocate and free so many that it would wrap. run(OSDCommand().set_create_partition(PVFS_OSD_DATA_PID)) if osddirtype == "pvfs": - cid = COLLECTION_OID_LB - run(OSDCommand().set_create_collection(PVFS_OSD_DATA_PID, cid)) + run(OSDCommand().set_create_collection(PVFS_OSD_DATA_PID, COLLECTION_OID_LB)) run(OSDCommand().set_create_partition(PVFS_OSD_META_PID)) if metalb != root_handle: run(OSDCommand().set_create(PVFS_OSD_META_PID, metalb)) # create root handle, the top level directory if root_handle: - if coll_object == "yes": - command = OSDCommand().set_create_collection(PVFS_OSD_META_PID, root_handle) + #if coll_object == "yes": + #command = OSDCommand().set_create_collection(PVFS_OSD_META_PID, root_handle) - else: - command = OSDCommand().set_create(PVFS_OSD_META_PID, root_handle) + #else: + command = OSDCommand().set_create(PVFS_OSD_META_PID, root_handle) command.attr_build([ \ OSDAttr(ATTR_SET, ANY_PG + PVFS_USEROBJECT_ATTR_PG, 0, 0), \ OSDAttr(ATTR_SET, ANY_PG + PVFS_USEROBJECT_ATTR_PG, 1, 0), \ diff --git a/osd-target/db.c b/osd-target/db.c index 21ace0e..bfa6680 100644 --- a/osd-target/db.c +++ b/osd-target/db.c @@ -218,9 +218,9 @@ int db_finalize(struct db_context *dbc) return OSD_ERROR; } -static const char db_delete_sql[] = "DELETE * FROM obj;\n" - "DELETE * FROM attr;\n" - "DELETE * FROM coll;\n"; +static const char db_delete_sql[] = "DELETE FROM obj;\n" + "DELETE FROM attr;\n" + "DELETE FROM coll;\n"; int db_delete_data(struct db_context *dbc) { char *err = NULL; diff --git a/osd-target/tests/command.c b/osd-target/tests/command.c deleted file mode 120000 index 0420fb1..0000000 --- a/osd-target/tests/command.c +++ /dev/null @@ -1 +0,0 @@ -../../osd-initiator/command.c \ No newline at end of file diff --git a/osd-target/tests/command.c b/osd-target/tests/command.c new file mode 100644 index 0000000..7df84fb --- /dev/null +++ b/osd-target/tests/command.c @@ -0,0 +1,1525 @@ +/* + * Commands and attributes. + * + * Copyright (C) 2007 OSD Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#ifndef __APPLE__ +#include +#include /* sg_iovec */ +#define bsg_iovec sg_iovec +typedef void* iov_base_t; +#else +typedef uint64_t iov_base_t; +#endif + +/* turn this on automatically with configure some day */ +#if 0 +#include +#else +#define VALGRIND_MAKE_MEM_DEFINED(p, len) +#endif + +#include "osd-util/osd-util.h" +#include "command.h" + + + +static void varlen_cdb_init(struct osd_command *command, uint16_t action) +{ + memset(command, 0, sizeof(*command)); + command->cdb_len = OSD_CDB_SIZE; + command->cdb[0] = VARLEN_CDB; + /* we do not support ACA or LINK in control byte cdb[1], leave as 0 */ + command->cdb[7] = OSD_CDB_SIZE - 8; + command->cdb[8] = (action & 0xff00U) >> 8; + command->cdb[9] = (action & 0x00ffU); + /* default data distribution type is contiguous (0) */ + command->cdb[11] = 3 << 4; /* default to list, but empty list lens */ + /* Update timestamps based on action 5.2.8 */ + command->cdb[12] = 0x7f; /* timestamps not updated */ +} + +/* + * Non-varlen commands. + */ +int osd_command_set_test_unit_ready(struct osd_command *command) +{ + memset(command, 0, sizeof(*command)); + command->cdb_len = 6; + return 0; +} + +#ifndef __APPLE__ +int osd_command_set_inquiry(struct osd_command *command, uint8_t page_code, + uint8_t outlen) +{ + memset(command, 0, sizeof(*command)); + command->cdb_len = 6; + command->cdb[0] = INQUIRY; + command->cdb[4] = outlen; + if (page_code) { + command->cdb[1] = 1; + command->cdb[2] = page_code; + } + return 0; +} +#endif + +/* + * These functions take a cdb of the appropriate size (200 bytes), + * and the arguments needed for the particular command. They marshall + * the arguments but do not submit the command. + */ +int osd_command_set_append(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len) +{ + varlen_cdb_init(command, OSD_APPEND); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + return 0; +} + +int osd_command_set_clear(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset) +{ + varlen_cdb_init(command, OSD_CLEAR); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + return 0; +} + +int osd_command_set_create(struct osd_command *command, uint64_t pid, + uint64_t requested_oid, uint16_t num_user_objects) +{ + varlen_cdb_init(command, OSD_CREATE); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], requested_oid); + set_htons(&command->cdb[32], num_user_objects); + return 0; +} + + +int osd_command_set_create_and_write(struct osd_command *command, uint64_t pid, + uint64_t requested_oid, uint64_t len, + uint64_t offset) +{ + varlen_cdb_init(command, OSD_CREATE_AND_WRITE); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], requested_oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + return 0; +} + + +int osd_command_set_create_collection(struct osd_command *command, + uint64_t pid, uint64_t requested_cid) +{ + varlen_cdb_init(command, OSD_CREATE_COLLECTION); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], requested_cid); + return 0; +} + +int osd_command_set_create_partition(struct osd_command *command, + uint64_t requested_pid) +{ + varlen_cdb_init(command, OSD_CREATE_PARTITION); + set_htonll(&command->cdb[16], requested_pid); + return 0; +} + + +int osd_command_set_create_user_tracking_collection(struct osd_command *command, + uint64_t pid, + uint64_t requested_cid, + uint64_t source_cid) +{ + varlen_cdb_init(command, OSD_CREATE_USER_TRACKING_COLLECTION); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], requested_cid); + set_htonll(&command->cdb[40], source_cid); + return 0; +} + + +int osd_command_set_flush(struct osd_command *command, uint64_t pid, uint64_t len, + uint64_t offset, uint64_t oid, int flush_scope) +{ + varlen_cdb_init(command, OSD_FLUSH); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + command->cdb[10] = (command->cdb[10] & ~0x3) | flush_scope; + return 0; +} + + +int osd_command_set_flush_collection(struct osd_command *command, uint64_t pid, + uint64_t cid, int flush_scope) +{ + varlen_cdb_init(command, OSD_FLUSH_COLLECTION); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], cid); + command->cdb[10] = (command->cdb[10] & ~0x3) | flush_scope; + return 0; +} + + +int osd_command_set_flush_osd(struct osd_command *command, int flush_scope) +{ + varlen_cdb_init(command, OSD_FLUSH_OSD); + command->cdb[10] = (command->cdb[10] & ~0x3) | flush_scope; + return 0; +} + + +int osd_command_set_flush_partition(struct osd_command *command, uint64_t pid, + int flush_scope) +{ + varlen_cdb_init(command, OSD_FLUSH_PARTITION); + set_htonll(&command->cdb[16], pid); + command->cdb[10] = (command->cdb[10] & ~0x3) | flush_scope; + return 0; +} + +/* + * Destroy the db and start over again. + */ +int osd_command_set_format_osd(struct osd_command *command, uint64_t capacity) +{ + varlen_cdb_init(command, OSD_FORMAT_OSD); + set_htonll(&command->cdb[32], capacity); + return 0; +} + + +int osd_command_set_get_attributes(struct osd_command *command, uint64_t pid, + uint64_t oid) +{ + varlen_cdb_init(command, OSD_GET_ATTRIBUTES); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + return 0; +} + +int osd_command_set_get_member_attributes(struct osd_command *command, + uint64_t pid, uint64_t cid, uint64_t min_oid, uint64_t max_oid) +{ + varlen_cdb_init(command, OSD_GET_MEMBER_ATTRIBUTES); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], cid); + set_htonll(&command->cdb[32], min_oid); + set_htonll(&command->cdb[40], max_oid); + return 0; +} + + +int osd_command_set_list(struct osd_command *command, uint64_t pid, + uint32_t list_id, uint64_t alloc_len, + uint64_t initial_oid, int list_attr) +{ + varlen_cdb_init(command, OSD_LIST); + if (list_attr) + command->cdb[11] |= 0x40; + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[32], alloc_len); + set_htonll(&command->cdb[40], initial_oid); + set_htonl(&command->cdb[48], list_id); + return 0; +} + +int osd_command_set_list_collection(struct osd_command *command, uint64_t pid, + uint64_t cid, uint32_t list_id, + uint64_t alloc_len, uint64_t initial_oid, + int list_attr) +{ + varlen_cdb_init(command, OSD_LIST_COLLECTION); + if (list_attr) + command->cdb[11] |= 0x40; + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], cid); + set_htonll(&command->cdb[32], alloc_len); + set_htonll(&command->cdb[40], initial_oid); + set_htonl(&command->cdb[48], list_id); + return 0; +} + +int osd_command_set_perform_scsi_command( + struct osd_command *command __attribute__((unused))) +{ + osd_error("%s: unimplemented", __func__); + return 1; +} + +int osd_command_set_perform_task_mgmt_func( + struct osd_command *command __attribute__((unused))) +{ + osd_error("%s: unimplemented", __func__); + return 1; +} + +int osd_command_set_punch(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset) +{ + varlen_cdb_init(command, OSD_PUNCH); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + return 0; +} + +int osd_command_set_query(struct osd_command *command, uint64_t pid, + uint64_t cid, uint32_t cont_len, uint64_t alloc_len, + uint64_t matches_cid) +{ + varlen_cdb_init(command, OSD_QUERY); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], cid); + set_htonll(&command->cdb[32], alloc_len); + set_htonll(&command->cdb[40], matches_cid); + set_htonl(&command->cdb[48], cont_len); + return 0; +} + +int osd_command_set_read(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset) +{ + varlen_cdb_init(command, OSD_READ); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + return 0; +} + +int osd_command_set_read_map(struct osd_command*command, uint64_t pid, uint64_t oid, + uint64_t alloc_len, uint64_t offset, uint8_t map_type) +{ + varlen_cdb_init(command, OSD_READ_MAP); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], alloc_len); + set_htonll(&command->cdb[40], offset); + set_htons(&command->cdb[48], map_type); + return 0; +} + + +int osd_command_set_remove(struct osd_command *command, uint64_t pid, + uint64_t oid) +{ + varlen_cdb_init(command, OSD_REMOVE); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + return 0; +} + + +int osd_command_set_remove_collection(struct osd_command *command, + uint64_t pid, uint64_t cid, int force) +{ + varlen_cdb_init(command, OSD_REMOVE_COLLECTION); + if (force) + command->cdb[11] |= 1; + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], cid); + return 0; +} + + +int osd_command_set_remove_member_objects(struct osd_command *command, + uint64_t pid, uint64_t cid) +{ + varlen_cdb_init(command, OSD_REMOVE_MEMBER_OBJECTS); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], cid); + return 0; +} + + +int osd_command_set_remove_partition(struct osd_command *command, uint64_t pid) +{ + varlen_cdb_init(command, OSD_REMOVE_PARTITION); + set_htonll(&command->cdb[16], pid); + return 0; +} + + +int osd_command_set_set_attributes(struct osd_command *command, uint64_t pid, + uint64_t oid) +{ + varlen_cdb_init(command, OSD_SET_ATTRIBUTES); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + return 0; +} + + +int osd_command_set_set_key(struct osd_command *command, int key_to_set, + uint64_t pid, uint64_t key, const uint8_t seed[20]) +{ + varlen_cdb_init(command, OSD_SET_KEY); + command->cdb[11] = (command->cdb[11] & ~0x3) | key_to_set; + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], key); + memcpy(&command->cdb[32], seed, 20); + return 0; +} + + +int osd_command_set_set_master_key(struct osd_command *command, int dh_step, + uint64_t key, uint32_t param_len, + uint32_t alloc_len) +{ + varlen_cdb_init(command, OSD_SET_KEY); + command->cdb[11] = (command->cdb[11] & ~0x3) | dh_step; + set_htonll(&command->cdb[24], key); + set_htonl(&command->cdb[32], param_len); + set_htonl(&command->cdb[36], alloc_len); + return 0; +} + + +int osd_command_set_set_member_attributes(struct osd_command *command, + uint64_t pid, uint64_t cid) +{ + varlen_cdb_init(command, OSD_SET_MEMBER_ATTRIBUTES); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], cid); + return 0; +} + + +int osd_command_set_write(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset) +{ + varlen_cdb_init(command, OSD_WRITE); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + return 0; +} + +int osd_command_set_cas(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset) +{ + varlen_cdb_init(command, OSD_CAS); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + return 0; +} + +int osd_command_set_fa(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset) +{ + varlen_cdb_init(command, OSD_FA); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + set_htonll(&command->cdb[32], len); + set_htonll(&command->cdb[40], offset); + return 0; +} + +int osd_command_set_gen_cas(struct osd_command *command, uint64_t pid, + uint64_t oid) +{ + varlen_cdb_init(command, OSD_GEN_CAS); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + return 0; +} + +int osd_command_set_cond_setattr(struct osd_command *command, uint64_t pid, + uint64_t oid) +{ + varlen_cdb_init(command, OSD_COND_SETATTR); + set_htonll(&command->cdb[16], pid); + set_htonll(&command->cdb[24], oid); + return 0; +} + +void osd_command_set_ddt(struct osd_command *command, uint8_t ddt_type) +{ + /* + * Using last 2 bits of option byte, just like flush_scope, see 5.2.5 + */ + command->cdb[10] = (command->cdb[10] & ~0x3) | ddt_type; +} + + +uint8_t osd_command_get_ddt(struct osd_command *command) +{ + return command->cdb[10] & 0x3; +} + +/* + * Header for internal use across attr_build to attr_resolve. Keeps + * the original iov structures. + */ +struct attr_malloc_header { + const void *orig_outdata; + size_t orig_outlen; + int orig_iov_outlen; + void *orig_indata; + size_t orig_inlen_alloc; + int orig_iov_inlen; + uint8_t *retrieved_buf; + uint64_t start_retrieved; + /* for convenience of resolve, points into the big buffer */ + struct attribute_get_multi_results *mr; +}; + +/* + * After setting the command (i.e. building the CDB), and connecting + * the indata and outdata, this function tacks on a list of attributes. + * To do this it will possibly create a new buffer for output data + * containing the request, and it will possibly create a new buffer for + * input data with the GET responses. And it will build an iovec to + * hold the command data as well as the attribute data. + * + * After the command completes, call the resolve function to fill in + * the results and free the temp buffers. + */ + +int osd_command_attr_build(struct osd_command *command, + const struct attribute_list *attr, int numattr) +{ + return osd_command_multi_attr_build(command, attr, numattr, 1); +} + +int osd_command_multi_attr_build(struct osd_command *command, + const struct attribute_list *attr, int numattr, int numobj) +{ + int use_getpage, use_set_one_attr = 0; + int numget, numgetpage, numgetmulti, numset, numresult; + uint32_t getsize, getpagesize, getmultisize, setsize, resultsize; + uint32_t getmulti_num_objects = 1; + struct attr_malloc_header *header; + uint8_t *p, *extra_out_buf, *extra_in_buf; + struct bsg_iovec *iov; + + int i, j; + int neediov; + int setattr_index; + uint64_t extra_out, extra_in; + uint32_t header_space, attr_space, iov_space, getmulti_result_space; + + /* + * These are values, in units of bytes (not offsets), in the + * out data. + */ + uint64_t end_outdata; + uint64_t size_pad_outdata; + uint64_t start_getlist; + uint64_t size_getlist; + uint64_t size_pad_setlist; + uint64_t start_setlist; + uint64_t size_setlist; + + /* + * Ditto, in data. + */ + uint64_t end_indata; + uint64_t size_pad_indata; + uint64_t start_retrieved; + uint64_t size_retrieved; + + /* + * These are used so that we know the setlist and retrieved + * areas start on 8-byte boundaries. Since padding after + * outdata or indata can be arbitrary, alloc a bit extra to + * keep the pointers nice. + */ + uint64_t size_pad_outdata_alloc; + uint64_t size_pad_indata_alloc; + uint64_t extra_out_alloc, extra_in_alloc; + + if (numattr == 0) + return 0; + + /* + * Figure out what operations to do. That will lead to constraints + * on the choice of getpage/setone versus getlist/setlist format. + */ + numget = numgetpage = numgetmulti = numset = numresult = 0; + getsize = getpagesize = getmultisize = setsize = resultsize = 0; + setattr_index = -1; + for (i=0; i 1) { + osd_error("%s: only one ATTR_GET_PAGE at a time", + __func__); + return -EINVAL; + } + if (numget) { + osd_error("%s: no ATTR_GET allowed with ATTR_GET_PAGE", + __func__); + return -EINVAL; + } + if (numgetmulti) { + osd_error( + "%s: no ATTR_GETMULTI allowed with ATTR_GET_PAGE", + __func__); + return -EINVAL; + } + if (numset > 1) { + osd_error("%s: ATTR_GET_PAGE limits ATTR_SET to one", + __func__); + return -EINVAL; + } + if (numresult) { + /* Only CAS uses ATTR_RESULT, which needs list fmt */ + osd_error("%s: ATTR_RESULT not allowed with " + "ATTR_GET_PAGE", __func__); + return -EINVAL; + } + use_getpage = 1; + + }else { + if (numgetmulti) { + uint16_t action = (command->cdb[8] << 8) + | command->cdb[9]; + if (numget) { + osd_error( + "%s: no ATTR_GET allowed with ATTR_GET_MULTI", + __func__); + return -EINVAL; + } + if (action != OSD_CREATE && action != OSD_GET_MEMBER_ATTRIBUTES) { + osd_error( + "%s: ATTR_GET_MULTI must only be used with CREATE or GET_MEMBER_ATTRIBUTES", + __func__); + return -EINVAL; + } + getmulti_num_objects = numobj; + } + use_getpage = 0; + if (numget == 0 && numgetmulti == 0 && numset == 1) { + /* + * For a single set and service action != + * OSD_SET_MEMBER_ATTRIBUTES *, prefer simpler page + * format, * except if page-to-set is zero, which is + * a noop in * this format. + */ + uint8_t *cdb = command->cdb; + uint16_t action = ((cdb[8] << 8) | cdb[9]); + if (attr[setattr_index].page != 0 && + (action != OSD_SET_MEMBER_ATTRIBUTES)) { + use_getpage = 1; + } + } + if (attr[0].len <= 18 && numset == 1 && numattr == 1) + use_set_one_attr = 1; + } + + /* + * Outdata: + * padding between real outdata and setlist + * setlist (including values) + * padding between setlist and getlist + * getlist + */ + end_outdata = command->outlen; + + size_pad_outdata = 0; + size_pad_outdata_alloc = 0; /* so setlist starts on 8-byte boundary */ + start_setlist = 0; + size_setlist = 0; + if (numset) { + start_setlist = next_offset(end_outdata); + size_pad_outdata = start_setlist - end_outdata; + size_pad_outdata_alloc = roundup8(size_pad_outdata); + if (use_getpage) + /* no list format around the single value */ + size_setlist = attr[setattr_index].len; + else + /* add list header; setsize already rounded */ + size_setlist = 8 + setsize; + } + + size_pad_setlist = 0; + start_getlist = 0; + size_getlist = 0; + if (numget || numgetmulti) { + uint64_t prev = start_setlist + size_setlist; + if (prev == 0) + prev = end_outdata; + start_getlist = next_offset(prev); + size_pad_setlist = start_getlist - prev; + if (size_setlist == 0) + size_pad_outdata_alloc = roundup8(size_pad_setlist); + size_getlist = 8 + 8 * getmulti_num_objects * (numget + numgetmulti); + } + + extra_out = size_pad_outdata + size_setlist + + size_pad_setlist + size_getlist; + extra_out_alloc = size_pad_outdata_alloc + size_setlist + + size_pad_setlist + size_getlist; + + /* + * Indata: + * padding between real indata and retrieved results area + * retrieved results area + */ + end_indata = command->inlen_alloc; + start_retrieved = 0; + size_pad_indata = 0; + size_pad_indata_alloc = 0; + size_retrieved = 0; + if (numget || numgetpage || numgetmulti || numresult) { + start_retrieved = next_offset(end_indata); + size_pad_indata = start_retrieved - end_indata; + size_pad_indata_alloc = roundup8(size_pad_indata); + if (numget) + size_retrieved = 8 + getsize; /* already rounded */ + if (numgetpage) + size_retrieved = getpagesize; /* no rounding */ + if (numgetmulti) + size_retrieved = 8 + (getmultisize + 16) * + getmulti_num_objects; + if (numresult) { + if (!size_retrieved) + size_retrieved += 8; + size_retrieved += resultsize; + } + } + + extra_in = size_pad_indata + size_retrieved; + extra_in_alloc = size_pad_indata_alloc + size_retrieved; + + /* + * Each ATTR_GET_MULTI will return an array of values, one for + * each object. Allocate space for that now, for use by + * attr_resolve(); + */ + getmulti_result_space = 0; + if (numgetmulti) { + struct attribute_get_multi_results *mr; + int one_space = sizeof(*mr) + + getmulti_num_objects + * (sizeof(*mr->oid) + sizeof(*mr->val) + + sizeof(*mr->outlen)); + getmulti_result_space = roundup8(numgetmulti * one_space); + } + + /* + * If we are building out or indata items, and user already + * had some data there, build replacement iovecs to hold the + * new list. + */ + neediov = 0; + if (extra_out && command->outdata) { + if (command->iov_outlen == 0) + neediov += 2; + else + neediov += command->iov_outlen + 1; + } + if (extra_in && command->indata) { + if (command->iov_inlen == 0) + neediov += 2; + else + neediov += command->iov_inlen + 1; + } + + /* + * Allocate space for the following things, in order: + * header struct of original iov/data, etc. + * attr array + * get_multi results + * out iovec + * in iovec + * outgoing getlist area + * outgoing setlist area + * incoming retrieved area + */ + header_space = roundup8(sizeof(*header)); + attr_space = roundup8(numattr * sizeof(*attr)); + iov_space = roundup8(neediov * sizeof(*iov)); + p = Malloc(header_space + + attr_space + + getmulti_result_space + + iov_space + + extra_out_alloc + + extra_in_alloc); + if (!p) + return 1; + + /* to free it later */ + command->attr_malloc = p; + + /* header holds original indata, iniovec, etc. */ + header = (void *) p; + p += header_space; + + /* copy user's passed-in attribute structure for use by resolve */ + command->attr = (void *) p; + memcpy(command->attr, attr, numattr * sizeof(*attr)); + command->numattr = numattr; + p += attr_space; + + /* for ATTR_GET_MULTI results */ + header->mr = (void *) p; + p += getmulti_result_space; + + /* space for replacement out and in iovecs */ + iov = (void *) p; + p += iov_space; + + /* extra out; including pad, setlist, pad, getlist */ + extra_out_buf = p; + p += extra_out_alloc; + + /* extra in; including pad, retrieved area */ + extra_in_buf = p; + + /* + * Initialize get multi result space. + */ + if (getmulti_result_space) { + struct attribute_get_multi_results *mr = header->mr; + uint8_t *q = (void *) &mr[numgetmulti]; + for (i=0; iretrieved_buf = extra_in_buf + size_pad_indata_alloc; + header->start_retrieved = start_retrieved; + + /* + * Update the CDB bits. + */ + if (use_set_one_attr) { + /* set one attribute */ + command->cdb[11] = (command->cdb[11] & ~(3 << 4)) | (1 << 4); + set_htonl(&command->cdb[52], attr[0].page); + set_htonl(&command->cdb[56], attr[0].number); + set_htons(&command->cdb[60], attr[0].len); + memcpy(&command->cdb[62], attr[0].val, attr[0].len); + } + + else if (use_getpage) { + /* page format */ + command->cdb[11] = (command->cdb[11] & ~(3 << 4)) | (2 << 4); + for (i=0; icdb[52], attr[i].page); + if (attr[i].type == ATTR_SET) { + set_htonl(&command->cdb[64], attr[i].page); + set_htonl(&command->cdb[68], attr[i].number); + } + } + set_htonl(&command->cdb[56], size_retrieved); + set_htonoffset(&command->cdb[60], start_retrieved); + set_htonl(&command->cdb[72], size_setlist); + set_htonoffset(&command->cdb[76], start_setlist); + } else { + /* list format, cdb[11] is this as default */ + set_htonl(&command->cdb[52], size_getlist); + set_htonoffset(&command->cdb[56], start_getlist); + set_htonl(&command->cdb[60], size_retrieved); + set_htonoffset(&command->cdb[64], start_retrieved); + set_htonl(&command->cdb[68], size_setlist); + set_htonoffset(&command->cdb[72], start_setlist); + set_htonl(&command->cdb[80], numobj); + } + + /* + * Adjust the iovecs. These use the real sizes, not the _alloc + * sizes. + */ + header->orig_outdata = command->outdata; + header->orig_outlen = command->outlen; + header->orig_iov_outlen = command->iov_outlen; + if (extra_out) { + /* ignore the 0..7 extra bytes so that data lands nicely */ + p = extra_out_buf + (extra_out_alloc - extra_out); + if (command->outdata) { + command->outdata = iov; + if (command->iov_outlen == 0) { + iov->iov_base = + (iov_base_t)(uintptr_t) header->orig_outdata; + iov->iov_len = command->outlen; + ++iov; + command->iov_outlen = 2; + } else { + memcpy(iov, header->orig_outdata, + command->iov_outlen * sizeof(*iov)); + iov += command->iov_outlen; + ++command->iov_outlen; + } + iov->iov_base = (iov_base_t) p; + iov->iov_len = extra_out; + ++iov; + } else { + command->outdata = p; + } + command->outlen += extra_out; + } + + header->orig_indata = command->indata; + header->orig_inlen_alloc = command->inlen_alloc; + header->orig_iov_inlen = command->iov_inlen; + if (extra_in) { + p = extra_in_buf + (extra_in_alloc - extra_in); + if (command->indata) { + command->indata = iov; + if (command->iov_inlen == 0) { + iov->iov_base = (iov_base_t) header->orig_indata; + iov->iov_len = command->inlen_alloc; + ++iov; + command->iov_inlen = 2; + } else { + memcpy(iov, header->orig_indata, + command->iov_inlen * sizeof(*iov)); + iov += command->iov_inlen; + ++command->iov_inlen; + } + iov->iov_base = (iov_base_t) p; + iov->iov_len = extra_in; + ++iov; + } else { + command->indata = p; + } + command->inlen_alloc += extra_in; + } + + return 0; +} + +/* + * Must be called once after a command involving attributes. Figures out + * where GET output data landed and sets .val pointers and .outlen + * appropriately. Returns 0 if all okay. + */ +int osd_command_attr_resolve(struct osd_command *command) +{ + struct attr_malloc_header *header = command->attr_malloc; + uint8_t *p; + uint64_t len; + uint32_t list_len; + int numget, numgetmulti, i; + int ret = -EINVAL; + struct attribute_list *attr = command->attr; + int numattr = command->numattr; + + if (command->inlen < header->start_retrieved) + goto unwind; + + p = header->retrieved_buf; + len = command->inlen - header->start_retrieved; + VALGRIND_MAKE_MEM_DEFINED(p, len); + + /* + * If getpage, just copy it in and done. Assumes checking was + * done properly at the start. Also error out the outlens for + * the non-getpage case to come later. + */ + numget = 0; + numgetmulti = 0; + for (i=0; i attr[i].len) + attr[i].outlen = attr[i].len; + attr[i].val = p; + ret = 0; + goto unwind; + } + if (attr[i].type == ATTR_GET) { + attr[i].outlen = 0xffff; + ++numget; + } + if (attr[i].type == ATTR_GET_MULTI) { + attr[i].val = &header->mr[numgetmulti]; + ++numgetmulti; + } + } + + /* + * No ATTR_GET to process, not an error. + */ + if (numget == 0 && numgetmulti == 0) { + ret = 0; + goto unwind; + } + + /* + * Read off the header first. + */ + if (len < 8) + goto unwind; + + if ((p[0] & 0xf) == 0x9) { + if (numgetmulti) { + osd_error("%s: got list type 9, expecting multi", + __func__); + goto unwind; + } + } else if ((p[0] & 0xf) == 0xe) { + if (!numgetmulti) { + osd_error("%s: got list type e, not expecting multi", + __func__); + goto unwind; + } + } else { + osd_error("%s: expecting list type 9 or e, got 0x%x", + __func__, p[0] & 0xf); + goto unwind; + } + + list_len = get_ntohl(&p[4]) + 8; + if (list_len > len) { + osd_error("%s: target says it returned %u, but really %llu", + __func__, list_len, llu(len)); + goto unwind; + } + len = list_len; + p += 8; + len -= 8; + + /* + * Process retrieved entries, figuring out where they go. + */ + for (;;) { + uint64_t oid = 0; + uint32_t page, number; + uint16_t item_len, pad; + uint16_t avail_len; + + if (len < 16u + 8 * !!numgetmulti) + break; + if (numgetmulti) { + oid = get_ntohll(&p[0]); + p += 16; + len -= 16; + } + page = get_ntohl(&p[0]); + number = get_ntohl(&p[4]); + item_len = get_ntohs(&p[14]); + p += 16; + len -= 16; + + for (i=0; i len) + avail_len = len; + + /* + * This can happen for a list of gets since the target does + * not know the requested size of each one, just return what + * we can. + */ + if (avail_len > attr[i].len) + avail_len = attr[i].len; + + /* set it, even if len is zero */ + if (attr[i].type == ATTR_GET_MULTI) { + struct attribute_get_multi_results *mr + = attr[i].val; + + mr->oid[mr->numoid] = oid; + mr->val[mr->numoid] = avail_len ? p : NULL; + //osd_debug("%d\n", mr->oid[mr->numoid]); + //osd_debug("%d\n", get_ntohll(((struct attribute_get_multi_results *)attr[i].val)->val[((struct attribute_get_multi_results *)attr[i].val)->numoid])); + mr->outlen[mr->numoid] = avail_len; + //osd_debug("%d\n", mr->outlen[mr->numoid]); + ++mr->numoid; + } else { + attr[i].val = avail_len ? p : NULL; + attr[i].outlen = avail_len; + } + + if (item_len == 0xffff) + item_len = 0; + + pad = roundup8(16 + item_len) - (16 + item_len); + if (item_len + pad >= len) + break; + + p += item_len + pad; + len -= item_len + pad; + } + ret = 0; + +unwind: + command->outdata = header->orig_outdata; + command->outlen = header->orig_outlen; + command->iov_outlen = header->orig_iov_outlen; + command->indata = header->orig_indata; + command->inlen_alloc = header->orig_inlen_alloc; + command->iov_inlen = header->orig_iov_inlen; + + /* This is tricky. We modified the inlen_alloc so that we + * could reserve extra space for the retrieved attributes. + * But if it was a short read, there is no way for the user + * to find that out without looking at the returned status, + * since the pad bytes papered over the short read. Instead + * of fixing it up here, or in wait_response, we just put + * inlen back so it is no bigger than what was asked for. But + * this is no guarantee that any of those bytes are valid + * read data! + */ + if (command->inlen > command->inlen_alloc) + command->inlen = command->inlen_alloc; + return ret; +} + +void osd_command_attr_free(struct osd_command *command) +{ + free(command->attr_malloc); +} + +/* + * All attributes can be retrieved if asking for number 0xffffffff + * of any page. Further, if the page is 0xffffffff, a list of all user-defined + * attributes on all pages will be returned. + * + * Could try to integrate this with the rest of the attr handlers, but it + * would be very messy. The number of returned entries is not known a priori. + * Signaling that there are more items available than for which space was + * requested is difficult too. Instead we just have a specialized set of + * all-attribute handlers, hoping that the need to combine this sort of + * attribute request with others will not happen. + */ +int osd_command_attr_all_build(struct osd_command *command, uint32_t page) +{ + struct attr_malloc_header *header; + uint8_t *p, *extra_out_buf, *extra_in_buf; + + /* + * In some of the later OSD specs, max space for a returned list + * is a 32-bit field. Get a big chunk of memory for this, because + * if we can't list all the items, there is no way to start the list + * again from the middle. + */ + int len = 512 << 10; /* 512k is the most BSG will let us do */ + + /* + * Cannot use normal attr build as it caps the lengths of items at + * 16 bits. We're asking for a whole bunch of items, each of which + * will be shorter than 16 bits, but together will exceed that. + */ + + /* not build to handle other in or out data */ + if (command->inlen_alloc || command->outlen) + return 1; + + p = Malloc(roundup8(sizeof(*header)) + 16 + len); + if (!p) + return 1; + + /* to free it later */ + command->attr_malloc = p; + + header = (void *) p; + p += roundup8(sizeof(*header)); + + extra_out_buf = p; + p += 16; + extra_in_buf = p; + + /* + * Build the getlist. + */ + p = extra_out_buf; + p[0] = 0x1; + p[1] = p[2] = p[3] = 0; + set_htonl(&p[4], 8); + set_htonl(&p[8], page); + set_htonl(&p[12], 0xffffffff); + + p = extra_in_buf; + header->retrieved_buf = p; + + /* + * Fill the CDB bits. List format. + */ + set_htonl(&command->cdb[52], 16); /* size getlist */ + set_htonl(&command->cdb[60], len); /* size retrieved */ + + command->outdata = extra_out_buf; + command->outlen = 16; + + command->indata = extra_in_buf; + command->inlen_alloc = len; + + return 0; +} + +/* + * Should have a bunch of "9 format" retrieved values. Allocate room + * for a new attr structure, return that. + */ +int osd_command_attr_all_resolve(struct osd_command *command) +{ + struct attr_malloc_header *header = command->attr_malloc; + uint8_t *p; + uint64_t len; + uint32_t list_len; + int ret = -EINVAL; + + p = header->retrieved_buf; + len = command->inlen; + VALGRIND_MAKE_MEM_DEFINED(p, len); + + /* + * Read off the header first. + */ + if (len < 8) + goto unwind; + + if ((p[0] & 0xf) != 0x9) { + osd_error("%s: expecting list type 9, got 0x%x", + __func__, p[0] & 0xf); + goto unwind; + } + + list_len = get_ntohl(&p[4]) + 8; + if (list_len > len) { + osd_error("%s: target says it returned %u, but really %llu", + __func__, list_len, llu(len)); + goto unwind; + } + len = list_len; + p += 8; + len -= 8; + + /* + * First figure out how many entries were returned. + */ + command->numattr = 0; + for (;;) { + uint16_t item_len, pad; + + if (len < 16u) /* 16 header plus val plus roundup */ + break; + item_len = get_ntohs(&p[14]); + p += 16; + len -= 16; + + if (item_len == 0xffff) { + osd_error("%s: target returned item_len -1", __func__); + goto unwind; + } + + ++command->numattr; + + pad = roundup8(16 + item_len) - (16 + item_len); + if (item_len + pad >= len) + break; + + p += item_len + pad; + len -= item_len + pad; + } + + /* + * Allocate space for them. Okay if none. + */ + ret = 0; + if (command->numattr == 0) + goto unwind; + + command->attr = Malloc(command->numattr * sizeof(*command->attr)); + + /* + * Now read it all, pointing their vals into the one big buf. + */ + p = header->retrieved_buf + 8; + len = list_len - 8; + command->numattr = 0; + for (;;) { + uint32_t page, number; + uint16_t item_len, pad; + uint16_t avail_len; + + if (len < 16u) + break; + page = get_ntohl(&p[0]); + number = get_ntohl(&p[4]); + item_len = get_ntohs(&p[14]); + p += 16; + len -= 16; + avail_len = item_len; + + /* + * Ran off the end of the allocated buffer? Just return + * the full entries and complain to caller. + */ + if (avail_len > len) { + avail_len = len; + ret = -E2BIG; + break; + } + + command->attr[command->numattr].val = p; + command->attr[command->numattr].page = page; + command->attr[command->numattr].number = number; + command->attr[command->numattr].outlen = avail_len; + ++command->numattr; + + pad = roundup8(16 + item_len) - (16 + item_len); + if (item_len + pad >= len) + break; + + p += item_len + pad; + len -= item_len + pad; + } + +unwind: + command->outdata = header->orig_outdata; + command->outlen = header->orig_outlen; + command->iov_outlen = header->orig_iov_outlen; + command->indata = header->orig_indata; + command->inlen_alloc = header->orig_inlen_alloc; + command->iov_inlen = header->orig_iov_inlen; + if (command->inlen > command->inlen_alloc) + command->inlen = command->inlen_alloc; + return ret; +} + +void osd_command_attr_all_free(struct osd_command *command) +{ + /* we hid the command->attr that points into attr_malloc, + * instead building our own at resolve time */ + if (command->numattr) + free(command->attr); + osd_command_attr_free(command); +} + +int osd_command_list_resolve(struct osd_command *command) +{ + uint8_t *p = command->indata; + uint64_t addl_len = get_ntohll(&p[0]); + uint64_t cont_oid = get_ntohll(&p[8]); + uint32_t lid = get_ntohl(&p[16]); + int num_results = (addl_len-24)/8; + uint64_t list[num_results]; + int i, listoid, list_attr; + + listoid = (p[23] & 0x40); + char title[4]; + (listoid ? strcpy(title, "OID") : strcpy(title, "PID")); + + if (p[23] & 0x08) + list_attr = 1; + else if (p[23] & 0x04) + list_attr = 0; + + /* + * For now, output the list elements. Later, work this into + * the normal attr_resolve above. Users have to specify what + * attributes they want to get, so we know what to expect and + * can fill in the results. Just LIST has some different formats + * not handled by the current (messy) attr_resolve. + */ + if (lid || cont_oid) + osd_debug("LID: %u CONTINUE_OID: %llu", lid, llu(cont_oid)); + + if (list_attr) { + /* List or store get/set attributes results in the + * command struct somehow, + * using a new method or perhaps attr_resolve? + * + * Also, will need to change how the data is extracted + * based on the value of list_attr, since each obj_descriptor + * isn't 8 bytes apart anymore if list_attr=1 (it depends + * on the number of attributes in the attr list + */ + } + + for (i=0; i < num_results; i++) { + list[i] = get_ntohll(&p[24+8*i]); + osd_debug("%s: %llu", title, llu(list[i])); + + } + + return 1; +} + +int osd_command_list_collection_resolve(struct osd_command *command) +{ + uint8_t *p = command->indata; + uint64_t addl_len = get_ntohll(&p[0]); + uint64_t cont_oid = get_ntohll(&p[8]); + uint32_t lid = get_ntohl(&p[16]); + int num_results = (addl_len-24)/8; + uint64_t list[num_results]; + int i, listoid, list_attr; + + listoid = (p[23] & 0x80); + char title[4]; + (listoid ? strcpy(title, "OID") : strcpy(title, "CID")); + + if (p[23] & 0x08) + list_attr = 1; + else if (p[23] & 0x04) + list_attr = 0; + + /* + * For now, output the list elements. Later, work this into + * the normal attr_resolve above. Users have to specify what + * attributes they want to get, so we know what to expect and + * can fill in the results. Just LIST has some different formats + * not handled by the current (messy) attr_resolve. + */ + if (lid || cont_oid) + osd_debug("LID: %u CONTINUE_OID: %llu", lid, llu(cont_oid)); + + if (list_attr) { + /* List or store get/set attributes results in the + * command struct somehow, + * using a new method or perhaps attr_resolve? + * + * Also, will need to change how the data is extracted + * based on the value of list_attr, since each obj_descriptor + * isn't 8 bytes apart anymore if list_attr=1 (it depends + * on the number of attributes in the attr list + */ + } + + for (i=0; i < num_results; i++) { + list[i] = get_ntohll(&p[24+8*i]); + osd_debug("%s: %llu", title, llu(list[i])); + } + + return 1; +} diff --git a/osd-target/tests/command.h b/osd-target/tests/command.h deleted file mode 120000 index 7a9d806..0000000 --- a/osd-target/tests/command.h +++ /dev/null @@ -1 +0,0 @@ -../../osd-initiator/command.h \ No newline at end of file diff --git a/osd-target/tests/command.h b/osd-target/tests/command.h new file mode 100644 index 0000000..4c763bc --- /dev/null +++ b/osd-target/tests/command.h @@ -0,0 +1,202 @@ +/* + * Commands and attributes. + * + * Copyright (C) 2007 OSD Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _COMMAND_H +#define _COMMAND_H + +#include +#include "osd-util/osd-defs.h" + +/* Data Structure Definition */ + +struct attribute_list { + enum { + ATTR_GET, + ATTR_GET_PAGE, + ATTR_GET_MULTI, + ATTR_SET, + ATTR_RESULT, + } type; + uint32_t page; + uint32_t number; + void *val; + uint16_t len; + uint16_t outlen; /* 0 -> empty or not exist, 0xffff -> overflow */ +}; + +/* + * In the case of ATTR_GET_MULTI, each returned attr->val will point to + * one of these. Look inside it to find the values for each oid. + */ +struct attribute_get_multi_results { + int numoid; + union { + uint64_t *oid; + uint64_t *cid; + uint64_t *pid; + }; + const void **val; /* arrays for each oid: val, outlen */ + uint16_t *outlen; +}; + +/* The Linux kernel does not currently support BSG iovecs. The + bsg_iovec struct below assumes a kernel patch that has not been + incorporated into the kernel. Therefore, it is removed for now, + and just set to point to the scsi/sg.h sg_iovec (which is ignored + in the kernel +*/ +#if 0 +/* + * This is copied from a kernel header to avoid including it. + */ +struct bsg_iovec { + uint64_t iov_base; + uint32_t iov_len; + uint32_t __pad1; +}; +#else +#include +#define bsg_iovec sg_iovec +#endif + +/* + * All information needed to submit a command to the kernel module. + * [i] = provided by caller to submit_osd() + * [o] = return from library to caller + */ +struct osd_command { + uint8_t cdb[OSD_CDB_SIZE]; /* [i] maximum length CDB */ + int cdb_len; /* [i] actual len of valid bytes */ + const void *outdata; /* [i] data, goes out to target */ + size_t outlen; /* [i] length */ + int iov_outlen; /* [i] if non-zero, data are iovecs */ + void *indata; /* [o] results, returned from target */ + size_t inlen_alloc; /* [i] alloc size for results */ + size_t inlen; /* [o] actual size returned */ + int iov_inlen; /* [i] */ + uint8_t status; /* [o] scsi status */ + uint8_t sense[OSD_MAX_SENSE]; /* [o] sense errors */ + int sense_len; /* [o] number of bytes in sense */ + struct attribute_list *attr; /* [o] after attr_resolve() */ + int numattr; /* [o] */ + void *attr_malloc; /* [x] internal use only */ +}; + + +/* Set up the CDB */ +int osd_command_set_test_unit_ready(struct osd_command *command); +int osd_command_set_inquiry(struct osd_command *command, uint8_t page_code, + uint8_t outlen); +int osd_command_set_append(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len); +int osd_command_set_clear(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset); +int osd_command_set_create(struct osd_command *command, uint64_t pid, + uint64_t requested_oid, uint16_t num_user_objects); +int osd_command_set_create_and_write(struct osd_command *command, uint64_t pid, + uint64_t requested_oid, uint64_t len, + uint64_t offset); +int osd_command_set_create_collection(struct osd_command *command, + uint64_t pid, uint64_t requested_cid); +int osd_command_set_create_partition(struct osd_command *command, + uint64_t requested_pid); +int osd_command_set_create_user_tracking_collection(struct osd_command *command, + uint64_t pid, + uint64_t requested_cid, + uint64_t source_cid); +int osd_command_set_flush(struct osd_command *command, uint64_t pid, uint64_t len, + uint64_t offset, uint64_t oid, int flush_scope); +int osd_command_set_flush_collection(struct osd_command *command, uint64_t pid, + uint64_t cid, int flush_scope); +int osd_command_set_flush_osd(struct osd_command *command, int flush_scope); +int osd_command_set_flush_partition(struct osd_command *command, uint64_t pid, + int flush_scope); +int osd_command_set_format_osd(struct osd_command *command, uint64_t capacity); +int osd_command_set_get_attributes(struct osd_command *command, uint64_t pid, + uint64_t oid); +int osd_command_set_get_member_attributes(struct osd_command *command, + uint64_t pid, uint64_t cid, uint64_t min_oid, uint64_t max_oid); +int osd_command_set_list(struct osd_command *command, uint64_t pid, + uint32_t list_id, uint64_t alloc_len, + uint64_t initial_oid, int list_attr); +int osd_command_set_list_collection(struct osd_command *command, uint64_t pid, + uint64_t cid, uint32_t list_id, + uint64_t alloc_len, + uint64_t initial_oid, + int list_attr); +int osd_command_set_perform_scsi_command(struct osd_command *command); +int osd_command_set_perform_task_mgmt_func(struct osd_command *command); +int osd_command_set_punch(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset); +int osd_command_set_query(struct osd_command *command, uint64_t pid, + uint64_t cid, uint32_t cont_len, uint64_t alloc_len, + uint64_t matches_cid); +int osd_command_set_read(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset); +int osd_command_set_read_map(struct osd_command*command, uint64_t pid, uint64_t oid, + uint64_t alloc_len, uint64_t offset, uint8_t map_type); +int osd_command_set_remove(struct osd_command *command, uint64_t pid, + uint64_t oid); +int osd_command_set_remove_collection(struct osd_command *command, + uint64_t pid, uint64_t cid, int force); +int osd_command_set_remove_member_objects(struct osd_command *command, + uint64_t pid, uint64_t cid); +int osd_command_set_remove_partition(struct osd_command *command, + uint64_t pid); +int osd_command_set_set_attributes(struct osd_command *command, uint64_t pid, + uint64_t oid); +int osd_command_set_set_key(struct osd_command *command, int key_to_set, + uint64_t pid, uint64_t key, const uint8_t seed[20]); +int osd_command_set_set_master_key(struct osd_command *command, int dh_step, + uint64_t key, uint32_t param_len, + uint32_t alloc_len); +int osd_command_set_set_member_attributes(struct osd_command *command, + uint64_t pid, uint64_t cid); +int osd_command_set_write(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset); +void osd_command_set_ddt(struct osd_command *command, uint8_t ddt_type); +uint8_t osd_command_get_ddt(struct osd_command *command); +/* + * Extensions, not yet in T10 or SNIA OSD spec. + */ +int osd_command_set_cas(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset); +int osd_command_set_fa(struct osd_command *command, uint64_t pid, + uint64_t oid, uint64_t len, uint64_t offset); +int osd_command_set_gen_cas(struct osd_command *command, uint64_t pid, + uint64_t oid); +int osd_command_set_cond_setattr(struct osd_command *command, uint64_t pid, + uint64_t oid); + +/* Attributes */ +int osd_command_attr_build(struct osd_command *command, + const struct attribute_list *const attrs, int num); +int osd_command_multi_attr_build(struct osd_command *command, + const struct attribute_list *const attrs, int num, int numobj); +int osd_command_attr_resolve(struct osd_command *command); +void osd_command_attr_free(struct osd_command *command); + +/* Get all attributes */ +int osd_command_attr_all_build(struct osd_command *command, uint32_t page); +int osd_command_attr_all_resolve(struct osd_command *command); +void osd_command_attr_all_free(struct osd_command *command); + +/* Lists */ +int osd_command_list_resolve(struct osd_command *command); +int osd_command_list_collection_resolve(struct osd_command *command); + +#endif diff --git a/osd-target/tests/db-test.c b/osd-target/tests/db-test.c index 4071a01..0038868 100644 --- a/osd-target/tests/db-test.c +++ b/osd-target/tests/db-test.c @@ -297,7 +297,7 @@ static void test_coll(struct osd_device *osd) ret = coll_insert(osd->dbc, 0x20, 0x1, 0x111, 2); assert(ret == 0); - ret = coll_get_oids_in_cid(osd->dbc, 0x20, 0x2, 0, 64*8, + ret = coll_get_oids_in_cid(osd->dbc, 0x20, 0x2, 0, 1, 64*8, (uint8_t *)oids, &usedlen, &addlen, &cont_id); assert(ret == 0); @@ -373,7 +373,7 @@ static void test_copy_coll(struct osd_device *osd) assert(ret == 0); /* list elements in dest collection */ - ret = coll_get_oids_in_cid(osd->dbc, 0x20, 0x3, 0, 64*8, + ret = coll_get_oids_in_cid(osd->dbc, 0x20, 0x3, 0, 1, 64*8, (uint8_t *)oids, &usedlen, &addlen, &cont_id); assert(ret == 0); diff --git a/osd-util/initiator b/osd-util/initiator index c1fcd62..e128b39 100755 --- a/osd-util/initiator +++ b/osd-util/initiator @@ -53,10 +53,6 @@ start() { if (( $# < 1 )) ; then usage ; fi fi - count=$# - last_arg=${@: -1} - complete=0 - # connect to each of the list of target hosts given while (( $# >= 1 )) ; do targethost=$1 @@ -72,37 +68,8 @@ start() { egrep ^$targetip: | sed -n 1p | cut -d\ -f2) else # hope it is the first/only IP we get back - if [[ $count = 2 ]] ; then - targetname=$last_arg - fi - - if [[ $count = 1 ]] ; then - - ##length of one line - oneline=$(iscsiadm -m discovery -t st -p $targethost |\ - sed -n 1p) - whole=$(iscsiadm -m discovery -t st -p $targethost) - length=$((${#oneline})) - wholelength=$((${#whole})) - numtargets=$(($wholelength/$length)) - var="p" - counter=0 - for (( counter=1; counter<=numtargets; counter++ )) - do - targetname=$(iscsiadm -m discovery -t st -p $targethost |\ - sed -n $counter$var | cut -d\ -f2) - targetip=$(iscsiadm -m discovery -t st -p $targethost |\ - sed -n $counter$var | cut -d\ -f1) - # set transport type; must provide targetname here - iscsiadm -m node -p $targetip -T $targetname --op update \ - -n node.transport_name -v $transport_type - # login - iscsiadm -m node -p $targetip -T $targetname -l - done - complete=1 - fi - - + targetname=$(iscsiadm -m discovery -t st -p $targethost |\ + sed -n 1p | cut -d\ -f2) if [[ -n $targetname ]] ; then targetip=$(iscsiadm -m discovery -t st -p $targethost |\ sed -n 1p | cut -d\ -f1) @@ -112,18 +79,11 @@ start() { echo "Could not connect to SCSI target on $targethost." >&2 continue fi - - if [[ $complete = 0 ]] ; then - # set transport type; must provide targetname here - iscsiadm -m node -p $targetip -T $targetname --op update \ - -n node.transport_name -v $transport_type - # login - iscsiadm -m node -p $targetip -T $targetname -l - fi - - if [[ $count = 2 ]] ; then - break - fi + # set transport type; must provide targetname here + iscsiadm -m node -p $targetip -T $targetname --op update \ + -n node.transport_name -v $transport_type + # login + iscsiadm -m node -p $targetip -T $targetname -l done } diff --git a/osd-util/perf.py b/osd-util/perf.py index 6a4aed5..525012f 100755 --- a/osd-util/perf.py +++ b/osd-util/perf.py @@ -57,7 +57,7 @@ elif id == "alin": elif id == "ananth": osd_dir = "/home/ananth/osd" else: - osd_dir = os.environ["HOME"] + osd_dir = os.environ["HOME"] + "/pvfs_on_osd" initiator = osd_dir + "/osd-util/initiator" tgtd = osd_dir + "/osc-osd/tgt/usr/otgtd" @@ -149,7 +149,7 @@ def usage(): #=====================================================USAGE=================================================================================== # filenames -testdir = os.environ["TMPDIR"] +testdir = osd_dir foptions = testdir + "/options" fnodes = testdir + "/nodes" fcompnodes = testdir + "/compnodes" @@ -263,7 +263,7 @@ def buildfiles(): port = 3334 if options["protocol"] == "ib": port = 3335 - mountpoint = "/pvfs" + mountpoint = "/mnt/pvfs2" if options["protocol"] != "tcp": mountpoint = mountpoint + "-" + options["protocol"] @@ -272,11 +272,23 @@ def buildfiles(): fd = open(nodes_dir, "r") while True: line = fd.readline() - if line == "#compnodes#\n" or line == "#osdnodes#\n" or line == "#pvfsnodes#\n": - continue; + if line.find("#clients#") > -1: + line_chunks = line.split() + for chunk in line_chunks: + if chunk != "#clients#": + nodes.append(chunk) + if not (options["osdtype"] == "none" and options["dirtype"] == "pvfs") and line.find("#osdnodes#") > -1: + line_chunks = line.split() + for chunk in line_chunks: + if chunk != "#osdnodes#": + nodes.append(chunk) + if line.find("#pvfsnodes#") > -1: + line_chunks = line.split() + for chunk in line_chunks: + if chunk != "#pvfsnodes#": + nodes.append(chunk) if line == "": break - nodes.append(line[:-1]) fd.close() if options["meta_on_io"] == "yes": @@ -617,7 +629,7 @@ def start(): mountup = "" for n in osdnodes: - os.system("'rsh " + n + " " + os.system("rsh " + n + " " + "cd " + testdir + " \; " + "rm -rf /tmp/tgt-" + id + " \; " + "mkdir /tmp/tgt-" + id + " \; " @@ -672,9 +684,9 @@ def start(): if len(myibosdnodes) > 0: for n in myibosdnodes: os.system("rsh " + n + " " - + "echo " + tabfile_contents + " \> " + tabfile + " \; " - + "sudo " + initiator + " " + startcmd + " " - + n) + + "echo " + tabfile_contents + " \> " + tabfile); + os.system("sudo " + initiator + " " + startcmd + " " + + n); elif len(compnodes) > 0: for n in compnodes: diff --git a/up b/up index cda26f8..54867b8 100755 --- a/up +++ b/up @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash up_dir=`dirname $0` up_conf=./up.conf @@ -94,7 +94,8 @@ echo "================ `date` =========================" >> $LOG_FILE # -d - debug level # DEBUG="-d 9" DEBUG="" -$OTGTD $DEBUG -f &>> $LOG_FILE & +#$OTGTD $DEBUG -f &>> $LOG_FILE & +$OTGTD $DEBUG -f & sleep 2 @@ -108,3 +109,4 @@ done $TGTADM --lld iscsi --mode target --op show echo "otgtd started, run \"up down\" to stop" +wait