^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* file-nommu.c: no-MMU version of ramfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written by David Howells (dhowells@redhat.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/backing-dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ramfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/pagevec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int ramfs_nommu_setattr(struct dentry *, struct iattr *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned long pgoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static unsigned ramfs_mmap_capabilities(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return NOMMU_MAP_DIRECT | NOMMU_MAP_COPY | NOMMU_MAP_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) NOMMU_MAP_WRITE | NOMMU_MAP_EXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) const struct file_operations ramfs_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .mmap_capabilities = ramfs_mmap_capabilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .mmap = ramfs_nommu_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .get_unmapped_area = ramfs_nommu_get_unmapped_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .read_iter = generic_file_read_iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .write_iter = generic_file_write_iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .fsync = noop_fsync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .splice_read = generic_file_splice_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .splice_write = iter_file_splice_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) const struct inode_operations ramfs_file_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .setattr = ramfs_nommu_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .getattr = simple_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * add a contiguous set of pages into a ramfs inode when it's truncated from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * size 0 on the assumption that it's going to be used for an mmap of shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned long npages, xpages, loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct page *pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) gfp_t gfp = mapping_gfp_mask(inode->i_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* make various checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) order = get_order(newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (unlikely(order >= MAX_ORDER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ret = inode_newsize_ok(inode, newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) i_size_write(inode, newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* allocate enough contiguous pages to be able to satisfy the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pages = alloc_pages(gfp, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* split the high-order page into an array of single pages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) xpages = 1UL << order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) npages = (newsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) split_page(pages, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* trim off any pages we don't actually require */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) for (loop = npages; loop < xpages; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) __free_page(pages + loop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* clear the memory we allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) newsize = PAGE_SIZE * npages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) data = page_address(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) memset(data, 0, newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* attach all the pages to the inode's address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) for (loop = 0; loop < npages; loop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct page *page = pages + loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ret = add_to_page_cache_lru(page, inode->i_mapping, loop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) goto add_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* prevent the page from being discarded on memory pressure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) SetPageDirty(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) SetPageUptodate(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unlock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) add_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) while (loop < npages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) __free_page(pages + loop++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* assume a truncate from zero size is going to be for the purposes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * shared mmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (unlikely(newsize >> 32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return ramfs_nommu_expand_for_mapping(inode, newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* check that a decrease in size doesn't cut off any shared mappings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (newsize < size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ret = nommu_shrink_inode_mappings(inode, size, newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) truncate_setsize(inode, newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * handle a change of attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * - we're specifically interested in a change of size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned int old_ia_valid = ia->ia_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* POSIX UID/GID verification for setting inode attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = setattr_prepare(dentry, ia);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* pick out size-changing events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (ia->ia_valid & ATTR_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) loff_t size = inode->i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (ia->ia_size != size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ret = ramfs_nommu_resize(inode, ia->ia_size, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (ret < 0 || ia->ia_valid == ATTR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* we skipped the truncate but must still update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * timestamps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ia->ia_valid |= ATTR_MTIME|ATTR_CTIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) setattr_copy(inode, ia);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ia->ia_valid = old_ia_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * try to determine where a shared mapping can be made
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * - we require that:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * - the pages to be mapped must exist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * - the pages be physically contiguous in sequence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned long addr, unsigned long len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned long pgoff, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned long maxpages, lpages, nr, loop, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct page **pages = NULL, **ptr, *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) loff_t isize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* the mapping mustn't extend beyond the EOF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) isize = i_size_read(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (pgoff >= maxpages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (maxpages - pgoff < lpages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* gang-find the pages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) pages = kcalloc(lpages, sizeof(struct page *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (!pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) nr = find_get_pages_contig(inode->i_mapping, pgoff, lpages, pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (nr != lpages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) goto out_free_pages; /* leave if some pages were missing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* check the pages for physical adjacency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ptr = pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) page = *ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) page++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) for (loop = lpages; loop > 1; loop--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (*ptr++ != page++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) goto out_free_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* okay - all conditions fulfilled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ret = (unsigned long) page_address(pages[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) out_free_pages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ptr = pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) for (loop = nr; loop > 0; loop--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) put_page(*ptr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) kfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * set up a mapping for shared memory segments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) file_accessed(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) vma->vm_ops = &generic_file_vm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }