diff --git a/btrfs-progs.spec b/btrfs-progs.spec
index 479d4fa..03b6986 100644
--- a/btrfs-progs.spec
+++ b/btrfs-progs.spec
@@ -1,6 +1,6 @@
 Name:           btrfs-progs
 Version:        0.20.rc1.20121017git91d9eec
-Release:        2%{?dist}
+Release:        3%{?dist}
 Summary:        Userspace programs for btrfs
 
 Group:          System Environment/Base
@@ -13,6 +13,10 @@ Patch2: btrfs-progs-build-fixes.patch
 Patch3: Btrfs-progs-add-btrfs-device-ready-command.patch
 Patch4: Btrfs-progs-detect-if-the-disk-we-are-formatting-is-.patch
 Patch5: btrfs-init-dev-list.patch
+# Partial fix for RHBZ#863978 (but only in Rawhide).
+# Upstream: https://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs.git;a=commitdiff;h=8fe354744cd7b5c4f7a3314dcdbb5095192a032f
+# See also: http://thread.gmane.org/gmane.comp.file-systems.btrfs/23249
+Patch6: clear-caches-when-opening-and-closing-devices.patch
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -32,6 +36,7 @@ check, modify and correct any inconsistencies in the btrfs filesystem.
 %patch3 -p1
 %patch4 -p1
 %patch5 -p1
+%patch6 -p1
 
 %build
 make CFLAGS="$RPM_OPT_FLAGS" %{?_smp_mflags}
@@ -68,6 +73,9 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man8/btrfs.8.gz
 
 %changelog
+* Wed Feb 13 2013 Richard W.M. Jones <rjones@redhat.com> 0.20.rc1.20121017git91d9eec-3
+- Include upstream patch to clear caches as a partial fix for RHBZ#863978.
+
 * Thu Nov  1 2012 Josef Bacik <josef@toxicpanda.com> 0.20.rc1.20121017git91d9eec-2
 - fix a bug when mkfs'ing a file (rhbz# 871778)
 
diff --git a/clear-caches-when-opening-and-closing-devices.patch b/clear-caches-when-opening-and-closing-devices.patch
new file mode 100644
index 0000000..37d254d
--- /dev/null
+++ b/clear-caches-when-opening-and-closing-devices.patch
@@ -0,0 +1,107 @@
+diff -ur btrfs-progs-0.20.rc1.20121017git91d9eec.old/disk-io.c btrfs-progs-0.20.rc1.20121017git91d9eec/disk-io.c
+--- btrfs-progs-0.20.rc1.20121017git91d9eec.old/disk-io.c	2013-02-13 11:04:05.361458311 +0000
++++ btrfs-progs-0.20.rc1.20121017git91d9eec/disk-io.c	2013-02-13 11:04:22.513377018 +0000
+@@ -634,6 +634,9 @@
+ 	if (sb_bytenr == 0)
+ 		sb_bytenr = BTRFS_SUPER_INFO_OFFSET;
+ 
++	/* try to drop all the caches */
++	posix_fadvise(fp, 0, 0, POSIX_FADV_DONTNEED);
++
+ 	ret = btrfs_scan_one_device(fp, path, &fs_devices,
+ 				    &total_devs, sb_bytenr);
+ 
+@@ -1083,6 +1086,10 @@
+ 	list = &fs_info->fs_devices->devices;
+ 	list_for_each_safe(next, tmp, list) {
+ 		device = list_entry(next, struct btrfs_device, dev_list);
++		if (device->fd) {
++			fsync(device->fd);
++			posix_fadvise(device->fd, 0, 0, POSIX_FADV_DONTNEED);
++		}
+ 		close(device->fd);
+ 		list_del(&device->dev_list);
+ 		free(device->name);
+diff -ur btrfs-progs-0.20.rc1.20121017git91d9eec.old/disk-io.c.orig btrfs-progs-0.20.rc1.20121017git91d9eec/disk-io.c.orig
+--- btrfs-progs-0.20.rc1.20121017git91d9eec.old/disk-io.c.orig	2012-10-05 01:35:31.000000000 +0100
++++ btrfs-progs-0.20.rc1.20121017git91d9eec/disk-io.c.orig	2013-02-13 11:04:05.361458311 +0000
+@@ -458,8 +458,10 @@
+ 	u64 blocknr = btrfs_super_log_root(disk_super);
+ 	struct btrfs_root *log_root = malloc(sizeof(struct btrfs_root));
+ 
+-	if (blocknr == 0)
++	if (blocknr == 0) {
++		free(log_root);
+ 		return 0;
++	}
+ 
+ 	blocksize = btrfs_level_size(tree_root,
+ 			     btrfs_super_log_root_level(disk_super));
+@@ -622,7 +624,7 @@
+ 	struct btrfs_root *chunk_root = malloc(sizeof(struct btrfs_root));
+ 	struct btrfs_root *dev_root = malloc(sizeof(struct btrfs_root));
+ 	struct btrfs_root *csum_root = malloc(sizeof(struct btrfs_root));
+-	struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info));
++	struct btrfs_fs_info *fs_info = malloc(sizeof(struct btrfs_fs_info));
+ 	int ret;
+ 	struct btrfs_super_block *disk_super;
+ 	struct btrfs_fs_devices *fs_devices = NULL;
+@@ -646,7 +648,7 @@
+ 			goto out;
+ 	}
+ 
+-	memset(fs_info, 0, sizeof(*fs_info));
++	memset(fs_info, 0, sizeof(struct btrfs_fs_info));
+ 	fs_info->tree_root = tree_root;
+ 	fs_info->extent_root = extent_root;
+ 	fs_info->chunk_root = chunk_root;
+@@ -1075,15 +1077,19 @@
+ {
+ 	struct list_head *list;
+ 	struct list_head *next;
++	struct list_head *tmp;
+ 	struct btrfs_device *device;
+ 
+-	return 0;
+-
+ 	list = &fs_info->fs_devices->devices;
+-	list_for_each(next, list) {
++	list_for_each_safe(next, tmp, list) {
+ 		device = list_entry(next, struct btrfs_device, dev_list);
+ 		close(device->fd);
++		list_del(&device->dev_list);
++		free(device->name);
++		free(device->label);
++		free(device);
+ 	}
++	free(fs_info->fs_devices);
+ 	return 0;
+ }
+ 
+@@ -1133,12 +1139,14 @@
+ 	extent_io_tree_cleanup(&fs_info->pinned_extents);
+ 	extent_io_tree_cleanup(&fs_info->pending_del);
+ 	extent_io_tree_cleanup(&fs_info->extent_ins);
++	btrfs_mapping_tree_free(&fs_info->mapping_tree);
+ 
+ 	free(fs_info->tree_root);
+ 	free(fs_info->extent_root);
+ 	free(fs_info->chunk_root);
+ 	free(fs_info->dev_root);
+ 	free(fs_info->csum_root);
++	free(fs_info->log_root_tree);
+ 	free(fs_info);
+ 
+ 	return 0;
+diff -ur btrfs-progs-0.20.rc1.20121017git91d9eec.old/volumes.c btrfs-progs-0.20.rc1.20121017git91d9eec/volumes.c
+--- btrfs-progs-0.20.rc1.20121017git91d9eec.old/volumes.c	2013-02-13 11:04:05.411458074 +0000
++++ btrfs-progs-0.20.rc1.20121017git91d9eec/volumes.c	2013-02-13 11:04:22.514377013 +0000
+@@ -176,6 +176,8 @@
+ 			goto fail;
+ 		}
+ 
++		posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
++
+ 		if (device->devid == fs_devices->latest_devid)
+ 			fs_devices->latest_bdev = fd;
+ 		if (device->devid == fs_devices->lowest_devid)