[PATCH] scsi: target: tcmu: fix size in calls to tcmu_flush_dcache_range

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



1) If remaining ring space before the end of the ring is
   smaller then the next cmd to write, tcmu writes a padding
   entry which fills the remaining space at the end of the
   ring.
   Then tcmu calls tcmu_flush_dcache_range() with the size
   of struct tcmu_cmd_entry as data length to flush.
   If the space filled by the padding was smaller then
   tcmu_cmd_entry, tcmu_flush_dcache_range() is called for
   an address range reaching behind the end of the vmalloc'ed
   ring.
   tcmu_flush_dcache_range() in a loop calls
      flush_dcache_page(virt_to_page(start));
   for every page being part of the range. On x86 the line is
   optimized out by the compiler, as flush_dcache_page() is
   empty on x86.
   But I assume the above can cause trouble on other
   architectures that really have a flush_dcache_page().
   For paddings only the header part of an entry is relevant
   Due to alignment rules the header always fits in the
   remaining space, if padding is needed.
   So tcmu_flush_dcache_range() can safely be called with
   sizeof(entry->hdr) as the length here.

2) After it has written a command to cmd ring, tcmu calls
   tcmu_flush_dcache_range() using the size of a struct
   tcmu_cmd_entry as data length to flush.
   But if a command needs many iovecs, the real size of the
   command may be bigger then tcmu_cmd_entry, so a part of
   the written command is not flushed then.

Signed-off-by: Bodo Stroesser <bstroesser@xxxxxxxxxxxxxx>
---
 drivers/target/target_core_user.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index f769bb1e3735..cdb4848d23c6 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -1026,7 +1026,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
 		entry->hdr.cmd_id = 0; /* not used for PAD */
 		entry->hdr.kflags = 0;
 		entry->hdr.uflags = 0;
-		tcmu_flush_dcache_range(entry, sizeof(*entry));
+		tcmu_flush_dcache_range(entry, sizeof(entry->hdr));
 
 		UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size);
 		tcmu_flush_dcache_range(mb, sizeof(*mb));
@@ -1084,7 +1084,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
 	cdb_off = CMDR_OFF + cmd_head + base_command_size;
 	memcpy((void *) mb + cdb_off, se_cmd->t_task_cdb, scsi_command_size(se_cmd->t_task_cdb));
 	entry->req.cdb_off = cdb_off;
-	tcmu_flush_dcache_range(entry, sizeof(*entry));
+	tcmu_flush_dcache_range(entry, command_size);
 
 	UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
 	tcmu_flush_dcache_range(mb, sizeof(*mb));
-- 
2.12.3




[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux