1/* 2 * mmap.c 3 * 4 * Copyright (C) 1995, 1996 by Volker Lendecke 5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache 6 * 7 */ 8 9#include <linux/stat.h> 10#include <linux/time.h> 11#include <linux/kernel.h> 12#include <linux/gfp.h> 13#include <linux/mm.h> 14#include <linux/shm.h> 15#include <linux/errno.h> 16#include <linux/mman.h> 17#include <linux/string.h> 18#include <linux/fcntl.h> 19#include <linux/memcontrol.h> 20 21#include <asm/uaccess.h> 22 23#include "ncp_fs.h" 24 25/* 26 * Fill in the supplied page for mmap 27 * XXX: how are we excluding truncate/invalidate here? Maybe need to lock 28 * page? 29 */ 30static int ncp_file_mmap_fault(struct vm_area_struct *area, 31 struct vm_fault *vmf) 32{ 33 struct inode *inode = file_inode(area->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 mem_cgroup_count_vm_event(area->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