This source file includes following definitions.
- nfs_mmap
- nfs_file_mmap_nopage
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/stat.h>
13 #include <linux/sched.h>
14 #include <linux/kernel.h>
15 #include <linux/mm.h>
16 #include <linux/shm.h>
17 #include <linux/errno.h>
18 #include <linux/mman.h>
19 #include <linux/string.h>
20 #include <asm/segment.h>
21 #include <asm/system.h>
22 #include <linux/nfs_fs.h>
23
24 extern int share_page(struct vm_area_struct * area, struct task_struct * tsk,
25 struct inode * inode, unsigned long address, unsigned long error_code,
26 unsigned long newpage);
27
28 extern unsigned long put_page(struct task_struct * tsk,unsigned long page,
29 unsigned long address,int prot);
30
31 static void nfs_file_mmap_nopage(int error_code, struct vm_area_struct * area,
32 unsigned long address);
33
34 extern void file_mmap_free(struct vm_area_struct * area);
35 extern int file_mmap_share(struct vm_area_struct * from, struct vm_area_struct * to,
36 unsigned long address);
37
38 struct vm_operations_struct nfs_file_mmap = {
39 NULL,
40 file_mmap_free,
41 nfs_file_mmap_nopage,
42 NULL,
43 file_mmap_share,
44 };
45
46
47
48 int nfs_mmap(struct inode * inode, struct file * file,
49 unsigned long addr, size_t len, int prot, unsigned long off)
50 {
51 struct vm_area_struct * mpnt;
52
53 if (prot & PAGE_RW)
54 return -EINVAL;
55 if (off & (inode->i_sb->s_blocksize - 1))
56 return -EINVAL;
57 if (!inode->i_sb || !S_ISREG(inode->i_mode))
58 return -EACCES;
59 if (!IS_RDONLY(inode)) {
60 inode->i_atime = CURRENT_TIME;
61 inode->i_dirt = 1;
62 }
63
64 mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
65 if (!mpnt)
66 return -ENOMEM;
67
68 unmap_page_range(addr, len);
69 mpnt->vm_task = current;
70 mpnt->vm_start = addr;
71 mpnt->vm_end = addr + len;
72 mpnt->vm_page_prot = prot;
73 mpnt->vm_share = NULL;
74 mpnt->vm_inode = inode;
75 inode->i_count++;
76 mpnt->vm_offset = off;
77 mpnt->vm_ops = &nfs_file_mmap;
78 mpnt->vm_next = current->mmap;
79 current->mmap = mpnt;
80 return 0;
81 }
82
83
84 static void nfs_file_mmap_nopage(int error_code, struct vm_area_struct * area,
85 unsigned long address)
86 {
87 struct inode * inode = area->vm_inode;
88 unsigned int clear;
89 unsigned long page;
90 unsigned long tmp;
91 int n;
92 int i;
93 int pos;
94 struct nfs_fattr fattr;
95
96 address &= PAGE_MASK;
97 pos = address - area->vm_start + area->vm_offset;
98
99 page = get_free_page(GFP_KERNEL);
100 if (share_page(area, area->vm_task, inode, address, error_code, page)) {
101 ++area->vm_task->min_flt;
102 return;
103 }
104
105 ++area->vm_task->maj_flt;
106 if (!page) {
107 oom(current);
108 put_page(area->vm_task, BAD_PAGE, address, PAGE_PRIVATE);
109 return;
110 }
111
112 clear = 0;
113 if (address + PAGE_SIZE > area->vm_end) {
114 clear = address + PAGE_SIZE - area->vm_end;
115 }
116
117 n = NFS_SERVER(inode)->rsize;
118
119 for (i = 0; i < (PAGE_SIZE - clear); i += n) {
120 int hunk, result;
121
122 hunk = PAGE_SIZE - i;
123 if (hunk > n)
124 hunk = n;
125 result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
126 pos, hunk, (char *) (page + i), &fattr);
127 if (result < 0)
128 break;
129 pos += result;
130 if (result < n) {
131 i += result;
132 break;
133 }
134 }
135
136 #ifdef doweneedthishere
137 nfs_refresh_inode(inode, &fattr);
138 #endif
139
140 if (!(error_code & PAGE_RW)) {
141 if (share_page(area, area->vm_task, inode, address, error_code, page))
142 return;
143 }
144
145 tmp = page + PAGE_SIZE;
146 while (clear--) {
147 *(char *)--tmp = 0;
148 }
149 if (put_page(area->vm_task,page,address,area->vm_page_prot))
150 return;
151 free_page(page);
152 oom(current);
153 }