diff --git a/osd-target/Makefile b/osd-target/Makefile index 75df94a..452adda 100644 --- a/osd-target/Makefile +++ b/osd-target/Makefile @@ -5,7 +5,7 @@ -include ../Makedefs SRC := attr.c db.c obj.c osd-schema.c osd.c cdb.c osd-sense.c list-entry.c -SRC += osd-schema.c coll.c mtq.c +SRC += osd-schema.c coll.c mtq.c tracking.c INC := attr.h db.h obj.h osd-types.h osd.h cdb.h list-entry.h target-sense.h INC += coll.h mtq.c DEP := .depend diff --git a/osd-target/cdb.c b/osd-target/cdb.c index d9ea231..b6aa8c6 100644 --- a/osd-target/cdb.c +++ b/osd-target/cdb.c @@ -70,6 +70,7 @@ struct command { int senselen; }; +/* get attribute by page has been made obsolete as of OSD3R02 */ static int get_attr_page(struct command *cmd, uint64_t pid, uint64_t oid, uint8_t isembedded, uint16_t numoid, uint32_t cdb_cont_len) { @@ -799,6 +800,16 @@ static int cdb_query(struct command *cmd, uint64_t pid, uint64_t cid, uint64_t alloc_len = get_ntohll(&cdb[32]); uint64_t matches_cid = get_ntohll(&cdb[40]); + uint8_t immed_tr = cdb[11] >> 7; + + /* osd2r04 6.26.1 - if immed_tr is one, then alloc_len should + be zero and matches_cid should be nonzero */ + if (immed_tr && (alloc_len != 0 || matches_cid == 0)) + goto out_query_cdb_err; + + if (alloc_len != 0 && matches_cid != 0) + goto out_query_cdb_err; + struct cdb_continuation_descriptor *query_desc; struct cdb_continuation_descriptor *descriptors = cmd->cont.descriptors; @@ -830,7 +841,8 @@ static int cdb_query(struct command *cmd, uint64_t pid, uint64_t cid, return osd_query(cmd->osd, pid, cid, query_desc->length, alloc_len, query_desc->desc_specific_hdr, cmd->outdata, - &cmd->used_outlen, cdb_cont_len, cmd->sense); + &cmd->used_outlen, cdb_cont_len, immed_tr, + matches_cid, cmd->sense); out_query_cdb_err: return sense_basic_build(cmd->sense, OSD_SSK_ILLEGAL_REQUEST, OSD_ASC_INVALID_FIELD_IN_CDB, pid, cid); @@ -1391,7 +1403,7 @@ osd_warning("%s:%d:", __FILE__, __LINE__); (typeof(desc_hdr))cdb_cont; uint16_t type = get_ntohs(&desc_hdr->type); uint32_t length = get_ntohl(&desc_hdr->length); - uint8_t pad_length = desc_hdr->pad_length & 0x7; + uint8_t pad_length = desc_hdr->pad_length; uint32_t desc_len = length + pad_length; @@ -1674,8 +1686,9 @@ static void exec_service_action(struct command *cmd) uint64_t requested_cid = get_ntohll(&cdb[24]); uint64_t source_cid = get_ntohll(&cdb[40]); - ret = osd_create_user_tracking_collection(osd, pid, requested_cid, - cdb_cont_len, source_cid, sense); + ret = osd_create_user_tracking_collection(osd, pid,requested_cid, + source_cid, + cdb_cont_len, sense); break; } case OSD_DETACH_CLONE: { diff --git a/osd-target/coll.c b/osd-target/coll.c index aeb9762..b606176 100644 --- a/osd-target/coll.c +++ b/osd-target/coll.c @@ -43,6 +43,7 @@ struct coll_tab { sqlite3_stmt *delcid; /* delete collection cid */ sqlite3_stmt *deloid; /* delete oid from all collections */ sqlite3_stmt *emptycid; /* is collection empty? */ + sqlite3_stmt *max; /* max object collection pointer value */ sqlite3_stmt *getcid; /* get collection */ sqlite3_stmt *getoids; /* get objects in a collection */ sqlite3_stmt *copyoids; /* copy oids from one collection to another */ @@ -117,6 +118,12 @@ int coll_initialize(struct db_context *dbc) if (ret != SQLITE_OK) goto out_finalize_emptycid; + sprintf(SQL, "SELECT MAX (number) FROM %s WHERE pid = ? AND cid = ?;", + dbc->coll->name); + ret = sqlite3_prepare(dbc->db, SQL, -1, &dbc->coll->max, NULL); + if (ret != SQLITE_OK) + goto out_finalize_max; + sprintf(SQL, "SELECT cid FROM %s WHERE pid = ? AND oid = ? AND " " number = ?;", dbc->coll->name); ret = sqlite3_prepare(dbc->db, SQL, -1, &dbc->coll->getcid, NULL); @@ -147,6 +154,9 @@ int coll_initialize(struct db_context *dbc) out_finalize_getcid: db_sqfinalize(dbc->db, dbc->coll->getcid, SQL); SQL[0] = '\0'; +out_finalize_max: + db_sqfinalize(dbc->db, dbc->coll->max, SQL); + SQL[0] = '\0'; out_finalize_emptycid: db_sqfinalize(dbc->db, dbc->coll->emptycid, SQL); SQL[0] = '\0'; @@ -178,6 +188,7 @@ int coll_finalize(struct db_context *dbc) sqlite3_finalize(dbc->coll->delcid); sqlite3_finalize(dbc->coll->deloid); sqlite3_finalize(dbc->coll->emptycid); + sqlite3_finalize(dbc->coll->max); sqlite3_finalize(dbc->coll->getcid); sqlite3_finalize(dbc->coll->getoids); sqlite3_finalize(dbc->coll->copyoids); @@ -375,6 +386,48 @@ int coll_isempty_cid(struct db_context *dbc, uint64_t pid, uint64_t cid, } +/* + * return the max object pointer for a particular pid,cid + * + * returns: + * -EINVAL: invalid arg, ignore value of isempty + * OSD_ERROR: in case of other errors, ignore value of isempty + * OSD_OK: success, isempty is set to: + * ==1: if collection is empty or absent + * ==0: if not empty + */ +int coll_max_pointer(struct db_context *dbc, uint64_t pid, uint64_t cid, + uint32_t *number) +{ + int ret = 0; + int bound = 0; + *number = 0; + + assert(dbc && dbc->db && dbc->coll && dbc->coll->max); + +repeat: + ret = 0; + ret |= sqlite3_bind_int64(dbc->coll->max, 1, pid); + ret |= sqlite3_bind_int64(dbc->coll->max, 2, cid); + bound = (ret == SQLITE_OK); + if (!bound) { + error_sql(dbc->db, "%s: bind failed", __func__); + goto out_reset; + } + + while ((ret = sqlite3_step(dbc->coll->max)) == SQLITE_BUSY); + if (ret == SQLITE_ROW) + *number = (0 == sqlite3_column_int(dbc->coll->max, 0)); + +out_reset: + ret = db_reset_stmt(dbc, dbc->coll->max, bound, __func__); + if (ret == OSD_REPEAT) + goto repeat; +out: + return ret; +} + + /* * returns: * -EINVAL: invalid arg, cid is not set diff --git a/osd-target/coll.h b/osd-target/coll.h index cb572a0..3c28703 100644 --- a/osd-target/coll.h +++ b/osd-target/coll.h @@ -52,6 +52,9 @@ int coll_get_oids_in_cid(struct db_context *dbc, uint64_t pid, uint64_t cid, uint8_t *outdata, uint64_t *used_outlen, uint64_t *add_len, uint64_t *cont_id); +int coll_max_pointer(struct db_context *dbc, uint64_t pid, uint64_t cid, + uint32_t *number); + int coll_copyoids(struct db_context *dbc, uint64_t pid, uint64_t dest_cid, uint64_t source_cid); diff --git a/osd-target/mtq.c b/osd-target/mtq.c index 74cfc0b..6abc280 100644 --- a/osd-target/mtq.c +++ b/osd-target/mtq.c @@ -46,7 +46,8 @@ */ int mtq_run_query(struct db_context *dbc, uint64_t pid, uint64_t cid, struct query_criteria *qc, void *outdata, - uint32_t alloc_len, uint64_t *used_outlen) + uint32_t alloc_len, uint64_t *used_outlen, + uint64_t matches_cid) { int ret = 0; int pos = 0; @@ -55,6 +56,7 @@ int mtq_run_query(struct db_context *dbc, uint64_t pid, uint64_t cid, uint8_t *p = NULL; uint32_t i = 0; uint32_t sqlen = 0; + uint32_t number; uint32_t factor = 2; /* this query fills space quickly */ uint64_t len = 0; const char *op = NULL; @@ -90,10 +92,24 @@ int mtq_run_query(struct db_context *dbc, uint64_t pid, uint64_t cid, */ /* build the SQL statment */ - sprintf(select_stmt, "SELECT attr.oid FROM %s as coll, %s as attr " - " WHERE coll.pid = coll.pid AND coll.oid = attr.oid AND " - " coll.pid = %llu AND coll.cid = %llu ", coll, attr, - llu(pid), llu(cid)); + if (matches_cid != 0) { + ret = coll_max_pointer(dbc, pid, cid, &number); + if (ret != SQLITE_OK) { + goto out; + } + sprintf(select_stmt, "SELECT coll.pid, %llu, attr.oid, %d " + "FROM %s AS coll, %s AS attr WHERE " + "coll.pid=coll.pid AND coll.oid=attr.oid " + "AND coll.pid = %llu AND coll.cid = %llu ", + llu(matches_cid), number, coll, attr, llu(pid), + llu(cid)); + } else { + sprintf(select_stmt, "SELECT attr.oid FROM %s AS coll, " + "%s AS attr WHERE coll.pid = coll.pid AND " + "coll.oid = attr.oid AND coll.pid = %llu " + "AND coll.cid = %llu ", + coll, attr, llu(pid), llu(cid)); + } strncpy(cp, select_stmt, MAXSQLEN*factor); sqlen += strlen(cp); cp += sqlen; @@ -123,6 +139,17 @@ int mtq_run_query(struct db_context *dbc, uint64_t pid, uint64_t cid, } cp = strcat(cp, " GROUP BY attr.oid ORDER BY 1;"); + if (matches_cid != 0) { + char *SQL2 = Malloc(strlen(SQL) + 100); + if (SQL2 == NULL) { + ret = -ENOMEM; + goto out; + } + sprintf(SQL2, "INSERT INTO %s %s", coll, SQL); + free(SQL); + SQL = SQL2; + } + ret = sqlite3_prepare(dbc->db, SQL, strlen(SQL)+1, &stmt, NULL); if (ret != SQLITE_OK) { error_sql(dbc->db, "%s: sqlite3_prepare", __func__); @@ -130,6 +157,7 @@ int mtq_run_query(struct db_context *dbc, uint64_t pid, uint64_t cid, goto out; } + repeat: /* bind the values */ pos = 1; for (i = 0; i < qc->qc_cnt; i++) { @@ -159,6 +187,13 @@ int mtq_run_query(struct db_context *dbc, uint64_t pid, uint64_t cid, } } + if (matches_cid != 0) { + ret = db_exec_dms(dbc, stmt, ret, __func__); + if (ret == OSD_REPEAT) + goto repeat; + goto out_finalize; + } + /* execute the query */ p = outdata; p += ML_ODL_OFF; @@ -442,10 +477,9 @@ int mtq_set_member_attrs(struct db_context *dbc, uint64_t pid, uint64_t cid, char *SQL = NULL; size_t sqlen = 0; sqlite3_stmt *stmt = NULL; - const char *coll = coll_getname(dbc); const char *attr = attr_getname(dbc); - assert(dbc && dbc->db && set_attr && coll && attr); + assert(dbc && dbc->db && set_attr && attr); if (set_attr->sz == 0) { ret = 0; @@ -466,8 +500,9 @@ int mtq_set_member_attrs(struct db_context *dbc, uint64_t pid, uint64_t cid, for (i = 0; i < set_attr->sz; i++) { sprintf(cp, " SELECT %llu, oid, %u, %u, ? FROM %s " - " WHERE cid = %llu ", llu(pid), set_attr->le[i].page, - set_attr->le[i].number, coll, llu(cid)); + " WHERE pid = %llu AND page = %u AND value = %llu", + llu(pid), set_attr->le[i].page, set_attr->le[i].number, + attr, llu(pid), USER_COLL_PG, llu(cid)); if (i < (set_attr->sz - 1)) cp = strcat(cp, " UNION ALL "); sqlen += strlen(cp); diff --git a/osd-target/mtq.h b/osd-target/mtq.h index ce32f6c..07810cb 100644 --- a/osd-target/mtq.h +++ b/osd-target/mtq.h @@ -23,7 +23,8 @@ int mtq_run_query(struct db_context *dbc, uint64_t pid, uint64_t cid, struct query_criteria *qc, void *outdata, - uint32_t alloc_len, uint64_t *used_outlen); + uint32_t alloc_len, uint64_t *used_outlen, + uint64_t matches_cid); int mtq_list_oids_attr(struct db_context *dbc, uint64_t pid, uint64_t initial_oid, struct getattr_list *get_attr, diff --git a/osd-target/obj.c b/osd-target/obj.c index 5e401ee..39dc5db 100644 --- a/osd-target/obj.c +++ b/osd-target/obj.c @@ -86,7 +86,7 @@ int obj_initialize(struct db_context *dbc) goto out; } - sprintf(SQL, "INSERT INTO %s VALUES (?, ?, ?);", dbc->obj->name); + sprintf(SQL, "INSERT INTO %s VALUES (?, ?, ?, ?);", dbc->obj->name); ret = sqlite3_prepare(dbc->db, SQL, -1, &dbc->obj->insert, NULL); if (ret != SQLITE_OK) goto out_finalize_insert; @@ -131,7 +131,7 @@ int obj_initialize(struct db_context *dbc) if (ret != SQLITE_OK) goto out_finalize_pcount; - sprintf(SQL, "SELECT type FROM %s WHERE pid = ? AND oid = ?;", + sprintf(SQL, "SELECT type, coll_type FROM %s WHERE pid = ? AND oid = ?;", dbc->obj->name); ret = sqlite3_prepare(dbc->db, SQL, -1, &dbc->obj->gettype, NULL); if (ret != SQLITE_OK) @@ -240,7 +240,7 @@ const char *obj_getname(struct db_context *dbc) * OSD_OK: success */ int obj_insert(struct db_context *dbc, uint64_t pid, uint64_t oid, - uint32_t type) + uint8_t type, uint8_t coll_type) { int ret = 0; @@ -252,6 +252,7 @@ int obj_insert(struct db_context *dbc, uint64_t pid, uint64_t oid, ret |= sqlite3_bind_int64(dbc->obj->insert, 1, pid); ret |= sqlite3_bind_int64(dbc->obj->insert, 2, oid); ret |= sqlite3_bind_int(dbc->obj->insert, 3, type); + ret |= sqlite3_bind_int(dbc->obj->insert, 4, coll_type); ret = db_exec_dms(dbc, dbc->obj->insert, ret, __func__); if (ret == OSD_REPEAT) goto repeat; @@ -493,7 +494,7 @@ int obj_pcount(struct db_context *dbc, uint64_t *pcount) * obj_types set to the determined type. */ int obj_get_type(struct db_context *dbc, uint64_t pid, uint64_t oid, - uint8_t *obj_type) + uint8_t *obj_type, uint8_t *coll_type) { int ret = 0; int bound = 0; @@ -514,6 +515,8 @@ int obj_get_type(struct db_context *dbc, uint64_t pid, uint64_t oid, while ((ret = sqlite3_step(dbc->obj->gettype)) == SQLITE_BUSY); if (ret == SQLITE_ROW) { *obj_type = sqlite3_column_int(dbc->obj->gettype, 0); + if (coll_type) + *coll_type = sqlite3_column_int(dbc->obj->gettype, 1); } else if (ret == SQLITE_DONE) { osd_debug("%s: object (%llu %llu) doesn't exist", __func__, llu(pid), llu(oid)); diff --git a/osd-target/obj.h b/osd-target/obj.h index 8dfbb70..b815a85 100644 --- a/osd-target/obj.h +++ b/osd-target/obj.h @@ -28,7 +28,7 @@ int obj_finalize(struct db_context *dbc); const char *obj_getname(struct db_context *dbc); int obj_insert(struct db_context *dbc, uint64_t pid, uint64_t oid, - uint32_t type); + uint8_t type, uint8_t coll_type); int obj_delete(struct db_context *dbc, uint64_t pid, uint64_t oid); @@ -46,7 +46,7 @@ int obj_isempty_pid(struct db_context *dbc, uint64_t pid, int *isempty); int obj_pcount(struct db_context *dbc, uint64_t *pcount); int obj_get_type(struct db_context *dbc, uint64_t pid, uint64_t oid, - uint8_t *obj_type); + uint8_t *obj_type, uint8_t *coll_type); int obj_get_oids_in_pid(struct db_context *dbc, uint64_t pid, uint64_t initial_oid, uint64_t alloc_len, diff --git a/osd-target/osd.c b/osd-target/osd.c index 5f49387..00cc7e2 100644 --- a/osd-target/osd.c +++ b/osd-target/osd.c @@ -40,6 +40,7 @@ #include "mtq.h" #include "osd-util/osd-sense.h" #include "list-entry.h" +#include "tracking.h" #define min(x,y) ({ \ typeof(x) _x = (x); \ @@ -103,7 +104,7 @@ static inline uint8_t get_obj_type(struct osd_device *osd, } else if (pid >= PARTITION_PID_LB && oid == PARTITION_OID) { return PARTITION; } else if (pid >= OBJECT_PID_LB && oid >= OBJECT_OID_LB) { - ret = obj_get_type(osd->dbc, pid, oid, &obj_type); + ret = obj_get_type(osd->dbc, pid, oid, &obj_type, NULL); if (ret == OSD_OK) return obj_type; } @@ -880,6 +881,97 @@ static int set_riap(struct osd_device *osd, uint64_t pid, uint64_t oid, } } +static int get_ciap(struct osd_device *osd, uint64_t pid, uint64_t cid, + uint32_t number, void *outbuf, + uint64_t outlen, uint8_t listfmt, uint32_t *used_outlen) +{ + int ret = 0; + const void *val = NULL; + uint16_t len = 0; + char name[ATTR_PAGE_ID_LEN]; + uint8_t ll[8]; + uint64_t pcount; + uint8_t obj_type = ILLEGAL_OBJ; + uint8_t coll_type = -1; + + switch (number) { + case 0: + /*{COLL_PG + 1, 0, "INCITS T10 Collection Information"},*/ + len = ATTR_PAGE_ID_LEN; + sprintf(name, "INCITS T10 Collection Information"); + val = name; + break; + case CIAP_PARTITION_ID: + ret = obj_get_type(osd->dbc, pid, cid, &obj_type, NULL); + if (ret == OSD_OK) + return obj_type; + if (obj_type == COLLECTION) { + len = CIAP_PARTITION_ID_LEN; + set_htonll(ll, pid); + } else { + /* the object is not a collection, so the CIAP + attribute page is not valid */ + len = 0; + set_htonll(ll, -1); + } + val = ll; + break; + case CIAP_COLLECTION_OBJECT_ID: + ret = obj_get_type(osd->dbc, pid, cid, &obj_type, NULL); + if (ret == OSD_OK) + return obj_type; + if (obj_type == COLLECTION) { + len = CIAP_COLLECTION_OBJECT_ID_LEN; + set_htonll(ll, cid); + } else { + /* the object is not a collection, so the CIAP + attribute page is not valid */ + len = 0; + set_htonll(ll, -1); + } + val = ll; + break; + case CIAP_COLLECTION_NAME: + return attr_get_attr(osd->dbc, pid, cid, COLL_INFO_PG, + CIAP_COLLECTION_NAME, outlen, outbuf, + listfmt, used_outlen); + case CIAP_COLLECTION_TYPE: + ret = obj_get_type(osd->dbc, pid, cid, &obj_type, &coll_type); + if (ret == OSD_OK) + return obj_type; + len = CIAP_COLLECTION_TYPE_LEN; + ll[0] = coll_type; + val = ll; + break; + case CIAP_USED_CAPACITY: + /*FIXME: return used capacity of collection*/ + len = CIAP_USED_CAPACITY_LEN; + set_htonll(ll, -1); + val = ll; + break; + default: + return OSD_ERROR; + } + + if (listfmt == RTRVD_SET_ATTR_LIST) + ret = le_pack_attr(outbuf, outlen, COLL_INFO_PG, number, len, val); + else if (listfmt == RTRVD_CREATE_MULTIOBJ_LIST) + ret = le_multiobj_pack_attr(outbuf, outlen, cid, COLL_INFO_PG, + number, len, val); + else + return OSD_ERROR; + + assert(ret == -EINVAL || ret == -EOVERFLOW || ret > 0); + if (ret == -EOVERFLOW) + *used_outlen = 0; + else if (ret > 0) + *used_outlen = ret; + else + return ret; + + return OSD_OK; +} + /* * returns: * OSD_ERROR: for error @@ -950,7 +1042,7 @@ static int osd_initialize_db(struct osd_device *osd) memset(&osd->idl, 0, sizeof(osd->idl)); /* tables already created by osd_db_open, so insertions can be done */ - ret = obj_insert(osd->dbc, ROOT_PID, ROOT_OID, ROOT); + ret = obj_insert(osd->dbc, ROOT_PID, ROOT_OID, ROOT, -1); if (ret != SQLITE_OK) goto out; @@ -1666,7 +1758,7 @@ int osd_create(struct osd_device *osd, uint64_t pid, uint64_t requested_oid, numoid = 1; /* create atleast one object */ for (i = oid; i < (oid + numoid); i++) { - ret = obj_insert(osd->dbc, pid, i, USEROBJECT); + ret = obj_insert(osd->dbc, pid, i, USEROBJECT, -1); if (ret != 0) { osd_remove_tmp_objects(osd, pid, oid, i, sense, cdb_cont_len); goto out_hw_err; @@ -1797,7 +1889,8 @@ int osd_create_collection(struct osd_device *osd, uint64_t pid, } /* if cid already exists, obj_insert will fail */ - ret = obj_insert(osd->dbc, pid, cid, COLLECTION); + ret = obj_insert(osd->dbc, pid, cid, COLLECTION, + CIAP_LINKED_COLLECTION_TYPE); if (ret) goto out_cdb_err; @@ -1847,7 +1940,7 @@ int osd_create_partition(struct osd_device *osd, uint64_t requested_pid, osd_error("%s: panasas create %s directory %m", __func__,path); #endif /* if pid already exists, obj_insert will fail */ - ret = obj_insert(osd->dbc, pid, PARTITION_OID, PARTITION); + ret = obj_insert(osd->dbc, pid, PARTITION_OID, PARTITION, -1); if (ret) goto out_cdb_err; @@ -1887,7 +1980,7 @@ int osd_create_user_tracking_collection(struct osd_device *osd, uint64_t pid, int ret = 0; uint64_t cid = 0; int present = 0; - int to_do_1=0, to_do_2=0, to_do_3=0; + int to_do_1=0, to_do_2=0; osd_debug("%s: pid %llu requested_cid %llu source_cid %llu cdb_cont_len %u", __func__, llu(pid), llu(requested_cid), llu(source_cid), cdb_cont_len); @@ -1905,15 +1998,11 @@ int osd_create_user_tracking_collection(struct osd_device *osd, uint64_t pid, if (ret != OSD_OK || !present) goto out_cdb_err; - /* Make sure source collection is present */ - ret = obj_ispresent(osd->dbc, pid, source_cid, &present); - if (ret != OSD_OK || !present) - goto out_cdb_err; - - /* Checks on cdb_cont_len */ + /* Checks on cdb_cont_len - + disable check until descriptor processing is implemented if (((source_cid != 0) && (cdb_cont_len == 0)) || ((source_cid == 0) && (cdb_cont_len != 0))) goto out_cdb_err; - + */ /* to_do_1 = CDB continuation segment does not contain one extension capabilities CDB continuation descriptor(5.4.6) to_do_2 = CDB continuation segment contains any cdb continuation descriptor other than the extension capabilities CDB continuation descriptor */ @@ -1922,13 +2011,20 @@ int osd_create_user_tracking_collection(struct osd_device *osd, uint64_t pid, /* Checking validity of the source collection */ if (source_cid != 0) { + uint8_t obj_type, coll_type; + struct ctp* ctp; + + ret = obj_get_type(osd->dbc, pid, source_cid, + &obj_type, &coll_type); + if (ret != OSD_OK || obj_type != COLLECTION || + (coll_type != CIAP_LINKED_COLLECTION_TYPE && + coll_type != CIAP_TRACKING_COLLECTION_TYPE && + coll_type != CIAP_SPONTANEOUS_COLLECTION_TYPE)) + goto out_cdb_err; - if ((! is_linked_coll(source_cid)) && (! is_tracking_coll(source_cid)) && (! is_spontaneous_coll(source_cid))) - goto out_cdb_err; - - /* to_do_3 = the active command status attribute in the Command Tracking attribute page(7.1.3.20) is not set to zero*/ - else if (is_tracking_coll(source_cid) && to_do_3) - goto out_cdb_err; + ctp = find_ctp(pid, cid); + if (ctp && ctp->status != 0x0000) + goto out_cdb_err; } if (requested_cid == 0) { @@ -1968,7 +2064,8 @@ int osd_create_user_tracking_collection(struct osd_device *osd, uint64_t pid, } /* if cid already exists, obj_insert will fail */ - ret = obj_insert(osd->dbc, pid, cid, COLLECTION); + ret = obj_insert(osd->dbc, pid, cid, COLLECTION, + CIAP_TRACKING_COLLECTION_TYPE); if (ret) goto out_cdb_err; @@ -2326,6 +2423,14 @@ int osd_getattr_list(struct osd_device *osd, uint64_t pid, uint64_t oid, ret = get_riap(osd, pid, oid, page, number, outbuf, outlen, listfmt, used_outlen); break; + case COLL_INFO_PG: + ret = get_ciap(osd, pid, oid, number, outbuf, + outlen, listfmt, used_outlen); + break; + case COLL_TRACKING_PG: + ret = get_ctp(osd, pid, oid, number, outbuf, + outlen, listfmt, used_outlen); + break; default: ret = mutiplex_getattr_list(osd, pid, oid, page, number, outbuf, outlen, @@ -2587,8 +2692,7 @@ int osd_list_collection(struct osd_device *osd, uint8_t list_attr, uint64_t add_len = 0; uint64_t cont_id = 0; - assert(osd && osd->root && osd->dbc && get_attr && outdata - && used_outlen && sense); + assert(osd && osd->root && osd->dbc && outdata && used_outlen && sense); if (alloc_len == 0) return 0; @@ -2598,12 +2702,10 @@ int osd_list_collection(struct osd_device *osd, uint8_t list_attr, memset(outdata, 0, 24); - if (list_attr == 0 && get_attr->sz != 0) - goto out_cdb_err; /* XXX: unimplemented */ - if (list_attr == 1 && get_attr->sz == 0) + if (list_attr == 1 && get_attr && get_attr->sz == 0) goto out_cdb_err; /* XXX: this seems like error? */ - if (list_attr == 0 && get_attr->sz == 0) { + if (list_attr == 0) { /* * If list_id is not 0, we are continuing * an old list, starting from cont_id @@ -2841,7 +2943,8 @@ static int parse_query_criteria(const uint8_t *cp, uint32_t qll, int osd_query(struct osd_device *osd, uint64_t pid, uint64_t cid, uint32_t query_list_len, uint64_t alloc_len, const void *indata, - void *outdata, uint64_t *used_outlen, uint32_t cdb_cont_len, uint8_t *sense) + void *outdata, uint64_t *used_outlen, uint32_t cdb_cont_len, + uint8_t immed_tr, uint64_t matches_cid, uint8_t *sense) { int ret = 0; int present = 0; @@ -2858,9 +2961,11 @@ int osd_query(struct osd_device *osd, uint64_t pid, uint64_t cid, .max_len = NULL, .max_val = NULL, }; + uint8_t obj_type, coll_type; + struct ctp* ctp; - osd_debug("%s pid %llu cid %llu query_list_len %u alloc_len %llu", - __func__, llu(pid), llu(cid), query_list_len, + osd_debug("%s pid %llu cid %llu matches_cid %llu query_list_len %u alloc_len %llu", + __func__, llu(pid), llu(cid), llu(matches_cid), query_list_len, llu(alloc_len)); assert(osd && osd->root && osd->dbc && indata && sense); @@ -2868,16 +2973,56 @@ int osd_query(struct osd_device *osd, uint64_t pid, uint64_t cid, if (pid < USEROBJECT_PID_LB) goto out_cdb_err; + if (cid == matches_cid) + goto out_cdb_err; + ret = obj_ispresent(osd->dbc, pid, cid, &present); if (ret != OSD_OK || !present) goto out_cdb_err; + /* As of osd2r04, the collection must be a tracking collection */ + ret = obj_get_type(osd->dbc, pid, cid, &obj_type, &coll_type); + if (ret != OSD_OK || obj_type != COLLECTION || + coll_type != CIAP_TRACKING_COLLECTION_TYPE) + goto out_cdb_err; + + ctp = find_ctp(pid, cid); + if (ctp && ctp->status != 0x0000) + goto out_cdb_err; + + ret = obj_ispresent(osd->dbc, pid, matches_cid, &present); + if (ret != OSD_OK || !present) + goto out_cdb_err; + + if (matches_cid) { + ret = obj_get_type(osd->dbc, pid, matches_cid, + &obj_type, &coll_type); + if (ret != OSD_OK || obj_type != COLLECTION || + coll_type != CIAP_TRACKING_COLLECTION_TYPE) + goto out_cdb_err; + + ctp = find_ctp(pid, matches_cid); + if (ctp && ctp->status != 0x0000) + goto out_cdb_err; + if (!ctp) + ctp = init_ctp(pid, matches_cid, OSD_QUERY); + if (!ctp) + goto out_cdb_err; + + /* remove members from matches collection */ + ret = coll_delete_cid(osd->dbc, pid, matches_cid); + if (ret != 0) + goto out_cdb_err; + } + if (immed_tr && !matches_cid) + goto out_cdb_err; + if (query_list_len < MINQLISTLEN) goto out_cdb_err; - if (alloc_len == 0) - return OSD_OK; - if (alloc_len < MIN_ML_LEN) + if (alloc_len < MIN_ML_LEN && matches_cid == 0) + goto out_cdb_err; + if (alloc_len != 0 && matches_cid != 0) goto out_cdb_err; ret = alloc_qc(&qc); @@ -2888,10 +3033,27 @@ int osd_query(struct osd_device *osd, uint64_t pid, uint64_t cid, if (ret != OSD_OK) goto out_cdb_err; - memset(cp+8, 0, 4); /* reserved area */ - cp[12] = (0x21 << 2); + if (alloc_len) { + memset(cp+8, 0, 4); /* reserved area */ + cp[12] = (0x21 << 2); + } + + if (immed_tr) { + /* TODO - when immed_tr is set, we should start the + query in the background and return right away. We + need multithreading support to make this work, so + we'll just wait for the query to finish. */ + } + ret = mtq_run_query(osd->dbc, pid, cid, &qc, outdata, alloc_len, - used_outlen); + used_outlen, matches_cid); + if (matches_cid != 0) { + ctp->status = ret; + if (ret) + sense_build_sdd(ctp->sense, OSD_SSK_HARDWARE_ERROR, + OSD_ASC_INVALID_FIELD_IN_CDB, pid, cid); + } + free_qc(&qc); if (ret != OSD_OK) goto out_hw_err; @@ -3378,7 +3540,7 @@ int osd_remove_collection(struct osd_device *osd, uint64_t pid, uint64_t cid, ret = coll_delete_cid(osd->dbc, pid, cid); if (ret != 0) - goto out_hw_err; + goto out_hw_err; } ret = attr_delete_all(osd->dbc, pid, cid); diff --git a/osd-target/osd.h b/osd-target/osd.h index c297075..b135148 100644 --- a/osd-target/osd.h +++ b/osd-target/osd.h @@ -93,7 +93,8 @@ int osd_punch(struct osd_device *osd, uint64_t pid, uint64_t oid, uint64_t len, uint64_t offset, uint32_t cdb_cont_len, uint8_t *sense); int osd_query(struct osd_device *osd, uint64_t pid, uint64_t cid, uint32_t query_list_len, uint64_t alloc_len, const void *indata, - void *outdata, uint64_t *used_outlen, uint32_t cdb_cont_len, uint8_t *sense); + void *outdata, uint64_t *used_outlen, uint32_t cdb_cont_len, + uint8_t immed_tr, uint64_t matches_cid, uint8_t *sense); int osd_read(struct osd_device *osd, uint64_t pid, uint64_t uid, uint64_t len, uint64_t offset, const uint8_t *indata, uint8_t *outdata, uint64_t *outlen, const struct sg_list *sglist, uint8_t *sense, uint8_t ddt); diff --git a/osd-target/osd.schema b/osd-target/osd.schema index 230413c..105cf3d 100644 --- a/osd-target/osd.schema +++ b/osd-target/osd.schema @@ -23,6 +23,7 @@ CREATE TABLE obj ( pid INTEGER NOT NULL, oid INTEGER NOT NULL, type INTEGER NOT NULL, + coll_type INTEGER NOT NULL, PRIMARY KEY (pid, oid) ); diff --git a/osd-target/tests/command.c b/osd-target/tests/command.c index ae3a7d0..4904f6b 100644 --- a/osd-target/tests/command.c +++ b/osd-target/tests/command.c @@ -149,6 +149,19 @@ int osd_command_set_create_partition(struct osd_command *command, } +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) { @@ -1413,7 +1426,7 @@ int osd_command_list_resolve(struct osd_command *command) int i, listoid, list_attr; listoid = (p[23] & 0x40); - char title[3]; + char title[4]; (listoid ? strcpy(title, "OID") : strcpy(title, "PID")); if (p[23] & 0x08) @@ -1463,7 +1476,7 @@ int osd_command_list_collection_resolve(struct osd_command *command) int i, listoid, list_attr; listoid = (p[23] & 0x80); - char title[3]; + char title[4]; (listoid ? strcpy(title, "OID") : strcpy(title, "CID")); if (p[23] & 0x08) diff --git a/osd-target/tests/command.h b/osd-target/tests/command.h index 115f893..e5ee95f 100644 --- a/osd-target/tests/command.h +++ b/osd-target/tests/command.h @@ -103,6 +103,10 @@ 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, diff --git a/osd-target/tests/db-test.c b/osd-target/tests/db-test.c index 2ecdb02..4071a01 100644 --- a/osd-target/tests/db-test.c +++ b/osd-target/tests/db-test.c @@ -32,7 +32,7 @@ static void test_obj(struct osd_device *osd) { int ret = 0; - ret = obj_insert(osd->dbc, 1, 2, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 2, USEROBJECT, -1); assert(ret == 0); ret = obj_delete(osd->dbc, 1, 2); @@ -43,11 +43,11 @@ static void test_dup_obj(struct osd_device *osd) { int ret = 0; - ret = obj_insert(osd->dbc, 1, 2, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 2, USEROBJECT, -1); assert(ret == 0); /* duplicate insert must fail */ - ret = obj_insert(osd->dbc, 1, 2, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 2, USEROBJECT, -1); assert(ret != 0); ret = obj_delete(osd->dbc, 1, 2); @@ -98,7 +98,7 @@ static void test_obj_manip(struct osd_device *osd) int present = 0; for (i =0; i < 4; i++) { - ret = obj_insert(osd->dbc, 1, 1<dbc, 1, 1<dbc, 1, 235, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 235, USEROBJECT, -1); assert(ret == 0); /* existing object, ret == 1 */ @@ -138,7 +138,7 @@ static void test_pid_isempty(struct osd_device *osd) int ret = 0; int isempty = 0; - ret = obj_insert(osd->dbc, 1, 1, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 1, USEROBJECT, -1); assert(ret == 0); /* pid is not empty, ret should be 0 */ @@ -157,26 +157,29 @@ static void test_get_obj_type(struct osd_device *osd) { int ret = 0; uint8_t obj_type = ILLEGAL_OBJ; + uint8_t coll_type = -1; - ret = obj_insert(osd->dbc, 1, 1, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 1, USEROBJECT, -1); assert(ret == 0); - ret = obj_insert(osd->dbc, 2, 2, COLLECTION); + ret = obj_insert(osd->dbc, 2, 2, COLLECTION, + CIAP_LINKED_COLLECTION_TYPE); assert(ret == 0); - ret = obj_insert(osd->dbc, 3, 0, PARTITION); + ret = obj_insert(osd->dbc, 3, 0, PARTITION, -1); assert(ret == 0); - ret = obj_get_type(osd->dbc, 0, 0, &obj_type); + ret = obj_get_type(osd->dbc, 0, 0, &obj_type, NULL); assert(ret == 0 && obj_type == ROOT); - ret = obj_get_type(osd->dbc, 1, 1, &obj_type); + ret = obj_get_type(osd->dbc, 1, 1, &obj_type, NULL); assert(ret == 0 && obj_type == USEROBJECT); - ret = obj_get_type(osd->dbc, 2, 2, &obj_type); - assert(ret == 0 && obj_type == COLLECTION); + ret = obj_get_type(osd->dbc, 2, 2, &obj_type, &coll_type); + assert(ret == 0 && obj_type == COLLECTION && + coll_type == CIAP_LINKED_COLLECTION_TYPE); - ret = obj_get_type(osd->dbc, 3, 0, &obj_type); + ret = obj_get_type(osd->dbc, 3, 0, &obj_type, NULL); assert(ret == 0 && obj_type == PARTITION); ret = obj_delete(osd->dbc, 3, 0); @@ -189,7 +192,7 @@ static void test_get_obj_type(struct osd_device *osd) assert(ret == 0); /* non-existing object's type must be ILLEGAL_OBJ */ - ret = obj_get_type(osd->dbc, 1, 1, &obj_type); + ret = obj_get_type(osd->dbc, 1, 1, &obj_type, NULL); assert(ret == 0 && obj_type == ILLEGAL_OBJ); } @@ -217,7 +220,7 @@ static void test_dir_page(struct osd_device *osd) delete_obj(osd, 1, 1); - ret = obj_insert(osd->dbc, 1, 1, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 1, USEROBJECT, -1); assert(ret == 0); val = 44; diff --git a/osd-target/tests/osd-test.c b/osd-target/tests/osd-test.c index 15ee427..23c5572 100644 --- a/osd-target/tests/osd-test.c +++ b/osd-target/tests/osd-test.c @@ -1091,18 +1091,55 @@ static void check_results(void *ml, uint64_t *idlist, uint64_t sz, memset(idlist, 0, sz*sizeof(*idlist)); } +static void osd_query_wrapper(struct osd_device *osd, uint64_t pid, uint64_t cid, + uint32_t query_list_len, const void *indata, + void *matcheslist, uint64_t matches_cid, + uint8_t *sense, uint64_t *idlist, uint64_t idsz) +{ + uint32_t cdb_cont_len = 0; + uint64_t usedlen = 0; + uint64_t add_len; + int ret = 0; + + if (matches_cid) { + uint8_t *cp = matcheslist; + ret = osd_query(osd, pid, cid, query_list_len, 0, indata, + matcheslist, &usedlen, cdb_cont_len, 0, + matches_cid, sense); + ret = osd_list_collection(osd, 0, pid, matches_cid, 4096, + 0, NULL, 0, matcheslist, + &usedlen, sense); + /* get rid of LIST header and replace with QUERY header */ + usedlen -= 24; + usedlen += 13; + add_len = get_ntohll(&cp[0]); + matcheslist = cp = cp+24-13; + set_htonll(&cp[0], add_len-24+13); + cp[12] = 0x21 << 2; + } else { + ret = osd_query(osd, pid, cid, query_list_len, 4096, indata, + matcheslist, &usedlen, cdb_cont_len, 0, + matches_cid, sense); + } + + assert(ret == 0); + + check_results(matcheslist, idlist, idsz, usedlen); +} + static void test_osd_query(struct osd_device *osd) { int ret = 0; + uint32_t cdb_cont_len = 0; uint64_t cid = 0; + uint64_t orig_cid = 0; + uint64_t matches_cid = 0; uint64_t oid = 0; uint64_t pid = 0; uint8_t *cp = NULL; uint64_t min = 0, max = 0; - uint64_t usedlen = 0; uint32_t page = USER_COLL_PG; uint32_t qll = 0; - uint32_t cdb_cont_len = 0; void *buf = Calloc(1, 1024); void *sense = Calloc(1, 1024); void *matcheslist = Calloc(1, 4096); @@ -1121,11 +1158,34 @@ static void test_osd_query(struct osd_device *osd) ret = osd_create_collection(osd, pid, 0, cdb_cont_len, sense); assert(ret == 0); - cid = COLLECTION_OID_LB + 10; - assert(osd->ccap.oid == cid); + cid = osd->ccap.oid; - /* set attributes */ oid = USEROBJECT_OID_LB; + + /* include some objects in the collection */ + page = USER_COLL_PG; + set_attr_int(osd, oid, page, 1, cid, sense); + set_attr_int(osd, oid+1, page, 1, cid, sense); + set_attr_int(osd, oid+3, page, 1, cid, sense); + set_attr_int(osd, oid+4, page, 1, cid, sense); + set_attr_int(osd, oid+5, page, 1, cid, sense); + set_attr_int(osd, oid+6, page, 1, cid, sense); + set_attr_int(osd, oid+7, page, 1, cid, sense); + set_attr_int(osd, oid+9, page, 1, cid, sense); + + /* as of osd2r04, queries must be done on user tracking collections */ + osd_create_user_tracking_collection(osd, pid, 0, cid, 1, sense); + orig_cid = cid; + cid = osd->ccap.oid; + matches_cid = 0; + + /* remove linked collection */ + ret = osd_remove_collection(osd, pid, orig_cid, 1, cdb_cont_len, sense); + assert(ret == 0); + + + do_again: + /* set attributes */ page = USEROBJECT_PG + LUN_PG_LB; set_attr_int(osd, oid, page, 1, 4, sense); set_attr_int(osd, oid+1, page, 1, 49, sense); @@ -1142,25 +1202,10 @@ static void test_osd_query(struct osd_device *osd) set_attr_int(osd, oid+9, page, 1, 1, sense); set_attr_int(osd, oid+9, page, 2, 19, sense); - /* include some objects in the collection */ - page = USER_COLL_PG; - set_attr_int(osd, oid, page, 1, cid, sense); - set_attr_int(osd, oid+1, page, 1, cid, sense); - set_attr_int(osd, oid+3, page, 1, cid, sense); - set_attr_int(osd, oid+4, page, 1, cid, sense); - set_attr_int(osd, oid+5, page, 1, cid, sense); - set_attr_int(osd, oid+6, page, 1, cid, sense); - set_attr_int(osd, oid+7, page, 1, cid, sense); - set_attr_int(osd, oid+9, page, 1, cid, sense); - /* 1: run without query criteria */ qll = MINQLISTLEN; memset(buf, 0, 1024); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); - idlist[0] = oid; idlist[1] = oid+1; idlist[2] = oid+3; @@ -1169,7 +1214,9 @@ static void test_osd_query(struct osd_device *osd) idlist[5] = oid+6; idlist[6] = oid+7; idlist[7] = oid+9; - check_results(matcheslist, idlist, 8, usedlen); + + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 8); /* 2: run one query without min/max constraints */ qll = 0; @@ -1180,14 +1227,11 @@ static void test_osd_query(struct osd_device *osd) set_qce(&cp[4], page, 2, 0, NULL, 0, NULL); qll += 4 + (4+4+4+2+2); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); - idlist[0] = oid+1; idlist[1] = oid+4; idlist[2] = oid+9; - check_results(matcheslist, idlist, 3, usedlen); + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 3); /* 3: run one query with criteria */ qll = 0; @@ -1201,15 +1245,13 @@ static void test_osd_query(struct osd_device *osd) set_qce(&cp[4], page, 1, sizeof(min), &min, sizeof(max), &max); qll += 4 + (4+4+4+2+sizeof(min)+2+sizeof(max)); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); - idlist[0] = oid+1; idlist[1] = oid+4; idlist[2] = oid+5; idlist[3] = oid+7; - check_results(matcheslist, idlist, 4, usedlen); + + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 4); /* 4: run union of two query criteria */ qll = 0; @@ -1234,12 +1276,10 @@ static void test_osd_query(struct osd_device *osd) qll += (4+4+4+2+sizeof(min)+2+sizeof(max)); cp += (4+4+4+2+sizeof(min)+2+sizeof(max)); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); idlist[0] = oid+3; idlist[1] = oid+6; - check_results(matcheslist, idlist, 2, usedlen); + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 2); /* 5: run intersection of 2 query criteria */ qll = 0; @@ -1264,13 +1304,10 @@ static void test_osd_query(struct osd_device *osd) qll += (4+4+4+2+sizeof(min)+2+sizeof(max)); cp += (4+4+4+2+sizeof(min)+2+sizeof(max)); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); - idlist[0] = oid+1; idlist[1] = oid+4; - check_results(matcheslist, idlist, 2, usedlen); + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 2); /* 6: run union of 3 query criteria, with missing min/max */ qll = 0; @@ -1301,14 +1338,12 @@ static void test_osd_query(struct osd_device *osd) qll += (4+4+4+2+0+2+sizeof(max)); cp += (4+4+4+2+0+2+sizeof(max)); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); idlist[3] = oid; idlist[4] = oid+1; idlist[5] = oid+6; idlist[2] = oid+9; - check_results(matcheslist, idlist, 4, usedlen); + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 4); /* set some attributes with text values */ oid = USEROBJECT_OID_LB; @@ -1348,16 +1383,14 @@ static void test_osd_query(struct osd_device *osd) qll += (4+4+4+2+2+2+5); cp += (4+4+4+2+2+2+5); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); idlist[3] = oid; idlist[4] = oid+1; idlist[0] = oid+4; idlist[1] = oid+5; idlist[5] = oid+6; idlist[2] = oid+7; - check_results(matcheslist, idlist, 6, usedlen); + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 6); /* 8: run intersection of 3 query criteria, with missing min/max */ qll = 0; @@ -1383,11 +1416,9 @@ static void test_osd_query(struct osd_device *osd) qll += (4+4+4+2+0+2+6); cp += (4+4+4+2+0+2+6); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); idlist[0] = oid+1; - check_results(matcheslist, idlist, 1, usedlen); + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 1); /* 9: run intersection of 2 query criteria with empty result */ qll = 0; @@ -1410,15 +1441,25 @@ static void test_osd_query(struct osd_device *osd) qll += (4+4+4+2+sizeof(min)+2+sizeof(max)); cp += (4+4+4+2+sizeof(min)+2+sizeof(max)); - ret = osd_query(osd, pid, cid, qll, 4096, buf, matcheslist, &usedlen, - cdb_cont_len, sense); - assert(ret == 0); - check_results(matcheslist, idlist, 0, usedlen); + osd_query_wrapper(osd, pid, cid, qll, buf, matcheslist, + matches_cid, sense, idlist, 0); + + if (matches_cid == 0) { + osd_create_user_tracking_collection(osd, pid, 0, 0, 0, sense); + matches_cid = osd->ccap.oid; + goto do_again; + } /* remove collection */ ret = osd_remove_collection(osd, pid, cid, 1, cdb_cont_len, sense); assert(ret == 0); + if (matches_cid != 0) { + ret = osd_remove_collection(osd, pid, matches_cid, + 1, cdb_cont_len, sense); + assert(ret == 0); + } + /* remove objects */ for (oid = USEROBJECT_OID_LB; oid < (USEROBJECT_OID_LB+10); oid++) { ret = osd_remove(osd, USEROBJECT_PID_LB, oid, cdb_cont_len, sense); diff --git a/osd-target/tests/query.c b/osd-target/tests/query.c index 18da781..a314db3 100644 --- a/osd-target/tests/query.c +++ b/osd-target/tests/query.c @@ -76,7 +76,10 @@ static void query_speed(struct osd_device *osd, int numiter, int numobj, osd_command_set_create_partition(&c, pid); run(osd, &c); - osd_command_set_create_collection(&c, pid, cid); + osd_command_set_create_collection(&c, pid, cid+1); + run(osd, &c); + + osd_command_set_create_user_tracking_collection(&c, pid, cid, cid+1); run(osd, &c); for (i=0; idbc, 1, 2, 128); + ret = obj_insert(osd->dbc, 1, 2, 128, -1); assert(ret == 0); ret = obj_delete(osd->dbc, 1, 2); assert(ret == 0); @@ -180,7 +180,7 @@ static void time_obj_insert(struct osd_device *osd, int numobj, int numiter, t[i] = 0.0; for (j = 0; j < numobj; j++) { rdtsc(start); - ret = obj_insert(osd->dbc, 1, j, 128); + ret = obj_insert(osd->dbc, 1, j, 128, -1); rdtsc(end); assert(ret == 0); @@ -192,13 +192,13 @@ static void time_obj_insert(struct osd_device *osd, int numobj, int numiter, } } else if (testone == 1) { for (i = 0; i < numobj; i++) { - ret = obj_insert(osd->dbc, 1, i, 1); + ret = obj_insert(osd->dbc, 1, i, 1, -1); assert(ret == 0); } for (i = 0; i < numiter; i++) { rdtsc(start); - ret = obj_insert(osd->dbc, 1, numobj, 128); + ret = obj_insert(osd->dbc, 1, numobj, 128, -1); rdtsc(end); assert(ret == 0); @@ -233,7 +233,7 @@ static void time_obj_delete(struct osd_device *osd, int numobj, int numiter, if (!t) return; - ret = obj_insert(osd->dbc, 1, 2, 128); + ret = obj_insert(osd->dbc, 1, 2, 128, -1); assert(ret == 0); ret = obj_delete(osd->dbc, 1, 2); assert(ret == 0); @@ -241,7 +241,7 @@ static void time_obj_delete(struct osd_device *osd, int numobj, int numiter, if (testone == 0) { for (i = 0; i < numiter; i++) { for (j = 0; j < numobj; j++) { - ret = obj_insert(osd->dbc, 1, j, 128); + ret = obj_insert(osd->dbc, 1, j, 128, -1); assert(ret == 0); } @@ -258,12 +258,12 @@ static void time_obj_delete(struct osd_device *osd, int numobj, int numiter, } } else if (testone == 1) { for (i = 0; i < numobj; i++) { - ret = obj_insert(osd->dbc, 1, i, 128); + ret = obj_insert(osd->dbc, 1, i, 128, -1); assert (ret == 0); } for (i = 0; i < numiter; i++) { - ret = obj_insert(osd->dbc, 1, numobj, 128); + ret = obj_insert(osd->dbc, 1, numobj, 128, -1); assert(ret == 0); rdtsc(start); @@ -298,14 +298,14 @@ static void time_obj_delpid(struct osd_device *osd, int numobj, int numiter) if (!t) return; - ret = obj_insert(osd->dbc, 1, 2, 128); + ret = obj_insert(osd->dbc, 1, 2, 128, -1); assert(ret == 0); ret = obj_delete_pid(osd->dbc, 1); assert(ret == 0); for (i = 0; i < numiter; i++) { for (j = 0; j < numobj; j++) { - ret = obj_insert(osd->dbc, 1, j, 128); + ret = obj_insert(osd->dbc, 1, j, 128, -1); assert(ret == 0); } @@ -357,7 +357,7 @@ static void time_obj_generic(struct osd_device *osd, int numobj, int numiter, /* run a pilot */ switch (test) { case 1: { - ret = obj_insert(osd->dbc, 20, 0, 2); + ret = obj_insert(osd->dbc, 20, 0, 2, -1); assert(ret == 0); pid = 0; ret = obj_get_nextpid(osd->dbc, &pid); @@ -369,7 +369,7 @@ static void time_obj_generic(struct osd_device *osd, int numobj, int numiter, break; } case 2: { - ret = obj_insert(osd->dbc, 1, 2, 128); + ret = obj_insert(osd->dbc, 1, 2, 128, -1); assert(ret == 0); oid = 0; ret = obj_get_nextoid(osd->dbc, 1, &oid); @@ -382,7 +382,7 @@ static void time_obj_generic(struct osd_device *osd, int numobj, int numiter, } case 3: case 4: { - ret = obj_insert(osd->dbc, 1, 2, 128); + ret = obj_insert(osd->dbc, 1, 2, 128, -1); assert(ret == 0); ret = obj_ispresent(osd->dbc, 1, 2, &present); assert(ret == 0 && present == 1); @@ -397,7 +397,7 @@ static void time_obj_generic(struct osd_device *osd, int numobj, int numiter, break; } case 5: { - ret = obj_insert(osd->dbc, 1, 2, 128); + ret = obj_insert(osd->dbc, 1, 2, 128, -1); assert(ret == 0); ret = obj_isempty_pid(osd->dbc, 1, &isempty); assert(ret == 0 && isempty == 0); @@ -409,9 +409,9 @@ static void time_obj_generic(struct osd_device *osd, int numobj, int numiter, break; } case 6: { - ret = obj_insert(osd->dbc, 1, 2, USEROBJECT); + ret = obj_insert(osd->dbc, 1, 2, USEROBJECT, -1); assert(ret == 0); - ret = obj_get_type(osd->dbc, 1, 2, &obj_type); + ret = obj_get_type(osd->dbc, 1, 2, &obj_type, NULL); assert(ret == 0 && obj_type == USEROBJECT); ret = obj_delete(osd->dbc, 1, 2); assert(ret == 0); @@ -426,9 +426,9 @@ static void time_obj_generic(struct osd_device *osd, int numobj, int numiter, for (i = 0; i < numiter; i++) { for (j = 1; j < numobj+1; j++) { if (test == 1) { - ret = obj_insert(osd->dbc, j, 0, PARTITION); + ret = obj_insert(osd->dbc, j, 0, PARTITION, -1); } else { - ret = obj_insert(osd->dbc, 1, j, USEROBJECT); + ret = obj_insert(osd->dbc, 1, j, USEROBJECT, -1); } assert(ret == 0); } @@ -478,7 +478,7 @@ static void time_obj_generic(struct osd_device *osd, int numobj, int numiter, case 6: { oid = numobj; rdtsc(start); - ret = obj_get_type(osd->dbc, 1, oid, &obj_type); + ret = obj_get_type(osd->dbc, 1, oid, &obj_type, NULL); rdtsc(end); assert(ret == 0 && obj_type == USEROBJECT); break; @@ -553,7 +553,7 @@ static void time_obj_fetch(struct osd_device *osd, int numobj, int numiter, /* run pilot tests */ switch (test) { case 1: { - ret = obj_insert(osd->dbc, 20, 11, 128); + ret = obj_insert(osd->dbc, 20, 11, 128, -1); assert(ret == 0); ret = obj_get_oids_in_pid(osd->dbc, 20, 0, sizeof(*ids)*1, cp, &usedlen, &addlen, &contid); @@ -569,7 +569,7 @@ static void time_obj_fetch(struct osd_device *osd, int numobj, int numiter, break; } case 2: { - ret = obj_insert(osd->dbc, 20, 11, 64); + ret = obj_insert(osd->dbc, 20, 11, 64, -1); assert(ret == 0); ret = obj_get_cids_in_pid(osd->dbc, 20, 0, sizeof(*ids)*1, cp, &usedlen, &addlen, &contid); @@ -586,9 +586,9 @@ static void time_obj_fetch(struct osd_device *osd, int numobj, int numiter, } case 3: case 4: { - ret = obj_insert(osd->dbc, 20, 0, 2); + ret = obj_insert(osd->dbc, 20, 0, 2, -1); assert(ret == 0); - ret = obj_insert(osd->dbc, 10, 0, 2); + ret = obj_insert(osd->dbc, 10, 0, 2, -1); assert(ret == 0); ret = obj_get_all_pids(osd->dbc, 0, sizeof(*ids)*2, cp, &usedlen, &addlen, &contid); @@ -622,10 +622,11 @@ static void time_obj_fetch(struct osd_device *osd, int numobj, int numiter, for (j = 0; j < numobj; j++) { if (test == 1) { ret = obj_insert(osd->dbc, 1, j, - USEROBJECT); + USEROBJECT, -1); } else { ret = obj_insert(osd->dbc, 1, j, - COLLECTION); + COLLECTION, + CIAP_LINKED_COLLECTION_TYPE); } assert(ret == 0); } @@ -656,7 +657,7 @@ static void time_obj_fetch(struct osd_device *osd, int numobj, int numiter, case 3: for (j = 0; j < numobj; j++) { ret = obj_insert(osd->dbc, j+1, 0, - PARTITION); + PARTITION, -1); assert(ret == 0); } cp = (uint8_t *)ids; @@ -679,11 +680,11 @@ static void time_obj_fetch(struct osd_device *osd, int numobj, int numiter, if (numobj % 32 != 0) numpid++; for (j = 0; j < numpid; j++) { - ret = obj_insert(osd->dbc, j+1, 0, PARTITION); + ret = obj_insert(osd->dbc, j+1, 0, PARTITION, -1); assert(ret == 0); for (k = 1; k < 32+1; k++) { ret = obj_insert(osd->dbc, j+1, k, - USEROBJECT); + USEROBJECT, -1); assert(ret == 0); } } diff --git a/osd-util/osd-defs.h b/osd-util/osd-defs.h index 66b42df..a896abe 100644 --- a/osd-util/osd-defs.h +++ b/osd-util/osd-defs.h @@ -186,16 +186,28 @@ enum { ROOT_DIR_PG = (ROOT_PG + 0x0) }; +/* attribute page offsets defined by osd spec, osd2r03 sec 7.1.2.1 */ +enum { + DIR_OFFSET = 0x0, + INFO_OFFSET = 0x1, + QUOTA_OFFSET = 0x2, + TMSTMP_OFFSET = 0x3, + POLICY_OFFSET = 0x5, + RECOVERY_OFFSET = 0x6, +}; + /* (selected) attribute pages defined by osd spec, osd2r01 sec 7.1.2.1 */ enum { - USER_DIR_PG = 0x0, - USER_INFO_PG = 0x1, - ROOT_INFO_PG = (ROOT_PG + 0x1), - USER_QUOTA_PG = 0x2, - USER_TMSTMP_PG = 0x3, - USER_COLL_PG = 0x4, - USER_POLICY_PG = 0x5, - USER_ATOMICS_PG = 0x6, + USER_DIR_PG = (USEROBJECT_PG + DIR_OFFSET), + USER_INFO_PG = (USEROBJECT_PG + INFO_OFFSET), + USER_QUOTA_PG = (USEROBJECT_PG + QUOTA_OFFSET), + USER_TMSTMP_PG = (USEROBJECT_PG + TMSTMP_OFFSET), + USER_COLL_PG = (USEROBJECT_PG + 0x4), + USER_POLICY_PG = (USEROBJECT_PG + POLICY_OFFSET), + USER_ATOMICS_PG = (USEROBJECT_PG + 0x7), /* non-standard */ + ROOT_INFO_PG = (ROOT_PG + INFO_OFFSET), + COLL_INFO_PG = (COLLECTION_PG + INFO_OFFSET), + COLL_TRACKING_PG = (COLLECTION_PG + 0x4), /* osd2r04 7.1.3.1 */ }; /* in all attribute pages, attribute number 0 is a 40-byte identification */ @@ -298,6 +310,30 @@ enum { RIAP_CLOCK_LEN = 6, }; +/* Collection information attribute page osd2r05 sec 7.1.3.10 */ +enum { + /* attributes */ + CIAP_PARTITION_ID = 0x1, /* 8 */ + CIAP_COLLECTION_OBJECT_ID = 0x2, /* 8 */ + CIAP_COLLECTION_NAME = 0x9, /* variable */ + CIAP_COLLECTION_TYPE = 0xA, /* 1 */ + CIAP_USED_CAPACITY = 0x81, /* 8 */ + + /* lengths */ + CIAP_PARTITION_ID_LEN = 8, + CIAP_COLLECTION_OBJECT_ID_LEN = 8, + CIAP_COLLECTION_NAME_LEN = 0, //variable + CIAP_COLLECTION_TYPE_LEN = 1, + CIAP_USED_CAPACITY_LEN = 8, +}; + +/* CIAP collection type osd2r05 sec 7.1.3.10 table 169 */ +enum { + CIAP_LINKED_COLLECTION_TYPE = 0x00, + CIAP_TRACKING_COLLECTION_TYPE = 0x01, + CIAP_SPONTANEOUS_COLLECTION_TYPE = 0xEF, +}; + /* userobject collections attribute page osd2r01 Sec 7.1.2.19 */ enum { UCAP_COLL_PTR_LB = 0x1, @@ -310,6 +346,18 @@ enum { UAP_FA = 0x2, }; +/* command tracking page osd2r04 Sec 7.1.3.20 */ +enum { + CTP_PERCENT_COMPLETE = 0x1, /* 1 */ + CTP_ACTIVE_COMMAND_STATUS = 0x2, /* 2 */ + CTP_ENDED_COMMAND_STATUS = 0x3, /* 2 */ + CTP_SENSE_DATA = 0x4, /* 0 or n */ + CTP_NUMBER_OF_MEMBERS = 0x10, /* 8 */ + CTP_OBJECTS_PROCESSED = 0x11, /* 0 or 8 */ + CTP_NEWER_OBJECTS_SKIPPED = 0x12, /* 0 or 8 */ + CTP_MISSING_OBJECTS_SKIPPED = 0x13, /* 0 or 8 */ +}; + enum { GETFIELD_SETVALUE = 0x1, GETPAGE_SETVALUE = 0x2,