diff options
Diffstat (limited to 'fs/ncpfs/mmap.c')
-rw-r--r-- | fs/ncpfs/mmap.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index 70a69115500f..a94473d3072c 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c | |||
@@ -24,31 +24,35 @@ | |||
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Fill in the supplied page for mmap | 26 | * Fill in the supplied page for mmap |
27 | * XXX: how are we excluding truncate/invalidate here? Maybe need to lock | ||
28 | * page? | ||
27 | */ | 29 | */ |
28 | static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, | 30 | static int ncp_file_mmap_fault(struct vm_area_struct *area, |
29 | unsigned long address, int *type) | 31 | struct vm_fault *vmf) |
30 | { | 32 | { |
31 | struct file *file = area->vm_file; | 33 | struct file *file = area->vm_file; |
32 | struct dentry *dentry = file->f_path.dentry; | 34 | struct dentry *dentry = file->f_path.dentry; |
33 | struct inode *inode = dentry->d_inode; | 35 | struct inode *inode = dentry->d_inode; |
34 | struct page* page; | ||
35 | char *pg_addr; | 36 | char *pg_addr; |
36 | unsigned int already_read; | 37 | unsigned int already_read; |
37 | unsigned int count; | 38 | unsigned int count; |
38 | int bufsize; | 39 | int bufsize; |
39 | int pos; | 40 | int pos; /* XXX: loff_t ? */ |
40 | 41 | ||
41 | page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages | 42 | /* |
42 | as long as recvmsg and memset works on it */ | 43 | * ncpfs has nothing against high pages as long |
43 | if (!page) | 44 | * as recvmsg and memset works on it |
44 | return page; | 45 | */ |
45 | pg_addr = kmap(page); | 46 | vmf->page = alloc_page(GFP_HIGHUSER); |
46 | address &= PAGE_MASK; | 47 | if (!vmf->page) |
47 | pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT); | 48 | return VM_FAULT_OOM; |
49 | pg_addr = kmap(vmf->page); | ||
50 | pos = vmf->pgoff << PAGE_SHIFT; | ||
48 | 51 | ||
49 | count = PAGE_SIZE; | 52 | count = PAGE_SIZE; |
50 | if (address + PAGE_SIZE > area->vm_end) { | 53 | if ((unsigned long)vmf->virtual_address + PAGE_SIZE > area->vm_end) { |
51 | count = area->vm_end - address; | 54 | WARN_ON(1); /* shouldn't happen? */ |
55 | count = area->vm_end - (unsigned long)vmf->virtual_address; | ||
52 | } | 56 | } |
53 | /* what we can read in one go */ | 57 | /* what we can read in one go */ |
54 | bufsize = NCP_SERVER(inode)->buffer_size; | 58 | bufsize = NCP_SERVER(inode)->buffer_size; |
@@ -83,23 +87,21 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, | |||
83 | 87 | ||
84 | if (already_read < PAGE_SIZE) | 88 | if (already_read < PAGE_SIZE) |
85 | memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); | 89 | memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); |
86 | flush_dcache_page(page); | 90 | flush_dcache_page(vmf->page); |
87 | kunmap(page); | 91 | kunmap(vmf->page); |
88 | 92 | ||
89 | /* | 93 | /* |
90 | * If I understand ncp_read_kernel() properly, the above always | 94 | * If I understand ncp_read_kernel() properly, the above always |
91 | * fetches from the network, here the analogue of disk. | 95 | * fetches from the network, here the analogue of disk. |
92 | * -- wli | 96 | * -- wli |
93 | */ | 97 | */ |
94 | if (type) | ||
95 | *type = VM_FAULT_MAJOR; | ||
96 | count_vm_event(PGMAJFAULT); | 98 | count_vm_event(PGMAJFAULT); |
97 | return page; | 99 | return VM_FAULT_MAJOR; |
98 | } | 100 | } |
99 | 101 | ||
100 | static struct vm_operations_struct ncp_file_mmap = | 102 | static struct vm_operations_struct ncp_file_mmap = |
101 | { | 103 | { |
102 | .nopage = ncp_file_mmap_nopage, | 104 | .fault = ncp_file_mmap_fault, |
103 | }; | 105 | }; |
104 | 106 | ||
105 | 107 | ||