diff options
author | Carsten Otte <cotte@de.ibm.com> | 2011-09-26 10:40:34 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2011-09-26 10:40:50 -0400 |
commit | 05873df981ca1dd32f398e7b4e19864de907e064 (patch) | |
tree | d15e7f32c6081cd81cbbc6cb7a321dad9fb6733f /arch/s390 | |
parent | f9783ec862ea8ce0071f34a7fd028229d9fd98b4 (diff) |
[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>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/mm/pgtable.c | 7 |
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) | |||
303 | /* Walk the guest addr space page table */ | 303 | /* Walk the guest addr space page table */ |
304 | table = gmap->table + (((to + off) >> 53) & 0x7ff); | 304 | table = gmap->table + (((to + off) >> 53) & 0x7ff); |
305 | if (*table & _REGION_ENTRY_INV) | 305 | if (*table & _REGION_ENTRY_INV) |
306 | return 0; | 306 | goto out; |
307 | table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); | 307 | table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); |
308 | table = table + (((to + off) >> 42) & 0x7ff); | 308 | table = table + (((to + off) >> 42) & 0x7ff); |
309 | if (*table & _REGION_ENTRY_INV) | 309 | if (*table & _REGION_ENTRY_INV) |
310 | return 0; | 310 | goto out; |
311 | table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); | 311 | table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); |
312 | table = table + (((to + off) >> 31) & 0x7ff); | 312 | table = table + (((to + off) >> 31) & 0x7ff); |
313 | if (*table & _REGION_ENTRY_INV) | 313 | if (*table & _REGION_ENTRY_INV) |
314 | return 0; | 314 | goto out; |
315 | table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); | 315 | table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); |
316 | table = table + (((to + off) >> 20) & 0x7ff); | 316 | table = table + (((to + off) >> 20) & 0x7ff); |
317 | 317 | ||
@@ -319,6 +319,7 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len) | |||
319 | flush |= gmap_unlink_segment(gmap, table); | 319 | flush |= gmap_unlink_segment(gmap, table); |
320 | *table = _SEGMENT_ENTRY_INV; | 320 | *table = _SEGMENT_ENTRY_INV; |
321 | } | 321 | } |
322 | out: | ||
322 | up_read(&gmap->mm->mmap_sem); | 323 | up_read(&gmap->mm->mmap_sem); |
323 | if (flush) | 324 | if (flush) |
324 | gmap_flush_tlb(gmap); | 325 | gmap_flush_tlb(gmap); |