linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/5] mm: improve remapping of vmalloc regions
@ 2006-04-20 17:06 Nick Piggin
  2006-04-20 17:06 ` [patch 1/5] mm: remap_vmalloc_range Nick Piggin
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:06 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Kernel, Nick Piggin, Linux Memory Management, Hugh Dickins

Hi,

I'd like some feedback about this patchset -- whether it is the right
design, and the implementation (e.g. people might dislike patch 4).

vm_insert_page and remap_pfn_range loops are really clever, bit
probably asking a bit too much of most drivers. I was able to get
rid of most of them without too much trouble.

Not tested, because I don't have any of the hardware, but it seems
compiles OK.

Nick

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 1/5] mm: remap_vmalloc_range
  2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
@ 2006-04-20 17:06 ` Nick Piggin
  2006-04-20 17:22   ` Christoph Hellwig
  2006-04-20 18:09   ` Nick Piggin
  2006-04-20 17:06 ` [patch 2/5] mm: deprecate vmalloc_to_pfn Nick Piggin
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:06 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Kernel, Nick Piggin, Linux Memory Management, Hugh Dickins

Add a remap_vmalloc_range and get rid of as many remap_pfn_range and
vm_insert_page loops as possible.

remap_vmalloc_range can do a whole lot of nice range checking even
if the caller gets it wrong (which it looks like one or two do).

Signed-off-by: Nick Piggin <npiggin@suse.de>

Index: linux-2.6/drivers/media/video/cpia.c
===================================================================
--- linux-2.6.orig/drivers/media/video/cpia.c
+++ linux-2.6/drivers/media/video/cpia.c
@@ -3750,9 +3750,7 @@ static int cpia_ioctl(struct inode *inod
 static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_device *dev = file->private_data;
-	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end - vma->vm_start;
-	unsigned long page, pos;
 	struct cam_data *cam = dev->priv;
 	int retval;
 
@@ -3778,19 +3776,9 @@ static int cpia_mmap(struct file *file, 
 		}
 	}
 
-	pos = (unsigned long)(cam->frame_buf);
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&cam->busy_lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+	if (remap_vmalloc_range(vma, cam->frame_buf, 0)) {
+		mutex_unlock(&cam->busy_lock);
+		return -EAGAIN;
 	}
 
 	DBG("cpia_mmap: %ld\n", size);
Index: linux-2.6/drivers/media/video/meye.c
===================================================================
--- linux-2.6.orig/drivers/media/video/meye.c
+++ linux-2.6/drivers/media/video/meye.c
@@ -1699,13 +1699,10 @@ static struct vm_operations_struct meye_
 
 static int meye_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	unsigned long start = vma->vm_start;
 	unsigned long size = vma->vm_end - vma->vm_start;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	unsigned long page, pos;
 
 	mutex_lock(&meye.lock);
-	if (size > gbuffers * gbufsize) {
+	if (size > gbuffers * gbufsize) { /* XXX: should be size + vm_pgoff? */
 		mutex_unlock(&meye.lock);
 		return -EINVAL;
 	}
@@ -1722,20 +1719,10 @@ static int meye_mmap(struct file *file, 
 		for (i = 0; i < gbuffers; i++)
 			meye.vma_use_count[i] = 0;
 	}
-	pos = (unsigned long)meye.grab_fbuffer + offset;
 
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&meye.lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+	if (remap_vmalloc_range(vma, meye.grab_fbuffer, vma->vm_pgoff)) {
+		mutex_unlock(&meye.lock);
+		return -EAGAIN;
 	}
 
 	vma->vm_ops = &meye_vm_ops;
Index: linux-2.6/drivers/media/video/ov511.c
===================================================================
--- linux-2.6.orig/drivers/media/video/ov511.c
+++ linux-2.6/drivers/media/video/ov511.c
@@ -4616,10 +4616,8 @@ static int
 ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_device *vdev = file->private_data;
-	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end - vma->vm_start;
 	struct usb_ov511 *ov = video_get_drvdata(vdev);
-	unsigned long page, pos;
 
 	if (ov->dev == NULL)
 		return -EIO;
@@ -4634,19 +4632,9 @@ ov51x_v4l1_mmap(struct file *file, struc
 	if (mutex_lock_interruptible(&ov->lock))
 		return -EINTR;
 
-	pos = (unsigned long)ov->fbuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&ov->lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+	if (remap_vmalloc_range(vma, ov->fbuf, 0)) {
+		mutex_unlock(&ov->lock);
+		return -EAGAIN;
 	}
 
 	mutex_unlock(&ov->lock);
Index: linux-2.6/drivers/media/video/pwc/pwc-if.c
===================================================================
--- linux-2.6.orig/drivers/media/video/pwc/pwc-if.c
+++ linux-2.6/drivers/media/video/pwc/pwc-if.c
@@ -1602,28 +1602,16 @@ static int pwc_video_mmap(struct file *f
 {
 	struct video_device *vdev = file->private_data;
 	struct pwc_device *pdev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
 
-	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
+	/* XXX: should check ranges */
+	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev,
+				vma->vm_start, vma->vm_end - vma->vm_start);
 	pdev = vdev->priv;
 
 	vma->vm_flags |= VM_IO;
 
-	pos = (unsigned long)pdev->image_data;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
+	if (remap_vmalloc_range(vma, pdev->image_data, 0))
+		return -EAGAIN;
 
 	return 0;
 }
Index: linux-2.6/drivers/media/video/se401.c
===================================================================
--- linux-2.6.orig/drivers/media/video/se401.c
+++ linux-2.6/drivers/media/video/se401.c
@@ -1153,9 +1153,7 @@ static int se401_mmap(struct file *file,
 {
 	struct video_device *dev = file->private_data;
 	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
 
 	mutex_lock(&se401->lock);
 
@@ -1167,19 +1165,9 @@ static int se401_mmap(struct file *file,
 		mutex_unlock(&se401->lock);
 		return -EINVAL;
 	}
-	pos = (unsigned long)se401->fbuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&se401->lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+	if (remap_vmalloc_range(vma, se401->fbuf, 0)) {
+		mutex_unlock(&se401->lock);
+		return -EAGAIN;
 	}
 	mutex_unlock(&se401->lock);
 
Index: linux-2.6/drivers/media/video/stv680.c
===================================================================
--- linux-2.6.orig/drivers/media/video/stv680.c
+++ linux-2.6/drivers/media/video/stv680.c
@@ -1254,9 +1254,7 @@ static int stv680_mmap (struct file *fil
 {
 	struct video_device *dev = file->private_data;
 	struct usb_stv *stv680 = video_get_drvdata(dev);
-	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
 
 	mutex_lock(&stv680->lock);
 
@@ -1269,19 +1267,9 @@ static int stv680_mmap (struct file *fil
 		mutex_unlock(&stv680->lock);
 		return -EINVAL;
 	}
-	pos = (unsigned long) stv680->fbuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&stv680->lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+	if (remap_vmalloc_range(vma, stv680->fbuf, 0)) {
+		mutex_unlock(&stv680->lock);
+		return -EAGAIN;
 	}
 	mutex_unlock(&stv680->lock);
 
Index: linux-2.6/drivers/media/video/usbvideo/usbvideo.c
===================================================================
--- linux-2.6.orig/drivers/media/video/usbvideo/usbvideo.c
+++ linux-2.6/drivers/media/video/usbvideo/usbvideo.c
@@ -1068,9 +1068,7 @@ EXPORT_SYMBOL(usbvideo_RegisterVideoDevi
 static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct uvd *uvd = file->private_data;
-	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
 
 	if (!CAMERA_IS_OPERATIONAL(uvd))
 		return -EFAULT;
@@ -1078,19 +1076,8 @@ static int usbvideo_v4l_mmap(struct file
 	if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
 		return -EINVAL;
 
-	pos = (unsigned long) uvd->fbuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
+	if (remap_vmalloc_range(vma, uvd->fbuf, 0))
+		return -EAGAIN;
 
 	return 0;
 }
Index: linux-2.6/drivers/media/video/usbvideo/vicam.c
===================================================================
--- linux-2.6.orig/drivers/media/video/usbvideo/vicam.c
+++ linux-2.6/drivers/media/video/usbvideo/vicam.c
@@ -1029,8 +1029,6 @@ static int
 vicam_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	// TODO: allocate the raw frame buffer if necessary
-	unsigned long page, pos;
-	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end-vma->vm_start;
 	struct vicam_camera *cam = file->private_data;
 
@@ -1039,25 +1037,16 @@ vicam_mmap(struct file *file, struct vm_
 
 	DBG("vicam_mmap: %ld\n", size);
 
-	/* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
-	 * to the size the application requested for mmap and it was screwing apps up.
-	 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
-	 return -EINVAL;
+	/* We let mmap allocate as much as it wants because Linux was adding
+	 * 2048 bytes to the size the application requested for mmap and it was
+	 * screwing apps up.
+	 *
+	 * It shouldn't have been, so let's try this check again -np
 	 */
+	 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
 
-	pos = (unsigned long)cam->framebuf;
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
+	if (remap_vmalloc_range(vma, cam->framebuf, 0))
+		return -EAGAIN;
 
 	return 0;
 }
Index: linux-2.6/drivers/media/video/w9968cf.c
===================================================================
--- linux-2.6.orig/drivers/media/video/w9968cf.c
+++ linux-2.6/drivers/media/video/w9968cf.c
@@ -2861,10 +2861,7 @@ static int w9968cf_mmap(struct file* fil
 	struct w9968cf_device* cam = (struct w9968cf_device*)
 				     video_get_drvdata(video_devdata(filp));
 	unsigned long vsize = vma->vm_end - vma->vm_start,
-		      psize = cam->nbuffers * cam->frame[0].size,
-		      start = vma->vm_start,
-		      pos = (unsigned long)cam->frame[0].buffer,
-		      page;
+		      psize = cam->nbuffers * cam->frame[0].size;
 
 	if (cam->disconnected) {
 		DBG(2, "Device not present")
@@ -2881,15 +2878,8 @@ static int w9968cf_mmap(struct file* fil
 	if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT))
 		return -EINVAL;
 
-	while (vsize > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page + vma->vm_pgoff,
-						PAGE_SIZE, vma->vm_page_prot))
-			return -EAGAIN;
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		vsize -= PAGE_SIZE;
-	}
+	if (remap_vmalloc_range(vma, cam->frame[0].buffer, vma->vm_pgoff))
+		return -EAGAIN;
 
 	DBG(5, "mmap method successfully called")
 	return 0;
Index: linux-2.6/arch/ia64/kernel/perfmon.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/perfmon.c
+++ linux-2.6/arch/ia64/kernel/perfmon.c
@@ -2237,25 +2237,6 @@ pfm_free_fd(int fd, struct file *file)
 	put_unused_fd(fd);
 }
 
-static int
-pfm_remap_buffer(struct vm_area_struct *vma, unsigned long buf, unsigned long addr, unsigned long size)
-{
-	DPRINT(("CPU%d buf=0x%lx addr=0x%lx size=%ld\n", smp_processor_id(), buf, addr, size));
-
-	while (size > 0) {
-		unsigned long pfn = ia64_tpa(buf) >> PAGE_SHIFT;
-
-
-		if (remap_pfn_range(vma, addr, pfn, PAGE_SIZE, PAGE_READONLY))
-			return -ENOMEM;
-
-		addr  += PAGE_SIZE;
-		buf   += PAGE_SIZE;
-		size  -= PAGE_SIZE;
-	}
-	return 0;
-}
-
 /*
  * allocate a sampling buffer and remaps it into the user address space of the task
  */
@@ -2343,7 +2324,7 @@ pfm_smpl_buffer_alloc(struct task_struct
 	DPRINT(("aligned size=%ld, hdr=%p mapped @0x%lx\n", size, ctx->ctx_smpl_hdr, vma->vm_start));
 
 	/* can only be applied to current task, need to have the mm semaphore held when called */
-	if (pfm_remap_buffer(vma, (unsigned long)smpl_buf, vma->vm_start, size)) {
+	if (remap_vmalloc_range(vma, smpl_buf, 0)) {
 		DPRINT(("Can't remap buffer\n"));
 		up_write(&task->mm->mmap_sem);
 		goto error;
Index: linux-2.6/include/linux/vmalloc.h
===================================================================
--- linux-2.6.orig/include/linux/vmalloc.h
+++ linux-2.6/include/linux/vmalloc.h
@@ -45,6 +45,9 @@ extern void vfree(void *addr);
 extern void *vmap(struct page **pages, unsigned int count,
 			unsigned long flags, pgprot_t prot);
 extern void vunmap(void *addr);
+
+extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
+							unsigned long pgoff);
  
 /*
  *	Lowlevel-APIs (not for driver use!)
Index: linux-2.6/mm/vmalloc.c
===================================================================
--- linux-2.6.orig/mm/vmalloc.c
+++ linux-2.6/mm/vmalloc.c
@@ -256,6 +256,20 @@ struct vm_struct *get_vm_area_node(unsig
 	return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node);
 }
 
+static struct vm_struct *find_vm_area(void *addr)
+{
+	struct vm_struct *tmp;
+
+	write_lock(&vmlist_lock);
+	for (tmp = vmlist; tmp != NULL; tmp = tmp->next) {
+		 if (tmp->addr == addr)
+			break;
+	}
+	write_unlock(&vmlist_lock);
+
+	return tmp;
+}
+
 /* Caller must hold vmlist_lock */
 struct vm_struct *__remove_vm_area(void *addr)
 {
@@ -630,3 +644,55 @@ finished:
 	read_unlock(&vmlist_lock);
 	return buf - buf_start;
 }
+
+/**
+ *	remap_vmalloc_range  -  map vmalloc pages to userspace
+ *
+ *	@vma:		vma to cover (map full range of vma)
+ *	@addr:		vmalloc memory
+ *	@pgoff:		number of pages into addr before first page to map
+ *	@returns:	0 for success, -Exxx on failure
+ *
+ *	This function checks that addr is a valid vmalloc'ed area, and
+ *	that it is big enough to cover the vma. Will return failure if
+ *	that criteria isn't met.
+ *
+ *	Similar to remap_pfn_range (see mm/memory.c)
+ */
+int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
+						unsigned long pgoff)
+{
+	struct vm_struct *area;
+	unsigned long uaddr = vma->vm_start;
+	unsigned long usize = vma->vm_end - vma->vm_start;
+	int ret;
+
+	if ((PAGE_SIZE-1) & (unsigned long)addr)
+		return -EINVAL;
+
+	area = find_vm_area(addr);
+	if (!area)
+		return -EINVAL;
+
+	if (usize + (pgoff << PAGE_SHIFT) > area->size - PAGE_SIZE)
+		return -EINVAL;
+
+	addr = (void *)((unsigned long)addr + (pgoff << PAGE_SHIFT));
+	do {
+		struct page *page = vmalloc_to_page(addr);
+		ret = vm_insert_page(vma, uaddr, page);
+		if (ret)
+			return ret;
+
+		uaddr += PAGE_SIZE;
+		addr = (void *)((unsigned long)addr+PAGE_SIZE);
+		usize -= PAGE_SIZE;
+	} while (usize > 0);
+
+	/* Prevent "things" like memory migration? VM_flags need a cleanup... */
+	vma->vm_flags |= VM_RESERVED;
+
+	return ret;
+}
+EXPORT_SYMBOL(remap_vmalloc_range);
+
Index: linux-2.6/drivers/media/video/em28xx/em28xx-video.c
===================================================================
--- linux-2.6.orig/drivers/media/video/em28xx/em28xx-video.c
+++ linux-2.6/drivers/media/video/em28xx/em28xx-video.c
@@ -34,6 +34,7 @@
 #include <linux/version.h>
 #include <linux/video_decoder.h>
 #include <linux/mutex.h>
+#include <linux/vmalloc.h>
 
 #include "em28xx.h"
 #include <media/tuner.h>
@@ -582,9 +583,7 @@ static struct vm_operations_struct em28x
  */
 static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-	unsigned long size = vma->vm_end - vma->vm_start,
-	    start = vma->vm_start;
-	void *pos;
+	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
 
 	struct em28xx *dev = filp->private_data;
@@ -625,16 +624,10 @@ static int em28xx_v4l2_mmap(struct file 
 	vma->vm_flags |= VM_IO;
 	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
 
-	pos = dev->frame[i].bufmem;
-	while (size > 0) {	/* size is page-aligned */
-		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-			em28xx_videodbg("mmap: vm_insert_page failed\n");
-			mutex_unlock(&dev->fileop_lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		size -= PAGE_SIZE;
+	if (remap_vmalloc_range(vma, dev->frame[i].bufmem, 0)) {
+		em28xx_videodbg("mmap: remap_vmalloc_range failed\n");
+		mutex_unlock(&dev->fileop_lock);
+		return -EAGAIN;
 	}
 
 	vma->vm_ops = &em28xx_vm_ops;
Index: linux-2.6/drivers/media/video/et61x251/et61x251_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/et61x251/et61x251_core.c
+++ linux-2.6/drivers/media/video/et61x251/et61x251_core.c
@@ -1464,9 +1464,7 @@ static struct vm_operations_struct et61x
 static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
 {
 	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
-	unsigned long size = vma->vm_end - vma->vm_start,
-		      start = vma->vm_start;
-	void *pos;
+	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
 
 	if (mutex_lock_interruptible(&cam->fileop_mutex))
@@ -1503,15 +1501,9 @@ static int et61x251_mmap(struct file* fi
 	vma->vm_flags |= VM_IO;
 	vma->vm_flags |= VM_RESERVED;
 
-	pos = cam->frame[i].bufmem;
-	while (size > 0) { /* size is page-aligned */
-		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-			mutex_unlock(&cam->fileop_mutex);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		size -= PAGE_SIZE;
+	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
+		mutex_unlock(&cam->fileop_mutex);
+		return -EAGAIN;
 	}
 
 	vma->vm_ops = &et61x251_vm_ops;
Index: linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/sn9c102/sn9c102_core.c
+++ linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1728,9 +1728,7 @@ static struct vm_operations_struct sn9c1
 static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
 {
 	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
-	unsigned long size = vma->vm_end - vma->vm_start,
-		      start = vma->vm_start;
-	void *pos;
+	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
 
 	if (mutex_lock_interruptible(&cam->fileop_mutex))
@@ -1767,15 +1765,9 @@ static int sn9c102_mmap(struct file* fil
 	vma->vm_flags |= VM_IO;
 	vma->vm_flags |= VM_RESERVED;
 
-	pos = cam->frame[i].bufmem;
-	while (size > 0) { /* size is page-aligned */
-		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-			mutex_unlock(&cam->fileop_mutex);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		size -= PAGE_SIZE;
+	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
+		mutex_unlock(&cam->fileop_mutex);
+		return -EAGAIN;
 	}
 
 	vma->vm_ops = &sn9c102_vm_ops;
Index: linux-2.6/drivers/media/video/zc0301/zc0301_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/zc0301/zc0301_core.c
+++ linux-2.6/drivers/media/video/zc0301/zc0301_core.c
@@ -929,9 +929,7 @@ static struct vm_operations_struct zc030
 static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma)
 {
 	struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
-	unsigned long size = vma->vm_end - vma->vm_start,
-		      start = vma->vm_start;
-	void *pos;
+	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
 
 	if (mutex_lock_interruptible(&cam->fileop_mutex))
@@ -968,15 +966,9 @@ static int zc0301_mmap(struct file* filp
 	vma->vm_flags |= VM_IO;
 	vma->vm_flags |= VM_RESERVED;
 
-	pos = cam->frame[i].bufmem;
-	while (size > 0) { /* size is page-aligned */
-		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-			mutex_unlock(&cam->fileop_mutex);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		size -= PAGE_SIZE;
+	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
+		mutex_unlock(&cam->fileop_mutex);
+		return -EAGAIN;
 	}
 
 	vma->vm_ops = &zc0301_vm_ops;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 2/5] mm: deprecate vmalloc_to_pfn
  2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
  2006-04-20 17:06 ` [patch 1/5] mm: remap_vmalloc_range Nick Piggin
@ 2006-04-20 17:06 ` Nick Piggin
  2006-04-20 17:22   ` Christoph Hellwig
  2006-04-20 17:06 ` [patch 3/5] mm: remove rvmalloc Nick Piggin
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:06 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Kernel, Nick Piggin, Linux Memory Management, Hugh Dickins

Deprecate vmalloc_to_pfn.

Signed-off-by: Nick Piggin <npiggin@suse.de>

Index: linux-2.6/Documentation/feature-removal-schedule.txt
===================================================================
--- linux-2.6.orig/Documentation/feature-removal-schedule.txt
+++ linux-2.6/Documentation/feature-removal-schedule.txt
@@ -238,3 +238,12 @@ Why:	The interface no longer has any cal
 Who:	Nick Piggin <npiggin@suse.de>
 
 ---------------------------
+
+What:	vmalloc_to_pfn
+When:	April 2007
+Why:	The interface no longer has any callers left in the kernel. It
+	was previously used so remap_pfn_range can be used on vmalloc memory,
+	but is deprecated with the introduction of remap_vmalloc_range.
+Who:	Nick Piggin <npiggin@suse.de>
+
+---------------------------
Index: linux-2.6/include/linux/mm.h
===================================================================
--- linux-2.6.orig/include/linux/mm.h
+++ linux-2.6/include/linux/mm.h
@@ -1002,7 +1002,7 @@ static inline unsigned long vma_pages(st
 
 struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
 struct page *vmalloc_to_page(void *addr);
-unsigned long vmalloc_to_pfn(void *addr);
+__deprecated_for_modules unsigned long vmalloc_to_pfn(void *addr);
 int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
 			unsigned long pfn, unsigned long size, pgprot_t);
 int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 3/5] mm: remove rvmalloc
  2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
  2006-04-20 17:06 ` [patch 1/5] mm: remap_vmalloc_range Nick Piggin
  2006-04-20 17:06 ` [patch 2/5] mm: deprecate vmalloc_to_pfn Nick Piggin
@ 2006-04-20 17:06 ` Nick Piggin
  2006-04-20 17:06 ` [patch 4/5] mm: extra remap_vmalloc_range check Nick Piggin
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:06 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Kernel, Nick Piggin, Linux Memory Management, Hugh Dickins

Some distros will be using 2.6.16ish kernels, which gives us a good
chance to start getting rid of the SetPageReserved which has stuck
around until now for its ability to catch paper bag type reference
counting bugs.

Signed-off-by: Nick Piggin <npiggin@suse.de>

Index: linux-2.6/drivers/ieee1394/dv1394-private.h
===================================================================
--- linux-2.6.orig/drivers/ieee1394/dv1394-private.h
+++ linux-2.6/drivers/ieee1394/dv1394-private.h
@@ -478,7 +478,7 @@ struct video_card {
 	/* support asynchronous I/O signals (SIGIO) */
 	struct fasync_struct *fasync;
 
-	/* the large, non-contiguous (rvmalloc()) ringbuffer for DV
+	/* the large, non-contiguous (vmalloc()) ringbuffer for DV
            data, exposed to user-space via mmap() */
 	unsigned long      dv_buf_size;
 	struct dma_region  dv_buf;
Index: linux-2.6/drivers/media/video/cpia.c
===================================================================
--- linux-2.6.orig/drivers/media/video/cpia.c
+++ linux-2.6/drivers/media/video/cpia.c
@@ -212,48 +212,6 @@ static void set_flicker(struct cam_param
 
 /**********************************************************************
  *
- * Memory management
- *
- **********************************************************************/
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-/**********************************************************************
- *
  * /proc interface
  *
  **********************************************************************/
@@ -1610,7 +1568,7 @@ static int allocate_frame_buf(struct cam
 {
 	int i;
 
-	cam->frame_buf = rvmalloc(FRAME_NUM * CPIA_MAX_FRAME_SIZE);
+	cam->frame_buf = vmalloc_32_user(FRAME_NUM * CPIA_MAX_FRAME_SIZE);
 	if (!cam->frame_buf)
 		return -ENOBUFS;
 
@@ -1624,7 +1582,7 @@ static int free_frame_buf(struct cam_dat
 {
 	int i;
 
-	rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE);
+	vfree(cam->frame_buf);
 	cam->frame_buf = NULL;
 	for (i=0; i < FRAME_NUM; i++)
 		cam->frame[i].data = NULL;
@@ -3188,13 +3146,13 @@ static int cpia_open(struct inode *inode
 	mutex_lock(&cam->busy_lock);
 	err = -ENOMEM;
 	if (!cam->raw_image) {
-		cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
+		cam->raw_image = vmalloc_32_user(CPIA_MAX_IMAGE_SIZE);
 		if (!cam->raw_image)
 			goto oops;
 	}
 
 	if (!cam->decompressed_frame.data) {
-		cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE);
+		cam->decompressed_frame.data = vmalloc_32_user(CPIA_MAX_FRAME_SIZE);
 		if (!cam->decompressed_frame.data)
 			goto oops;
 	}
@@ -3231,11 +3189,11 @@ static int cpia_open(struct inode *inode
 
  oops:
 	if (cam->decompressed_frame.data) {
-		rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+		vfree(cam->decompressed_frame.data);
 		cam->decompressed_frame.data = NULL;
 	}
 	if (cam->raw_image) {
-		rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+		vfree(cam->raw_image);
 		cam->raw_image = NULL;
 	}
 	mutex_unlock(&cam->busy_lock);
@@ -3274,12 +3232,12 @@ static int cpia_close(struct inode *inod
 	if (--cam->open_count == 0) {
 		/* clean up capture-buffers */
 		if (cam->raw_image) {
-			rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+			vfree(cam->raw_image);
 			cam->raw_image = NULL;
 		}
 
 		if (cam->decompressed_frame.data) {
-			rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+			vfree(cam->decompressed_frame.data);
 			cam->decompressed_frame.data = NULL;
 		}
 
Index: linux-2.6/drivers/media/video/cpia2/cpia2_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/cpia2/cpia2_core.c
+++ linux-2.6/drivers/media/video/cpia2/cpia2_core.c
@@ -86,47 +86,6 @@ static inline unsigned long kvirt_to_pa(
 	return ret;
 }
 
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	/* Round it off to PAGE_SIZE */
-	size = PAGE_ALIGN(size);
-
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size);	/* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-
-	while ((long)size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	size = PAGE_ALIGN(size);
-
-	adr = (unsigned long) mem;
-	while ((long)size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
 /******************************************************************************
  *
  *  cpia2_do_command
@@ -2300,7 +2259,8 @@ int cpia2_allocate_buffers(struct camera
 	}
 
 	if(!cam->frame_buffer) {
-		cam->frame_buffer = rvmalloc(cam->frame_size*cam->num_frames);
+		cam->frame_buffer = vmalloc_32_user(cam->frame_size *
+							cam->num_frames);
 		if (!cam->frame_buffer) {
 			ERR("couldn't vmalloc frame buffer data area\n");
 			kfree(cam->buffers);
@@ -2342,7 +2302,7 @@ void cpia2_free_buffers(struct camera_da
 		cam->buffers = NULL;
 	}
 	if(cam->frame_buffer) {
-		rvfree(cam->frame_buffer, cam->frame_size*cam->num_frames);
+		vfree(cam->frame_buffer);
 		cam->frame_buffer = NULL;
 	}
 }
Index: linux-2.6/drivers/media/video/meye.c
===================================================================
--- linux-2.6.orig/drivers/media/video/meye.c
+++ linux-2.6/drivers/media/video/meye.c
@@ -71,43 +71,6 @@ MODULE_PARM_DESC(video_nr, "video device
 /* driver structure - only one possible */
 static struct meye meye;
 
-/****************************************************************************/
-/* Memory allocation routines (stolen from bttv-driver.c)                   */
-/****************************************************************************/
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (mem) {
-		memset(mem, 0, size);
-		adr = (unsigned long) mem;
-		while (size > 0) {
-			SetPageReserved(vmalloc_to_page((void *)adr));
-			adr += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (mem) {
-		adr = (unsigned long) mem;
-		while ((long) size > 0) {
-			ClearPageReserved(vmalloc_to_page((void *)adr));
-			adr += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-}
-
 /*
  * return a page table pointing to N pages of locked memory
  *
@@ -1516,12 +1479,12 @@ static int meye_do_ioctl(struct inode *i
 					mutex_unlock(&meye.lock);
 					return -EINVAL;
 				}
-			rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
+			vfree(meye.grab_fbuffer);
 			meye.grab_fbuffer = NULL;
 		}
 		gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
 		req->count = gbuffers;
-		meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
+		meye.grab_fbuffer = vmalloc_32_user(gbuffers * gbufsize);
 		if (!meye.grab_fbuffer) {
 			printk(KERN_ERR "meye: v4l framebuffer allocation"
 					" failed\n");
@@ -1710,7 +1673,7 @@ static int meye_mmap(struct file *file, 
 		int i;
 
 		/* lazy allocation */
-		meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize);
+		meye.grab_fbuffer = vmalloc_32_user(gbuffers*gbufsize);
 		if (!meye.grab_fbuffer) {
 			printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
 			mutex_unlock(&meye.lock);
@@ -1982,7 +1945,7 @@ static void __devexit meye_remove(struct
 	vfree(meye.grab_temp);
 
 	if (meye.grab_fbuffer) {
-		rvfree(meye.grab_fbuffer, gbuffers*gbufsize);
+		vfree(meye.grab_fbuffer);
 		meye.grab_fbuffer = NULL;
 	}
 
Index: linux-2.6/drivers/media/video/ov511.c
===================================================================
--- linux-2.6.orig/drivers/media/video/ov511.c
+++ linux-2.6/drivers/media/video/ov511.c
@@ -11,7 +11,6 @@
  * Original SAA7111A code by Dave Perks <dperks@ibm.net>
  * URB error messages from pwc driver by Nemosoft
  * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox
- * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others
  *
  * Based on the Linux CPiA driver written by Peter Pregler,
  * Scott J. Bertin and Johannes Erdfelt.
@@ -310,48 +309,6 @@ static struct symbolic_list urb_errlist[
 };
 
 /**********************************************************************
- * Memory management
- **********************************************************************/
-static void *
-rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void
-rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-/**********************************************************************
  *
  * Register I/O
  *
@@ -3791,8 +3748,7 @@ ov51x_do_dealloc(struct usb_ov511 *ov)
 	PDEBUG(4, "entered");
 
 	if (ov->fbuf) {
-		rvfree(ov->fbuf, OV511_NUMFRAMES
-		       * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
+		vfree(ov->fbuf);
 		ov->fbuf = NULL;
 	}
 
@@ -3837,7 +3793,7 @@ ov51x_alloc(struct usb_ov511 *ov)
 	if (ov->buf_state == BUF_ALLOCATED)
 		goto out;
 
-	ov->fbuf = rvmalloc(data_bufsize);
+	ov->fbuf = vmalloc_32_user(data_bufsize);
 	if (!ov->fbuf)
 		goto error;
 
Index: linux-2.6/drivers/media/video/pwc/pwc-if.c
===================================================================
--- linux-2.6.orig/drivers/media/video/pwc/pwc-if.c
+++ linux-2.6/drivers/media/video/pwc/pwc-if.c
@@ -213,47 +213,6 @@ static inline unsigned long kvirt_to_pa(
 	return ret;
 }
 
-static void * rvmalloc(unsigned long size)
-{
-	void * mem;
-	unsigned long adr;
-
-	size=PAGE_ALIGN(size);
-	mem=vmalloc_32(size);
-	if (mem)
-	{
-		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-		adr=(unsigned long) mem;
-		while (size > 0)
-		{
-			SetPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (mem)
-	{
-		adr=(unsigned long) mem;
-		while ((long) size > 0)
-		{
-			ClearPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-}
-
-
-
-
 static int pwc_allocate_buffers(struct pwc_device *pdev)
 {
 	int i;
@@ -335,7 +294,7 @@ static int pwc_allocate_buffers(struct p
 	pdev->decompress_data = kbuf;
 
 	/* Allocate image buffer; double buffer for mmap() */
-	kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
+	kbuf = vmalloc_32_user(default_mbufs * pdev->len_per_image);
 	if (kbuf == NULL) {
 		Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image);
 		return -ENOMEM;
@@ -400,7 +359,7 @@ static void pwc_free_buffers(struct pwc_
 	/* Release image buffers */
 	if (pdev->image_data != NULL) {
 		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
-		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
+		vfree(pdev->image_data);
 	}
 	pdev->image_data = NULL;
 
Index: linux-2.6/drivers/media/video/se401.c
===================================================================
--- linux-2.6.orig/drivers/media/video/se401.c
+++ linux-2.6/drivers/media/video/se401.c
@@ -60,50 +60,6 @@ module_param(video_nr, int, 0);
 static struct usb_driver se401_driver;
 
 
-/**********************************************************************
- *
- * Memory management
- *
- **********************************************************************/
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-
-
 /****************************************************************************
  *
  * se401 register read/write functions
@@ -907,7 +863,7 @@ static int se401_open(struct inode *inod
 
 	if (se401->user)
 		return -EBUSY;
-	se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
+	se401->fbuf = vmalloc_32_user(se401->maxframesize * SE401_NUMFRAMES);
 	if (se401->fbuf)
 		file->private_data = dev;
 	else
@@ -923,7 +879,7 @@ static int se401_close(struct inode *ino
 	struct usb_se401 *se401 = (struct usb_se401 *)dev;
 	int i;
 
-	rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
+	vfree(se401->fbuf);
 	if (se401->removed) {
 		usb_se401_remove_disconnected(se401);
 		info("device unregistered");
Index: linux-2.6/drivers/media/video/stv680.c
===================================================================
--- linux-2.6.orig/drivers/media/video/stv680.c
+++ linux-2.6/drivers/media/video/stv680.c
@@ -100,62 +100,6 @@ module_param(swapRGB_on, int, 0);
 MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never");
 module_param(video_nr, int, 0);
 
-/********************************************************************
- *
- * Memory management
- *
- * This is a shameless copy from the USB-cpia driver (linux kernel
- * version 2.3.29 or so, I have no idea what this code actually does ;).
- * Actually it seems to be a copy of a shameless copy of the bttv-driver.
- * Or that is a copy of a shameless copy of ... (To the powers: is there
- * no generic kernel-function to do this sort of stuff?)
- *
- * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
- * there will be one, but apparentely not yet -jerdfelt
- *
- * So I copied it again for the ov511 driver -claudio
- *
- * Same for the se401 driver -Jeroen
- *
- * And the STV0680 driver - Kevin
- ********************************************************************/
-static void *rvmalloc (unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32 (size);
-	if (!mem)
-		return NULL;
-
-	memset (mem, 0, size);	/* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	return mem;
-}
-
-static void rvfree (void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree (mem);
-}
-
-
 /*********************************************************************
  * pencam read/write functions
  ********************************************************************/
@@ -1037,9 +981,10 @@ static int stv_open (struct inode *inode
 	err = stv_init (stv680);	/* main initialization routine for camera */
 
 	if (err >= 0) {
-		stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);
+		stv680->fbuf = vmalloc_32_user(stv680->maxframesize *
+							STV680_NUMFRAMES);
 		if (!stv680->fbuf) {
-			PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");
+			PDEBUG (0, "STV(e): Could not vmalloc frame bufer");
 			err = -ENOMEM;
 		}
 		file->private_data = dev;
@@ -1064,7 +1009,7 @@ static int stv_close (struct inode *inod
 	if ((i = stv_stop_video (stv680)) < 0)
 		PDEBUG (1, "STV(e): stop_video failed in stv_close");
 
-	rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);
+	vfree(stv680->fbuf);
 	stv680->user = 0;
 
 	if (stv680->removed) {
Index: linux-2.6/drivers/media/video/usbvideo/usbvideo.c
===================================================================
--- linux-2.6.orig/drivers/media/video/usbvideo/usbvideo.c
+++ linux-2.6/drivers/media/video/usbvideo/usbvideo.c
@@ -57,46 +57,6 @@ static int usbvideo_NewFrame(struct uvd 
 static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
 						struct usbvideo_frame *frame);
 
-/*******************************/
-/* Memory management functions */
-/*******************************/
-static void *usbvideo_rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void usbvideo_rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
 static void RingQueue_Initialize(struct RingQueue *rq)
 {
 	assert(rq != NULL);
@@ -120,7 +80,7 @@ static void RingQueue_Allocate(struct Ri
 
 	rq->length = rqLen;
 	rq->ri = rq->wi = 0;
-	rq->queue = usbvideo_rvmalloc(rq->length);
+	rq->queue = vmalloc_32_user(rq->length);
 	assert(rq->queue != NULL);
 }
 
@@ -135,7 +95,7 @@ static void RingQueue_Free(struct RingQu
 {
 	assert(rq != NULL);
 	if (RingQueue_IsAllocated(rq)) {
-		usbvideo_rvfree(rq->queue, rq->length);
+		vfree(rq->queue);
 		rq->queue = NULL;
 		rq->length = 0;
 	}
@@ -1122,7 +1082,7 @@ static int usbvideo_v4l_open(struct inod
 
 		/* Allocate memory for the frame buffers */
 		uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
-		uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
+		uvd->fbuf = vmalloc_32_user(uvd->fbuf_size);
 		RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
 		if ((uvd->fbuf == NULL) ||
 		    (!RingQueue_IsAllocated(&uvd->dp))) {
@@ -1151,7 +1111,7 @@ static int usbvideo_v4l_open(struct inod
 		if (errCode != 0) {
 			/* Have to free all that memory */
 			if (uvd->fbuf != NULL) {
-				usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
+				vfree(uvd->fbuf);
 				uvd->fbuf = NULL;
 			}
 			RingQueue_Free(&uvd->dp);
@@ -1219,7 +1179,7 @@ static int usbvideo_v4l_close(struct ino
 
 	mutex_lock(&uvd->lock);
 	GET_CALLBACK(uvd, stopDataPump)(uvd);
-	usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
+	vfree(uvd->fbuf);
 	uvd->fbuf = NULL;
 	RingQueue_Free(&uvd->dp);
 
Index: linux-2.6/drivers/media/video/usbvideo/vicam.c
===================================================================
--- linux-2.6.orig/drivers/media/video/usbvideo/vicam.c
+++ linux-2.6/drivers/media/video/usbvideo/vicam.c
@@ -352,50 +352,6 @@ static unsigned char setup5[] = {
 	0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
 };
 
-/* rvmalloc / rvfree copied from usbvideo.c
- *
- * Not sure why these are not yet non-statics which I can reference through
- * usbvideo.h the same as it is in 2.4.20.  I bet this will get fixed sometime
- * in the future.
- *
-*/
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
 struct vicam_camera {
 	u16 shutter_speed;	// capture shutter speed
 	u16 gain;		// capture gain
@@ -783,7 +739,7 @@ vicam_open(struct inode *inode, struct f
 		return -ENOMEM;
 	}
 
-	cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+	cam->framebuf = vmalloc_32_user(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
 	if (!cam->framebuf) {
 		kfree(cam->raw_image);
 		return -ENOMEM;
@@ -792,7 +748,7 @@ vicam_open(struct inode *inode, struct f
 	cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!cam->cntrlbuf) {
 		kfree(cam->raw_image);
-		rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+		vfree(cam->framebuf);
 		return -ENOMEM;
 	}
 
@@ -830,7 +786,7 @@ vicam_close(struct inode *inode, struct 
 	set_camera_power(cam, 0);
 
 	kfree(cam->raw_image);
-	rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+	vfree(cam->framebuf);
 	kfree(cam->cntrlbuf);
 
 	mutex_lock(&cam->cam_lock);
Index: linux-2.6/drivers/media/video/w9968cf.c
===================================================================
--- linux-2.6.orig/drivers/media/video/w9968cf.c
+++ linux-2.6/drivers/media/video/w9968cf.c
@@ -449,8 +449,6 @@ static int w9968cf_i2c_control(struct i2
 			       unsigned long arg);
 
 /* Memory management */
-static void* rvmalloc(unsigned long size);
-static void rvfree(void *mem, unsigned long size);
 static void w9968cf_deallocate_memory(struct w9968cf_device*);
 static int  w9968cf_allocate_memory(struct w9968cf_device*);
 
@@ -593,50 +591,6 @@ static struct w9968cf_symbolic_list urb_
 	{ -1, NULL }
 };
 
-
-
-/****************************************************************************
- * Memory management functions                                              *
- ****************************************************************************/
-static void* rvmalloc(unsigned long size)
-{
-	void* mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-
-static void rvfree(void* mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-
 /*--------------------------------------------------------------------------
   Deallocate previously allocated memory.
   --------------------------------------------------------------------------*/
@@ -652,19 +606,19 @@ static void w9968cf_deallocate_memory(st
 
 	/* Free temporary frame buffer */
 	if (cam->frame_tmp.buffer) {
-		rvfree(cam->frame_tmp.buffer, cam->frame_tmp.size);
+		vfree(cam->frame_tmp.buffer);
 		cam->frame_tmp.buffer = NULL;
 	}
 
 	/* Free helper buffer */
 	if (cam->frame_vpp.buffer) {
-		rvfree(cam->frame_vpp.buffer, cam->frame_vpp.size);
+		vfree(cam->frame_vpp.buffer);
 		cam->frame_vpp.buffer = NULL;
 	}
 
 	/* Free video frame buffers */
 	if (cam->frame[0].buffer) {
-		rvfree(cam->frame[0].buffer, cam->nbuffers*cam->frame[0].size);
+		vfree(cam->frame[0].buffer);
 		cam->frame[0].buffer = NULL;
 	}
 
@@ -711,7 +665,7 @@ static int w9968cf_allocate_memory(struc
 	}
 
 	/* Allocate memory for the temporary frame buffer */
-	if (!(cam->frame_tmp.buffer = rvmalloc(hw_bufsize))) {
+	if (!(cam->frame_tmp.buffer = vmalloc_32_user(hw_bufsize))) {
 		DBG(1, "Couldn't allocate memory for the temporary "
 		       "video frame buffer (%lu bytes)", hw_bufsize)
 		return -ENOMEM;
@@ -721,7 +675,7 @@ static int w9968cf_allocate_memory(struc
 
 	/* Allocate memory for the helper buffer */
 	if (w9968cf_vpp) {
-		if (!(cam->frame_vpp.buffer = rvmalloc(vpp_bufsize))) {
+		if (!(cam->frame_vpp.buffer = vmalloc_32_user(vpp_bufsize))) {
 			DBG(1, "Couldn't allocate memory for the helper buffer"
 			       " (%lu bytes)", vpp_bufsize)
 			return -ENOMEM;
@@ -733,7 +687,7 @@ static int w9968cf_allocate_memory(struc
 	/* Allocate memory for video frame buffers */
 	cam->nbuffers = cam->max_buffers;
 	while (cam->nbuffers >= 2) {
-		if ((buff = rvmalloc(cam->nbuffers * vpp_bufsize)))
+		if ((buff = vmalloc_32_user(cam->nbuffers * vpp_bufsize)))
 			break;
 		else
 			cam->nbuffers--;
Index: linux-2.6/include/linux/vmalloc.h
===================================================================
--- linux-2.6.orig/include/linux/vmalloc.h
+++ linux-2.6/include/linux/vmalloc.h
@@ -32,9 +32,11 @@ struct vm_struct {
  *	Highlevel APIs for driver use
  */
 extern void *vmalloc(unsigned long size);
+extern void *vmalloc_user(unsigned long size);
 extern void *vmalloc_node(unsigned long size, int node);
 extern void *vmalloc_exec(unsigned long size);
 extern void *vmalloc_32(unsigned long size);
+extern void *vmalloc_32_user(unsigned long size);
 extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot);
 extern void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask,
 				pgprot_t prot);
Index: linux-2.6/kernel/power/snapshot.c
===================================================================
--- linux-2.6.orig/kernel/power/snapshot.c
+++ linux-2.6/kernel/power/snapshot.c
@@ -89,10 +89,9 @@ static int save_highmem_zone(struct zone
 			continue;
 		page = pfn_to_page(pfn);
 		/*
-		 * This condition results from rvmalloc() sans vmalloc_32()
-		 * and architectural memory reservations. This should be
-		 * corrected eventually when the cases giving rise to this
-		 * are better understood.
+		 * This condition results from architectural memory
+		 * reservations. This should be corrected eventually when the
+		 * cases giving rise to this are better understood.
 		 */
 		if (PageReserved(page))
 			continue;
Index: linux-2.6/mm/vmalloc.c
===================================================================
--- linux-2.6.orig/mm/vmalloc.c
+++ linux-2.6/mm/vmalloc.c
@@ -512,11 +512,24 @@ EXPORT_SYMBOL(__vmalloc);
  */
 void *vmalloc(unsigned long size)
 {
-       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
+	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
 }
 EXPORT_SYMBOL(vmalloc);
 
 /**
+ *	vmalloc_user  -  allocate virtually contiguous memory which has
+ *			   been zeroed so it can be mapped to userspace without
+ *			   leaking data.
+ *
+ *	@size:		allocation size
+ */
+void *vmalloc_user(unsigned long size)
+{
+	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+}
+EXPORT_SYMBOL(vmalloc_user);
+
+/**
  *	vmalloc_node  -  allocate memory on a specific node
  *
  *	@size:		allocation size
@@ -530,7 +543,7 @@ EXPORT_SYMBOL(vmalloc);
  */
 void *vmalloc_node(unsigned long size, int node)
 {
-       return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node);
+	return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node);
 }
 EXPORT_SYMBOL(vmalloc_node);
 
@@ -570,6 +583,19 @@ void *vmalloc_32(unsigned long size)
 }
 EXPORT_SYMBOL(vmalloc_32);
 
+/**
+ *	vmalloc_32_user  -  allocate virtually contiguous memory (32bit
+ *			      addressable) which is zeroed so it can be
+ *			      mapped to userspace without leaking data.
+ *
+ *	@size:		allocation size
+ */
+void *vmalloc_32_user(unsigned long size)
+{
+	return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+}
+EXPORT_SYMBOL(vmalloc_32_user);
+
 long vread(char *buf, char *addr, unsigned long count)
 {
 	struct vm_struct *tmp;
Index: linux-2.6/arch/ia64/kernel/perfmon.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/perfmon.c
+++ linux-2.6/arch/ia64/kernel/perfmon.c
@@ -558,17 +558,6 @@ pfm_clear_task_notify(void)
 	clear_thread_flag(TIF_NOTIFY_RESUME);
 }
 
-static inline void
-pfm_reserve_page(unsigned long a)
-{
-	SetPageReserved(vmalloc_to_page((void *)a));
-}
-static inline void
-pfm_unreserve_page(unsigned long a)
-{
-	ClearPageReserved(vmalloc_to_page((void*)a));
-}
-
 static inline unsigned long
 pfm_protect_ctx_ctxsw(pfm_context_t *x)
 {
@@ -799,45 +788,6 @@ pfm_reset_msgq(pfm_context_t *ctx)
 	DPRINT(("ctx=%p msgq reset\n", ctx));
 }
 
-static void *
-pfm_rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long addr;
-
-	size = PAGE_ALIGN(size);
-	mem  = vmalloc(size);
-	if (mem) {
-		//printk("perfmon: CPU%d pfm_rvmalloc(%ld)=%p\n", smp_processor_id(), size, mem);
-		memset(mem, 0, size);
-		addr = (unsigned long)mem;
-		while (size > 0) {
-			pfm_reserve_page(addr);
-			addr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void
-pfm_rvfree(void *mem, unsigned long size)
-{
-	unsigned long addr;
-
-	if (mem) {
-		DPRINT(("freeing physical buffer @%p size=%lu\n", mem, size));
-		addr = (unsigned long) mem;
-		while ((long) size > 0) {
-			pfm_unreserve_page(addr);
-			addr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-	return;
-}
-
 static pfm_context_t *
 pfm_context_alloc(void)
 {
@@ -1455,7 +1405,7 @@ pfm_free_smpl_buffer(pfm_context_t *ctx)
 	/*
 	 * free the buffer
 	 */
-	pfm_rvfree(ctx->ctx_smpl_hdr, ctx->ctx_smpl_size);
+	vfree(ctx->ctx_smpl_hdr);
 
 	ctx->ctx_smpl_hdr  = NULL;
 	ctx->ctx_smpl_size = 0UL;
@@ -2106,12 +2056,14 @@ doit:
 	 * All memory free operations (especially for vmalloc'ed memory)
 	 * MUST be done with interrupts ENABLED.
 	 */
-	if (smpl_buf_addr)  pfm_rvfree(smpl_buf_addr, smpl_buf_size);
+	if (smpl_buf_addr)
+		vfree(smpl_buf_addr);
 
 	/*
 	 * return the memory used by the context
 	 */
-	if (free_possible) pfm_context_free(ctx);
+	if (free_possible)
+		pfm_context_free(ctx);
 
 	return 0;
 }
@@ -2270,9 +2222,9 @@ pfm_smpl_buffer_alloc(struct task_struct
 	/*
 	 * We do the easy to undo allocations first.
  	 *
-	 * pfm_rvmalloc(), clears the buffer, so there is no leak
+	 * vmalloc_user(), clears the buffer, so there is no leak
 	 */
-	smpl_buf = pfm_rvmalloc(size);
+	smpl_buf = vmalloc_user(size);
 	if (smpl_buf == NULL) {
 		DPRINT(("Can't allocate sampling buffer\n"));
 		return -ENOMEM;
@@ -2352,7 +2304,7 @@ pfm_smpl_buffer_alloc(struct task_struct
 error:
 	kmem_cache_free(vm_area_cachep, vma);
 error_kmem:
-	pfm_rvfree(smpl_buf, size);
+	vfree(smpl_buf);
 
 	return -ENOMEM;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 4/5] mm: extra remap_vmalloc_range check
  2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
                   ` (2 preceding siblings ...)
  2006-04-20 17:06 ` [patch 3/5] mm: remove rvmalloc Nick Piggin
@ 2006-04-20 17:06 ` Nick Piggin
  2006-04-20 17:07 ` [patch 5/5] drivers: leave vm_flags alone Nick Piggin
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:06 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Kernel, Nick Piggin, Linux Memory Management, Hugh Dickins

Add a flag to ensure all remap_vmalloc_range memory has been allocated
with the vmalloc _user variants, so data does not get leaked.

Signed-off-by: Nick Piggin <npiggin@suse.de>

Index: linux-2.6/include/linux/vmalloc.h
===================================================================
--- linux-2.6.orig/include/linux/vmalloc.h
+++ linux-2.6/include/linux/vmalloc.h
@@ -8,6 +8,7 @@
 #define VM_IOREMAP	0x00000001	/* ioremap() and friends */
 #define VM_ALLOC	0x00000002	/* vmalloc() */
 #define VM_MAP		0x00000004	/* vmap()ed pages */
+#define VM_USERMAP	0x00000008	/* suitable for remap_vmalloc_range */
 /* bits [20..32] reserved for arch specific ioremap internals */
 
 /*
Index: linux-2.6/drivers/media/video/et61x251/et61x251_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/et61x251/et61x251_core.c
+++ linux-2.6/drivers/media/video/et61x251/et61x251_core.c
@@ -133,7 +133,8 @@ et61x251_request_buffers(struct et61x251
 
 	cam->nbuffers = count;
 	while (cam->nbuffers > 0) {
-		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+		if ((buff = vmalloc_32_user(cam->nbuffers *
+						PAGE_ALIGN(imagesize))))
 			break;
 		cam->nbuffers--;
 	}
Index: linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/sn9c102/sn9c102_core.c
+++ linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
@@ -149,7 +149,7 @@ sn9c102_request_buffers(struct sn9c102_d
 
 	cam->nbuffers = count;
 	while (cam->nbuffers > 0) {
-		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+		if ((buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize))))
 			break;
 		cam->nbuffers--;
 	}
Index: linux-2.6/drivers/media/video/zc0301/zc0301_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/zc0301/zc0301_core.c
+++ linux-2.6/drivers/media/video/zc0301/zc0301_core.c
@@ -136,7 +136,7 @@ zc0301_request_buffers(struct zc0301_dev
 
 	cam->nbuffers = count;
 	while (cam->nbuffers > 0) {
-		if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
+		if ((buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize))))
 			break;
 		cam->nbuffers--;
 	}
Index: linux-2.6/mm/vmalloc.c
===================================================================
--- linux-2.6.orig/mm/vmalloc.c
+++ linux-2.6/mm/vmalloc.c
@@ -525,7 +525,15 @@ EXPORT_SYMBOL(vmalloc);
  */
 void *vmalloc_user(unsigned long size)
 {
-	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+	struct vm_struct *area;
+	void *ret;
+
+	ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+	area = find_vm_area(ret);
+	BUG_ON(!area);
+	area->flags |= VM_USERMAP;
+
+	return ret;
 }
 EXPORT_SYMBOL(vmalloc_user);
 
@@ -592,7 +600,15 @@ EXPORT_SYMBOL(vmalloc_32);
  */
 void *vmalloc_32_user(unsigned long size)
 {
-	return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+	struct vm_struct *area;
+	void *ret;
+
+	ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+	area = find_vm_area(ret);
+	BUG_ON(!area);
+	area->flags |= VM_USERMAP;
+
+	return ret;
 }
 EXPORT_SYMBOL(vmalloc_32_user);
 
@@ -700,6 +716,9 @@ int remap_vmalloc_range(struct vm_area_s
 	if (!area)
 		return -EINVAL;
 
+	if (!(area->flags & VM_USERMAP))
+		return -EINVAL;
+
 	if (usize + (pgoff << PAGE_SHIFT) > area->size - PAGE_SIZE)
 		return -EINVAL;
 
Index: linux-2.6/drivers/media/video/em28xx/em28xx-core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/em28xx/em28xx-core.c
+++ linux-2.6/drivers/media/video/em28xx/em28xx-core.c
@@ -79,10 +79,8 @@ u32 em28xx_request_buffers(struct em28xx
 
 	dev->num_frames = count;
 	while (dev->num_frames > 0) {
-		if ((buff = vmalloc_32(dev->num_frames * imagesize))) {
-			memset(buff, 0, dev->num_frames * imagesize);
+		if ((buff = vmalloc_32_user(dev->num_frames * imagesize)))
 			break;
-		}
 		dev->num_frames--;
 	}
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 5/5] drivers: leave vm_flags alone
  2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
                   ` (3 preceding siblings ...)
  2006-04-20 17:06 ` [patch 4/5] mm: extra remap_vmalloc_range check Nick Piggin
@ 2006-04-20 17:07 ` Nick Piggin
  2006-04-20 17:27 ` [patch 6/5] mm: find_vm_area locking fixes Nick Piggin
  2006-04-20 18:14 ` [patch][rfc] improve remap_vmalloc_range callers' return values Nick Piggin
  6 siblings, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:07 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Kernel, Nick Piggin, Linux Memory Management, Hugh Dickins

Get rid of some vm_flags twiddling from driver code. The net result of
this + the last 4 patches is that all converted remap_vmalloc_range
memory can support get_user_pages - do we want that? Can't hurt, can it?

Signed-off-by: Nick Piggin <npiggin@suse.de>

Index: linux-2.6/drivers/media/video/em28xx/em28xx-video.c
===================================================================
--- linux-2.6.orig/drivers/media/video/em28xx/em28xx-video.c
+++ linux-2.6/drivers/media/video/em28xx/em28xx-video.c
@@ -620,10 +620,6 @@ static int em28xx_v4l2_mmap(struct file 
 		return -EINVAL;
 	}
 
-	/* VM_IO is eventually going to replace PageReserved altogether */
-	vma->vm_flags |= VM_IO;
-	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
-
 	if (remap_vmalloc_range(vma, dev->frame[i].bufmem, 0)) {
 		em28xx_videodbg("mmap: remap_vmalloc_range failed\n");
 		mutex_unlock(&dev->fileop_lock);
Index: linux-2.6/drivers/media/video/et61x251/et61x251_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/et61x251/et61x251_core.c
+++ linux-2.6/drivers/media/video/et61x251/et61x251_core.c
@@ -1499,9 +1499,6 @@ static int et61x251_mmap(struct file* fi
 		return -EINVAL;
 	}
 
-	vma->vm_flags |= VM_IO;
-	vma->vm_flags |= VM_RESERVED;
-
 	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
 		mutex_unlock(&cam->fileop_mutex);
 		return -EAGAIN;
Index: linux-2.6/drivers/media/video/meye.c
===================================================================
--- linux-2.6.orig/drivers/media/video/meye.c
+++ linux-2.6/drivers/media/video/meye.c
@@ -1689,8 +1689,6 @@ static int meye_mmap(struct file *file, 
 	}
 
 	vma->vm_ops = &meye_vm_ops;
-	vma->vm_flags &= ~VM_IO;	/* not I/O memory */
-	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
 	vma->vm_private_data = (void *) (offset / gbufsize);
 	meye_vm_open(vma);
 
Index: linux-2.6/drivers/media/video/pwc/pwc-if.c
===================================================================
--- linux-2.6.orig/drivers/media/video/pwc/pwc-if.c
+++ linux-2.6/drivers/media/video/pwc/pwc-if.c
@@ -1567,8 +1567,6 @@ static int pwc_video_mmap(struct file *f
 				vma->vm_start, vma->vm_end - vma->vm_start);
 	pdev = vdev->priv;
 
-	vma->vm_flags |= VM_IO;
-
 	if (remap_vmalloc_range(vma, pdev->image_data, 0))
 		return -EAGAIN;
 
Index: linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/sn9c102/sn9c102_core.c
+++ linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1762,9 +1762,6 @@ static int sn9c102_mmap(struct file* fil
 		return -EINVAL;
 	}
 
-	vma->vm_flags |= VM_IO;
-	vma->vm_flags |= VM_RESERVED;
-
 	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
 		mutex_unlock(&cam->fileop_mutex);
 		return -EAGAIN;
Index: linux-2.6/drivers/media/video/zc0301/zc0301_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/zc0301/zc0301_core.c
+++ linux-2.6/drivers/media/video/zc0301/zc0301_core.c
@@ -963,9 +963,6 @@ static int zc0301_mmap(struct file* filp
 		return -EINVAL;
 	}
 
-	vma->vm_flags |= VM_IO;
-	vma->vm_flags |= VM_RESERVED;
-
 	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
 		mutex_unlock(&cam->fileop_mutex);
 		return -EAGAIN;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] mm: remap_vmalloc_range
  2006-04-20 17:06 ` [patch 1/5] mm: remap_vmalloc_range Nick Piggin
@ 2006-04-20 17:22   ` Christoph Hellwig
  2006-04-20 17:33     ` Nick Piggin
  2006-04-20 18:09   ` Nick Piggin
  1 sibling, 1 reply; 14+ messages in thread
From: Christoph Hellwig @ 2006-04-20 17:22 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Andrew Morton, Linux Kernel, Linux Memory Management,
	Hugh Dickins

On Thu, Apr 20, 2006 at 07:06:18PM +0200, Nick Piggin wrote:
> Add a remap_vmalloc_range and get rid of as many remap_pfn_range and
> vm_insert_page loops as possible.
> 
> remap_vmalloc_range can do a whole lot of nice range checking even
> if the caller gets it wrong (which it looks like one or two do).

This looks very nice, thanks!  Although it might be better to split it
into one patch to introduce remap_vmalloc_range and various patches to
switch over one susbsyetm for merging purposes.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 2/5] mm: deprecate vmalloc_to_pfn
  2006-04-20 17:06 ` [patch 2/5] mm: deprecate vmalloc_to_pfn Nick Piggin
@ 2006-04-20 17:22   ` Christoph Hellwig
  2006-04-20 17:36     ` Nick Piggin
  0 siblings, 1 reply; 14+ messages in thread
From: Christoph Hellwig @ 2006-04-20 17:22 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Andrew Morton, Linux Kernel, Linux Memory Management,
	Hugh Dickins

On Thu, Apr 20, 2006 at 07:06:30PM +0200, Nick Piggin wrote:
> Deprecate vmalloc_to_pfn.

I don't think there's any point to even keep it.  There's a trivial replcement.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 6/5] mm: find_vm_area locking fixes
  2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
                   ` (4 preceding siblings ...)
  2006-04-20 17:07 ` [patch 5/5] drivers: leave vm_flags alone Nick Piggin
@ 2006-04-20 17:27 ` Nick Piggin
  2006-04-20 18:14 ` [patch][rfc] improve remap_vmalloc_range callers' return values Nick Piggin
  6 siblings, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:27 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Linux Kernel, Linux Memory Management, Hugh Dickins

Bite the bullet and try to get the locking correct the first^Wsecond time.

(subtle bugs like area->flagas modification not having the right memory
consistency could be a nightmare to track down)

Signed-off-by: Nick Piggin <npiggin@suse.de>

Index: linux-2.6/mm/vmalloc.c
===================================================================
--- linux-2.6.orig/mm/vmalloc.c
+++ linux-2.6/mm/vmalloc.c
@@ -256,16 +256,15 @@ struct vm_struct *get_vm_area_node(unsig
 	return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node);
 }
 
-static struct vm_struct *find_vm_area(void *addr)
+/* Caller must hold vmlist_lock */
+static struct vm_struct *__find_vm_area(void *addr)
 {
 	struct vm_struct *tmp;
 
-	write_lock(&vmlist_lock);
 	for (tmp = vmlist; tmp != NULL; tmp = tmp->next) {
 		 if (tmp->addr == addr)
 			break;
 	}
-	write_unlock(&vmlist_lock);
 
 	return tmp;
 }
@@ -529,9 +528,10 @@ void *vmalloc_user(unsigned long size)
 	void *ret;
 
 	ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
-	area = find_vm_area(ret);
-	BUG_ON(!area);
+	write_lock(&vmlist_lock);
+	area = __find_vm_area(ret);
 	area->flags |= VM_USERMAP;
+	write_unlock(&vmlist_lock);
 
 	return ret;
 }
@@ -604,9 +604,10 @@ void *vmalloc_32_user(unsigned long size
 	void *ret;
 
 	ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
-	area = find_vm_area(ret);
-	BUG_ON(!area);
+	write_lock(&vmlist_lock);
+	area = __find_vm_area(ret);
 	area->flags |= VM_USERMAP;
+	write_unlock(&vmlist_lock);
 
 	return ret;
 }
@@ -712,15 +713,17 @@ int remap_vmalloc_range(struct vm_area_s
 	if ((PAGE_SIZE-1) & (unsigned long)addr)
 		return -EINVAL;
 
-	area = find_vm_area(addr);
+	read_lock(&vmlist_lock);
+	area = __find_vm_area(addr);
 	if (!area)
-		return -EINVAL;
+		goto out_einval_locked;
 
 	if (!(area->flags & VM_USERMAP))
-		return -EINVAL;
+		goto out_einval_locked;
 
 	if (usize + (pgoff << PAGE_SHIFT) > area->size - PAGE_SIZE)
-		return -EINVAL;
+		goto out_einval_locked;
+	read_unlock(&vmlist_lock);
 
 	addr = (void *)((unsigned long)addr + (pgoff << PAGE_SHIFT));
 	do {
@@ -738,6 +741,10 @@ int remap_vmalloc_range(struct vm_area_s
 	vma->vm_flags |= VM_RESERVED;
 
 	return ret;
+
+out_einval_locked:
+	read_unlock(&vmlist_lock);
+	return -EINVAL;
 }
 EXPORT_SYMBOL(remap_vmalloc_range);
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] mm: remap_vmalloc_range
  2006-04-20 17:22   ` Christoph Hellwig
@ 2006-04-20 17:33     ` Nick Piggin
  0 siblings, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:33 UTC (permalink / raw)
  To: Christoph Hellwig, Nick Piggin, Andrew Morton, Linux Kernel,
	Linux Memory Management, Hugh Dickins

On Thu, Apr 20, 2006 at 06:22:05PM +0100, Christoph Hellwig wrote:
> On Thu, Apr 20, 2006 at 07:06:18PM +0200, Nick Piggin wrote:
> > Add a remap_vmalloc_range and get rid of as many remap_pfn_range and
> > vm_insert_page loops as possible.
> > 
> > remap_vmalloc_range can do a whole lot of nice range checking even
> > if the caller gets it wrong (which it looks like one or two do).
> 
> This looks very nice, thanks!

Thank you

> Although it might be better to split it
> into one patch to introduce remap_vmalloc_range and various patches to
> switch over one susbsyetm for merging purposes.

Sure, if anyone insists ;)

I tend to agree. I would tend to do it in just 2 patches
(1 for implementation, 1 for conversion) to make administrative
overheads smaller -- the conversions are small and very well
contained. Is there a good reason to split further?

Nick

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 2/5] mm: deprecate vmalloc_to_pfn
  2006-04-20 17:22   ` Christoph Hellwig
@ 2006-04-20 17:36     ` Nick Piggin
  2006-04-20 20:03       ` Andrew Morton
  0 siblings, 1 reply; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 17:36 UTC (permalink / raw)
  To: Christoph Hellwig, Nick Piggin, Andrew Morton, Linux Kernel,
	Linux Memory Management, Hugh Dickins

On Thu, Apr 20, 2006 at 06:22:40PM +0100, Christoph Hellwig wrote:
> On Thu, Apr 20, 2006 at 07:06:30PM +0200, Nick Piggin wrote:
> > Deprecate vmalloc_to_pfn.
> 
> I don't think there's any point to even keep it.  There's a trivial replcement.

It is exported, is the only thing. I tend to stick my head in the sand
with these matters, and try to go with whatever I think will help Andrew
merge it.

If nobody cares, I'd just as soon remove it completely.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] mm: remap_vmalloc_range
  2006-04-20 17:06 ` [patch 1/5] mm: remap_vmalloc_range Nick Piggin
  2006-04-20 17:22   ` Christoph Hellwig
@ 2006-04-20 18:09   ` Nick Piggin
  1 sibling, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 18:09 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Linux Kernel, Linux Memory Management, Hugh Dickins

Hotfix #1


Index: linux-2.6/drivers/media/video/usbvideo/vicam.c
===================================================================
--- linux-2.6.orig/drivers/media/video/usbvideo/vicam.c
+++ linux-2.6/drivers/media/video/usbvideo/vicam.c
@@ -1000,6 +1000,7 @@ vicam_mmap(struct file *file, struct vm_
 	 * It shouldn't have been, so let's try this check again -np
 	 */
 	 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
+		return -EINVAL;
 
 	if (remap_vmalloc_range(vma, cam->framebuf, 0))
 		return -EAGAIN;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch][rfc] improve remap_vmalloc_range callers' return values
  2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
                   ` (5 preceding siblings ...)
  2006-04-20 17:27 ` [patch 6/5] mm: find_vm_area locking fixes Nick Piggin
@ 2006-04-20 18:14 ` Nick Piggin
  6 siblings, 0 replies; 14+ messages in thread
From: Nick Piggin @ 2006-04-20 18:14 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Kernel, Linux Memory Management, Hugh Dickins,
	Stephane Eranian

Not directly related to the current patchset... but does anyone
see a reason why we shouldn't try to return saner values from
remap_vmalloc_range callers?

(This patch is slightly more involved for perfmon, so Stephane
CCed. It catches insert_vm_struct errors, and moves
remap_vmalloc_range below it so we needn't have to clean up
by unmapping stuff).

--
Index: linux-2.6/arch/ia64/kernel/perfmon.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/perfmon.c
+++ linux-2.6/arch/ia64/kernel/perfmon.c
@@ -2199,6 +2199,7 @@ pfm_smpl_buffer_alloc(struct task_struct
 	struct vm_area_struct *vma = NULL;
 	unsigned long size;
 	void *smpl_buf;
+	int ret = -ENOMEM;
 
 
 	/*
@@ -2217,7 +2218,7 @@ pfm_smpl_buffer_alloc(struct task_struct
 	 * 	return -ENOMEM;
 	 */
 	if (size > task->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
-		return -ENOMEM;
+		goto out;
 
 	/*
 	 * We do the easy to undo allocations first.
@@ -2227,7 +2228,7 @@ pfm_smpl_buffer_alloc(struct task_struct
 	smpl_buf = vmalloc_user(size);
 	if (smpl_buf == NULL) {
 		DPRINT(("Can't allocate sampling buffer\n"));
-		return -ENOMEM;
+		goto out;
 	}
 
 	DPRINT(("smpl_buf @%p\n", smpl_buf));
@@ -2267,7 +2268,6 @@ pfm_smpl_buffer_alloc(struct task_struct
 	vma->vm_start = pfm_get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS, 0);
 	if (vma->vm_start == 0UL) {
 		DPRINT(("Cannot find unmapped area for size %ld\n", size));
-		up_write(&task->mm->mmap_sem);
 		goto error;
 	}
 	vma->vm_end = vma->vm_start + size;
@@ -2275,23 +2275,24 @@ pfm_smpl_buffer_alloc(struct task_struct
 
 	DPRINT(("aligned size=%ld, hdr=%p mapped @0x%lx\n", size, ctx->ctx_smpl_hdr, vma->vm_start));
 
-	/* can only be applied to current task, need to have the mm semaphore held when called */
-	if (remap_vmalloc_range(vma, smpl_buf, 0)) {
-		DPRINT(("Can't remap buffer\n"));
-		up_write(&task->mm->mmap_sem);
-		goto error;
-	}
-
 	/*
 	 * now insert the vma in the vm list for the process, must be
 	 * done with mmap lock held
 	 */
-	insert_vm_struct(mm, vma);
+	if ((ret = insert_vm_struct(mm, vma)) {
+		DPRINT(("Can't insert vma\n"));
+		goto error;
+	}
+
+	/* can only be applied to current task, need to have the mm semaphore held when called */
+	if ((ret = remap_vmalloc_range(vma, smpl_buf, 0))) {
+		DPRINT(("Can't remap buffer\n"));
+		goto error;
+	}
 
 	mm->total_vm  += size >> PAGE_SHIFT;
 	vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
 							vma_pages(vma));
-	up_write(&task->mm->mmap_sem);
 
 	/*
 	 * keep track of user level virtual address
@@ -2299,14 +2300,17 @@ pfm_smpl_buffer_alloc(struct task_struct
 	ctx->ctx_smpl_vaddr = (void *)vma->vm_start;
 	*(unsigned long *)user_vaddr = vma->vm_start;
 
+	up_write(&task->mm->mmap_sem);
+
 	return 0;
 
 error:
+	up_write(&task->mm->mmap_sem);
 	kmem_cache_free(vm_area_cachep, vma);
 error_kmem:
 	vfree(smpl_buf);
-
-	return -ENOMEM;
+out:
+	return ret;
 }
 
 /*
Index: linux-2.6/drivers/media/video/cpia.c
===================================================================
--- linux-2.6.orig/drivers/media/video/cpia.c
+++ linux-2.6/drivers/media/video/cpia.c
@@ -3734,9 +3734,9 @@ static int cpia_mmap(struct file *file, 
 		}
 	}
 
-	if (remap_vmalloc_range(vma, cam->frame_buf, 0)) {
+	if ((retval = remap_vmalloc_range(vma, cam->frame_buf, 0))) {
 		mutex_unlock(&cam->busy_lock);
-		return -EAGAIN;
+		return retval;
 	}
 
 	DBG("cpia_mmap: %ld\n", size);
Index: linux-2.6/drivers/media/video/em28xx/em28xx-video.c
===================================================================
--- linux-2.6.orig/drivers/media/video/em28xx/em28xx-video.c
+++ linux-2.6/drivers/media/video/em28xx/em28xx-video.c
@@ -585,6 +585,7 @@ static int em28xx_v4l2_mmap(struct file 
 {
 	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
+	int ret;
 
 	struct em28xx *dev = filp->private_data;
 
@@ -593,21 +594,21 @@ static int em28xx_v4l2_mmap(struct file 
 
 	if (dev->state & DEV_DISCONNECTED) {
 		em28xx_videodbg("mmap: device not present\n");
-		mutex_unlock(&dev->fileop_lock);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out;
 	}
 
 	if (dev->state & DEV_MISCONFIGURED) {
 		em28xx_videodbg ("mmap: Device is misconfigured; close and "
 						"open it again\n");
-		mutex_unlock(&dev->fileop_lock);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
 	    size != PAGE_ALIGN(dev->frame[0].buf.length)) {
-		mutex_unlock(&dev->fileop_lock);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	for (i = 0; i < dev->num_frames; i++) {
@@ -616,22 +617,23 @@ static int em28xx_v4l2_mmap(struct file 
 	}
 	if (i == dev->num_frames) {
 		em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
-		mutex_unlock(&dev->fileop_lock);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
-	if (remap_vmalloc_range(vma, dev->frame[i].bufmem, 0)) {
+	if ((ret = remap_vmalloc_range(vma, dev->frame[i].bufmem, 0))) {
 		em28xx_videodbg("mmap: remap_vmalloc_range failed\n");
-		mutex_unlock(&dev->fileop_lock);
-		return -EAGAIN;
+		goto out;
 	}
 
 	vma->vm_ops = &em28xx_vm_ops;
 	vma->vm_private_data = &dev->frame[i];
 
 	em28xx_vm_open(vma);
+
+out:
 	mutex_unlock(&dev->fileop_lock);
-	return 0;
+	return ret;
 }
 
 /*
Index: linux-2.6/drivers/media/video/meye.c
===================================================================
--- linux-2.6.orig/drivers/media/video/meye.c
+++ linux-2.6/drivers/media/video/meye.c
@@ -1663,11 +1663,12 @@ static struct vm_operations_struct meye_
 static int meye_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	unsigned long size = vma->vm_end - vma->vm_start;
+	int ret;
 
 	mutex_lock(&meye.lock);
 	if (size > gbuffers * gbufsize) { /* XXX: should be size + vm_pgoff? */
-		mutex_unlock(&meye.lock);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	if (!meye.grab_fbuffer) {
 		int i;
@@ -1676,24 +1677,23 @@ static int meye_mmap(struct file *file, 
 		meye.grab_fbuffer = vmalloc_32_user(gbuffers*gbufsize);
 		if (!meye.grab_fbuffer) {
 			printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
-			mutex_unlock(&meye.lock);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto out;
 		}
 		for (i = 0; i < gbuffers; i++)
 			meye.vma_use_count[i] = 0;
 	}
 
-	if (remap_vmalloc_range(vma, meye.grab_fbuffer, vma->vm_pgoff)) {
-		mutex_unlock(&meye.lock);
-		return -EAGAIN;
-	}
+	if ((ret = remap_vmalloc_range(vma, meye.grab_fbuffer, vma->vm_pgoff)))
+		goto out;
 
 	vma->vm_ops = &meye_vm_ops;
 	vma->vm_private_data = (void *) (offset / gbufsize);
 	meye_vm_open(vma);
 
+out:
 	mutex_unlock(&meye.lock);
-	return 0;
+	return ret;
 }
 
 static struct file_operations meye_fops = {
Index: linux-2.6/drivers/media/video/ov511.c
===================================================================
--- linux-2.6.orig/drivers/media/video/ov511.c
+++ linux-2.6/drivers/media/video/ov511.c
@@ -4574,6 +4574,7 @@ ov51x_v4l1_mmap(struct file *file, struc
 	struct video_device *vdev = file->private_data;
 	unsigned long size  = vma->vm_end - vma->vm_start;
 	struct usb_ov511 *ov = video_get_drvdata(vdev);
+	int ret;
 
 	if (ov->dev == NULL)
 		return -EIO;
@@ -4588,13 +4589,10 @@ ov51x_v4l1_mmap(struct file *file, struc
 	if (mutex_lock_interruptible(&ov->lock))
 		return -EINTR;
 
-	if (remap_vmalloc_range(vma, ov->fbuf, 0)) {
-		mutex_unlock(&ov->lock);
-		return -EAGAIN;
-	}
+	ret = remap_vmalloc_range(vma, ov->fbuf, 0);
 
 	mutex_unlock(&ov->lock);
-	return 0;
+	return ret;
 }
 
 static struct file_operations ov511_fops = {
Index: linux-2.6/drivers/media/video/pwc/pwc-if.c
===================================================================
--- linux-2.6.orig/drivers/media/video/pwc/pwc-if.c
+++ linux-2.6/drivers/media/video/pwc/pwc-if.c
@@ -1567,10 +1567,7 @@ static int pwc_video_mmap(struct file *f
 				vma->vm_start, vma->vm_end - vma->vm_start);
 	pdev = vdev->priv;
 
-	if (remap_vmalloc_range(vma, pdev->image_data, 0))
-		return -EAGAIN;
-
-	return 0;
+	return remap_vmalloc_range(vma, pdev->image_data, 0);
 }
 
 /***************************************************************************/
Index: linux-2.6/drivers/media/video/se401.c
===================================================================
--- linux-2.6.orig/drivers/media/video/se401.c
+++ linux-2.6/drivers/media/video/se401.c
@@ -1110,24 +1110,24 @@ static int se401_mmap(struct file *file,
 	struct video_device *dev = file->private_data;
 	struct usb_se401 *se401 = (struct usb_se401 *)dev;
 	unsigned long size  = vma->vm_end-vma->vm_start;
+	int ret;
 
 	mutex_lock(&se401->lock);
 
 	if (se401->dev == NULL) {
-		mutex_unlock(&se401->lock);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 	if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
-		mutex_unlock(&se401->lock);
-		return -EINVAL;
-	}
-	if (remap_vmalloc_range(vma, se401->fbuf, 0)) {
-		mutex_unlock(&se401->lock);
-		return -EAGAIN;
+		ret = -EINVAL;
+		goto out;
 	}
-	mutex_unlock(&se401->lock);
 
-	return 0;
+	ret = remap_vmalloc_range(vma, se401->fbuf, 0);
+
+out:
+	mutex_unlock(&se401->lock);
+	return ret;
 }
 
 static struct file_operations se401_fops = {
Index: linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/sn9c102/sn9c102_core.c
+++ linux-2.6/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1730,27 +1730,28 @@ static int sn9c102_mmap(struct file* fil
 	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
 	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
+	int ret;
 
 	if (mutex_lock_interruptible(&cam->fileop_mutex))
 		return -ERESTARTSYS;
 
 	if (cam->state & DEV_DISCONNECTED) {
 		DBG(1, "Device not present");
-		mutex_unlock(&cam->fileop_mutex);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out;
 	}
 
 	if (cam->state & DEV_MISCONFIGURED) {
 		DBG(1, "The camera is misconfigured. Close and open it "
 		       "again.");
-		mutex_unlock(&cam->fileop_mutex);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
 	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	for (i = 0; i < cam->nbuffers; i++) {
@@ -1758,23 +1759,21 @@ static int sn9c102_mmap(struct file* fil
 			break;
 	}
 	if (i == cam->nbuffers) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
-	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EAGAIN;
-	}
+	if ((ret = remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)))
+		goto out;
 
 	vma->vm_ops = &sn9c102_vm_ops;
 	vma->vm_private_data = &cam->frame[i];
 
 	sn9c102_vm_open(vma);
 
+out:
 	mutex_unlock(&cam->fileop_mutex);
-
-	return 0;
+	return ret;
 }
 
 /*****************************************************************************/
Index: linux-2.6/drivers/media/video/stv680.c
===================================================================
--- linux-2.6.orig/drivers/media/video/stv680.c
+++ linux-2.6/drivers/media/video/stv680.c
@@ -1200,25 +1200,25 @@ static int stv680_mmap (struct file *fil
 	struct video_device *dev = file->private_data;
 	struct usb_stv *stv680 = video_get_drvdata(dev);
 	unsigned long size  = vma->vm_end-vma->vm_start;
+	int ret;
 
 	mutex_lock(&stv680->lock);
 
 	if (stv680->udev == NULL) {
-		mutex_unlock(&stv680->lock);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 	if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
 		    & ~(PAGE_SIZE - 1))) {
-		mutex_unlock(&stv680->lock);
-		return -EINVAL;
-	}
-	if (remap_vmalloc_range(vma, stv680->fbuf, 0)) {
-		mutex_unlock(&stv680->lock);
-		return -EAGAIN;
+		ret = -EINVAL;
+		goto out;
 	}
-	mutex_unlock(&stv680->lock);
 
-	return 0;
+	ret = remap_vmalloc_range(vma, stv680->fbuf, 0);
+
+out:
+	mutex_unlock(&stv680->lock);
+	return ret;
 }
 
 static ssize_t stv680_read (struct file *file, char __user *buf,
Index: linux-2.6/drivers/media/video/usbvideo/usbvideo.c
===================================================================
--- linux-2.6.orig/drivers/media/video/usbvideo/usbvideo.c
+++ linux-2.6/drivers/media/video/usbvideo/usbvideo.c
@@ -1036,10 +1036,7 @@ static int usbvideo_v4l_mmap(struct file
 	if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
 		return -EINVAL;
 
-	if (remap_vmalloc_range(vma, uvd->fbuf, 0))
-		return -EAGAIN;
-
-	return 0;
+	return remap_vmalloc_range(vma, uvd->fbuf, 0);
 }
 
 /*
Index: linux-2.6/drivers/media/video/usbvideo/vicam.c
===================================================================
--- linux-2.6.orig/drivers/media/video/usbvideo/vicam.c
+++ linux-2.6/drivers/media/video/usbvideo/vicam.c
@@ -1002,10 +1002,7 @@ vicam_mmap(struct file *file, struct vm_
 	 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
 		return -EINVAL;
 
-	if (remap_vmalloc_range(vma, cam->framebuf, 0))
-		return -EAGAIN;
-
-	return 0;
+	return remap_vmalloc_range(vma, cam->framebuf, 0);
 }
 
 #if defined(CONFIG_VIDEO_PROC_FS)
Index: linux-2.6/drivers/media/video/w9968cf.c
===================================================================
--- linux-2.6.orig/drivers/media/video/w9968cf.c
+++ linux-2.6/drivers/media/video/w9968cf.c
@@ -2816,6 +2816,7 @@ static int w9968cf_mmap(struct file* fil
 				     video_get_drvdata(video_devdata(filp));
 	unsigned long vsize = vma->vm_end - vma->vm_start,
 		      psize = cam->nbuffers * cam->frame[0].size;
+	int ret;
 
 	if (cam->disconnected) {
 		DBG(2, "Device not present")
@@ -2832,11 +2833,10 @@ static int w9968cf_mmap(struct file* fil
 	if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT))
 		return -EINVAL;
 
-	if (remap_vmalloc_range(vma, cam->frame[0].buffer, vma->vm_pgoff))
-		return -EAGAIN;
+	ret = remap_vmalloc_range(vma, cam->frame[0].buffer, vma->vm_pgoff);
 
 	DBG(5, "mmap method successfully called")
-	return 0;
+	return ret;
 }
 
 
Index: linux-2.6/drivers/media/video/zc0301/zc0301_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/zc0301/zc0301_core.c
+++ linux-2.6/drivers/media/video/zc0301/zc0301_core.c
@@ -931,27 +931,28 @@ static int zc0301_mmap(struct file* filp
 	struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
 	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
+	int ret;
 
 	if (mutex_lock_interruptible(&cam->fileop_mutex))
 		return -ERESTARTSYS;
 
 	if (cam->state & DEV_DISCONNECTED) {
 		DBG(1, "Device not present");
-		mutex_unlock(&cam->fileop_mutex);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out;
 	}
 
 	if (cam->state & DEV_MISCONFIGURED) {
 		DBG(1, "The camera is misconfigured. Close and open it "
 		       "again.");
-		mutex_unlock(&cam->fileop_mutex);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
 	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	for (i = 0; i < cam->nbuffers; i++) {
@@ -959,23 +960,21 @@ static int zc0301_mmap(struct file* filp
 			break;
 	}
 	if (i == cam->nbuffers) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
-	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EAGAIN;
-	}
+	if ((ret = remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)))
+		goto out;
 
 	vma->vm_ops = &zc0301_vm_ops;
 	vma->vm_private_data = &cam->frame[i];
 
 	zc0301_vm_open(vma);
 
+out:
 	mutex_unlock(&cam->fileop_mutex);
-
-	return 0;
+	return ret;
 }
 
 /*****************************************************************************/
Index: linux-2.6/drivers/media/video/et61x251/et61x251_core.c
===================================================================
--- linux-2.6.orig/drivers/media/video/et61x251/et61x251_core.c
+++ linux-2.6/drivers/media/video/et61x251/et61x251_core.c
@@ -1467,27 +1467,28 @@ static int et61x251_mmap(struct file* fi
 	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
 	unsigned long size = vma->vm_end - vma->vm_start;
 	u32 i;
+	int ret;
 
 	if (mutex_lock_interruptible(&cam->fileop_mutex))
 		return -ERESTARTSYS;
 
 	if (cam->state & DEV_DISCONNECTED) {
 		DBG(1, "Device not present");
-		mutex_unlock(&cam->fileop_mutex);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out;
 	}
 
 	if (cam->state & DEV_MISCONFIGURED) {
 		DBG(1, "The camera is misconfigured. Close and open it "
 		       "again.");
-		mutex_unlock(&cam->fileop_mutex);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
 	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	for (i = 0; i < cam->nbuffers; i++) {
@@ -1495,23 +1496,21 @@ static int et61x251_mmap(struct file* fi
 			break;
 	}
 	if (i == cam->nbuffers) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
-	if (remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)) {
-		mutex_unlock(&cam->fileop_mutex);
-		return -EAGAIN;
-	}
+	if ((ret = remap_vmalloc_range(vma, cam->frame[i].bufmem, 0)))
+		goto out;
 
 	vma->vm_ops = &et61x251_vm_ops;
 	vma->vm_private_data = &cam->frame[i];
 
 	et61x251_vm_open(vma);
 
+out:
 	mutex_unlock(&cam->fileop_mutex);
-
-	return 0;
+	return ret;
 }
 
 /*****************************************************************************/

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 2/5] mm: deprecate vmalloc_to_pfn
  2006-04-20 17:36     ` Nick Piggin
@ 2006-04-20 20:03       ` Andrew Morton
  0 siblings, 0 replies; 14+ messages in thread
From: Andrew Morton @ 2006-04-20 20:03 UTC (permalink / raw)
  To: Nick Piggin; +Cc: hch, linux-kernel, linux-mm, hugh

Nick Piggin <npiggin@suse.de> wrote:
>
> On Thu, Apr 20, 2006 at 06:22:40PM +0100, Christoph Hellwig wrote:
> > On Thu, Apr 20, 2006 at 07:06:30PM +0200, Nick Piggin wrote:
> > > Deprecate vmalloc_to_pfn.
> > 
> > I don't think there's any point to even keep it.  There's a trivial replcement.
> 
> It is exported, is the only thing. I tend to stick my head in the sand
> with these matters, and try to go with whatever I think will help Andrew
> merge it.
> 
> If nobody cares, I'd just as soon remove it completely.

It's been in there for a long time.  Theoretically we should mark it
deprecated, kill it in six months or so.

But vmalloc_to_page() is EXPORT_SYMBOLed, so fixing up downstream breakage
will be so trivial it's hardly worth bothering.  So let's zap vmalloc_to_pfn()
in 2.6.18.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2006-04-20 20:03 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-20 17:06 [patch 0/5] mm: improve remapping of vmalloc regions Nick Piggin
2006-04-20 17:06 ` [patch 1/5] mm: remap_vmalloc_range Nick Piggin
2006-04-20 17:22   ` Christoph Hellwig
2006-04-20 17:33     ` Nick Piggin
2006-04-20 18:09   ` Nick Piggin
2006-04-20 17:06 ` [patch 2/5] mm: deprecate vmalloc_to_pfn Nick Piggin
2006-04-20 17:22   ` Christoph Hellwig
2006-04-20 17:36     ` Nick Piggin
2006-04-20 20:03       ` Andrew Morton
2006-04-20 17:06 ` [patch 3/5] mm: remove rvmalloc Nick Piggin
2006-04-20 17:06 ` [patch 4/5] mm: extra remap_vmalloc_range check Nick Piggin
2006-04-20 17:07 ` [patch 5/5] drivers: leave vm_flags alone Nick Piggin
2006-04-20 17:27 ` [patch 6/5] mm: find_vm_area locking fixes Nick Piggin
2006-04-20 18:14 ` [patch][rfc] improve remap_vmalloc_range callers' return values Nick Piggin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).