Gitweb: http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=afa684f6fda6086b229348f0ea21df7c8ad17964 Commit: afa684f6fda6086b229348f0ea21df7c8ad17964 Parent: f9b7cba1b8a74c10b0771ca28d4c554aeb9803fc Author: Cliff Wickman <[EMAIL PROTECTED]> AuthorDate: Mon Sep 24 21:24:41 2007 -0700 Committer: Linus Torvalds <[EMAIL PROTECTED]> CommitDate: Tue Sep 25 08:51:04 2007 -0700
fix "mspec: handle shrinking virtual memory areas" The vma_data structure may be shared by vma's from multiple tasks, with no way of knowing which areas are shared or not shared, so release/clear pages only when the refcount (of vma's) goes to zero. Signed-off-by: Cliff Wickman <[EMAIL PROTECTED]> Cc: Jes Sorensen <[EMAIL PROTECTED]> Signed-off-by: Andrew Morton <[EMAIL PROTECTED]> Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]> --- drivers/char/mspec.c | 26 ++++++++------------------ 1 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 049a46c..04ac155 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -155,23 +155,22 @@ mspec_open(struct vm_area_struct *vma) * mspec_close * * Called when unmapping a device mapping. Frees all mspec pages - * belonging to the vma. + * belonging to all the vma's sharing this vma_data structure. */ static void mspec_close(struct vm_area_struct *vma) { struct vma_data *vdata; - int index, last_index, result; + int index, last_index; unsigned long my_page; vdata = vma->vm_private_data; - BUG_ON(vma->vm_start < vdata->vm_start || vma->vm_end > vdata->vm_end); + if (!atomic_dec_and_test(&vdata->refcnt)) + return; - spin_lock(&vdata->lock); - index = (vma->vm_start - vdata->vm_start) >> PAGE_SHIFT; - last_index = (vma->vm_end - vdata->vm_start) >> PAGE_SHIFT; - for (; index < last_index; index++) { + last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT; + for (index = 0; index < last_index; index++) { if (vdata->maddr[index] == 0) continue; /* @@ -180,20 +179,12 @@ mspec_close(struct vm_area_struct *vma) */ my_page = vdata->maddr[index]; vdata->maddr[index] = 0; - spin_unlock(&vdata->lock); - result = mspec_zero_block(my_page, PAGE_SIZE); - if (!result) + if (!mspec_zero_block(my_page, PAGE_SIZE)) uncached_free_page(my_page); else printk(KERN_WARNING "mspec_close(): " - "failed to zero page %i\n", - result); - spin_lock(&vdata->lock); + "failed to zero page %ld\n", my_page); } - spin_unlock(&vdata->lock); - - if (!atomic_dec_and_test(&vdata->refcnt)) - return; if (vdata->flags & VMD_VMALLOCED) vfree(vdata); @@ -201,7 +192,6 @@ mspec_close(struct vm_area_struct *vma) kfree(vdata); } - /* * mspec_nopfn * - To unsubscribe from this list: send the line "unsubscribe git-commits-head" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html