Skip to contentSkip to conversation

xfs: horrifying eBPF hacks

PATCH In review Darrick J. Wong 3 participants 7 messages Dec 13, 2017 – Jan 4, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover xfs: horrifying eBPF hacks

Heh.

So here's a kernel patch that builds on Josef's eBPF return value override patch series to provide an eBPF-kprobe-overridable hook function so that administrators can program XFS to redirect a file to the rt device or the data device depending on their own funny constraints any time that the system is doing the first write into an empty file.

The second patch is against Brendan Gregg's bcc repository; it adds a python script to compile and inject a sample eBPF program that behaves (roughly) the same as Richard's earlier patches.

Soooo... rather than dumping a bunch of static code into XFS to support his particular usecase, we're building him an eBPF Bazooka and telling him to have fun. :P

(More generally, it's a science fair project for letting people customize XFS behavior with eBPF in a controlled manner.)

--D

#1 lore raw

PATCH 1/2 xfs: eBPF user hacks insanity

From: Darrick J. Wong <[email protected]>

Create some special filter functions to which userspace can attach eBPF programs which override the return value and thereby allow userspace to assist XFS in making contextualized decisions about where to put files.

In other words, users can upload their own custom algorithms into XFS to override the default rtdev/datadev placement code.

---
 fs/xfs/Kconfig              |    9 ++
 fs/xfs/Makefile             |    2 +
 fs/xfs/xfs_bmap_util.c      |    5 +
 fs/xfs/xfs_hacks.c          |  159 +++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_hacks.h          |   29 ++++++++
 fs/xfs/xfs_iomap.c          |    7 ++
 kernel/trace/trace_kprobe.c |    2 +
 7 files changed, 213 insertions(+)
 create mode 100644 fs/xfs/xfs_hacks.c
 create mode 100644 fs/xfs/xfs_hacks.h
fs/xfs/Kconfig +9 -0
index 06be67d..1594822 100644
@@ -143,3 +143,12 @@ config XFS_ASSERT_FATAL
 	  result in warnings.
 
 	  This behavior can be modified at runtime via sysfs.
+
+config XFS_HACKS
+	bool "XFS Userspace eBPF Hacks"
+	default n
+	depends on XFS_FS && BPF_KPROBE_OVERRIDE
+	help
+	  Allow userspace to attach eBPF programs to various parts of XFS
+	  in order to customize its decisions.  This is insane; you get
+	  to keep the pieces!
fs/xfs/Makefile +2 -0
index 9f4de14..03e2a37 100644
@@ -176,3 +176,5 @@ xfs-$(CONFIG_XFS_RT)		+= $(addprefix scrub/, \
 				   )
 xfs-$(CONFIG_XFS_QUOTA)		+= scrub/quota.o
 endif
+
+xfs-$(CONFIG_XFS_HACKS)		+= xfs_hacks.o
fs/xfs/xfs_bmap_util.c +5 -0
index 6d37ab4..39ce418 100644
@@ -45,6 +45,7 @@
 #include "xfs_iomap.h"
 #include "xfs_reflink.h"
 #include "xfs_refcount.h"
+#include "xfs_hacks.h"
 
 /* Kernel only BMAP related definitions and functions */
 
@@ -918,6 +919,10 @@ xfs_alloc_file_space(
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
+	error = xfs_hacks_retarget_iflags(ip, offset, len);
+	if (error)
+		return error;
+
 	error = xfs_qm_dqattach(ip, 0);
 	if (error)
 		return error;
fs/xfs/xfs_hacks.c new file +159 -0

159 lines not on this page · raw message

fs/xfs/xfs_hacks.h new file +29 -0
new file mode 100644
index 0000000..2c556f1
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 Oracle.  All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef __XFS_HACKS_H__
+#define __XFS_HACKS_H__
+
+#ifdef CONFIG_XFS_HACKS
+int xfs_hacks_retarget_iflags(struct xfs_inode *ip, loff_t offset, loff_t length);
+#else
+# define xfs_hacks_retarget_iflags(ip, off, len)	(0)
+#endif
+
+#endif /* __XFS_HACKS_H__ */
fs/xfs/xfs_iomap.c +7 -0
index 7ab52a8..f69d274 100644
@@ -42,6 +42,7 @@
 #include "xfs_dquot_item.h"
 #include "xfs_dquot.h"
 #include "xfs_reflink.h"
+#include "xfs_hacks.h"
 
 
 #define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
@@ -987,6 +988,12 @@ xfs_file_iomap_begin(
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
+	if (flags & IOMAP_WRITE) {
+		error = xfs_hacks_retarget_iflags(ip, offset, length);
+		if (error)
+			return error;
+	}
+
 	if (((flags & (IOMAP_WRITE | IOMAP_DIRECT)) == IOMAP_WRITE) &&
 			!IS_DAX(inode) && !xfs_get_extsz_hint(ip)) {
 		/* Reserve delalloc blocks for regular writeback. */
kernel/trace/trace_kprobe.c +2 -0
index 5db8498..fd948e3 100644
@@ -1215,8 +1215,10 @@ kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs)
 		if (__this_cpu_read(bpf_kprobe_override)) {
 			__this_cpu_write(bpf_kprobe_override, 0);
 			reset_current_kprobe();
+			preempt_enable();
 			return 1;
 		}
+		preempt_enable();
 		if (!ret)
 			return 0;
 	}
#2 lore raw

PATCH 2/2 tools/xfs: use XFS hacks to override data block device placement

In reply to Darrick J. Wong

From: Darrick J. Wong <[email protected]>

This (bcc) patch modifies bcc so that we can override some function return values. We then create a new python script containing custom logic to decide where a file's data goes (rtdev or datadev) and inject the compiled eBPF code into the kernel.

---
 src/cc/compat/linux/bpf.h         |    7 ++
 src/cc/compat/linux/virtual_bpf.h |    3 +
 src/cc/export/helpers.h           |    2 +
 tools/xfs_rt.py                   |  130 +++++++++++++++++++++++++++++++++++++
 4 files changed, 140 insertions(+), 2 deletions(-)
 create mode 100755 tools/xfs_rt.py
src/cc/compat/linux/bpf.h +6 -1
index f896897..5a3ec0b 100644
@@ -677,6 +677,10 @@ union bpf_attr {
  *     @buf: buf to fill
  *     @buf_size: size of the buf
  *     Return : 0 on success or negative error code
+ *
+ * int bpf_override_return(pt_regs, rc)
+ *     @pt_regs: pointer to struct pt_regs
+ *     @rc: the return value to set
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -736,7 +740,8 @@ union bpf_attr {
 	FN(xdp_adjust_meta),		\
 	FN(perf_event_read_value),	\
 	FN(perf_prog_read_value),	\
-	FN(getsockopt),
+	FN(getsockopt),			\
+	FN(override_return),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
src/cc/compat/linux/virtual_bpf.h +2 -1
index a2bcf07..7fbc365 100644
@@ -735,7 +735,8 @@ union bpf_attr {
 	FN(xdp_adjust_meta),		\
 	FN(perf_event_read_value),	\
 	FN(perf_prog_read_value),	\
-	FN(getsockopt),
+	FN(getsockopt),			\
+	FN(override_return),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
src/cc/export/helpers.h +2 -0
index 2b64ee8..571191e 100644
@@ -204,6 +204,8 @@ static int (*bpf_probe_read)(void *dst, u64 size, const void *unsafe_ptr) =
   (void *) BPF_FUNC_probe_read;
 static u64 (*bpf_ktime_get_ns)(void) =
   (void *) BPF_FUNC_ktime_get_ns;
+static void (*bpf_override_return)(void *ctx, unsigned long rc) =
+  (void *) BPF_FUNC_override_return;
 static u32 (*bpf_get_prandom_u32)(void) =
   (void *) BPF_FUNC_get_prandom_u32;
 static int (*bpf_trace_printk_)(const char *fmt, u64 fmt_size, ...) =
tools/xfs_rt.py new file +130 -0

130 lines not on this page · raw message

#4 lore raw
Quoted 2 lines · Christoph Hellwig

Eek. Whie eBPF is a really nice debug tool we should never use it for actual required kernel I/O functionality.

Certainly not in its current hacky form. I'm curious if Richard has had a chance to try out these patches to see if it affects performance in a noticeable way?

I /think/ bpf has enough safety mechanisms (no loops, no direct writing to kernel memory, bytecode verifiers, opcode count limits) that such a beast could be hidden behind a kconfig option that isn't turned for the general public. For people who have these particularly specific use cases I think it better to have a general mechanism to accomodate them vs. scattering code all over xfs vs. "no sorry go away", though this ebpf thing isn't necessarily the final answer. We do validate that the proposed iflags are allowed for the fs geometry, though I acknowledge that the prospect of running ebpf with ilock_excl does give me pause.

I'm curious, though, what are your (and everyone else's) concerns about this?

--D

Quoted 4 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw

Hey Darrick,

I'll try to get to testing this out early next week, I was out on vacation the last couple weeks so I kinda fell off the earth for a bit.

I will test for functionality & performance as best I can, but we'll probably want to explore everyone's concerns on leveraging eBPF in this way as well. I have pretty limited experience with BPF, so I'm probably not going to be super useful in such a discussion, though I'll certainly try to get read up on it.

Is there any precedence for doing this sort of thing with BPF anywhere else in the kernel?

Richard

Quoted 29 lines · Darrick J. Wong
Quoted 2 lines · Christoph Hellwig

Eek. Whie eBPF is a really nice debug tool we should never use it for actual required kernel I/O functionality.

Certainly not in its current hacky form. I'm curious if Richard has had a chance to try out these patches to see if it affects performance in a noticeable way?

I /think/ bpf has enough safety mechanisms (no loops, no direct writing to kernel memory, bytecode verifiers, opcode count limits) that such a beast could be hidden behind a kconfig option that isn't turned for the general public. For people who have these particularly specific use cases I think it better to have a general mechanism to accomodate them vs. scattering code all over xfs vs. "no sorry go away", though this ebpf thing isn't necessarily the final answer. We do validate that the proposed iflags are allowed for the fs geometry, though I acknowledge that the prospect of running ebpf with ilock_excl does give me pause.

I'm curious, though, what are your (and everyone else's) concerns about this?

--D

Quoted 4 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw
Quoted 5 lines · Richard Wareing

Hey Darrick,

I'll try to get to testing this out early next week, I was out on vacation the last couple weeks so I kinda fell off the earth for a bit.

Quoted 8 lines

I will test for functionality & performance as best I can, but we'll probably want to explore everyone's concerns on leveraging eBPF in this way as well. I have pretty limited experience with BPF, so I'm probably not going to be super useful in such a discussion, though I'll certainly try to get read up on it.

Is there any precedence for doing this sort of thing with BPF anywhere else in the kernel?

Well, we use JIT compiled eBPF to allow userspace to read kernel memory now, so it's probably fine to let it fiddle with XFS since we've all already lost anyway. ;)

Seriously, no, there isn't any precedent, hence the ZOMFG RFCRAP tags. I'm pretty sure that at best BPF XFS falls into a gray area where in theory all the protections are sufficient but nobody will ever believe it...

...but that doesn't mean it isn't worth giving the idea a healthy shake on the mailing list. <cue flames>

--D

Quoted 37 lines

Richard

Quoted 20 lines · Darrick J. Wong
Quoted 2 lines · Christoph Hellwig

Eek. Whie eBPF is a really nice debug tool we should never use it for actual required kernel I/O functionality.

Certainly not in its current hacky form. I'm curious if Richard has had a chance to try out these patches to see if it affects performance in a noticeable way?

I /think/ bpf has enough safety mechanisms (no loops, no direct writing to kernel memory, bytecode verifiers, opcode count limits) that such a beast could be hidden behind a kconfig option that isn't turned for the general public. For people who have these particularly specific use cases I think it better to have a general mechanism to accomodate them vs. scattering code all over xfs vs. "no sorry go away", though this ebpf thing isn't necessarily the final answer. We do validate that the proposed iflags are allowed for the fs geometry, though I acknowledge that the prospect of running ebpf with ilock_excl does give me pause.

Quoted 9 lines

I'm curious, though, what are your (and everyone else's) concerns about this?

--D

Quoted 4 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html