[PATCH] NOMMU: Set BDI capabilities for /dev/mem and /dev/kmem
Set the backing device info capabilities for /dev/mem and /dev/kmem to
permit direct sharing under no-MMU conditions and full mapping capabilities
under MMU conditions. Make the BDI used by these available to all directly
mappable character devices.
Also comment the capabilities for /dev/zero.
[akpm@osdl.org: ifdef reductions]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 917b204..4ac70ec 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -238,6 +238,32 @@
}
#endif
+#ifndef CONFIG_MMU
+static unsigned long get_unmapped_area_mem(struct file *file,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags)
+{
+ if (!valid_mmap_phys_addr_range(pgoff, len))
+ return (unsigned long) -EINVAL;
+ return pgoff;
+}
+
+/* can't do an in-place private mapping if there's no MMU */
+static inline int private_mapping_ok(struct vm_area_struct *vma)
+{
+ return vma->vm_flags & VM_MAYSHARE;
+}
+#else
+#define get_unmapped_area_mem NULL
+
+static inline int private_mapping_ok(struct vm_area_struct *vma)
+{
+ return 1;
+}
+#endif
+
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
size_t size = vma->vm_end - vma->vm_start;
@@ -245,6 +271,9 @@
if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
return -EINVAL;
+ if (!private_mapping_ok(vma))
+ return -ENOSYS;
+
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
size,
vma->vm_page_prot);
@@ -782,6 +811,7 @@
.write = write_mem,
.mmap = mmap_mem,
.open = open_mem,
+ .get_unmapped_area = get_unmapped_area_mem,
};
static const struct file_operations kmem_fops = {
@@ -790,6 +820,7 @@
.write = write_kmem,
.mmap = mmap_kmem,
.open = open_kmem,
+ .get_unmapped_area = get_unmapped_area_mem,
};
static const struct file_operations null_fops = {
@@ -815,6 +846,10 @@
.mmap = mmap_zero,
};
+/*
+ * capabilities for /dev/zero
+ * - permits private mappings, "copies" are taken of the source of zeros
+ */
static struct backing_dev_info zero_bdi = {
.capabilities = BDI_CAP_MAP_COPY,
};
@@ -862,9 +897,13 @@
switch (iminor(inode)) {
case 1:
filp->f_op = &mem_fops;
+ filp->f_mapping->backing_dev_info =
+ &directly_mappable_cdev_bdi;
break;
case 2:
filp->f_op = &kmem_fops;
+ filp->f_mapping->backing_dev_info =
+ &directly_mappable_cdev_bdi;
break;
case 3:
filp->f_op = &null_fops;