diff --git a/libbpf b/libbpf
index c91f1175e2273825767160fdc54448c19c97ba13..b940fc498656a2d9f295fab0a9dbf530267bdcd6 160000
--- a/libbpf
+++ b/libbpf
@@ -1 +1 @@
-Subproject commit c91f1175e2273825767160fdc54448c19c97ba13
+Subproject commit b940fc498656a2d9f295fab0a9dbf530267bdcd6
diff --git a/src/Makefile b/src/Makefile
index f46ca8a47e8f818e644029a340f21ba5c951250e..a873021953c09fc40ffc4172975ccfb01754370c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -9,7 +9,7 @@ INCLUDES := -I$(OUTPUT) -idirafter $(abspath ../libbpf/include)
 CFLAGS := -g -Wall
 ARCH := $(shell uname -m | sed 's/x86_64/x86/')
 
-APPS = minimal bootstrap uprobe task_mmap task_bulk_minimal task_find task_filter_magic # task_ag task_sleep task task_bulk
+APPS = minimal bootstrap uprobe task_mmap task_bulk task_bulk_minimal task_find task_filter_magic # task_ag task_sleep task
 
 # Get Clang's default includes on this system. We'll explicitly add these dirs
 # to the includes list when compiling with `-target bpf` because otherwise some
diff --git a/src/task_find.bpf.c b/src/task_find.bpf.c
index c9b6a01bf2721e88b2e0ab0698ba0dc8a8fc19af..cb36f8338ad4e35be7c017c46ec9357cd7f86ab9 100644
--- a/src/task_find.bpf.c
+++ b/src/task_find.bpf.c
@@ -12,12 +12,12 @@ struct {
 	__uint(type, BPF_MAP_TYPE_ARRAY);
 	__uint(max_entries, NR_STATE_MAP_KEYS);
 	__type(key, int);
-	__type(value, int);
+	__type(value, unsigned long);
 } state_map SEC(".maps");
 
 struct {
 	__uint(type, BPF_MAP_TYPE_ARRAY);
-	__uint(max_entries, MAX_DEPTH);
+	__uint(max_entries, MAX_DEPTH * 2);
 	__type(key, int);
 	__type(value, int);
 } dfd_map SEC(".maps");
@@ -27,10 +27,11 @@ void *u_ascend;
 void *u_newline;
 void *u_iterdents64_buf;
 size_t root_namelen;
-
+void *u_statbuf;
 int type;
+int flags;
 
-static long iter_dir(uint32_t d_type, size_t namelen, bool print) {
+static long iter_dir(uint32_t d_type, size_t namelen, bool match) {
 	long err = 0;
 
 	if (namelen + 1 > PATHLEN) {
@@ -39,43 +40,72 @@ static long iter_dir(uint32_t d_type, size_t namelen, bool print) {
 		goto end;
 	}
 
-	int *curr_depth_p = bpf_map_lookup_elem(&state_map, &CURR_DEPTH_KEY);
+	unsigned long *curr_depth_p = bpf_map_lookup_elem(&state_map, &CURR_DEPTH_KEY);
 	if (!curr_depth_p) {
 		bpf_printk("Error: bpf_map_lookup_elem(&state_map, &CURR_DEPTH_KEY)");
 		goto end;
 	}
-	int depth = *curr_depth_p;
+	unsigned long depth = *curr_depth_p;
 	if (depth >= MAX_DEPTH) {
 		bpf_printk("Error: max_depth exceeded");
 		err = -1;
 		goto end;
 	}
-
-	void *name_user = u_iterdents64_buf + depth * PATHLEN;
-	if (print) {
-		write(STDOUT_FILENO, name_user, namelen);
-		write(STDOUT_FILENO, u_newline, 1);
-	}
-	if (d_type != DT_DIR) {
-		goto end;
-	}
-
 	int *parent_dfd = bpf_map_lookup_elem(&dfd_map, &depth);
 	if (!parent_dfd) {
 		bpf_printk("Error: bpf_map_lookup_elem(&dfd_map, depth)");
 		goto end;
 	}
 
+	void *name_user = u_iterdents64_buf + depth * PATHLEN;
+	if (match) {
+		if (flags & PRINT_MATCHES) {
+			write(STDOUT_FILENO, name_user, namelen);
+			write(STDOUT_FILENO, u_newline, 1);
+		}
+		if (flags & SUMMARIZE_DISK_USAGE) {
+			err = bpf_task_sys_newfstatat_4(*parent_dfd, (uint64_t) name_user,
+							(uint64_t) u_statbuf, AT_SYMLINK_NOFOLLOW);
+			if (err) {
+				bpf_printk("Error");
+				goto end;
+			}
+			struct stat statbuf;
+			err = bpf_probe_read_user(&statbuf, sizeof(statbuf), u_statbuf);
+			if (err) {
+				bpf_printk("Error");
+				goto end;
+			}
+			unsigned long *disk_usage_p = bpf_map_lookup_elem(&state_map, &DISK_USAGE_KEY);
+			if (!disk_usage_p) {
+				bpf_printk("Error: bpf_map_lookup_elem(&state_map, &DISK_USAGE_KEY)");
+				goto end;
+			}
+			unsigned long n = *disk_usage_p;
+			n += statbuf.st_size;
+			err = bpf_map_update_elem(&state_map, &DISK_USAGE_KEY, &n, BPF_ANY);
+			if (err) {
+				bpf_printk("Error");
+				goto end;
+			}
+		}
+	}
+
+	if (d_type != DT_DIR) {
+		goto end;
+	}
 	int dfd = openat(*parent_dfd, name_user, O_RDONLY | O_DIRECTORY, 0777);
 	if (dfd < 0) {
 		bpf_printk("Warning: openat failed, is someone modifying the tree?");
 		/* Not a directory, no need to iterate. */
 		goto end;
 	}
-	write(STDOUT_FILENO, name_user, namelen);
-	write(STDOUT_FILENO, u_descend, 2);
+	if (flags & PRINT_MATCHES) {
+		write(STDOUT_FILENO, name_user, namelen);
+		write(STDOUT_FILENO, u_descend, 2);
+	}
 
-	int child_depth = depth + 1;
+	unsigned long child_depth = depth + 1;
 	void *child_name_user = u_iterdents64_buf + child_depth * PATHLEN;
 
 	err = bpf_map_update_elem(&state_map, &CURR_DEPTH_KEY, &child_depth, BPF_ANY);
@@ -93,7 +123,7 @@ static long iter_dir(uint32_t d_type, size_t namelen, bool print) {
 	int *prog_fd = bpf_map_lookup_elem(&state_map, &PDPF_KEY);
 	if (!prog_fd) {
 		bpf_printk("Error: !bpf_map_lookup_elem(&state_map, &PDPF_KEY)");
-		goto end;
+		goto reset_depth;
 	}
 
 	err = bpf_task_iterdents64(dfd, *prog_fd, child_name_user, PATHLEN);
@@ -108,7 +138,9 @@ reset_depth:
 		bpf_printk("bpf_map_update_elem(&state_map, &CURR_DEPTH_KEY, depth, BPF_ANY) = %d", err);
 	}
 close:
-	write(STDOUT_FILENO, u_ascend, 3);
+	if (flags & PRINT_MATCHES) {
+		write(STDOUT_FILENO, u_ascend, 3);
+	}
 	err = bpf_task_sys_close_1(dfd);
 	if (err) {
 		bpf_printk("close(%d) = %d", dfd, err);
@@ -122,7 +154,7 @@ int entry(void *ctx)
 {
 	long err = 0;
 
-	err = iter_dir(DT_DIR, root_namelen, false);
+	err = iter_dir(DT_DIR, root_namelen, true);
 	if (err) {
 		goto end;
 	}
@@ -147,7 +179,7 @@ int process_dirent(struct bpf_dirent64 *d) {
 		}
 	}
 
-	err = iter_dir(d->d_type, d->namelen, type != -1 && d->d_type == type);
+	err = iter_dir(d->d_type, d->namelen, type == -1 || d->d_type == type);
 	if (err) {
 		goto end;
 	}
diff --git a/src/task_find.c b/src/task_find.c
index c553a87b74f76f1542f6e184d53bd6439babd546..31a3efcc2a1199ad6b89b3f75f110e348ecc52fe 100644
--- a/src/task_find.c
+++ b/src/task_find.c
@@ -28,6 +28,7 @@
 #include <inttypes.h>
 
 #include <sys/resource.h>
+#include <bpf/bpf.h>
 #include <bpf/libbpf.h>
 #include "task_find.skel.h"
 #include "task_find.h"
@@ -157,7 +158,7 @@ static void print_usage(char **argv) {
 	fprintf(stderr, "Usage: %s [-D --debug] [-v --variant bpf] PATH -name LITERAL\n", argv[0]);
 }
 
-static int bpf_find(const char *path, const char *name, bool debug, int type) {
+static int bpf_find(const char *path, const char *name, bool debug, int type, int flags) {
 	struct NAME_BPF *skel;
 	int err = 0, ret = EXIT_SUCCESS;
 
@@ -184,6 +185,10 @@ static int bpf_find(const char *path, const char *name, bool debug, int type) {
 
 	skel->bss->root_namelen = strlen(path);
 	skel->bss->type = type;
+	skel->bss->flags = flags;
+
+	struct stat statbuf;
+	skel->bss->u_statbuf = &statbuf;
 
 	/* Load & verify BPF programs */
 	err = BPF_LOAD(skel);
@@ -193,17 +198,25 @@ static int bpf_find(const char *path, const char *name, bool debug, int type) {
 		goto destroy;
 	}
 
-	/* BPF_NOEXIST means: add new element if it doesn't exist */
 	int value = bpf_program__fd(skel->progs.process_dirent);
 	err = bpf_map_update_elem(bpf_map__fd(skel->maps.state_map), &PDPF_KEY, &value, BPF_ANY);
 	if (err == -1) {
 		perror("bpf_map_update_elem(bpf_map__fd(skel->maps.state_map), &PDPF_KEY, &value, BPF_NOEXIST)");
+		ret = EXIT_FAILURE;
 		goto destroy;
 	}
 
 	int root_key = 0, root_value = AT_FDCWD;
 	err = bpf_map_update_elem(bpf_map__fd(skel->maps.dfd_map), &root_key, &root_value, BPF_ANY);
 	if (err == -1) {
+		ret = EXIT_FAILURE;
+		goto destroy;
+	}
+
+	unsigned long zero = 0;
+	err = bpf_map_update_elem(bpf_map__fd(skel->maps.state_map), &DISK_USAGE_KEY, &zero, BPF_ANY);
+	if (err == -1) {
+		ret = EXIT_FAILURE;
 		goto destroy;
 	}
 
@@ -215,6 +228,14 @@ static int bpf_find(const char *path, const char *name, bool debug, int type) {
 		goto destroy;
 	}
 
+	unsigned long total_disk_usage;
+	err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.state_map), &DISK_USAGE_KEY, &total_disk_usage);
+	if (err) {
+		ret = EXIT_FAILURE;
+		goto destroy;
+	}
+	printf("%lu %s\n", total_disk_usage, path);
+
 destroy:
 	BPF_DESTROY(skel);
 	return ret;
@@ -234,15 +255,9 @@ struct linux_dirent64 {
 /* Same as in GNU find. */
 #define BUF_SIZE (32*1024)
 
-enum action {
-	SUMMARIZE_DISK_USAGE = 1,
-	PRINT_LIBC = 1 << 1,
-	PRINT_MATCHES = 1 << 2,
-};
-
 static int do_user_find(unsigned char d_type, int parent_dfd, const char *name,
 			const char *search_name, int search_type, bool debug,
-			int flags, size_t *disk_usage_total) {
+			int flags, unsigned long *disk_usage_total) {
 	int err = 0;
 	size_t namelen = strlen(name);
 
@@ -250,8 +265,8 @@ static int do_user_find(unsigned char d_type, int parent_dfd, const char *name,
 		return 0;
 	}
 
-	bool match = (search_type != -1 && d_type == search_type)
-		|| (search_name != NULL && strcmp(search_name, name) == 0);
+	bool match = (search_type == -1 || d_type == search_type)
+		&& (search_name == NULL || strcmp(search_name, name) == 0);
 	if (match) {
 		if (flags & PRINT_MATCHES) {
 			if (flags & PRINT_LIBC) {
@@ -262,10 +277,9 @@ static int do_user_find(unsigned char d_type, int parent_dfd, const char *name,
 			}
 		}
 
-		if (d_type == DT_REG &&
-		    flags & SUMMARIZE_DISK_USAGE) {
+		if (flags & SUMMARIZE_DISK_USAGE) {
 			struct stat statbuf;
-			err = fstatat(parent_dfd, name, &statbuf, 0);
+			err = fstatat(parent_dfd, name, &statbuf, AT_SYMLINK_NOFOLLOW);
 			if (err) {
 				perror("fstatat");
 				exit(EXIT_FAILURE);
@@ -329,11 +343,11 @@ close:
 
 static int user_find(const char *path, const char *search_name,
 		     bool debug, int search_type, int flags) {
-	size_t disk_usage_total = 0;
+	unsigned long disk_usage_total = 0;
 	int err = do_user_find(DT_DIR, AT_FDCWD, path, search_name, search_type,
 			       debug, flags, &disk_usage_total);
 	if (!err) {
-		printf("%zu %s\n", disk_usage_total, path);
+		printf("%lu %s\n", disk_usage_total, path);
 	}
 	return err;
 }
@@ -431,7 +445,7 @@ int main(int argc, char **argv)
 
 	int ret;
 	if (variant_bpf) {
-		ret = bpf_find(path, name, debug, type);
+		ret = bpf_find(path, name, debug, type, flags);
 	} else {
 		ret = user_find(path, name, debug, type, flags);
 	}
diff --git a/src/task_find.h b/src/task_find.h
index 5703074e6750709ffc8c6871bfd7a30187f2f5df..1d9bb534872a63fa427295d2a73d99a502e97bb6 100644
--- a/src/task_find.h
+++ b/src/task_find.h
@@ -1,7 +1,7 @@
 #ifndef __TASK_H_
 #define __TASK_H_
 
-#define MAX_DEPTH 32
+#define MAX_DEPTH 16
 #define UBUF_SIZE 1024
 #define PATHLEN 512
 
@@ -14,6 +14,13 @@ struct __packed __attribute__((__aligned__(4096))) bpfmem {
  * bpf_map_*() helpers. */
 static int PDPF_KEY = 0;
 static int CURR_DEPTH_KEY = 1;
-#define NR_STATE_MAP_KEYS 2
+static int DISK_USAGE_KEY = 2;
+#define NR_STATE_MAP_KEYS 3
+
+enum action {
+	SUMMARIZE_DISK_USAGE = 1,
+	PRINT_LIBC = 1 << 1,
+	PRINT_MATCHES = 1 << 2,
+};
 
 #endif // __TASK_H_
diff --git a/src/task_lib.bpf.h b/src/task_lib.bpf.h
index 7545e82bdc9e49af6d083725fbd7d394720dd5e3..ad1d13657c96c783aeb244db9a6690cc83c624aa 100644
--- a/src/task_lib.bpf.h
+++ b/src/task_lib.bpf.h
@@ -25,7 +25,6 @@ typedef uintptr_t size_t;
 typedef intptr_t ssize_t;
 typedef __u64 ino64_t;
 typedef __u64 off64_t;
-typedef off64_t off_t;
 
 #define STDIN_FILENO 0
 #define STDOUT_FILENO 1
@@ -94,16 +93,18 @@ struct timespec {
 	long   tv_nsec;       /* nanoseconds */
 };
 
-/* fstat(2) */
-/* TODO: fix */
-typedef int dev_t;
-typedef int ino_t;
-typedef int mode_t;
-typedef int nlink_t;
-typedef int uid_t;
-typedef int gid_t;
-typedef int blksize_t;
-typedef int blkcnt_t;
+/* for stat(), via linux/tools/include/nolibc/nolibc.h */
+typedef unsigned int          dev_t;
+typedef unsigned long         ino_t;
+typedef unsigned int         mode_t;
+typedef   signed int          pid_t;
+typedef unsigned int          uid_t;
+typedef unsigned int          gid_t;
+typedef unsigned long       nlink_t;
+typedef   signed long         off_t;
+typedef   signed long     blksize_t;
+typedef   signed long      blkcnt_t;
+typedef   signed long        time_t;
 struct stat {
 	dev_t     st_dev;         /* ID of device containing file */
 	ino_t     st_ino;         /* Inode number */