mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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:

  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®