linux/drivers/staging/ncpfs/mmap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  mmap.c
   4 *
   5 *  Copyright (C) 1995, 1996 by Volker Lendecke
   6 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
   7 *
   8 */
   9
  10#include <linux/stat.h>
  11#include <linux/time.h>
  12#include <linux/kernel.h>
  13#include <linux/gfp.h>
  14#include <linux/mm.h>
  15#include <linux/shm.h>
  16#include <linux/errno.h>
  17#include <linux/mman.h>
  18#include <linux/string.h>
  19#include <linux/fcntl.h>
  20#include <linux/memcontrol.h>
  21
  22#include <linux/uaccess.h>
  23
  24#include "ncp_fs.h"
  25
  26/*
  27 * Fill in the supplied page for mmap
  28 * XXX: how are we excluding truncate/invalidate here? Maybe need to lock
  29 * page?
  30 */
  31static int ncp_file_mmap_fault(struct vm_fault *vmf)
  32{
  33        struct inode *inode = file_inode(vmf->vma->vm_file);
  34        char *pg_addr;
  35        unsigned int already_read;
  36        unsigned int count;
  37        int bufsize;
  38        int pos; /* XXX: loff_t ? */
  39
  40        /*
  41         * ncpfs has nothing against high pages as long
  42         * as recvmsg and memset works on it
  43         */
  44        vmf->page = alloc_page(GFP_HIGHUSER);
  45        if (!vmf->page)
  46                return VM_FAULT_OOM;
  47        pg_addr = kmap(vmf->page);
  48        pos = vmf->pgoff << PAGE_SHIFT;
  49
  50        count = PAGE_SIZE;
  51        /* what we can read in one go */
  52        bufsize = NCP_SERVER(inode)->buffer_size;
  53
  54        already_read = 0;
  55        if (ncp_make_open(inode, O_RDONLY) >= 0) {
  56                while (already_read < count) {
  57                        int read_this_time;
  58                        int to_read;
  59
  60                        to_read = bufsize - (pos % bufsize);
  61
  62                        to_read = min_t(unsigned int, to_read, count - already_read);
  63
  64                        if (ncp_read_kernel(NCP_SERVER(inode),
  65                                     NCP_FINFO(inode)->file_handle,
  66                                     pos, to_read,
  67                                     pg_addr + already_read,
  68                                     &read_this_time) != 0) {
  69                                read_this_time = 0;
  70                        }
  71                        pos += read_this_time;
  72                        already_read += read_this_time;
  73
  74                        if (read_this_time < to_read) {
  75                                break;
  76                        }
  77                }
  78                ncp_inode_close(inode);
  79
  80        }
  81
  82        if (already_read < PAGE_SIZE)
  83                memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
  84        flush_dcache_page(vmf->page);
  85        kunmap(vmf->page);
  86
  87        /*
  88         * If I understand ncp_read_kernel() properly, the above always
  89         * fetches from the network, here the analogue of disk.
  90         * -- nyc
  91         */
  92        count_vm_event(PGMAJFAULT);
  93        count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT);
  94        return VM_FAULT_MAJOR;
  95}
  96
  97static const struct vm_operations_struct ncp_file_mmap =
  98{
  99        .fault = ncp_file_mmap_fault,
 100};
 101
 102
 103/* This is used for a general mmap of a ncp file */
 104int ncp_mmap(struct file *file, struct vm_area_struct *vma)
 105{
 106        struct inode *inode = file_inode(file);
 107        
 108        ncp_dbg(1, "called\n");
 109
 110        if (!ncp_conn_valid(NCP_SERVER(inode)))
 111                return -EIO;
 112
 113        /* only PAGE_COW or read-only supported now */
 114        if (vma->vm_flags & VM_SHARED)
 115                return -EINVAL;
 116        /* we do not support files bigger than 4GB... We eventually 
 117           supports just 4GB... */
 118        if (vma_pages(vma) + vma->vm_pgoff
 119           > (1U << (32 - PAGE_SHIFT)))
 120                return -EFBIG;
 121
 122        vma->vm_ops = &ncp_file_mmap;
 123        file_accessed(file);
 124        return 0;
 125}
 126