Re: [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]

 





On 5/28/20 2:31 PM, Bodo Stroesser wrote:
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));


Acked-by: Mike Christie <michael.christie@xxxxxxxxxx>



[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