From: Greg Kroah-Hartman Date: Tue, 13 May 2014 23:54:13 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.4.91~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=73ff01bada3473e65b5fe1acdf1184246e63ec6b;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: blktrace-fix-accounting-of-partially-completed-requests.patch netfilter-nf_tables-fix-nft_cmp_fast-failure-on-big-endian-for-size-4.patch --- diff --git a/queue-3.14/blktrace-fix-accounting-of-partially-completed-requests.patch b/queue-3.14/blktrace-fix-accounting-of-partially-completed-requests.patch new file mode 100644 index 00000000000..03b1d0aa9cc --- /dev/null +++ b/queue-3.14/blktrace-fix-accounting-of-partially-completed-requests.patch @@ -0,0 +1,181 @@ +From af5040da01ef980670b3741b3e10733ee3e33566 Mon Sep 17 00:00:00 2001 +From: Roman Pen +Date: Tue, 4 Mar 2014 23:13:10 +0900 +Subject: blktrace: fix accounting of partially completed requests + +From: Roman Pen + +commit af5040da01ef980670b3741b3e10733ee3e33566 upstream. + +trace_block_rq_complete does not take into account that request can +be partially completed, so we can get the following incorrect output +of blkparser: + + C R 232 + 240 [0] + C R 240 + 232 [0] + C R 248 + 224 [0] + C R 256 + 216 [0] + +but should be: + + C R 232 + 8 [0] + C R 240 + 8 [0] + C R 248 + 8 [0] + C R 256 + 8 [0] + +Also, the whole output summary statistics of completed requests and +final throughput will be incorrect. + +This patch takes into account real completion size of the request and +fixes wrong completion accounting. + +Signed-off-by: Roman Pen +CC: Steven Rostedt +CC: Frederic Weisbecker +CC: Ingo Molnar +CC: linux-kernel@vger.kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + block/blk-core.c | 2 +- + include/trace/events/block.h | 33 ++++++++++++++++++++++++++++++--- + kernel/trace/blktrace.c | 20 +++++++++++--------- + 3 files changed, 42 insertions(+), 13 deletions(-) + +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -2353,7 +2353,7 @@ bool blk_update_request(struct request * + if (!req->bio) + return false; + +- trace_block_rq_complete(req->q, req); ++ trace_block_rq_complete(req->q, req, nr_bytes); + + /* + * For fs requests, rq is just carrier of independent bio's +--- a/include/trace/events/block.h ++++ b/include/trace/events/block.h +@@ -132,6 +132,7 @@ DEFINE_EVENT(block_rq_with_error, block_ + * block_rq_complete - block IO operation completed by device driver + * @q: queue containing the block operation request + * @rq: block operations request ++ * @nr_bytes: number of completed bytes + * + * The block_rq_complete tracepoint event indicates that some portion + * of operation request has been completed by the device driver. If +@@ -139,11 +140,37 @@ DEFINE_EVENT(block_rq_with_error, block_ + * do for the request. If @rq->bio is non-NULL then there is + * additional work required to complete the request. + */ +-DEFINE_EVENT(block_rq_with_error, block_rq_complete, ++TRACE_EVENT(block_rq_complete, + +- TP_PROTO(struct request_queue *q, struct request *rq), ++ TP_PROTO(struct request_queue *q, struct request *rq, ++ unsigned int nr_bytes), + +- TP_ARGS(q, rq) ++ TP_ARGS(q, rq, nr_bytes), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( int, errors ) ++ __array( char, rwbs, RWBS_LEN ) ++ __dynamic_array( char, cmd, blk_cmd_buf_len(rq) ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0; ++ __entry->sector = blk_rq_pos(rq); ++ __entry->nr_sector = nr_bytes >> 9; ++ __entry->errors = rq->errors; ++ ++ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, nr_bytes); ++ blk_dump_cmd(__get_str(cmd), rq); ++ ), ++ ++ TP_printk("%d,%d %s (%s) %llu + %u [%d]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __entry->rwbs, __get_str(cmd), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->errors) + ); + + DECLARE_EVENT_CLASS(block_rq, +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -702,6 +702,7 @@ void blk_trace_shutdown(struct request_q + * blk_add_trace_rq - Add a trace for a request oriented action + * @q: queue the io is for + * @rq: the source request ++ * @nr_bytes: number of completed bytes + * @what: the action + * + * Description: +@@ -709,7 +710,7 @@ void blk_trace_shutdown(struct request_q + * + **/ + static void blk_add_trace_rq(struct request_queue *q, struct request *rq, +- u32 what) ++ unsigned int nr_bytes, u32 what) + { + struct blk_trace *bt = q->blk_trace; + +@@ -718,11 +719,11 @@ static void blk_add_trace_rq(struct requ + + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + what |= BLK_TC_ACT(BLK_TC_PC); +- __blk_add_trace(bt, 0, blk_rq_bytes(rq), rq->cmd_flags, ++ __blk_add_trace(bt, 0, nr_bytes, rq->cmd_flags, + what, rq->errors, rq->cmd_len, rq->cmd); + } else { + what |= BLK_TC_ACT(BLK_TC_FS); +- __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), ++ __blk_add_trace(bt, blk_rq_pos(rq), nr_bytes, + rq->cmd_flags, what, rq->errors, 0, NULL); + } + } +@@ -730,33 +731,34 @@ static void blk_add_trace_rq(struct requ + static void blk_add_trace_rq_abort(void *ignore, + struct request_queue *q, struct request *rq) + { +- blk_add_trace_rq(q, rq, BLK_TA_ABORT); ++ blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_ABORT); + } + + static void blk_add_trace_rq_insert(void *ignore, + struct request_queue *q, struct request *rq) + { +- blk_add_trace_rq(q, rq, BLK_TA_INSERT); ++ blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_INSERT); + } + + static void blk_add_trace_rq_issue(void *ignore, + struct request_queue *q, struct request *rq) + { +- blk_add_trace_rq(q, rq, BLK_TA_ISSUE); ++ blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_ISSUE); + } + + static void blk_add_trace_rq_requeue(void *ignore, + struct request_queue *q, + struct request *rq) + { +- blk_add_trace_rq(q, rq, BLK_TA_REQUEUE); ++ blk_add_trace_rq(q, rq, blk_rq_bytes(rq), BLK_TA_REQUEUE); + } + + static void blk_add_trace_rq_complete(void *ignore, + struct request_queue *q, +- struct request *rq) ++ struct request *rq, ++ unsigned int nr_bytes) + { +- blk_add_trace_rq(q, rq, BLK_TA_COMPLETE); ++ blk_add_trace_rq(q, rq, nr_bytes, BLK_TA_COMPLETE); + } + + /** diff --git a/queue-3.14/netfilter-nf_tables-fix-nft_cmp_fast-failure-on-big-endian-for-size-4.patch b/queue-3.14/netfilter-nf_tables-fix-nft_cmp_fast-failure-on-big-endian-for-size-4.patch new file mode 100644 index 00000000000..1e467f40b67 --- /dev/null +++ b/queue-3.14/netfilter-nf_tables-fix-nft_cmp_fast-failure-on-big-endian-for-size-4.patch @@ -0,0 +1,77 @@ +From b855d416dc17061ebb271ea7ef1201d100531770 Mon Sep 17 00:00:00 2001 +From: Patrick McHardy +Date: Sat, 12 Apr 2014 13:17:57 +0200 +Subject: netfilter: nf_tables: fix nft_cmp_fast failure on big endian for size < 4 + +From: Patrick McHardy + +commit b855d416dc17061ebb271ea7ef1201d100531770 upstream. + +nft_cmp_fast is used for equality comparisions of size <= 4. For +comparisions of size < 4 byte a mask is calculated that is applied to +both the data from userspace (during initialization) and the register +value (during runtime). Both values are stored using (in effect) memcpy +to a memory area that is then interpreted as u32 by nft_cmp_fast. + +This works fine on little endian since smaller types have the same base +address, however on big endian this is not true and the smaller types +are interpreted as a big number with trailing zero bytes. + +The mask therefore must not include the lower bytes, but the higher bytes +on big endian. Add a helper function that does a cpu_to_le32 to switch +the bytes on big endian. Since we're dealing with a mask of just consequitive +bits, this works out fine. + +Signed-off-by: Patrick McHardy +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + include/net/netfilter/nf_tables_core.h | 10 ++++++++++ + net/netfilter/nf_tables_core.c | 3 +-- + net/netfilter/nft_cmp.c | 2 +- + 3 files changed, 12 insertions(+), 3 deletions(-) + +--- a/include/net/netfilter/nf_tables_core.h ++++ b/include/net/netfilter/nf_tables_core.h +@@ -13,6 +13,16 @@ struct nft_cmp_fast_expr { + u8 len; + }; + ++/* Calculate the mask for the nft_cmp_fast expression. On big endian the ++ * mask needs to include the *upper* bytes when interpreting that data as ++ * something smaller than the full u32, therefore a cpu_to_le32 is done. ++ */ ++static inline u32 nft_cmp_fast_mask(unsigned int len) ++{ ++ return cpu_to_le32(~0U >> (FIELD_SIZEOF(struct nft_cmp_fast_expr, ++ data) * BITS_PER_BYTE - len)); ++} ++ + extern const struct nft_expr_ops nft_cmp_fast_ops; + + int nft_cmp_module_init(void); +--- a/net/netfilter/nf_tables_core.c ++++ b/net/netfilter/nf_tables_core.c +@@ -25,9 +25,8 @@ static void nft_cmp_fast_eval(const stru + struct nft_data data[NFT_REG_MAX + 1]) + { + const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); +- u32 mask; ++ u32 mask = nft_cmp_fast_mask(priv->len); + +- mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - priv->len); + if ((data[priv->sreg].data[0] & mask) == priv->data) + return; + data[NFT_REG_VERDICT].verdict = NFT_BREAK; +--- a/net/netfilter/nft_cmp.c ++++ b/net/netfilter/nft_cmp.c +@@ -128,7 +128,7 @@ static int nft_cmp_fast_init(const struc + BUG_ON(err < 0); + desc.len *= BITS_PER_BYTE; + +- mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - desc.len); ++ mask = nft_cmp_fast_mask(desc.len); + priv->data = data.data[0] & mask; + priv->len = desc.len; + return 0; diff --git a/queue-3.14/series b/queue-3.14/series index da37f381ece..adc0e8b038e 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -5,3 +5,5 @@ kvm-x86-remove-warn_on-from-get_kernel_ns.patch tools-lib-traceevent-fix-memory-leak-in-pretty_print.patch pid-get-pid_t-ppid-of-task-in-init_pid_ns.patch audit-convert-ppids-to-the-inital-pid-namespace.patch +netfilter-nf_tables-fix-nft_cmp_fast-failure-on-big-endian-for-size-4.patch +blktrace-fix-accounting-of-partially-completed-requests.patch