diff options
Diffstat (limited to 'fs/ncpfs/mmap.c')
-rw-r--r-- | fs/ncpfs/mmap.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c new file mode 100644 index 000000000000..52d60c3d8996 --- /dev/null +++ b/fs/ncpfs/mmap.c | |||
@@ -0,0 +1,128 @@ | |||
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/mm.h> | ||
13 | #include <linux/shm.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/mman.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/fcntl.h> | ||
19 | #include <linux/ncp_fs.h> | ||
20 | |||
21 | #include "ncplib_kernel.h" | ||
22 | #include <asm/uaccess.h> | ||
23 | #include <asm/system.h> | ||
24 | |||
25 | /* | ||
26 | * Fill in the supplied page for mmap | ||
27 | */ | ||
28 | static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, | ||
29 | unsigned long address, int *type) | ||
30 | { | ||
31 | struct file *file = area->vm_file; | ||
32 | struct dentry *dentry = file->f_dentry; | ||
33 | struct inode *inode = dentry->d_inode; | ||
34 | struct page* page; | ||
35 | char *pg_addr; | ||
36 | unsigned int already_read; | ||
37 | unsigned int count; | ||
38 | int bufsize; | ||
39 | int pos; | ||
40 | |||
41 | page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages | ||
42 | as long as recvmsg and memset works on it */ | ||
43 | if (!page) | ||
44 | return page; | ||
45 | pg_addr = kmap(page); | ||
46 | address &= PAGE_MASK; | ||
47 | pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT); | ||
48 | |||
49 | count = PAGE_SIZE; | ||
50 | if (address + PAGE_SIZE > area->vm_end) { | ||
51 | count = area->vm_end - address; | ||
52 | } | ||
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(page); | ||
87 | kunmap(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 | * -- wli | ||
93 | */ | ||
94 | if (type) | ||
95 | *type = VM_FAULT_MAJOR; | ||
96 | inc_page_state(pgmajfault); | ||
97 | return page; | ||
98 | } | ||
99 | |||
100 | static struct vm_operations_struct ncp_file_mmap = | ||
101 | { | ||
102 | .nopage = ncp_file_mmap_nopage, | ||
103 | }; | ||
104 | |||
105 | |||
106 | /* This is used for a general mmap of a ncp file */ | ||
107 | int ncp_mmap(struct file *file, struct vm_area_struct *vma) | ||
108 | { | ||
109 | struct inode *inode = file->f_dentry->d_inode; | ||
110 | |||
111 | DPRINTK("ncp_mmap: called\n"); | ||
112 | |||
113 | if (!ncp_conn_valid(NCP_SERVER(inode))) | ||
114 | return -EIO; | ||
115 | |||
116 | /* only PAGE_COW or read-only supported now */ | ||
117 | if (vma->vm_flags & VM_SHARED) | ||
118 | return -EINVAL; | ||
119 | /* we do not support files bigger than 4GB... We eventually | ||
120 | supports just 4GB... */ | ||
121 | if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff | ||
122 | > (1U << (32 - PAGE_SHIFT))) | ||
123 | return -EFBIG; | ||
124 | |||
125 | vma->vm_ops = &ncp_file_mmap; | ||
126 | file_accessed(file); | ||
127 | return 0; | ||
128 | } | ||