Revision 89a2848381b5fcd9c4d9c0cd97680e3b28730e31 authored by Johannes Weiner on 28 October 2016, 00:46:56 UTC, committed by Linus Torvalds on 28 October 2016, 01:43:43 UTC
On 4.0, we saw a stack corruption from a page fault entering direct memory cgroup reclaim, calling into btrfs_releasepage(), which then tried to allocate an extent and recursed back into a kmem charge ad nauseam: [...] btrfs_releasepage+0x2c/0x30 try_to_release_page+0x32/0x50 shrink_page_list+0x6da/0x7a0 shrink_inactive_list+0x1e5/0x510 shrink_lruvec+0x605/0x7f0 shrink_zone+0xee/0x320 do_try_to_free_pages+0x174/0x440 try_to_free_mem_cgroup_pages+0xa7/0x130 try_charge+0x17b/0x830 memcg_charge_kmem+0x40/0x80 new_slab+0x2d9/0x5a0 __slab_alloc+0x2fd/0x44f kmem_cache_alloc+0x193/0x1e0 alloc_extent_state+0x21/0xc0 __clear_extent_bit+0x2b5/0x400 try_release_extent_mapping+0x1a3/0x220 __btrfs_releasepage+0x31/0x70 btrfs_releasepage+0x2c/0x30 try_to_release_page+0x32/0x50 shrink_page_list+0x6da/0x7a0 shrink_inactive_list+0x1e5/0x510 shrink_lruvec+0x605/0x7f0 shrink_zone+0xee/0x320 do_try_to_free_pages+0x174/0x440 try_to_free_mem_cgroup_pages+0xa7/0x130 try_charge+0x17b/0x830 mem_cgroup_try_charge+0x65/0x1c0 handle_mm_fault+0x117f/0x1510 __do_page_fault+0x177/0x420 do_page_fault+0xc/0x10 page_fault+0x22/0x30 On later kernels, kmem charging is opt-in rather than opt-out, and that particular kmem allocation in btrfs_releasepage() is no longer being charged and won't recurse and overrun the stack anymore. But it's not impossible for an accounted allocation to happen from the memcg direct reclaim context, and we needed to reproduce this crash many times before we even got a useful stack trace out of it. Like other direct reclaimers, mark tasks in memcg reclaim PF_MEMALLOC to avoid recursing into any other form of direct reclaim. Then let recursive charges from PF_MEMALLOC contexts bypass the cgroup limit. Link: http://lkml.kernel.org/r/20161025141050.GA13019@cmpxchg.org Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Michal Hocko <mhocko@suse.com> Cc: Vladimir Davydov <vdavydov.dev@gmail.com> Cc: Tejun Heo <tj@kernel.org> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 8f72cb4
soundfont.h
#ifndef __SOUND_SOUNDFONT_H
#define __SOUND_SOUNDFONT_H
/*
* Soundfont defines and definitions.
*
* Copyright (C) 1999 Steve Ratcliffe
* Copyright (c) 1999-2000 Takashi iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sound/sfnt_info.h>
#include <sound/util_mem.h>
#define SF_MAX_INSTRUMENTS 128 /* maximum instrument number */
#define SF_MAX_PRESETS 256 /* drums are mapped from 128 to 256 */
#define SF_IS_DRUM_BANK(z) ((z) == 128)
struct snd_sf_zone {
struct snd_sf_zone *next; /* Link to next */
unsigned char bank; /* Midi bank for this zone */
unsigned char instr; /* Midi program for this zone */
unsigned char mapped; /* True if mapped to something else */
struct soundfont_voice_info v; /* All the soundfont parameters */
int counter;
struct snd_sf_sample *sample; /* Link to sample */
/* The following deals with preset numbers (programs) */
struct snd_sf_zone *next_instr; /* Next zone of this instrument */
struct snd_sf_zone *next_zone; /* Next zone in play list */
};
struct snd_sf_sample {
struct soundfont_sample_info v;
int counter;
struct snd_util_memblk *block; /* allocated data block */
struct snd_sf_sample *next;
};
/*
* This represents all the information relating to a soundfont.
*/
struct snd_soundfont {
struct snd_soundfont *next; /* Link to next */
/*struct snd_soundfont *prev;*/ /* Link to previous */
short id; /* file id */
short type; /* font type */
unsigned char name[SNDRV_SFNT_PATCH_NAME_LEN]; /* identifier */
struct snd_sf_zone *zones; /* Font information */
struct snd_sf_sample *samples; /* The sample headers */
};
/*
* Type of the sample access callback
*/
struct snd_sf_callback {
void *private_data;
int (*sample_new)(void *private_data, struct snd_sf_sample *sp,
struct snd_util_memhdr *hdr,
const void __user *buf, long count);
int (*sample_free)(void *private_data, struct snd_sf_sample *sp,
struct snd_util_memhdr *hdr);
void (*sample_reset)(void *private);
};
/*
* List of soundfonts.
*/
struct snd_sf_list {
struct snd_soundfont *currsf; /* The currently open soundfont */
int open_client; /* client pointer for lock */
int mem_used; /* used memory size */
struct snd_sf_zone *presets[SF_MAX_PRESETS];
struct snd_soundfont *fonts; /* The list of soundfonts */
int fonts_size; /* number of fonts allocated */
int zone_counter; /* last allocated time for zone */
int sample_counter; /* last allocated time for sample */
int zone_locked; /* locked time for zone */
int sample_locked; /* locked time for sample */
struct snd_sf_callback callback; /* callback functions */
int presets_locked;
struct mutex presets_mutex;
spinlock_t lock;
struct snd_util_memhdr *memhdr;
};
/* Prototypes for soundfont.c */
int snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
long count, int client);
int snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
long count, int client);
int snd_soundfont_close_check(struct snd_sf_list *sflist, int client);
struct snd_sf_list *snd_sf_new(struct snd_sf_callback *callback,
struct snd_util_memhdr *hdr);
void snd_sf_free(struct snd_sf_list *sflist);
int snd_soundfont_remove_samples(struct snd_sf_list *sflist);
int snd_soundfont_remove_unlocked(struct snd_sf_list *sflist);
int snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
int preset, int bank,
int def_preset, int def_bank,
struct snd_sf_zone **table, int max_layers);
/* Parameter conversions */
int snd_sf_calc_parm_hold(int msec);
int snd_sf_calc_parm_attack(int msec);
int snd_sf_calc_parm_decay(int msec);
#define snd_sf_calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725)
extern int snd_sf_vol_table[128];
int snd_sf_linear_to_log(unsigned int amount, int offset, int ratio);
#endif /* __SOUND_SOUNDFONT_H */
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...