Blame view

fs/ncpfs/mmap.c 3.04 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  /*
   *  mmap.c
   *
   *  Copyright (C) 1995, 1996 by Volker Lendecke
   *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
   *
   */
  
  #include <linux/stat.h>
  #include <linux/time.h>
  #include <linux/kernel.h>
  #include <linux/mm.h>
  #include <linux/shm.h>
  #include <linux/errno.h>
  #include <linux/mman.h>
  #include <linux/string.h>
  #include <linux/slab.h>
  #include <linux/fcntl.h>
  #include <linux/ncp_fs.h>
  
  #include "ncplib_kernel.h"
  #include <asm/uaccess.h>
  #include <asm/system.h>
  
  /*
   * Fill in the supplied page for mmap
d0217ac04   Nick Piggin   mm: fault feedbac...
27
28
   * XXX: how are we excluding truncate/invalidate here? Maybe need to lock
   * page?
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
   */
d0217ac04   Nick Piggin   mm: fault feedbac...
30
31
  static int ncp_file_mmap_fault(struct vm_area_struct *area,
  					struct vm_fault *vmf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  {
  	struct file *file = area->vm_file;
92e5baef8   Josef Sipek   [PATCH] struct pa...
34
  	struct dentry *dentry = file->f_path.dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  	struct inode *inode = dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
  	char *pg_addr;
  	unsigned int already_read;
  	unsigned int count;
  	int bufsize;
d0217ac04   Nick Piggin   mm: fault feedbac...
40
  	int pos; /* XXX: loff_t ? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41

d0217ac04   Nick Piggin   mm: fault feedbac...
42
43
44
45
46
47
48
49
50
  	/*
  	 * ncpfs has nothing against high pages as long
  	 * as recvmsg and memset works on it
  	 */
  	vmf->page = alloc_page(GFP_HIGHUSER);
  	if (!vmf->page)
  		return VM_FAULT_OOM;
  	pg_addr = kmap(vmf->page);
  	pos = vmf->pgoff << PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  
  	count = PAGE_SIZE;
d0217ac04   Nick Piggin   mm: fault feedbac...
53
  	if ((unsigned long)vmf->virtual_address + PAGE_SIZE > area->vm_end) {
54cb8821d   Nick Piggin   mm: merge populat...
54
  		WARN_ON(1); /* shouldn't happen? */
d0217ac04   Nick Piggin   mm: fault feedbac...
55
  		count = area->vm_end - (unsigned long)vmf->virtual_address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  	}
  	/* what we can read in one go */
  	bufsize = NCP_SERVER(inode)->buffer_size;
  
  	already_read = 0;
  	if (ncp_make_open(inode, O_RDONLY) >= 0) {
  		while (already_read < count) {
  			int read_this_time;
  			int to_read;
  
  			to_read = bufsize - (pos % bufsize);
  
  			to_read = min_t(unsigned int, to_read, count - already_read);
  
  			if (ncp_read_kernel(NCP_SERVER(inode),
  				     NCP_FINFO(inode)->file_handle,
  				     pos, to_read,
  				     pg_addr + already_read,
  				     &read_this_time) != 0) {
  				read_this_time = 0;
  			}
  			pos += read_this_time;
  			already_read += read_this_time;
  
  			if (read_this_time < to_read) {
  				break;
  			}
  		}
  		ncp_inode_close(inode);
  
  	}
  
  	if (already_read < PAGE_SIZE)
  		memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
d0217ac04   Nick Piggin   mm: fault feedbac...
90
91
  	flush_dcache_page(vmf->page);
  	kunmap(vmf->page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
  
  	/*
  	 * If I understand ncp_read_kernel() properly, the above always
  	 * fetches from the network, here the analogue of disk.
  	 * -- wli
  	 */
f8891e5e1   Christoph Lameter   [PATCH] Light wei...
98
  	count_vm_event(PGMAJFAULT);
d0217ac04   Nick Piggin   mm: fault feedbac...
99
  	return VM_FAULT_MAJOR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
  }
  
  static struct vm_operations_struct ncp_file_mmap =
  {
54cb8821d   Nick Piggin   mm: merge populat...
104
  	.fault = ncp_file_mmap_fault,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
110
  };
  
  
  /* This is used for a general mmap of a ncp file */
  int ncp_mmap(struct file *file, struct vm_area_struct *vma)
  {
92e5baef8   Josef Sipek   [PATCH] struct pa...
111
  	struct inode *inode = file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  	
  	DPRINTK("ncp_mmap: called
  ");
  
  	if (!ncp_conn_valid(NCP_SERVER(inode)))
  		return -EIO;
  
  	/* only PAGE_COW or read-only supported now */
  	if (vma->vm_flags & VM_SHARED)
  		return -EINVAL;
  	/* we do not support files bigger than 4GB... We eventually 
  	   supports just 4GB... */
  	if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff 
  	   > (1U << (32 - PAGE_SHIFT)))
  		return -EFBIG;
  
  	vma->vm_ops = &ncp_file_mmap;
  	file_accessed(file);
  	return 0;
  }