diff --git a/kernel/persist.c b/kernel/persist.c index a8d73da..f88b2ed 100644 --- a/kernel/persist.c +++ b/kernel/persist.c @@ -44,15 +44,13 @@ static void pr_in_report_capabilities(struct iscsi_cmnd *cmnd, u16 allocation_length) { - struct tio *tio = tio_alloc(1); - u8 *data = page_address(tio->pvec[0]); + u8 *data = page_address(cmnd->tio->pvec[0]); const u32 min_len = min_t(u16, allocation_length, sizeof(pr_capabilities)); BUG_ON(!data); - cmnd->tio = tio; memcpy(data, &pr_capabilities, min_len); - tio_set(tio, min_len, 0); + tio_set(cmnd->tio, min_len, 0); dprintk_pr(cmnd, "ret len %u\n", min_len); } @@ -63,16 +61,13 @@ pr_in_read_reservation(struct iscsi_cmnd *cmnd, { struct iet_volume *volume = cmnd->lun; const struct reservation *reservation = &volume->reservation; - struct tio *tio = tio_alloc(1); struct pr_in_read_reservation_data *pin_data = - (struct pr_in_read_reservation_data *)page_address(tio->pvec[0]); + (struct pr_in_read_reservation_data *)page_address(cmnd->tio->pvec[0]); u32 size; BUG_ON(!pin_data); memset(pin_data, 0x0, sizeof(*pin_data)); - cmnd->tio = tio; - spin_lock(&volume->reserve_lock); pin_data->generation = cpu_to_be32(reservation->generation); @@ -102,7 +97,7 @@ pr_in_read_reservation(struct iscsi_cmnd *cmnd, spin_unlock(&volume->reserve_lock); - tio_set(tio, min_t(u32, size, allocation_length), 0); + tio_set(cmnd->tio, min_t(u32, size, allocation_length), 0); } static void @@ -111,25 +106,17 @@ pr_in_read_full_status(struct iscsi_cmnd *cmnd, { struct iet_volume *volume = cmnd->lun; const struct reservation *reservation = &volume->reservation; - struct tio *tio = tio_alloc(get_pgcnt(allocation_length, 0)); struct tio_iterator tio_it; struct pr_in_read_full_status_data *pfull = - (struct pr_in_read_full_status_data *)page_address(tio->pvec[0]); + (struct pr_in_read_full_status_data *)page_address(cmnd->tio->pvec[0]); struct registration *reg; - u16 left = allocation_length - 8; + u16 left = (allocation_length > sizeof(*pfull)) ? + allocation_length - sizeof(*pfull) : + 0; u32 addl_data_len = 0; - if (allocation_length < 8) { - iscsi_cmnd_set_sense(cmnd, - ILLEGAL_REQUEST, - INVALID_FIELD_IN_CDB_ASC, - INVALID_FIELD_IN_CDB_ASCQ); - return; - } - - cmnd->tio = tio; - tio_init_iterator(tio, &tio_it); - tio_it.pg_off += 8; /* generation + additional length */ + tio_init_iterator(cmnd->tio, &tio_it); + tio_it.pg_off += sizeof(*pfull); spin_lock(&volume->reserve_lock); @@ -189,7 +176,7 @@ pr_in_read_full_status(struct iscsi_cmnd *cmnd, allocation_length - left); pfull->additional_length = cpu_to_be32(addl_data_len); - tio_set(tio, allocation_length - left, 0); + tio_set(cmnd->tio, allocation_length - left, 0); } static void @@ -198,25 +185,17 @@ pr_in_read_keys(struct iscsi_cmnd *cmnd, { struct iet_volume *volume = cmnd->lun; const struct reservation *reservation = &volume->reservation; - struct tio *tio = tio_alloc(get_pgcnt(allocation_length, 0)); struct tio_iterator tio_it; struct pr_in_read_keys_data *kdata = - (struct pr_in_read_keys_data *)page_address(tio->pvec[0]); + (struct pr_in_read_keys_data *)page_address(cmnd->tio->pvec[0]); struct registration *reg; - u16 left = allocation_length - 8; + u16 left = (allocation_length >= sizeof(*kdata)) ? + allocation_length - sizeof(*kdata) : + 0; u32 addl_data_len = 0; - if (allocation_length < 8) { - iscsi_cmnd_set_sense(cmnd, - ILLEGAL_REQUEST, - INVALID_FIELD_IN_CDB_ASC, - INVALID_FIELD_IN_CDB_ASCQ); - return; - } - - cmnd->tio = tio; - tio_init_iterator(tio, &tio_it); - tio_it.pg_off += 8; /* generation + additional length */ + tio_init_iterator(cmnd->tio, &tio_it); + tio_it.pg_off += sizeof(*kdata); spin_lock(&volume->reserve_lock); @@ -249,7 +228,7 @@ pr_in_read_keys(struct iscsi_cmnd *cmnd, allocation_length - left); kdata->additional_length = cpu_to_be32(addl_data_len); - tio_set(tio, allocation_length - left, 0); + tio_set(cmnd->tio, allocation_length - left, 0); dprintk_pr(cmnd, "keys[0]: %#Lx\n", kdata->keys[0]); @@ -271,6 +250,27 @@ build_persistent_reserve_in_response(struct iscsi_cmnd *cmnd) switch (action) { case SERVICE_ACTION_READ_KEYS: + case SERVICE_ACTION_READ_RESERVATION: + case SERVICE_ACTION_REPORT_CAPABILITIES: + case SERVICE_ACTION_READ_FULL_STATUS: + if (allocation_length == 0) + return; + cmnd->tio = tio_alloc(get_pgcnt(allocation_length, 0)); + break; + default: + eprintk("%#Lx:%hu: invalid PR In Service Action %x\n", + cmnd->conn->session->sid, + cmnd->conn->cid, + action); + iscsi_cmnd_set_sense(cmnd, + ILLEGAL_REQUEST, + INVALID_FIELD_IN_CDB_ASC, + INVALID_FIELD_IN_CDB_ASCQ); + return; + } + + switch (action) { + case SERVICE_ACTION_READ_KEYS: pr_in_read_keys(cmnd, allocation_length); break; case SERVICE_ACTION_READ_RESERVATION: @@ -282,12 +282,6 @@ build_persistent_reserve_in_response(struct iscsi_cmnd *cmnd) case SERVICE_ACTION_READ_FULL_STATUS: pr_in_read_full_status(cmnd, allocation_length); break; - default: - iscsi_cmnd_set_sense(cmnd, - ILLEGAL_REQUEST, - INVALID_FIELD_IN_CDB_ASC, - INVALID_FIELD_IN_CDB_ASCQ); - break; } } @@ -302,9 +296,10 @@ pr_out_register(struct iscsi_cmnd *cmnd, bool ignore) struct registration *reg; struct registration *new_reg = kzalloc(sizeof(*new_reg), GFP_KERNEL); - dprintk_pr(cmnd, "rkey %#Lx, skey %#Lx, ignore %d\n", + dprintk_pr(cmnd, "rkey %#Lx, skey %#Lx, spec_i_pt_all_tg_pt_aptl %x ignore %d\n", param->reservation_key, param->service_action_key, + param->spec_i_pt_all_tg_pt_aptl, ignore); if (!new_reg) { @@ -673,14 +668,42 @@ build_persistent_reserve_out_response(struct iscsi_cmnd *cmnd) (const struct persistent_reserve_out *)(cmnd_hdr(cmnd)->scb); const enum pr_out_service_actions action = pr_out->service_action & PR_SERVICE_ACTION_MASK; + const u32 param_list_length = be32_to_cpu(pr_out->parameter_list_length); dprintk_pr(cmnd, "svc action %x, scope_type %x, param len %u\n", action, pr_out->scope_type, - be32_to_cpu(pr_out->parameter_list_length)); + param_list_length); + + switch (action) { + case SERVICE_ACTION_REGISTER: + case SERVICE_ACTION_REGISTER_IGNORE: + case SERVICE_ACTION_RESERVE: + case SERVICE_ACTION_RELEASE: + case SERVICE_ACTION_CLEAR: + case SERVICE_ACTION_PREEMPT: + case SERVICE_ACTION_PREEMPT_ABORT: + break; + case SERVICE_ACTION_REGISTER_MOVE: + /* not implemented (yet) */ + default: + eprintk("%#Lx:%hu: invalid PR Out Service Action %x\n", + cmnd->conn->session->sid, + cmnd->conn->cid, + action); + iscsi_cmnd_set_sense(cmnd, + ILLEGAL_REQUEST, + INVALID_FIELD_IN_CDB_ASC, + INVALID_FIELD_IN_CDB_ASCQ); + return; + } - if ((pr_out->scope_type & PR_SCOPE_MASK)) { + if ((pr_out->scope_type & PR_SCOPE_MASK) != PR_SCOPE_LU) { + eprintk("%#Lx:%hu: invalid PR scope %x\n", + cmnd->conn->session->sid, + cmnd->conn->cid, + pr_out->scope_type & PR_SCOPE_MASK); iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB_ASC, @@ -688,7 +711,11 @@ build_persistent_reserve_out_response(struct iscsi_cmnd *cmnd) return; } - if (be32_to_cpu(pr_out->parameter_list_length) != 24) { + if (param_list_length < sizeof(struct pr_out_param_list)) { + eprintk("%#Lx:%hu: invalid PR Out parameter list length %d\n", + cmnd->conn->session->sid, + cmnd->conn->cid, + param_list_length); iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, PARAMETER_LIST_LENGTH_ERROR_ASC, @@ -722,11 +749,10 @@ build_persistent_reserve_out_response(struct iscsi_cmnd *cmnd) pr_out->scope_type & PR_TYPE_MASK, true); break; + case SERVICE_ACTION_REGISTER_MOVE: + /* not implemented (yet) */ default: - iscsi_cmnd_set_sense(cmnd, - ILLEGAL_REQUEST, - INVALID_FIELD_IN_CDB_ASC, - INVALID_FIELD_IN_CDB_ASCQ); - break; + /* not reachable due to the earlier switch stmt */ + BUG(); } } diff --git a/usr/types.h b/usr/types.h index c08d356..e9d1081 100644 --- a/usr/types.h +++ b/usr/types.h @@ -14,6 +14,7 @@ #include #if __BYTE_ORDER == __BIG_ENDIAN + #define cpu_to_le16(x) bswap_16(x) #define le16_to_cpu(x) bswap_16(x) #define cpu_to_le32(x) bswap_32(x) @@ -22,6 +23,9 @@ #define be16_to_cpu(x) (x) #define cpu_to_be32(x) (x) #define be32_to_cpu(x) (x) +#define cpu_to_be64(x) (x) +#define be64_to_cpu(x) (x) + #elif __BYTE_ORDER == __LITTLE_ENDIAN #define cpu_to_le16(x) (x) #define le16_to_cpu(x) (x) @@ -31,6 +35,9 @@ #define be16_to_cpu(x) bswap_16(x) #define cpu_to_be32(x) bswap_32(x) #define be32_to_cpu(x) bswap_32(x) +#define cpu_to_be64(x) bswap_64(x) +#define be64_to_cpu(x) bswap_64(x) + #else #error "unknown endianess!" #endif