diff options
author | Christoph Hellwig <hch@lst.de> | 2015-01-14 04:42:32 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-01-20 16:02:58 -0500 |
commit | b4caecd48005fbed3949dde6c1cb233142fd69e9 (patch) | |
tree | 1fdd9b7c15568c79eb3c1ed84a39858ddbcbc88b /mm | |
parent | 97b713ba3ebaa6c8d84c2c720f5468a7c6a6eb4e (diff) |
fs: introduce f_op->mmap_capabilities for nommu mmap support
Since "BDI: Provide backing device capability information [try #3]" the
backing_dev_info structure also provides flags for the kind of mmap
operation available in a nommu environment, which is entirely unrelated
to it's original purpose.
Introduce a new nommu-only file operation to provide this information to
the nommu mmap code instead. Splitting this from the backing_dev_info
structure allows to remove lots of backing_dev_info instance that aren't
otherwise needed, and entirely gets rid of the concept of providing a
backing_dev_info for a character device. It also removes the need for
the mtd_inodefs filesystem.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Tejun Heo <tj@kernel.org>
Acked-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/backing-dev.c | 7 | ||||
-rw-r--r-- | mm/nommu.c | 69 |
2 files changed, 32 insertions, 44 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 0ae0df55000b..16c68958aeda 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -17,8 +17,6 @@ static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); | |||
17 | struct backing_dev_info default_backing_dev_info = { | 17 | struct backing_dev_info default_backing_dev_info = { |
18 | .name = "default", | 18 | .name = "default", |
19 | .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE, | 19 | .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE, |
20 | .state = 0, | ||
21 | .capabilities = BDI_CAP_MAP_COPY, | ||
22 | }; | 20 | }; |
23 | EXPORT_SYMBOL_GPL(default_backing_dev_info); | 21 | EXPORT_SYMBOL_GPL(default_backing_dev_info); |
24 | 22 | ||
@@ -513,13 +511,12 @@ EXPORT_SYMBOL(bdi_destroy); | |||
513 | * For use from filesystems to quickly init and register a bdi associated | 511 | * For use from filesystems to quickly init and register a bdi associated |
514 | * with dirty writeback | 512 | * with dirty writeback |
515 | */ | 513 | */ |
516 | int bdi_setup_and_register(struct backing_dev_info *bdi, char *name, | 514 | int bdi_setup_and_register(struct backing_dev_info *bdi, char *name) |
517 | unsigned int cap) | ||
518 | { | 515 | { |
519 | int err; | 516 | int err; |
520 | 517 | ||
521 | bdi->name = name; | 518 | bdi->name = name; |
522 | bdi->capabilities = cap; | 519 | bdi->capabilities = 0; |
523 | err = bdi_init(bdi); | 520 | err = bdi_init(bdi); |
524 | if (err) | 521 | if (err) |
525 | return err; | 522 | return err; |
diff --git a/mm/nommu.c b/mm/nommu.c index b51eadf6d952..13af96f35a4b 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -946,9 +946,6 @@ static int validate_mmap_request(struct file *file, | |||
946 | return -EOVERFLOW; | 946 | return -EOVERFLOW; |
947 | 947 | ||
948 | if (file) { | 948 | if (file) { |
949 | /* validate file mapping requests */ | ||
950 | struct address_space *mapping; | ||
951 | |||
952 | /* files must support mmap */ | 949 | /* files must support mmap */ |
953 | if (!file->f_op->mmap) | 950 | if (!file->f_op->mmap) |
954 | return -ENODEV; | 951 | return -ENODEV; |
@@ -957,28 +954,22 @@ static int validate_mmap_request(struct file *file, | |||
957 | * - we support chardevs that provide their own "memory" | 954 | * - we support chardevs that provide their own "memory" |
958 | * - we support files/blockdevs that are memory backed | 955 | * - we support files/blockdevs that are memory backed |
959 | */ | 956 | */ |
960 | mapping = file->f_mapping; | 957 | if (file->f_op->mmap_capabilities) { |
961 | if (!mapping) | 958 | capabilities = file->f_op->mmap_capabilities(file); |
962 | mapping = file_inode(file)->i_mapping; | 959 | } else { |
963 | |||
964 | capabilities = 0; | ||
965 | if (mapping && mapping->backing_dev_info) | ||
966 | capabilities = mapping->backing_dev_info->capabilities; | ||
967 | |||
968 | if (!capabilities) { | ||
969 | /* no explicit capabilities set, so assume some | 960 | /* no explicit capabilities set, so assume some |
970 | * defaults */ | 961 | * defaults */ |
971 | switch (file_inode(file)->i_mode & S_IFMT) { | 962 | switch (file_inode(file)->i_mode & S_IFMT) { |
972 | case S_IFREG: | 963 | case S_IFREG: |
973 | case S_IFBLK: | 964 | case S_IFBLK: |
974 | capabilities = BDI_CAP_MAP_COPY; | 965 | capabilities = NOMMU_MAP_COPY; |
975 | break; | 966 | break; |
976 | 967 | ||
977 | case S_IFCHR: | 968 | case S_IFCHR: |
978 | capabilities = | 969 | capabilities = |
979 | BDI_CAP_MAP_DIRECT | | 970 | NOMMU_MAP_DIRECT | |
980 | BDI_CAP_READ_MAP | | 971 | NOMMU_MAP_READ | |
981 | BDI_CAP_WRITE_MAP; | 972 | NOMMU_MAP_WRITE; |
982 | break; | 973 | break; |
983 | 974 | ||
984 | default: | 975 | default: |
@@ -989,9 +980,9 @@ static int validate_mmap_request(struct file *file, | |||
989 | /* eliminate any capabilities that we can't support on this | 980 | /* eliminate any capabilities that we can't support on this |
990 | * device */ | 981 | * device */ |
991 | if (!file->f_op->get_unmapped_area) | 982 | if (!file->f_op->get_unmapped_area) |
992 | capabilities &= ~BDI_CAP_MAP_DIRECT; | 983 | capabilities &= ~NOMMU_MAP_DIRECT; |
993 | if (!file->f_op->read) | 984 | if (!file->f_op->read) |
994 | capabilities &= ~BDI_CAP_MAP_COPY; | 985 | capabilities &= ~NOMMU_MAP_COPY; |
995 | 986 | ||
996 | /* The file shall have been opened with read permission. */ | 987 | /* The file shall have been opened with read permission. */ |
997 | if (!(file->f_mode & FMODE_READ)) | 988 | if (!(file->f_mode & FMODE_READ)) |
@@ -1010,29 +1001,29 @@ static int validate_mmap_request(struct file *file, | |||
1010 | if (locks_verify_locked(file)) | 1001 | if (locks_verify_locked(file)) |
1011 | return -EAGAIN; | 1002 | return -EAGAIN; |
1012 | 1003 | ||
1013 | if (!(capabilities & BDI_CAP_MAP_DIRECT)) | 1004 | if (!(capabilities & NOMMU_MAP_DIRECT)) |
1014 | return -ENODEV; | 1005 | return -ENODEV; |
1015 | 1006 | ||
1016 | /* we mustn't privatise shared mappings */ | 1007 | /* we mustn't privatise shared mappings */ |
1017 | capabilities &= ~BDI_CAP_MAP_COPY; | 1008 | capabilities &= ~NOMMU_MAP_COPY; |
1018 | } else { | 1009 | } else { |
1019 | /* we're going to read the file into private memory we | 1010 | /* we're going to read the file into private memory we |
1020 | * allocate */ | 1011 | * allocate */ |
1021 | if (!(capabilities & BDI_CAP_MAP_COPY)) | 1012 | if (!(capabilities & NOMMU_MAP_COPY)) |
1022 | return -ENODEV; | 1013 | return -ENODEV; |
1023 | 1014 | ||
1024 | /* we don't permit a private writable mapping to be | 1015 | /* we don't permit a private writable mapping to be |
1025 | * shared with the backing device */ | 1016 | * shared with the backing device */ |
1026 | if (prot & PROT_WRITE) | 1017 | if (prot & PROT_WRITE) |
1027 | capabilities &= ~BDI_CAP_MAP_DIRECT; | 1018 | capabilities &= ~NOMMU_MAP_DIRECT; |
1028 | } | 1019 | } |
1029 | 1020 | ||
1030 | if (capabilities & BDI_CAP_MAP_DIRECT) { | 1021 | if (capabilities & NOMMU_MAP_DIRECT) { |
1031 | if (((prot & PROT_READ) && !(capabilities & BDI_CAP_READ_MAP)) || | 1022 | if (((prot & PROT_READ) && !(capabilities & NOMMU_MAP_READ)) || |
1032 | ((prot & PROT_WRITE) && !(capabilities & BDI_CAP_WRITE_MAP)) || | 1023 | ((prot & PROT_WRITE) && !(capabilities & NOMMU_MAP_WRITE)) || |
1033 | ((prot & PROT_EXEC) && !(capabilities & BDI_CAP_EXEC_MAP)) | 1024 | ((prot & PROT_EXEC) && !(capabilities & NOMMU_MAP_EXEC)) |
1034 | ) { | 1025 | ) { |
1035 | capabilities &= ~BDI_CAP_MAP_DIRECT; | 1026 | capabilities &= ~NOMMU_MAP_DIRECT; |
1036 | if (flags & MAP_SHARED) { | 1027 | if (flags & MAP_SHARED) { |
1037 | printk(KERN_WARNING | 1028 | printk(KERN_WARNING |
1038 | "MAP_SHARED not completely supported on !MMU\n"); | 1029 | "MAP_SHARED not completely supported on !MMU\n"); |
@@ -1049,21 +1040,21 @@ static int validate_mmap_request(struct file *file, | |||
1049 | } else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) { | 1040 | } else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) { |
1050 | /* handle implication of PROT_EXEC by PROT_READ */ | 1041 | /* handle implication of PROT_EXEC by PROT_READ */ |
1051 | if (current->personality & READ_IMPLIES_EXEC) { | 1042 | if (current->personality & READ_IMPLIES_EXEC) { |
1052 | if (capabilities & BDI_CAP_EXEC_MAP) | 1043 | if (capabilities & NOMMU_MAP_EXEC) |
1053 | prot |= PROT_EXEC; | 1044 | prot |= PROT_EXEC; |
1054 | } | 1045 | } |
1055 | } else if ((prot & PROT_READ) && | 1046 | } else if ((prot & PROT_READ) && |
1056 | (prot & PROT_EXEC) && | 1047 | (prot & PROT_EXEC) && |
1057 | !(capabilities & BDI_CAP_EXEC_MAP) | 1048 | !(capabilities & NOMMU_MAP_EXEC) |
1058 | ) { | 1049 | ) { |
1059 | /* backing file is not executable, try to copy */ | 1050 | /* backing file is not executable, try to copy */ |
1060 | capabilities &= ~BDI_CAP_MAP_DIRECT; | 1051 | capabilities &= ~NOMMU_MAP_DIRECT; |
1061 | } | 1052 | } |
1062 | } else { | 1053 | } else { |
1063 | /* anonymous mappings are always memory backed and can be | 1054 | /* anonymous mappings are always memory backed and can be |
1064 | * privately mapped | 1055 | * privately mapped |
1065 | */ | 1056 | */ |
1066 | capabilities = BDI_CAP_MAP_COPY; | 1057 | capabilities = NOMMU_MAP_COPY; |
1067 | 1058 | ||
1068 | /* handle PROT_EXEC implication by PROT_READ */ | 1059 | /* handle PROT_EXEC implication by PROT_READ */ |
1069 | if ((prot & PROT_READ) && | 1060 | if ((prot & PROT_READ) && |
@@ -1095,7 +1086,7 @@ static unsigned long determine_vm_flags(struct file *file, | |||
1095 | vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags); | 1086 | vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags); |
1096 | /* vm_flags |= mm->def_flags; */ | 1087 | /* vm_flags |= mm->def_flags; */ |
1097 | 1088 | ||
1098 | if (!(capabilities & BDI_CAP_MAP_DIRECT)) { | 1089 | if (!(capabilities & NOMMU_MAP_DIRECT)) { |
1099 | /* attempt to share read-only copies of mapped file chunks */ | 1090 | /* attempt to share read-only copies of mapped file chunks */ |
1100 | vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; | 1091 | vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; |
1101 | if (file && !(prot & PROT_WRITE)) | 1092 | if (file && !(prot & PROT_WRITE)) |
@@ -1104,7 +1095,7 @@ static unsigned long determine_vm_flags(struct file *file, | |||
1104 | /* overlay a shareable mapping on the backing device or inode | 1095 | /* overlay a shareable mapping on the backing device or inode |
1105 | * if possible - used for chardevs, ramfs/tmpfs/shmfs and | 1096 | * if possible - used for chardevs, ramfs/tmpfs/shmfs and |
1106 | * romfs/cramfs */ | 1097 | * romfs/cramfs */ |
1107 | vm_flags |= VM_MAYSHARE | (capabilities & BDI_CAP_VMFLAGS); | 1098 | vm_flags |= VM_MAYSHARE | (capabilities & NOMMU_VMFLAGS); |
1108 | if (flags & MAP_SHARED) | 1099 | if (flags & MAP_SHARED) |
1109 | vm_flags |= VM_SHARED; | 1100 | vm_flags |= VM_SHARED; |
1110 | } | 1101 | } |
@@ -1157,7 +1148,7 @@ static int do_mmap_private(struct vm_area_struct *vma, | |||
1157 | * shared mappings on devices or memory | 1148 | * shared mappings on devices or memory |
1158 | * - VM_MAYSHARE will be set if it may attempt to share | 1149 | * - VM_MAYSHARE will be set if it may attempt to share |
1159 | */ | 1150 | */ |
1160 | if (capabilities & BDI_CAP_MAP_DIRECT) { | 1151 | if (capabilities & NOMMU_MAP_DIRECT) { |
1161 | ret = vma->vm_file->f_op->mmap(vma->vm_file, vma); | 1152 | ret = vma->vm_file->f_op->mmap(vma->vm_file, vma); |
1162 | if (ret == 0) { | 1153 | if (ret == 0) { |
1163 | /* shouldn't return success if we're not sharing */ | 1154 | /* shouldn't return success if we're not sharing */ |
@@ -1346,7 +1337,7 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
1346 | if ((pregion->vm_pgoff != pgoff || rpglen != pglen) && | 1337 | if ((pregion->vm_pgoff != pgoff || rpglen != pglen) && |
1347 | !(pgoff >= pregion->vm_pgoff && pgend <= rpgend)) { | 1338 | !(pgoff >= pregion->vm_pgoff && pgend <= rpgend)) { |
1348 | /* new mapping is not a subset of the region */ | 1339 | /* new mapping is not a subset of the region */ |
1349 | if (!(capabilities & BDI_CAP_MAP_DIRECT)) | 1340 | if (!(capabilities & NOMMU_MAP_DIRECT)) |
1350 | goto sharing_violation; | 1341 | goto sharing_violation; |
1351 | continue; | 1342 | continue; |
1352 | } | 1343 | } |
@@ -1385,7 +1376,7 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
1385 | * - this is the hook for quasi-memory character devices to | 1376 | * - this is the hook for quasi-memory character devices to |
1386 | * tell us the location of a shared mapping | 1377 | * tell us the location of a shared mapping |
1387 | */ | 1378 | */ |
1388 | if (capabilities & BDI_CAP_MAP_DIRECT) { | 1379 | if (capabilities & NOMMU_MAP_DIRECT) { |
1389 | addr = file->f_op->get_unmapped_area(file, addr, len, | 1380 | addr = file->f_op->get_unmapped_area(file, addr, len, |
1390 | pgoff, flags); | 1381 | pgoff, flags); |
1391 | if (IS_ERR_VALUE(addr)) { | 1382 | if (IS_ERR_VALUE(addr)) { |
@@ -1397,10 +1388,10 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
1397 | * the mapping so we'll have to attempt to copy | 1388 | * the mapping so we'll have to attempt to copy |
1398 | * it */ | 1389 | * it */ |
1399 | ret = -ENODEV; | 1390 | ret = -ENODEV; |
1400 | if (!(capabilities & BDI_CAP_MAP_COPY)) | 1391 | if (!(capabilities & NOMMU_MAP_COPY)) |
1401 | goto error_just_free; | 1392 | goto error_just_free; |
1402 | 1393 | ||
1403 | capabilities &= ~BDI_CAP_MAP_DIRECT; | 1394 | capabilities &= ~NOMMU_MAP_DIRECT; |
1404 | } else { | 1395 | } else { |
1405 | vma->vm_start = region->vm_start = addr; | 1396 | vma->vm_start = region->vm_start = addr; |
1406 | vma->vm_end = region->vm_end = addr + len; | 1397 | vma->vm_end = region->vm_end = addr + len; |
@@ -1411,7 +1402,7 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
1411 | vma->vm_region = region; | 1402 | vma->vm_region = region; |
1412 | 1403 | ||
1413 | /* set up the mapping | 1404 | /* set up the mapping |
1414 | * - the region is filled in if BDI_CAP_MAP_DIRECT is still set | 1405 | * - the region is filled in if NOMMU_MAP_DIRECT is still set |
1415 | */ | 1406 | */ |
1416 | if (file && vma->vm_flags & VM_SHARED) | 1407 | if (file && vma->vm_flags & VM_SHARED) |
1417 | ret = do_mmap_shared_file(vma); | 1408 | ret = do_mmap_shared_file(vma); |