|
@@ -946,9 +946,6 @@ static int validate_mmap_request(struct file *file,
|
|
|
return -EOVERFLOW;
|
|
|
|
|
|
if (file) {
|
|
|
- /* validate file mapping requests */
|
|
|
- struct address_space *mapping;
|
|
|
-
|
|
|
/* files must support mmap */
|
|
|
if (!file->f_op->mmap)
|
|
|
return -ENODEV;
|
|
@@ -957,28 +954,22 @@ static int validate_mmap_request(struct file *file,
|
|
|
* - we support chardevs that provide their own "memory"
|
|
|
* - we support files/blockdevs that are memory backed
|
|
|
*/
|
|
|
- mapping = file->f_mapping;
|
|
|
- if (!mapping)
|
|
|
- mapping = file_inode(file)->i_mapping;
|
|
|
-
|
|
|
- capabilities = 0;
|
|
|
- if (mapping && mapping->backing_dev_info)
|
|
|
- capabilities = mapping->backing_dev_info->capabilities;
|
|
|
-
|
|
|
- if (!capabilities) {
|
|
|
+ if (file->f_op->mmap_capabilities) {
|
|
|
+ capabilities = file->f_op->mmap_capabilities(file);
|
|
|
+ } else {
|
|
|
/* no explicit capabilities set, so assume some
|
|
|
* defaults */
|
|
|
switch (file_inode(file)->i_mode & S_IFMT) {
|
|
|
case S_IFREG:
|
|
|
case S_IFBLK:
|
|
|
- capabilities = BDI_CAP_MAP_COPY;
|
|
|
+ capabilities = NOMMU_MAP_COPY;
|
|
|
break;
|
|
|
|
|
|
case S_IFCHR:
|
|
|
capabilities =
|
|
|
- BDI_CAP_MAP_DIRECT |
|
|
|
- BDI_CAP_READ_MAP |
|
|
|
- BDI_CAP_WRITE_MAP;
|
|
|
+ NOMMU_MAP_DIRECT |
|
|
|
+ NOMMU_MAP_READ |
|
|
|
+ NOMMU_MAP_WRITE;
|
|
|
break;
|
|
|
|
|
|
default:
|
|
@@ -989,9 +980,9 @@ static int validate_mmap_request(struct file *file,
|
|
|
/* eliminate any capabilities that we can't support on this
|
|
|
* device */
|
|
|
if (!file->f_op->get_unmapped_area)
|
|
|
- capabilities &= ~BDI_CAP_MAP_DIRECT;
|
|
|
+ capabilities &= ~NOMMU_MAP_DIRECT;
|
|
|
if (!file->f_op->read)
|
|
|
- capabilities &= ~BDI_CAP_MAP_COPY;
|
|
|
+ capabilities &= ~NOMMU_MAP_COPY;
|
|
|
|
|
|
/* The file shall have been opened with read permission. */
|
|
|
if (!(file->f_mode & FMODE_READ))
|
|
@@ -1010,29 +1001,29 @@ static int validate_mmap_request(struct file *file,
|
|
|
if (locks_verify_locked(file))
|
|
|
return -EAGAIN;
|
|
|
|
|
|
- if (!(capabilities & BDI_CAP_MAP_DIRECT))
|
|
|
+ if (!(capabilities & NOMMU_MAP_DIRECT))
|
|
|
return -ENODEV;
|
|
|
|
|
|
/* we mustn't privatise shared mappings */
|
|
|
- capabilities &= ~BDI_CAP_MAP_COPY;
|
|
|
+ capabilities &= ~NOMMU_MAP_COPY;
|
|
|
} else {
|
|
|
/* we're going to read the file into private memory we
|
|
|
* allocate */
|
|
|
- if (!(capabilities & BDI_CAP_MAP_COPY))
|
|
|
+ if (!(capabilities & NOMMU_MAP_COPY))
|
|
|
return -ENODEV;
|
|
|
|
|
|
/* we don't permit a private writable mapping to be
|
|
|
* shared with the backing device */
|
|
|
if (prot & PROT_WRITE)
|
|
|
- capabilities &= ~BDI_CAP_MAP_DIRECT;
|
|
|
+ capabilities &= ~NOMMU_MAP_DIRECT;
|
|
|
}
|
|
|
|
|
|
- if (capabilities & BDI_CAP_MAP_DIRECT) {
|
|
|
- if (((prot & PROT_READ) && !(capabilities & BDI_CAP_READ_MAP)) ||
|
|
|
- ((prot & PROT_WRITE) && !(capabilities & BDI_CAP_WRITE_MAP)) ||
|
|
|
- ((prot & PROT_EXEC) && !(capabilities & BDI_CAP_EXEC_MAP))
|
|
|
+ if (capabilities & NOMMU_MAP_DIRECT) {
|
|
|
+ if (((prot & PROT_READ) && !(capabilities & NOMMU_MAP_READ)) ||
|
|
|
+ ((prot & PROT_WRITE) && !(capabilities & NOMMU_MAP_WRITE)) ||
|
|
|
+ ((prot & PROT_EXEC) && !(capabilities & NOMMU_MAP_EXEC))
|
|
|
) {
|
|
|
- capabilities &= ~BDI_CAP_MAP_DIRECT;
|
|
|
+ capabilities &= ~NOMMU_MAP_DIRECT;
|
|
|
if (flags & MAP_SHARED) {
|
|
|
printk(KERN_WARNING
|
|
|
"MAP_SHARED not completely supported on !MMU\n");
|
|
@@ -1049,21 +1040,21 @@ static int validate_mmap_request(struct file *file,
|
|
|
} else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) {
|
|
|
/* handle implication of PROT_EXEC by PROT_READ */
|
|
|
if (current->personality & READ_IMPLIES_EXEC) {
|
|
|
- if (capabilities & BDI_CAP_EXEC_MAP)
|
|
|
+ if (capabilities & NOMMU_MAP_EXEC)
|
|
|
prot |= PROT_EXEC;
|
|
|
}
|
|
|
} else if ((prot & PROT_READ) &&
|
|
|
(prot & PROT_EXEC) &&
|
|
|
- !(capabilities & BDI_CAP_EXEC_MAP)
|
|
|
+ !(capabilities & NOMMU_MAP_EXEC)
|
|
|
) {
|
|
|
/* backing file is not executable, try to copy */
|
|
|
- capabilities &= ~BDI_CAP_MAP_DIRECT;
|
|
|
+ capabilities &= ~NOMMU_MAP_DIRECT;
|
|
|
}
|
|
|
} else {
|
|
|
/* anonymous mappings are always memory backed and can be
|
|
|
* privately mapped
|
|
|
*/
|
|
|
- capabilities = BDI_CAP_MAP_COPY;
|
|
|
+ capabilities = NOMMU_MAP_COPY;
|
|
|
|
|
|
/* handle PROT_EXEC implication by PROT_READ */
|
|
|
if ((prot & PROT_READ) &&
|
|
@@ -1095,7 +1086,7 @@ static unsigned long determine_vm_flags(struct file *file,
|
|
|
vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags);
|
|
|
/* vm_flags |= mm->def_flags; */
|
|
|
|
|
|
- if (!(capabilities & BDI_CAP_MAP_DIRECT)) {
|
|
|
+ if (!(capabilities & NOMMU_MAP_DIRECT)) {
|
|
|
/* attempt to share read-only copies of mapped file chunks */
|
|
|
vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
|
|
|
if (file && !(prot & PROT_WRITE))
|
|
@@ -1104,7 +1095,7 @@ static unsigned long determine_vm_flags(struct file *file,
|
|
|
/* overlay a shareable mapping on the backing device or inode
|
|
|
* if possible - used for chardevs, ramfs/tmpfs/shmfs and
|
|
|
* romfs/cramfs */
|
|
|
- vm_flags |= VM_MAYSHARE | (capabilities & BDI_CAP_VMFLAGS);
|
|
|
+ vm_flags |= VM_MAYSHARE | (capabilities & NOMMU_VMFLAGS);
|
|
|
if (flags & MAP_SHARED)
|
|
|
vm_flags |= VM_SHARED;
|
|
|
}
|
|
@@ -1157,7 +1148,7 @@ static int do_mmap_private(struct vm_area_struct *vma,
|
|
|
* shared mappings on devices or memory
|
|
|
* - VM_MAYSHARE will be set if it may attempt to share
|
|
|
*/
|
|
|
- if (capabilities & BDI_CAP_MAP_DIRECT) {
|
|
|
+ if (capabilities & NOMMU_MAP_DIRECT) {
|
|
|
ret = vma->vm_file->f_op->mmap(vma->vm_file, vma);
|
|
|
if (ret == 0) {
|
|
|
/* shouldn't return success if we're not sharing */
|
|
@@ -1346,7 +1337,7 @@ unsigned long do_mmap_pgoff(struct file *file,
|
|
|
if ((pregion->vm_pgoff != pgoff || rpglen != pglen) &&
|
|
|
!(pgoff >= pregion->vm_pgoff && pgend <= rpgend)) {
|
|
|
/* new mapping is not a subset of the region */
|
|
|
- if (!(capabilities & BDI_CAP_MAP_DIRECT))
|
|
|
+ if (!(capabilities & NOMMU_MAP_DIRECT))
|
|
|
goto sharing_violation;
|
|
|
continue;
|
|
|
}
|
|
@@ -1385,7 +1376,7 @@ unsigned long do_mmap_pgoff(struct file *file,
|
|
|
* - this is the hook for quasi-memory character devices to
|
|
|
* tell us the location of a shared mapping
|
|
|
*/
|
|
|
- if (capabilities & BDI_CAP_MAP_DIRECT) {
|
|
|
+ if (capabilities & NOMMU_MAP_DIRECT) {
|
|
|
addr = file->f_op->get_unmapped_area(file, addr, len,
|
|
|
pgoff, flags);
|
|
|
if (IS_ERR_VALUE(addr)) {
|
|
@@ -1397,10 +1388,10 @@ unsigned long do_mmap_pgoff(struct file *file,
|
|
|
* the mapping so we'll have to attempt to copy
|
|
|
* it */
|
|
|
ret = -ENODEV;
|
|
|
- if (!(capabilities & BDI_CAP_MAP_COPY))
|
|
|
+ if (!(capabilities & NOMMU_MAP_COPY))
|
|
|
goto error_just_free;
|
|
|
|
|
|
- capabilities &= ~BDI_CAP_MAP_DIRECT;
|
|
|
+ capabilities &= ~NOMMU_MAP_DIRECT;
|
|
|
} else {
|
|
|
vma->vm_start = region->vm_start = addr;
|
|
|
vma->vm_end = region->vm_end = addr + len;
|
|
@@ -1411,7 +1402,7 @@ unsigned long do_mmap_pgoff(struct file *file,
|
|
|
vma->vm_region = region;
|
|
|
|
|
|
/* set up the mapping
|
|
|
- * - the region is filled in if BDI_CAP_MAP_DIRECT is still set
|
|
|
+ * - the region is filled in if NOMMU_MAP_DIRECT is still set
|
|
|
*/
|
|
|
if (file && vma->vm_flags & VM_SHARED)
|
|
|
ret = do_mmap_shared_file(vma);
|