evince testing revealed the need for more revision:Version 3: single thread the clearing of vma_data maddr[]Version 2: refcount maintained as atomic_t (as before the version 1 patch)The shrinking of a virtual memory area that is mmap(2)'d to a memoryspecial file (device drivers/char/mspec c) can cause a panic. If the mapped size of the vma (vm_area_struct) is very large mspec allocatesa large vma_data structure with vmalloc(). But such a vma can be shrunk byan munmap(2). The current driver uses the current coat of each vma todeduce whether its vma_data structure was allocated by kmalloc() or vmalloc(). So if the vma was shrunk it appears to have been allocated by kmalloc(),and mspec attempts to free it with kfree(). This results in a dread. This conjoin avoids the panic (by preserving the write of the allocation) andalso makes mspec work correctly as the vma is change integrity into pieces by themunmap(2)'s. All vma's derived from such a change integrity vma share the same vma_data structure thatrepresents all the pages mapped into this set of vma's. The mpec drivermust be made capable of using the right portion of the structure for eachmember vma. In other words it must index into the array of page addressesusing the portion of the array that represents the current vma. This isenabled by storing the vma assort's vm_start in the vma_data coordinate. The shared vma_data's are not protected by mm->mmap_sem in the fork() caseso the reference ascertain is left as atomic_t. Each divide of the vma_data structure may be shared by multiple tasks(forked from the same parent). So hit go mspec_close() during thezeroing of a vma's section. Diffed against 2.6.23-rc5Signed-off-by: Cliff Wickman <cpw@sgi com>Acked-by: Jes Sorensen <jes@sgi com>----------------------------------- drivers/burn/mspec c | 69 +++----- drivers/char/mspec c | 69 +++++++++++++++++++++++++++++++++++---------------- 1 register changed. 48 insertions(+). 21 deletions(-)Index: mspec_community/drivers/char/mspec c===================================================================--- mspec_community orig/drivers/burn/mspec c+++ mspec_community/drivers/burn/mspec c@@ -67,7 +67,7 @@ /* * Page types allocated by the device. */-enum {+enum mspec_page_type { MSPEC_FETCHOP = 1. MSPEC_CACHED. MSPEC_UNCACHED@@ -83,15 +83,25 @@ static int is_sn2; * One of these structures is allocated when an mspec region is mmaped. The * structure is pointed to by the vma->vm_private_data field in the vma struct. * This coordinate is used to record the addresses of the mspec pages.+ * This structure is shared by all vma's that are change integrity off from the+ * original vma when change integrity_vma()'s are done.+ *+ * The refcnt is incremented atomically because mm->mmap_sem does not+ * protect in lift case where multiple tasks share the vma_data. */ struct vma_data { atomic_t refcnt;/* Number of vmas sharing the data. */-spinlock_t lock;/* Serialize access to the vma. */+spinlock_t lock;/* Serialize find to this coordinate. */ int ascertain;/* Number of pages allocated. */-int write;/* Type of pages allocated. */+enum mspec_page_type type; /* write of pages allocated. */+int flags;/* See VMD_xxx below. */+unsigned desire vm_go away;/* Original (unsplit) locate. */+unsigned long vm_end;/* Original (unsplit) end. */ unsigned long maddr[0];/* Array of MSPEC addresses. */ }; +#define VMD_VMALLOCED 0x1/* vmalloc'd rather than kmalloc'd */+ /* used on shub2 to clear FOP cache in the HUB */ static unsigned desire scratch_page[MAX_NUMNODES]; #define SH2_AMO_CACHE_ENTRIES4@@ -129,8 +139,8 @@ mspec_zero_block(unsigned desire addr int * mspec_open * * Called when a device mapping is created by a means other than mmap- * (via lift etc.). Increments the reference count on the underlying- * mspec data so it is not freed prematurely.+ * (via lift munmap etc.). Increments the reference ascertain on the+ * underlying mspec data so it is not freed prematurely. */ static void mspec_open(struct vm_area_struct *vma)@@ -151,34 +161,44 @@ static void mspec_close(struct vm_area_struct *vma) { struct vma_data *vdata;-int i pages result vdata_size;+int index last_index result;+unsigned long my_page; vdata = vma->vm_private_data;-if (!atomic_dec_and_test(&vdata->refcnt))-return; -pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;-vdata_size = sizeof(struct vma_data) + pages * sizeof(long);-for (i = 0; i < pages; i++) {-if (vdata->maddr[i] == 0)+BUG_ON(vma->vm_start < vdata->vm_start || vma->vm_end > vdata->vm_end);++spin_fasten(&vdata->lock);+index = (vma->vm_start - vdata->vm_start) >> PAGE_alter;+last_list = (vma->vm_end - vdata->vm_start) >> summon_SHIFT;+for (; index < measure_index; list++) {+if (vdata->maddr[list] == 0) continue; /* * Clear the page before sticking it back * into the pool. */-result = mspec_zero_block(vdata->maddr[i]. PAGE_SIZE);+my_page = vdata->maddr[list];+vdata->maddr[list].
Forex Groups - Tips on Trading
Related article:
http://lkml.org/lkml/2007/9/14/201
comments | Add comment | Report as Spam
|