--- /dev/null
+From b50c2de51e611da90cf3cf04c058f7e9bbe79e93 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zyan@redhat.com>
+Date: Mon, 24 Apr 2017 11:56:50 +0800
+Subject: ceph: choose readdir frag based on previous readdir reply
+
+From: Yan, Zheng <zyan@redhat.com>
+
+commit b50c2de51e611da90cf3cf04c058f7e9bbe79e93 upstream.
+
+The dirfragtree is lazily updated, it's not always accurate. Infinite
+loops happens in following circumstance.
+
+- client send request to read frag A
+- frag A has been fragmented into frag B and C. So mds fills the reply
+ with contents of frag B
+- client wants to read next frag C. ceph_choose_frag(frag value of C)
+ return frag A.
+
+The fix is using previous readdir reply to calculate next readdir frag
+when possible.
+
+Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ceph/dir.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/fs/ceph/dir.c
++++ b/fs/ceph/dir.c
+@@ -294,7 +294,7 @@ static int ceph_readdir(struct file *fil
+ struct ceph_mds_client *mdsc = fsc->mdsc;
+ int i;
+ int err;
+- u32 ftype;
++ unsigned frag = -1;
+ struct ceph_mds_reply_info_parsed *rinfo;
+
+ dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos);
+@@ -341,7 +341,6 @@ more:
+ /* do we have the correct frag content buffered? */
+ if (need_send_readdir(fi, ctx->pos)) {
+ struct ceph_mds_request *req;
+- unsigned frag;
+ int op = ceph_snap(inode) == CEPH_SNAPDIR ?
+ CEPH_MDS_OP_LSSNAP : CEPH_MDS_OP_READDIR;
+
+@@ -352,8 +351,11 @@ more:
+ }
+
+ if (is_hash_order(ctx->pos)) {
+- frag = ceph_choose_frag(ci, fpos_hash(ctx->pos),
+- NULL, NULL);
++ /* fragtree isn't always accurate. choose frag
++ * based on previous reply when possible. */
++ if (frag == (unsigned)-1)
++ frag = ceph_choose_frag(ci, fpos_hash(ctx->pos),
++ NULL, NULL);
+ } else {
+ frag = fpos_frag(ctx->pos);
+ }
+@@ -476,6 +478,7 @@ more:
+ struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
+ struct ceph_vino vino;
+ ino_t ino;
++ u32 ftype;
+
+ BUG_ON(rde->offset < ctx->pos);
+
+@@ -498,15 +501,17 @@ more:
+ ctx->pos++;
+ }
+
++ ceph_mdsc_put_request(fi->last_readdir);
++ fi->last_readdir = NULL;
++
+ if (fi->next_offset > 2) {
+- ceph_mdsc_put_request(fi->last_readdir);
+- fi->last_readdir = NULL;
++ frag = fi->frag;
+ goto more;
+ }
+
+ /* more frags? */
+ if (!ceph_frag_is_rightmost(fi->frag)) {
+- unsigned frag = ceph_frag_next(fi->frag);
++ frag = ceph_frag_next(fi->frag);
+ if (is_hash_order(ctx->pos)) {
+ loff_t new_pos = ceph_make_fpos(ceph_frag_value(frag),
+ fi->next_offset, true);
--- /dev/null
+From 9e52b32567126fe146f198971364f68d3bc5233f Mon Sep 17 00:00:00 2001
+From: Sabrina Dubroca <sd@queasysnail.net>
+Date: Thu, 22 Jun 2017 11:24:42 +0200
+Subject: tracing/kprobes: Allow to create probe with a module name starting with a digit
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+commit 9e52b32567126fe146f198971364f68d3bc5233f upstream.
+
+Always try to parse an address, since kstrtoul() will safely fail when
+given a symbol as input. If that fails (which will be the case for a
+symbol), try to parse a symbol instead.
+
+This allows creating a probe such as:
+
+ p:probe/vlan_gro_receive 8021q:vlan_gro_receive+0
+
+Which is necessary for this command to work:
+
+ perf probe -m 8021q -a vlan_gro_receive
+
+Link: http://lkml.kernel.org/r/fd72d666f45b114e2c5b9cf7e27b91de1ec966f1.1498122881.git.sd@queasysnail.net
+
+Fixes: 413d37d1e ("tracing: Add kprobe-based event tracer")
+Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/trace_kprobe.c | 21 ++++++++-------------
+ 1 file changed, 8 insertions(+), 13 deletions(-)
+
+--- a/kernel/trace/trace_kprobe.c
++++ b/kernel/trace/trace_kprobe.c
+@@ -680,30 +680,25 @@ static int create_trace_kprobe(int argc,
+ pr_info("Probe point is not specified.\n");
+ return -EINVAL;
+ }
+- if (isdigit(argv[1][0])) {
+- if (is_return) {
+- pr_info("Return probe point must be a symbol.\n");
+- return -EINVAL;
+- }
+- /* an address specified */
+- ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
+- if (ret) {
+- pr_info("Failed to parse address.\n");
+- return ret;
+- }
+- } else {
++
++ /* try to parse an address. if that fails, try to read the
++ * input as a symbol. */
++ if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
+ /* a symbol specified */
+ symbol = argv[1];
+ /* TODO: support .init module functions */
+ ret = traceprobe_split_symbol_offset(symbol, &offset);
+ if (ret) {
+- pr_info("Failed to parse symbol.\n");
++ pr_info("Failed to parse either an address or a symbol.\n");
+ return ret;
+ }
+ if (offset && is_return) {
+ pr_info("Return probe must be used without offset.\n");
+ return -EINVAL;
+ }
++ } else if (is_return) {
++ pr_info("Return probe point must be a symbol.\n");
++ return -EINVAL;
+ }
+ argc -= 2; argv += 2;
+