summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Otte <cotte@de.ibm.com>2011-09-26 16:40:34 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-09-26 16:40:50 +0200
commit05873df981ca1dd32f398e7b4e19864de907e064 (patch)
treed15e7f32c6081cd81cbbc6cb7a321dad9fb6733f
parentf9783ec862ea8ce0071f34a7fd028229d9fd98b4 (diff)
downloadlinux-3.10-05873df981ca1dd32f398e7b4e19864de907e064.tar.gz
linux-3.10-05873df981ca1dd32f398e7b4e19864de907e064.tar.bz2
linux-3.10-05873df981ca1dd32f398e7b4e19864de907e064.zip
[S390] gmap: always up mmap_sem properly
If gmap_unmap_segment figures that the segment was not mapped in the first place, it need to up mmap_sem on exit. Cc: <stable@kernel.org> Signed-off-by: Carsten Otte <cotte@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/mm/pgtable.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index f69ff3c1349..5d56c2b95b1 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -303,15 +303,15 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
/* Walk the guest addr space page table */
table = gmap->table + (((to + off) >> 53) & 0x7ff);
if (*table & _REGION_ENTRY_INV)
- return 0;
+ goto out;
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
table = table + (((to + off) >> 42) & 0x7ff);
if (*table & _REGION_ENTRY_INV)
- return 0;
+ goto out;
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
table = table + (((to + off) >> 31) & 0x7ff);
if (*table & _REGION_ENTRY_INV)
- return 0;
+ goto out;
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
table = table + (((to + off) >> 20) & 0x7ff);
@@ -319,6 +319,7 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
flush |= gmap_unlink_segment(gmap, table);
*table = _SEGMENT_ENTRY_INV;
}
+out:
up_read(&gmap->mm->mmap_sem);
if (flush)
gmap_flush_tlb(gmap);