Revision 0740a50b9baa4472cfb12442df4b39e2712a64a4 authored by Mike Rapoport on 13 March 2021, 05:07:12 UTC, committed by Linus Torvalds on 13 March 2021, 19:27:30 UTC
There could be struct pages that are not backed by actual physical memory. This can happen when the actual memory bank is not a multiple of SECTION_SIZE or when an architecture does not register memory holes reserved by the firmware as memblock.memory. Such pages are currently initialized using init_unavailable_mem() function that iterates through PFNs in holes in memblock.memory and if there is a struct page corresponding to a PFN, the fields of this page are set to default values and it is marked as Reserved. init_unavailable_mem() does not take into account zone and node the page belongs to and sets both zone and node links in struct page to zero. Before commit 73a6e474cb37 ("mm: memmap_init: iterate over memblock regions rather that check each PFN") the holes inside a zone were re-initialized during memmap_init() and got their zone/node links right. However, after that commit nothing updates the struct pages representing such holes. On a system that has firmware reserved holes in a zone above ZONE_DMA, for instance in a configuration below: # grep -A1 E820 /proc/iomem 7a17b000-7a216fff : Unknown E820 type 7a217000-7bffffff : System RAM unset zone link in struct page will trigger VM_BUG_ON_PAGE(!zone_spans_pfn(page_zone(page), pfn), page); in set_pfnblock_flags_mask() when called with a struct page from a range other than E820_TYPE_RAM because there are pages in the range of ZONE_DMA32 but the unset zone link in struct page makes them appear as a part of ZONE_DMA. Interleave initialization of the unavailable pages with the normal initialization of memory map, so that zone and node information will be properly set on struct pages that are not backed by the actual memory. With this change the pages for holes inside a zone will get proper zone/node links and the pages that are not spanned by any node will get links to the adjacent zone/node. The holes between nodes will be prepended to the zone/node above the hole and the trailing pages in the last section that will be appended to the zone/node below. [akpm@linux-foundation.org: don't initialize static to zero, use %llu for u64] Link: https://lkml.kernel.org/r/20210225224351.7356-2-rppt@kernel.org Fixes: 73a6e474cb37 ("mm: memmap_init: iterate over memblock regions rather that check each PFN") Signed-off-by: Mike Rapoport <rppt@linux.ibm.com> Reported-by: Qian Cai <cai@lca.pw> Reported-by: Andrea Arcangeli <aarcange@redhat.com> Reviewed-by: Baoquan He <bhe@redhat.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Reviewed-by: David Hildenbrand <david@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ćukasz Majczak <lma@semihalf.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Michal Hocko <mhocko@kernel.org> Cc: "Sarvela, Tomi P" <tomi.p.sarvela@intel.com> Cc: Thomas Gleixner <tglx@linutronix.de> 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 ea29b20
ide-cd.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 1996-98 Erik Andersen
* Copyright (C) 1998-2000 Jens Axboe
*/
#ifndef _IDE_CD_H
#define _IDE_CD_H
#include <linux/cdrom.h>
#include <asm/byteorder.h>
#define IDECD_DEBUG_LOG 0
#if IDECD_DEBUG_LOG
#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, ## args)
#else
#define ide_debug_log(lvl, fmt, args...) do {} while (0)
#endif
#define ATAPI_WAIT_WRITE_BUSY (10 * HZ)
/************************************************************************/
#define SECTORS_PER_FRAME (CD_FRAMESIZE >> SECTOR_SHIFT)
#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32)
/* Capabilities Page size including 8 bytes of Mode Page Header */
#define ATAPI_CAPABILITIES_PAGE_SIZE (8 + 20)
#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE 4
/* Structure of a MSF cdrom address. */
struct atapi_msf {
u8 reserved;
u8 minute;
u8 second;
u8 frame;
};
/* Space to hold the disk TOC. */
#define MAX_TRACKS 99
struct atapi_toc_header {
unsigned short toc_length;
u8 first_track;
u8 last_track;
};
struct atapi_toc_entry {
u8 reserved1;
#if defined(__BIG_ENDIAN_BITFIELD)
u8 adr : 4;
u8 control : 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
u8 control : 4;
u8 adr : 4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
u8 track;
u8 reserved2;
union {
unsigned lba;
struct atapi_msf msf;
} addr;
};
struct atapi_toc {
int last_session_lba;
int xa_flag;
unsigned long capacity;
struct atapi_toc_header hdr;
struct atapi_toc_entry ent[MAX_TRACKS+1];
/* One extra for the leadout. */
};
/* Extra per-device info for cdrom drives. */
struct cdrom_info {
ide_drive_t *drive;
struct ide_driver *driver;
struct gendisk *disk;
struct device dev;
/* Buffer for table of contents. NULL if we haven't allocated
a TOC buffer for this device yet. */
struct atapi_toc *toc;
u8 max_speed; /* Max speed of the drive. */
u8 current_speed; /* Current speed of the drive. */
/* Per-device info needed by cdrom.c generic driver. */
struct cdrom_device_info devinfo;
unsigned long write_timeout;
};
/* ide-cd_verbose.c */
void ide_cd_log_error(const char *, struct request *, struct request_sense *);
/* ide-cd.c functions used by ide-cd_ioctl.c */
int ide_cd_queue_pc(ide_drive_t *, const unsigned char *, int, void *,
unsigned *, struct scsi_sense_hdr *, int, req_flags_t);
int ide_cd_read_toc(ide_drive_t *);
int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
void ide_cdrom_update_speed(ide_drive_t *, u8 *);
int cdrom_check_status(ide_drive_t *, struct scsi_sense_hdr *);
/* ide-cd_ioctl.c */
int ide_cdrom_open_real(struct cdrom_device_info *, int);
void ide_cdrom_release_real(struct cdrom_device_info *);
int ide_cdrom_drive_status(struct cdrom_device_info *, int);
unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *,
unsigned int clearing, int slot_nr);
int ide_cdrom_tray_move(struct cdrom_device_info *, int);
int ide_cdrom_lock_door(struct cdrom_device_info *, int);
int ide_cdrom_select_speed(struct cdrom_device_info *, int);
int ide_cdrom_get_last_session(struct cdrom_device_info *,
struct cdrom_multisession *);
int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *);
int ide_cdrom_reset(struct cdrom_device_info *cdi);
int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
int ide_cdrom_packet(struct cdrom_device_info *, struct packet_command *);
#endif /* _IDE_CD_H */
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...