From e3adc06b8b8214478aa1d3e85fd5f83b79d039b4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Jun 2008 11:39:06 -0700 Subject: [PATCH] Catch and recover from yet another linux kernel bug in mprotect. --- src/linux_sysfs.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c index 9e53fac..b1d196c 100644 --- a/src/linux_sysfs.c +++ b/src/linux_sysfs.c @@ -537,12 +537,11 @@ pci_device_linux_sysfs_map_range(struct pci_device *dev, map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset); if (map->memory == MAP_FAILED) { - err = errno; map->memory = NULL; + close(fd); + return errno; } - close(fd); - #ifdef HAVE_MTRR if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) != 0) { sentry.type = MTRR_TYPE_WRBACK; @@ -562,11 +561,27 @@ pci_device_linux_sysfs_map_range(struct pci_device *dev, } /* KLUDGE ALERT -- rewrite the PTEs to turn off the CD and WT bits */ mprotect (map->memory, map->size, PROT_NONE); - mprotect (map->memory, map->size, PROT_READ|PROT_WRITE); + err = mprotect (map->memory, map->size, PROT_READ|PROT_WRITE); + + if (err != 0) { + fprintf(stderr, "mprotect(PROT_READ | PROT_WRITE) failed: %s\n", + strerror(errno)); + fprintf(stderr, "remapping without mprotect performace kludge.\n"); + + munmap(map->memory, map->size); + map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset); + if (map->memory == MAP_FAILED) { + map->memory = NULL; + close(fd); + return errno; + } + } } #endif - return err; + close(fd); + + return 0; } /** -- 2.7.4