All of lore.kernel.org
 help / color / mirror / Atom feed
From: lizf@kernel.org
To: stable@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
	Hin-Tak Leung <htl10@users.sourceforge.net>,
	Sergei Antonov <saproj@gmail.com>,
	Al Viro <viro@zeniv.linux.org.uk>,
	Christoph Hellwig <hch@infradead.org>,
	Vyacheslav Dubeyko <slava@dubeyko.com>,
	Sougata Santra <sougata@tuxera.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Zefan Li <lizefan@huawei.com>
Subject: [PATCH 3.4 27/92] hfs,hfsplus: cache pages correctly between bnode_create and bnode_free
Date: Mon, 18 Apr 2016 18:45:32 +0800	[thread overview]
Message-ID: <1460976397-5688-27-git-send-email-lizf@kernel.org> (raw)
In-Reply-To: <1460976338-5631-1-git-send-email-lizf@kernel.org>

From: Hin-Tak Leung <htl10@users.sourceforge.net>

3.4.112-rc1 review patch.  If anyone has any objections, please let me know.

------------------


commit 7cb74be6fd827e314f81df3c5889b87e4c87c569 upstream.

Pages looked up by __hfs_bnode_create() (called by hfs_bnode_create() and
hfs_bnode_find() for finding or creating pages corresponding to an inode)
are immediately kmap()'ed and used (both read and write) and kunmap()'ed,
and should not be page_cache_release()'ed until hfs_bnode_free().

This patch fixes a problem I first saw in July 2012: merely running "du"
on a large hfsplus-mounted directory a few times on a reasonably loaded
system would get the hfsplus driver all confused and complaining about
B-tree inconsistencies, and generates a "BUG: Bad page state".  Most
recently, I can generate this problem on up-to-date Fedora 22 with shipped
kernel 4.0.5, by running "du /" (="/" + "/home" + "/mnt" + other smaller
mounts) and "du /mnt" simultaneously on two windows, where /mnt is a
lightly-used QEMU VM image of the full Mac OS X 10.9:

$ df -i / /home /mnt
Filesystem                  Inodes   IUsed      IFree IUse% Mounted on
/dev/mapper/fedora-root    3276800  551665    2725135   17% /
/dev/mapper/fedora-home   52879360  716221   52163139    2% /home
/dev/nbd0p2             4294967295 1387818 4293579477    1% /mnt

After applying the patch, I was able to run "du /" (60+ times) and "du
/mnt" (150+ times) continuously and simultaneously for 6+ hours.

There are many reports of the hfsplus driver getting confused under load
and generating "BUG: Bad page state" or other similar issues over the
years.  [1]

The unpatched code [2] has always been wrong since it entered the kernel
tree.  The only reason why it gets away with it is that the
kmap/memcpy/kunmap follow very quickly after the page_cache_release() so
the kernel has not had a chance to reuse the memory for something else,
most of the time.

The current RW driver appears to have followed the design and development
of the earlier read-only hfsplus driver [3], where-by version 0.1 (Dec
2001) had a B-tree node-centric approach to
read_cache_page()/page_cache_release() per bnode_get()/bnode_put(),
migrating towards version 0.2 (June 2002) of caching and releasing pages
per inode extents.  When the current RW code first entered the kernel [2]
in 2005, there was an REF_PAGES conditional (and "//" commented out code)
to switch between B-node centric paging to inode-centric paging.  There
was a mistake with the direction of one of the REF_PAGES conditionals in
__hfs_bnode_create().  In a subsequent "remove debug code" commit [4], the
read_cache_page()/page_cache_release() per bnode_get()/bnode_put() were
removed, but a page_cache_release() was mistakenly left in (propagating
the "REF_PAGES <-> !REF_PAGE" mistake), and the commented-out
page_cache_release() in bnode_release() (which should be spanned by
!REF_PAGES) was never enabled.

References:
[1]:
Michael Fox, Apr 2013
http://www.spinics.net/lists/linux-fsdevel/msg63807.html
("hfsplus volume suddenly inaccessable after 'hfs: recoff %d too large'")

Sasha Levin, Feb 2015
http://lkml.org/lkml/2015/2/20/85 ("use after free")

https://bugs.launchpad.net/ubuntu/+source/linux/+bug/740814
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1027887
https://bugzilla.kernel.org/show_bug.cgi?id=42342
https://bugzilla.kernel.org/show_bug.cgi?id=63841
https://bugzilla.kernel.org/show_bug.cgi?id=78761

[2]:
http://git.kernel.org/cgit/linux/kernel/git/tglx/history.git/commit/\
fs/hfs/bnode.c?id=d1081202f1d0ee35ab0beb490da4b65d4bc763db
commit d1081202f1d0ee35ab0beb490da4b65d4bc763db
Author: Andrew Morton <akpm@osdl.org>
Date:   Wed Feb 25 16:17:36 2004 -0800

    [PATCH] HFS rewrite

http://git.kernel.org/cgit/linux/kernel/git/tglx/history.git/commit/\
fs/hfsplus/bnode.c?id=91556682e0bf004d98a529bf829d339abb98bbbd

commit 91556682e0bf004d98a529bf829d339abb98bbbd
Author: Andrew Morton <akpm@osdl.org>
Date:   Wed Feb 25 16:17:48 2004 -0800

    [PATCH] HFS+ support

[3]:
http://sourceforge.net/projects/linux-hfsplus/

http://sourceforge.net/projects/linux-hfsplus/files/Linux%202.4.x%20patch/hfsplus%200.1/
http://sourceforge.net/projects/linux-hfsplus/files/Linux%202.4.x%20patch/hfsplus%200.2/

http://linux-hfsplus.cvs.sourceforge.net/viewvc/linux-hfsplus/linux/\
fs/hfsplus/bnode.c?r1=1.4&r2=1.5

Date:   Thu Jun 6 09:45:14 2002 +0000
Use buffer cache instead of page cache in bnode.c. Cache inode extents.

[4]:
http://git.kernel.org/cgit/linux/kernel/git/\
stable/linux-stable.git/commit/?id=a5e3985fa014029eb6795664c704953720cc7f7d

commit a5e3985fa014029eb6795664c704953720cc7f7d
Author: Roman Zippel <zippel@linux-m68k.org>
Date:   Tue Sep 6 15:18:47 2005 -0700

[PATCH] hfs: remove debug code

Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: Sergei Antonov <saproj@gmail.com>
Reviewed-by: Anton Altaparmakov <anton@tuxera.com>
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Vyacheslav Dubeyko <slava@dubeyko.com>
Cc: Sougata Santra <sougata@tuxera.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Zefan Li <lizefan@huawei.com>
---
 fs/hfs/bnode.c     | 9 ++++-----
 fs/hfsplus/bnode.c | 3 ---
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index cdb41a1..8daea16 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -287,7 +287,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 			page_cache_release(page);
 			goto fail;
 		}
-		page_cache_release(page);
 		node->page[i] = page;
 	}
 
@@ -397,11 +396,11 @@ node_error:
 
 void hfs_bnode_free(struct hfs_bnode *node)
 {
-	//int i;
+	int i;
 
-	//for (i = 0; i < node->tree->pages_per_bnode; i++)
-	//	if (node->page[i])
-	//		page_cache_release(node->page[i]);
+	for (i = 0; i < node->tree->pages_per_bnode; i++)
+		if (node->page[i])
+			page_cache_release(node->page[i]);
 	kfree(node);
 }
 
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 1c42cc5..a1e9109 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -454,7 +454,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 			page_cache_release(page);
 			goto fail;
 		}
-		page_cache_release(page);
 		node->page[i] = page;
 	}
 
@@ -566,13 +565,11 @@ node_error:
 
 void hfs_bnode_free(struct hfs_bnode *node)
 {
-#if 0
 	int i;
 
 	for (i = 0; i < node->tree->pages_per_bnode; i++)
 		if (node->page[i])
 			page_cache_release(node->page[i]);
-#endif
 	kfree(node);
 }
 
-- 
1.9.1

  parent reply	other threads:[~2016-04-18 10:48 UTC|newest]

Thread overview: 98+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-18 10:45 [PATCH 3.4 00/92] 3.4.112-rc1 review lizf
2016-04-18 10:45 ` [PATCH 3.4 01/92] rc-core: fix remove uevent generation lizf
2016-04-18 10:45 ` [PATCH 3.4 02/92] PCI: Fix TI816X class code quirk lizf
2016-04-18 10:45 ` [PATCH 3.4 03/92] mac80211: enable assoc check for mesh interfaces lizf
2016-04-18 10:45 ` [PATCH 3.4 04/92] PCI: Add dev_flags bit to access VPD through function 0 lizf
2016-04-18 10:45 ` [PATCH 3.4 05/92] PCI: Add VPD function 0 quirk for Intel Ethernet devices lizf
2016-04-18 10:45 ` [PATCH 3.4 06/92] powerpc/rtas: Introduce rtas_get_sensor_fast() for IRQ handlers lizf
2016-04-18 10:45 ` [PATCH 3.4 07/92] svcrdma: Fix send_reply() scatter/gather set-up lizf
2016-04-18 10:45 ` [PATCH 3.4 08/92] md/raid0: update queue parameter in a safer location lizf
2016-04-18 10:45 ` [PATCH 3.4 09/92] auxdisplay: ks0108: fix refcount lizf
2016-04-18 10:45 ` [PATCH 3.4 10/92] devres: fix devres_get() lizf
2016-04-18 10:45 ` [PATCH 3.4 11/92] windfarm: decrement client count when unregistering lizf
2016-04-18 10:45 ` [PATCH 3.4 12/92] NFSv4: don't set SETATTR for O_RDONLY|O_EXCL lizf
2016-04-18 10:45 ` [PATCH 3.4 13/92] usb: host: ehci-sys: delete useless bus_to_hcd conversion lizf
2016-04-18 10:45 ` [PATCH 3.4 14/92] USB: ftdi_sio: Added custom PID for CustomWare products lizf
2016-04-18 10:45 ` [PATCH 3.4 15/92] eCryptfs: Invalidate dcache entries when lower i_nlink is zero lizf
2016-04-18 10:45 ` [PATCH 3.4 16/92] DRM - radeon: Don't link train DisplayPort on HPD until we get the dpcd lizf
2016-04-18 10:45 ` [PATCH 3.4 17/92] of/address: Don't loop forever in of_find_matching_node_by_address() lizf
2016-04-18 10:45 ` [PATCH 3.4 18/92] drivercore: Fix unregistration path of platform devices lizf
2016-04-18 10:45 ` [PATCH 3.4 19/92] SUNRPC: xs_reset_transport must mark the connection as disconnected lizf
2016-04-18 10:45 ` [PATCH 3.4 20/92] IB/mlx4: Use correct SL on AH query under RoCE lizf
2016-04-18 10:45 ` [PATCH 3.4 21/92] IB/uverbs: Fix race between ib_uverbs_open and remove_one lizf
2016-04-18 10:45 ` [PATCH 3.4 22/92] Add radeon suspend/resume quirk for HP Compaq dc5750 lizf
2016-04-18 10:45 ` [PATCH 3.4 23/92] IB/uverbs: reject invalid or unknown opcodes lizf
2016-04-18 10:45 ` [PATCH 3.4 24/92] hpfs: update ctime and mtime on directory modification lizf
2016-04-18 10:45 ` [PATCH 3.4 25/92] crypto: ghash-clmulni: specify context size for ghash async algorithm lizf
2016-04-18 10:45 ` [PATCH 3.4 26/92] fs: create and use seq_show_option for escaping lizf
2016-04-18 10:45 ` lizf [this message]
2016-04-18 10:45 ` [PATCH 3.4 28/92] hfs: fix B-tree corruption after insertion at position 0 lizf
2016-04-18 10:45 ` [PATCH 3.4 29/92] scsi_dh: fix randconfig build error lizf
2016-04-18 10:45 ` [PATCH 3.4 30/92] ARM: 8429/1: disable GCC SRA optimization lizf
2016-04-18 10:45 ` [PATCH 3.4 31/92] powerpc/MSI: Fix race condition in tearing down MSI interrupts lizf
2016-04-18 10:45 ` [PATCH 3.4 32/92] perf header: Fixup reading of HEADER_NRCPUS feature lizf
2016-04-18 10:45 ` [PATCH 3.4 33/92] ARM: 7880/1: Clear the IT state independent of the Thumb-2 mode lizf
2016-04-18 10:45 ` [PATCH 3.4 34/92] ARM: fix Thumb2 signal handling when ARMv6 is enabled lizf
2016-04-18 10:45 ` [PATCH 3.4 35/92] x86/platform: Fix Geode LX timekeeping in the generic x86 build lizf
2016-04-18 10:45 ` [PATCH 3.4 36/92] module: Fix locking in symbol_put_addr() lizf
2016-04-18 10:45 ` [PATCH 3.4 37/92] ipv6: Fix IPsec pre-encap fragmentation check lizf
2016-04-18 10:45 ` [PATCH 3.4 38/92] ASoC: fix broken pxa SoC support lizf
2016-04-18 10:45 ` [PATCH 3.4 39/92] MIPS: dma-default: Fix 32-bit fall back to GFP_DMA lizf
2016-04-18 10:45 ` [PATCH 3.4 40/92] md/raid0: apply base queue limits *before* disk_stack_limits lizf
2016-04-18 10:45 ` [PATCH 3.4 41/92] iwlwifi: dvm: fix D3 firmware PN programming lizf
2016-04-18 10:45 ` [PATCH 3.4 42/92] sched/core: Fix TASK_DEAD race in finish_task_switch() lizf
2016-04-18 10:45 ` [PATCH 3.4 43/92] IB/cm: Fix rb-tree duplicate free and use-after-free lizf
2016-04-18 10:45 ` [PATCH 3.4 44/92] powerpc/rtas: Validate rtas.entry before calling enter_rtas() lizf
2016-04-18 10:45 ` [PATCH 3.4 45/92] md/raid10: ensure device failure recorded before write request returns lizf
2016-04-18 10:45 ` [PATCH 3.4 46/92] md/raid10: don't clear bitmap bit when bad-block-list write fails lizf
2016-04-18 10:45 ` [PATCH 3.4 47/92] md/raid1: ensure device failure recorded before write request returns lizf
2016-04-18 10:45 ` [PATCH 3.4 48/92] md/raid1: don't clear bitmap bit when bad-block-list write fails lizf
2016-04-18 10:45 ` [PATCH 3.4 49/92] drm: crtc: integer overflow in drm_property_create_blob() lizf
2016-04-18 10:45 ` [PATCH 3.4 50/92] spi: spi-pxa2xx: Check status register to determine if SSSR_TINT is disabled lizf
2016-04-18 10:45 ` [PATCH 3.4 51/92] spi: Fix documentation of spi_alloc_master() lizf
2016-04-18 10:45 ` [PATCH 3.4 52/92] btrfs: skip waiting on ordered range for special files lizf
2016-04-18 10:45 ` [PATCH 3.4 53/92] regmap: debugfs: Ensure we don't underflow when printing access masks lizf
2016-04-18 10:45 ` [PATCH 3.4 54/92] regmap: debugfs: Don't bother actually printing when calculating max length lizf
2016-04-18 10:46 ` [PATCH 3.4 55/92] KVM: x86: trap AMD MSRs for the TSeg base and mask lizf
2016-04-18 10:46 ` [PATCH 3.4 56/92] usb: Use the USB_SS_MULT() macro to get the burst multiplier lizf
2016-04-18 10:46 ` [PATCH 3.4 57/92] xhci: give command abortion one more chance before killing xhci lizf
2016-04-18 10:46 ` [PATCH 3.4 58/92] usb: xhci: Clear XHCI_STATE_DYING on start lizf
2016-04-18 10:46 ` [PATCH 3.4 59/92] xhci: change xhci 1.0 only restrictions to support xhci 1.1 lizf
2016-04-18 10:46 ` [PATCH 3.4 60/92] cifs: use server timestamp for ntlmv2 authentication lizf
2016-04-18 10:46 ` [PATCH 3.4 61/92] ocfs2/dlm: fix deadlock when dispatch assert master lizf
2016-04-18 11:29   ` Joseph Qi
2016-04-19  0:18     ` Zefan Li
2016-04-18 10:46 ` [PATCH 3.4 62/92] ath9k: declare required extra tx headroom lizf
2016-04-18 10:46 ` [PATCH 3.4 63/92] m68k: Define asmlinkage_protect lizf
2016-04-18 10:46 ` [PATCH 3.4 64/92] x86/xen: Do not clip xen_e820_map to xen_e820_map_entries when sanitizing map lizf
2016-04-18 10:46 ` [PATCH 3.4 65/92] UBI: Validate data_size lizf
2016-04-18 10:46 ` [PATCH 3.4 66/92] UBI: return ENOSPC if no enough space available lizf
2016-04-18 10:46 ` [PATCH 3.4 67/92] x86/process: Add proper bound checks in 64bit get_wchan() lizf
2016-04-18 10:46 ` [PATCH 3.4 68/92] genirq: Fix race in register_irq_proc() lizf
2016-04-18 10:46 ` [PATCH 3.4 69/92] mm: hugetlbfs: skip shared VMAs when unmapping private pages to satisfy a fault lizf
2016-04-18 10:46 ` [PATCH 3.4 70/92] clocksource: Fix abs() usage w/ 64bit values lizf
2016-04-18 10:46 ` [PATCH 3.4 71/92] USB: Add reset-resume quirk for two Plantronics usb headphones lizf
2016-04-18 10:46 ` [PATCH 3.4 72/92] usb: Add device quirk for Logitech PTZ cameras lizf
2016-04-18 10:46 ` [PATCH 3.4 73/92] tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c lizf
2016-04-18 10:46 ` [PATCH 3.4 74/92] drivers/tty: require read access for controlling terminal lizf
2016-04-18 10:46 ` [PATCH 3.4 75/92] ALSA: synth: Fix conflicting OSS device registration on AWE32 lizf
2016-04-18 10:46 ` [PATCH 3.4 76/92] xen-blkfront: check for null drvdata in blkback_changed (XenbusStateClosing) lizf
2016-04-18 10:46 ` [PATCH 3.4 77/92] crypto: ahash - ensure statesize is non-zero lizf
2016-04-18 10:46 ` [PATCH 3.4 78/92] iommu/vt-d: fix range computation when making room for large pages lizf
2016-04-18 10:46 ` [PATCH 3.4 79/92] xhci: handle no ping response error properly lizf
2016-04-18 10:46 ` [PATCH 3.4 80/92] xhci: Add spurious wakeup quirk for LynxPoint-LP controllers lizf
2016-04-18 10:46 ` [PATCH 3.4 81/92] crypto: api - Only abort operations on fatal signal lizf
2016-04-18 10:46 ` [PATCH 3.4 82/92] ASoC: wm8904: Correct number of EQ registers lizf
2016-04-18 10:46 ` [PATCH 3.4 83/92] iommu/amd: Don't clear DTE flags when modifying it lizf
2016-04-18 10:46 ` [PATCH 3.4 84/92] drm/nouveau/gem: return only valid domain when there's only one lizf
2016-04-18 10:46 ` [PATCH 3.4 85/92] mm: make sendfile(2) killable lizf
2016-04-18 10:46 ` [PATCH 3.4 86/92] dm btree: fix leak of bufio-backed block in btree_split_beneath error path lizf
2016-04-18 10:46 ` [PATCH 3.4 87/92] mvsas: Fix NULL pointer dereference in mvs_slot_task_free lizf
2016-04-18 10:46 ` [PATCH 3.4 88/92] raid1: include bio_end_io_list in nr_queued to prevent freeze_array hang lizf
2016-04-18 10:46 ` [PATCH 3.4 89/92] usb: Use the USB_SS_MULT() macro to decode burst multiplier for log message lizf
2016-04-18 10:46 ` [PATCH 3.4 90/92] pipe: Fix buffer offset after partially failed read lizf
2016-04-18 10:46 ` [PATCH 3.4 91/92] splice: sendfile() at once fails for big files lizf
2016-04-18 10:57 ` [PATCH 3.4 92/92] x86/iopl/64: Properly context-switch IOPL on Xen PV lizf
2016-04-18 16:37 ` [PATCH 3.4 00/92] 3.4.112-rc1 review Guenter Roeck
2016-04-19  0:18   ` Zefan Li
2016-04-22 16:48 ` Christoph Biedl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1460976397-5688-27-git-send-email-lizf@kernel.org \
    --to=lizf@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=hch@infradead.org \
    --cc=htl10@users.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=saproj@gmail.com \
    --cc=slava@dubeyko.com \
    --cc=sougata@tuxera.com \
    --cc=stable@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.