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