Skip to content

Commit 8c4e0f2

Browse files
BStroessermartinkpetersen
authored andcommitted
scsi: target: tcmu: Fix size in calls to tcmu_flush_dcache_range
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. Link: https://lore.kernel.org/r/[email protected] Acked-by: Mike Christie <[email protected]> Signed-off-by: Bodo Stroesser <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 22617e2 commit 8c4e0f2

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

drivers/target/target_core_user.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
10071007
entry->hdr.cmd_id = 0; /* not used for PAD */
10081008
entry->hdr.kflags = 0;
10091009
entry->hdr.uflags = 0;
1010-
tcmu_flush_dcache_range(entry, sizeof(*entry));
1010+
tcmu_flush_dcache_range(entry, sizeof(entry->hdr));
10111011

10121012
UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size);
10131013
tcmu_flush_dcache_range(mb, sizeof(*mb));
@@ -1072,7 +1072,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
10721072
cdb_off = CMDR_OFF + cmd_head + base_command_size;
10731073
memcpy((void *) mb + cdb_off, se_cmd->t_task_cdb, scsi_command_size(se_cmd->t_task_cdb));
10741074
entry->req.cdb_off = cdb_off;
1075-
tcmu_flush_dcache_range(entry, sizeof(*entry));
1075+
tcmu_flush_dcache_range(entry, command_size);
10761076

10771077
UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
10781078
tcmu_flush_dcache_range(mb, sizeof(*mb));

0 commit comments

Comments
 (0)