From 8f8ea536e06d9e2d2fe191e5e460ab7da06f22bd Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 15 Jul 2010 12:45:31 +0000 Subject: [PATCH] - Logging cleanup - Added debug facility to catch possible data corruption case. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1827 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/scst_mem.c | 35 +++++++++++++++++++++++++++++++++++ scst/src/scst_targ.c | 14 ++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/scst/src/scst_mem.c b/scst/src/scst_mem.c index 4dfb519e0..0dee95ac8 100644 --- a/scst/src/scst_mem.c +++ b/scst/src/scst_mem.c @@ -1182,6 +1182,41 @@ void sgv_pool_free(struct sgv_pool_obj *obj, struct scst_mem_lim *mem_lim) TRACE_MEM("Freeing obj %p, cache num %d, pages %d, sg_entries %p, " "sg_count %d, allocator_priv %p", obj, obj->cache_num, pages, obj->sg_entries, obj->sg_count, obj->allocator_priv); + +/* + * Enable it if you are investigating a data corruption and want to make + * sure that target or dev handler didn't leave the pages mapped somewhere and, + * hence, provoked a data corruption. + * + * Make sure the check value for _count is set correctly. In most cases, 1 is + * correct, but, e.g., iSCSI-SCST can call it with value 2, because + * it frees the corresponding cmd before the last put_page() call from + * net_put_page() for the last page in the SG. Also, user space dev handlers + * usually have their memory mapped in their address space. + */ +#if 0 + { + struct scatterlist *sg = obj->sg_entries; + int i; + for (i = 0; i < obj->sg_count; i++) { + struct page *p = sg_page(&sg[i]); + int len = sg[i].length; + int pages = (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0); + while (pages > 0) { + if (atomic_read(&p->_count) != 1) { + PRINT_WARNING("Freeing page %p with " + "additional owners (_count %d). " + "Data corruption possible!", + p, atomic_read(&p->_count)); + WARN_ON(1); + } + pages--; + p++; + } + } + } +#endif + if (obj->cache_num >= 0) { obj->sg_entries[obj->orig_sg].length = obj->orig_length; sgv_put_obj(obj); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index a882ee92b..c9cf688fc 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -564,9 +564,19 @@ static int scst_parse_cmd(struct scst_cmd *cmd) goto out_done; } #else - PRINT_ERROR("Unknown opcode %x", cmd->cdb[0]); + /* + * Let's ignore reporting T10/04-262r7 16-byte and 12-byte ATA + * pass-thru commands to not pollute logs (udev(?) checks them + * for some reason). If somebody has their description, please, + * update scst_scsi_op_table. + */ + if ((cmd->cdb[0] != 0x85) && (cmd->cdb[0] != 0xa1)) + PRINT_ERROR("Refusing unknown opcode %x", cmd->cdb[0]); + else + TRACE(TRACE_MINOR, "Refusing unknown opcode %x", + cmd->cdb[0]); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_invalid_opcode)); + SCST_LOAD_SENSE(scst_sense_invalid_opcode)); goto out_done; #endif }