From: Hugh Dickins <hughd@google.com>
To: Greg KH <gregkh@suse.de>
Cc: linux-kernel@vger.kernel.org, stable@kernel.org,
stable-review@kernel.org, torvalds@linux-foundation.org,
akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
Konstantin Khlebnikov <khlebnikov@openvz.org>,
Witold Baryluk <baryluk@smp.if.uj.edu.pl>,
Nitin Gupta <ngupta@vflare.org>
Subject: Re: [23/71] tmpfs: fix race between umount and swapoff
Date: Fri, 20 May 2011 21:48:26 -0700 (PDT) [thread overview]
Message-ID: <alpine.LSU.2.00.1105202139001.1847@sister.anvils> (raw)
In-Reply-To: <20110519180556.482988919@clark.kroah.org>
On Thu, 19 May 2011, Greg KH wrote:
> 2.6.38-stable review patch. If anyone has any objections, please let us know.
Witold has found that I screwed up the highmem case in this patch.
Please add the commit appended at the bottom - or else delay both
until the next 2.6.38-stable if you prefer.
Thanks,
Hugh
>
> ------------------
>
> From: Hugh Dickins <hughd@google.com>
>
> commit 778dd893ae785c5fd505dac30b5fc40aae188bf1 upstream.
>
> The use of igrab() in swapoff's shmem_unuse_inode() is just as vulnerable
> to umount as that in shmem_writepage().
>
> Fix this instance by extending the protection of shmem_swaplist_mutex
> right across shmem_unuse_inode(): while it's on the list, the inode cannot
> be evicted (and the filesystem cannot be unmounted) without
> shmem_evict_inode() taking that mutex to remove it from the list.
>
> But since shmem_writepage() might take that mutex, we should avoid making
> memory allocations or memcg charges while holding it: prepare them at the
> outer level in shmem_unuse(). When mem_cgroup_cache_charge() was
> originally placed, we didn't know until that point that the page from swap
> was actually a shmem page; but nowadays it's noted in the swap_map, so
> we're safe to charge upfront. For the radix_tree, do as is done in
> shmem_getpage(): preload upfront, but don't pin to the cpu; so we make a
> habit of refreshing the node pool, but might dip into GFP_NOWAIT reserves
> on occasion if subsequently preempted.
>
> With the allocation and charge moved out from shmem_unuse_inode(),
> we can also hold index map and info->lock over from finding the entry.
>
> Signed-off-by: Hugh Dickins <hughd@google.com>
> Cc: Konstantin Khlebnikov <khlebnikov@openvz.org>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
>
> ---
> mm/shmem.c | 88 +++++++++++++++++++++++++++++--------------------------------
> 1 file changed, 43 insertions(+), 45 deletions(-)
>
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -852,7 +852,7 @@ static inline int shmem_find_swp(swp_ent
>
> static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
> {
> - struct inode *inode;
> + struct address_space *mapping;
> unsigned long idx;
> unsigned long size;
> unsigned long limit;
> @@ -875,8 +875,10 @@ static int shmem_unuse_inode(struct shme
> if (size > SHMEM_NR_DIRECT)
> size = SHMEM_NR_DIRECT;
> offset = shmem_find_swp(entry, ptr, ptr+size);
> - if (offset >= 0)
> + if (offset >= 0) {
> + shmem_swp_balance_unmap();
> goto found;
> + }
> if (!info->i_indirect)
> goto lost2;
>
> @@ -914,11 +916,11 @@ static int shmem_unuse_inode(struct shme
> if (size > ENTRIES_PER_PAGE)
> size = ENTRIES_PER_PAGE;
> offset = shmem_find_swp(entry, ptr, ptr+size);
> - shmem_swp_unmap(ptr);
> if (offset >= 0) {
> shmem_dir_unmap(dir);
> goto found;
> }
> + shmem_swp_unmap(ptr);
> }
> }
> lost1:
> @@ -928,8 +930,7 @@ lost2:
> return 0;
> found:
> idx += offset;
> - inode = igrab(&info->vfs_inode);
> - spin_unlock(&info->lock);
> + ptr += offset;
>
> /*
> * Move _head_ to start search for next from here.
> @@ -940,37 +941,18 @@ found:
> */
> if (shmem_swaplist.next != &info->swaplist)
> list_move_tail(&shmem_swaplist, &info->swaplist);
> - mutex_unlock(&shmem_swaplist_mutex);
>
> - error = 1;
> - if (!inode)
> - goto out;
> /*
> - * Charge page using GFP_KERNEL while we can wait.
> - * Charged back to the user(not to caller) when swap account is used.
> - * add_to_page_cache() will be called with GFP_NOWAIT.
> + * We rely on shmem_swaplist_mutex, not only to protect the swaplist,
> + * but also to hold up shmem_evict_inode(): so inode cannot be freed
> + * beneath us (pagelock doesn't help until the page is in pagecache).
> */
> - error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
> - if (error)
> - goto out;
> - error = radix_tree_preload(GFP_KERNEL);
> - if (error) {
> - mem_cgroup_uncharge_cache_page(page);
> - goto out;
> - }
> - error = 1;
> -
> - spin_lock(&info->lock);
> - ptr = shmem_swp_entry(info, idx, NULL);
> - if (ptr && ptr->val == entry.val) {
> - error = add_to_page_cache_locked(page, inode->i_mapping,
> - idx, GFP_NOWAIT);
> - /* does mem_cgroup_uncharge_cache_page on error */
> - } else /* we must compensate for our precharge above */
> - mem_cgroup_uncharge_cache_page(page);
> + mapping = info->vfs_inode.i_mapping;
> + error = add_to_page_cache_locked(page, mapping, idx, GFP_NOWAIT);
> + /* which does mem_cgroup_uncharge_cache_page on error */
>
> if (error == -EEXIST) {
> - struct page *filepage = find_get_page(inode->i_mapping, idx);
> + struct page *filepage = find_get_page(mapping, idx);
> error = 1;
> if (filepage) {
> /*
> @@ -990,14 +972,8 @@ found:
> swap_free(entry);
> error = 1; /* not an error, but entry was found */
> }
> - if (ptr)
> - shmem_swp_unmap(ptr);
> + shmem_swp_unmap(ptr);
> spin_unlock(&info->lock);
> - radix_tree_preload_end();
> -out:
> - unlock_page(page);
> - page_cache_release(page);
> - iput(inode); /* allows for NULL */
> return error;
> }
>
> @@ -1009,6 +985,26 @@ int shmem_unuse(swp_entry_t entry, struc
> struct list_head *p, *next;
> struct shmem_inode_info *info;
> int found = 0;
> + int error;
> +
> + /*
> + * Charge page using GFP_KERNEL while we can wait, before taking
> + * the shmem_swaplist_mutex which might hold up shmem_writepage().
> + * Charged back to the user (not to caller) when swap account is used.
> + * add_to_page_cache() will be called with GFP_NOWAIT.
> + */
> + error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
> + if (error)
> + goto out;
> + /*
> + * Try to preload while we can wait, to not make a habit of
> + * draining atomic reserves; but don't latch on to this cpu,
> + * it's okay if sometimes we get rescheduled after this.
> + */
> + error = radix_tree_preload(GFP_KERNEL);
> + if (error)
> + goto uncharge;
> + radix_tree_preload_end();
>
> mutex_lock(&shmem_swaplist_mutex);
> list_for_each_safe(p, next, &shmem_swaplist) {
> @@ -1016,17 +1012,19 @@ int shmem_unuse(swp_entry_t entry, struc
> found = shmem_unuse_inode(info, entry, page);
> cond_resched();
> if (found)
> - goto out;
> + break;
> }
> mutex_unlock(&shmem_swaplist_mutex);
> - /*
> - * Can some race bring us here? We've been holding page lock,
> - * so I think not; but would rather try again later than BUG()
> - */
> +
> +uncharge:
> + if (!found)
> + mem_cgroup_uncharge_cache_page(page);
> + if (found < 0)
> + error = found;
> +out:
> unlock_page(page);
> page_cache_release(page);
> -out:
> - return (found < 0) ? found : 0;
> + return error;
> }
>
> /*
commit e6c9366b2adb52cba64b359b3050200743c7568c
Author: Hugh Dickins <hughd@google.com>
Date: Fri May 20 15:47:33 2011 -0700
tmpfs: fix highmem swapoff crash regression
Commit 778dd893ae78 ("tmpfs: fix race between umount and swapoff")
forgot the new rules for strict atomic kmap nesting, causing
WARNING: at arch/x86/mm/highmem_32.c:81
from __kunmap_atomic(), then
BUG: unable to handle kernel paging request at fffb9000
from shmem_swp_set() when shmem_unuse_inode() is handling swapoff with
highmem in use. My disgrace again.
See
https://bugzilla.kernel.org/show_bug.cgi?id=35352
Reported-by: Witold Baryluk <baryluk@smp.if.uj.edu.pl>
Signed-off-by: Hugh Dickins <hughd@google.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/mm/shmem.c b/mm/shmem.c
index dfc7069..ba4ad28 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -916,11 +916,12 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
if (size > ENTRIES_PER_PAGE)
size = ENTRIES_PER_PAGE;
offset = shmem_find_swp(entry, ptr, ptr+size);
+ shmem_swp_unmap(ptr);
if (offset >= 0) {
shmem_dir_unmap(dir);
+ ptr = shmem_swp_map(subdir);
goto found;
}
- shmem_swp_unmap(ptr);
}
}
lost1:
next prev parent reply other threads:[~2011-05-21 4:48 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-19 18:06 [00/71] 2.6.38.7-stable review Greg KH
2011-05-19 18:04 ` [01/71] cifs: change bleft in decode_unicode_ssetup back to signed type Greg KH
2011-05-19 18:04 ` [02/71] cifs: check for bytes_remaining going to zero in CIFS_SessSetup Greg KH
2011-05-19 18:04 ` [03/71] cifs: sanitize length checking in coalesce_t2 (try #3) Greg KH
2011-05-19 18:04 ` [04/71] cifs: refactor mid finding loop in cifs_demultiplex_thread Greg KH
2011-05-19 18:04 ` [05/71] cifs: handle errors from coalesce_t2 Greg KH
2011-05-19 18:04 ` [06/71] Validate size of EFI GUID partition entries Greg KH
2011-05-19 18:04 ` [07/71] drm/radeon/kms: add pci id to acer travelmate quirk for 5730 Greg KH
2011-05-19 18:04 ` [08/71] thinkpad-acpi: module autoloading for newer Lenovo ThinkPads Greg KH
2011-05-20 0:58 ` Henrique de Moraes Holschuh
2011-05-19 18:04 ` [09/71] x86, hw_breakpoints: Fix racy access to ptrace breakpoints Greg KH
2011-05-19 18:04 ` [10/71] ptrace: Prepare to fix racy accesses on task breakpoints Greg KH
2011-05-19 18:04 ` [11/71] hw_breakpoints, powerpc: Fix CONFIG_HAVE_HW_BREAKPOINT off-case in ptrace_set_debugreg() Greg KH
2011-05-19 18:04 ` [12/71] iwlwifi: add {ack, plpc}_check module parameters Greg KH
2011-05-19 18:04 ` [13/71] [stable] [PATCH] drm/radeon/kms: fix gart setup on fusion parts (v2) backport Greg KH
2011-05-19 18:04 ` [14/71] vm: fix vm_pgoff wrap in upward expansion Greg KH
2011-05-19 18:04 ` [15/71] Dont lock guardpage if the stack is growing up Greg KH
2011-05-19 18:04 ` [16/71] drm/i915/dp: Be paranoid in case we disable a DP before it is attached Greg KH
2011-05-19 18:04 ` [17/71] drm/i915/lvds: Only act on lid notify when the device is on Greg KH
2011-05-19 18:04 ` [18/71] drm/i915: Release object along create user fb error path Greg KH
2011-05-19 18:04 ` [19/71] dccp: handle invalid feature options length Greg KH
2011-05-19 18:04 ` [20/71] CIFS: Fix memory over bound bug in cifs_parse_mount_options Greg KH
2011-05-19 18:04 ` [21/71] drivers/rtc/rtc-s3c.c: fixup wake support for rtc Greg KH
2011-05-19 18:04 ` [22/71] mm: use alloc_bootmem_node_nopanic() on really needed path Greg KH
2011-05-19 18:04 ` [23/71] tmpfs: fix race between umount and swapoff Greg KH
2011-05-21 4:48 ` Hugh Dickins [this message]
2011-05-21 21:43 ` Greg KH
2011-05-19 18:04 ` [24/71] ARM: zImage: make sure the stack is 64-bit aligned Greg KH
2011-05-19 18:04 ` [25/71] PM: Fix warning in pm_restrict_gfp_mask() during SNAPSHOT_S2RAM ioctl Greg KH
2011-05-19 18:04 ` [26/71] PM / Hibernate: Make snapshot_release() restore GFP mask Greg KH
2011-05-19 18:04 ` [27/71] PM / Hibernate: Fix ioctl SNAPSHOT_S2RAM Greg KH
2011-05-19 18:04 ` [28/71] net: ip_expire() must revalidate route Greg KH
2011-05-19 18:04 ` [29/71] can: fix SJA1000 dlc for RTR packets Greg KH
2011-05-19 20:17 ` Kurt Van Dijck
2011-05-19 18:04 ` [30/71] ipheth: Properly distinguish length and alignment in URBs and skbs Greg KH
2011-05-19 18:04 ` [31/71] vmxnet3: Consistently disable irqs when taking adapter->cmd_lock Greg KH
2011-05-19 18:05 ` [32/71] ehea: fix wrongly reported speed and port Greg KH
2011-05-19 18:05 ` [33/71] NET: slip, fix ldisc->open retval Greg KH
2011-05-19 18:05 ` [34/71] PCH_GbE : Fixed the issue of collision detection Greg KH
2011-05-19 18:05 ` [35/71] PCH_GbE : Fixed the issue of checksum judgment Greg KH
2011-05-19 18:05 ` [36/71] pch_gbe: support ML7223 IOH Greg KH
2011-05-19 18:05 ` [37/71] net: dev_close() should check IFF_UP Greg KH
2011-05-19 18:05 ` [38/71] slcan: fix ldisc->open retval Greg KH
2011-05-19 18:05 ` [39/71] ASoC: UDA134x: Remove POWER_OFF_ON_STANDBY define Greg KH
2011-05-19 18:05 ` [40/71] ASoC: SSM2602: Fix Mic Boost2 control Greg KH
2011-05-19 18:05 ` [41/71] ne-h8300: Fix regression caused during net_device_ops conversion Greg KH
2011-05-19 18:05 ` [42/71] hydra: " Greg KH
2011-05-19 18:05 ` [43/71] ehea: Fix memory hotplug oops Greg KH
2011-05-19 18:05 ` [44/71] libertas: fix cmdpendingq locking Greg KH
2011-05-19 18:05 ` [45/71] zorro8390: Fix regression caused during net_device_ops conversion Greg KH
2011-05-19 18:05 ` [46/71] tmpfs: fix race between umount and writepage Greg KH
2011-05-19 18:05 ` [47/71] tmpfs: fix race between swapoff " Greg KH
2011-05-19 18:05 ` [48/71] tmpfs: fix off-by-one in max_blocks checks Greg KH
2011-05-19 18:05 ` [49/71] tmpfs: fix spurious ENOSPC when racing with unswap Greg KH
2011-05-19 18:05 ` [50/71] libata: fix oops when LPM is used with PMP Greg KH
2011-05-19 18:05 ` [51/71] drm/radeon/kms: fix extended lvds info parsing Greg KH
2011-05-19 18:05 ` [52/71] Revert "mmc: fix a race between card-detect rescan and clock-gate work instances" Greg KH
2011-05-19 18:05 ` [53/71] cifs: add fallback in is_path_accessible for old servers Greg KH
2011-05-19 18:05 ` [54/71] rapidio: fix default routing initialization Greg KH
2011-05-19 18:05 ` [55/71] Revert "x86, AMD: Fix APIC timer erratum 400 affecting K8 Rev.A-E processors" Greg KH
2011-05-19 18:05 ` [56/71] x86, AMD: Fix ARAT feature setting again Greg KH
2011-05-19 18:05 ` [57/71] block: rescan partitions on invalidated devices on -ENOMEDIA too Greg KH
2011-05-19 18:12 ` Tejun Heo
2011-05-19 18:18 ` Greg KH
2011-05-25 9:09 ` Tejun Heo
2011-05-30 0:01 ` [stable] " Greg KH
2011-05-19 18:05 ` [58/71] clocksource: Install completely before selecting Greg KH
2011-05-19 18:05 ` [59/71] tick: Clear broadcast active bit when switching to oneshot Greg KH
2011-05-19 18:05 ` [60/71] x86, apic: Fix spurious error interrupts triggering on all non-boot APs Greg KH
2011-05-19 18:05 ` [61/71] [media] Fix cx88 remote control input Greg KH
2011-05-19 18:05 ` [62/71] [media] v4l: Release module if subdev registration fails Greg KH
2011-05-19 18:05 ` [63/71] x86: Fix UV BAU for non-consecutive nasids Greg KH
2011-05-19 18:05 ` [64/71] x86, mce, AMD: Fix leaving freed data in a list Greg KH
2011-05-19 18:05 ` [65/71] [SCSI] megaraid_sas: Sanity check user supplied length before passing it to dma_alloc_coherent() Greg KH
2011-05-19 18:05 ` [66/71] cdrom: always check_disk_change() on open Greg KH
2011-05-19 18:05 ` [67/71] vmxnet3: Fix inconsistent LRO state after initialization Greg KH
2011-05-19 18:05 ` [68/71] [SCSI] Revert "[SCSI] Retrieve the Caching mode page" Greg KH
2011-05-19 18:05 ` [69/71] cifs: clean up various nits in unicode routines (try #2) Greg KH
2011-05-19 18:05 ` [70/71] cifs: fix cifsConvertToUCS() for the mapchars case Greg KH
2011-05-19 18:05 ` [71/71] iwlegacy: fix IBSS mode crashes Greg KH
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=alpine.LSU.2.00.1105202139001.1847@sister.anvils \
--to=hughd@google.com \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=baryluk@smp.if.uj.edu.pl \
--cc=gregkh@suse.de \
--cc=khlebnikov@openvz.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ngupta@vflare.org \
--cc=stable-review@kernel.org \
--cc=stable@kernel.org \
--cc=torvalds@linux-foundation.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®