summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Yao <[email protected]>2014-10-10 11:23:23 -0400
committerRichard Yao <[email protected]>2015-09-04 15:37:24 -0400
commitfa56567630cfad95b77dee507595d77f24e99cb9 (patch)
tree4d7c1c971fff66f18f0715d4a48edcdc26a4dd72
parent37f9dac592bf5889c3efb305c48ac39b4c7dd140 (diff)
Support secure discard on zvols
Linux 2.6.36 introduced REQ_SECURE to indicate when discards *must* be processed, such that we cannot do optimizations like block alignment. Consequently, the discard semantics prior to 2.6.36 require us to always process unaligned discards. Previously, we would do this optimization regardless. This patch changes things to correctly restrict this optimization to situations where REQ_SECURE exists, but is not included in the flags. Signed-off-by: Richard Yao <[email protected]>
-rw-r--r--module/zfs/zvol.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index 074ec51e6..492f8ff87 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -650,14 +650,19 @@ zvol_discard(struct bio *bio)
return (SET_ERROR(EIO));
/*
- * Align the request to volume block boundaries. If we don't,
- * then this will force dnode_free_range() to zero out the
- * unaligned parts, which is slow (read-modify-write) and
- * useless since we are not freeing any space by doing so.
- * XXX: We should handle secure discard by zeroing out unaligned parts.
+ * Align the request to volume block boundaries when REQ_SECURE is
+ * available, but not requested. If we don't, then this will force
+ * dnode_free_range() to zero out the unaligned parts, which is slow
+ * (read-modify-write) and useless since we are not freeing any space
+ * by doing so. Kernels that do not support REQ_SECURE (2.6.32 through
+ * 2.6.35) will not receive this optimization.
*/
- start = P2ROUNDUP(start, zv->zv_volblocksize);
- end = P2ALIGN(end, zv->zv_volblocksize);
+#ifdef REQ_SECURE
+ if (!(bio->bi_rw & REQ_SECURE)) {
+ start = P2ROUNDUP(start, zv->zv_volblocksize);
+ end = P2ALIGN(end, zv->zv_volblocksize);
+ }
+#endif
if (start >= end)
return (0);