Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.12 127 lines 2.9 kB view raw
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 file *file = area->vm_file; 34 struct dentry *dentry = file->f_path.dentry; 35 struct inode *inode = dentry->d_inode; 36 char *pg_addr; 37 unsigned int already_read; 38 unsigned int count; 39 int bufsize; 40 int pos; /* XXX: loff_t ? */ 41 42 /* 43 * ncpfs has nothing against high pages as long 44 * as recvmsg and memset works on it 45 */ 46 vmf->page = alloc_page(GFP_HIGHUSER); 47 if (!vmf->page) 48 return VM_FAULT_OOM; 49 pg_addr = kmap(vmf->page); 50 pos = vmf->pgoff << PAGE_SHIFT; 51 52 count = PAGE_SIZE; 53 /* what we can read in one go */ 54 bufsize = NCP_SERVER(inode)->buffer_size; 55 56 already_read = 0; 57 if (ncp_make_open(inode, O_RDONLY) >= 0) { 58 while (already_read < count) { 59 int read_this_time; 60 int to_read; 61 62 to_read = bufsize - (pos % bufsize); 63 64 to_read = min_t(unsigned int, to_read, count - already_read); 65 66 if (ncp_read_kernel(NCP_SERVER(inode), 67 NCP_FINFO(inode)->file_handle, 68 pos, to_read, 69 pg_addr + already_read, 70 &read_this_time) != 0) { 71 read_this_time = 0; 72 } 73 pos += read_this_time; 74 already_read += read_this_time; 75 76 if (read_this_time < to_read) { 77 break; 78 } 79 } 80 ncp_inode_close(inode); 81 82 } 83 84 if (already_read < PAGE_SIZE) 85 memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); 86 flush_dcache_page(vmf->page); 87 kunmap(vmf->page); 88 89 /* 90 * If I understand ncp_read_kernel() properly, the above always 91 * fetches from the network, here the analogue of disk. 92 * -- nyc 93 */ 94 count_vm_event(PGMAJFAULT); 95 mem_cgroup_count_vm_event(area->vm_mm, PGMAJFAULT); 96 return VM_FAULT_MAJOR; 97} 98 99static const struct vm_operations_struct ncp_file_mmap = 100{ 101 .fault = ncp_file_mmap_fault, 102}; 103 104 105/* This is used for a general mmap of a ncp file */ 106int ncp_mmap(struct file *file, struct vm_area_struct *vma) 107{ 108 struct inode *inode = file_inode(file); 109 110 DPRINTK("ncp_mmap: called\n"); 111 112 if (!ncp_conn_valid(NCP_SERVER(inode))) 113 return -EIO; 114 115 /* only PAGE_COW or read-only supported now */ 116 if (vma->vm_flags & VM_SHARED) 117 return -EINVAL; 118 /* we do not support files bigger than 4GB... We eventually 119 supports just 4GB... */ 120 if (vma_pages(vma) + vma->vm_pgoff 121 > (1U << (32 - PAGE_SHIFT))) 122 return -EFBIG; 123 124 vma->vm_ops = &ncp_file_mmap; 125 file_accessed(file); 126 return 0; 127}