“9865f1d46a68a5f58cb623054c8308484007d8a4”上不存在“README.md”
mmap.c 3.0 KB
Newer Older
L
Linus Torvalds 已提交
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 27
/*
 *  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
 */
28 29
static struct page* ncp_file_mmap_fault(struct vm_area_struct *area,
						struct fault_data *fdata)
L
Linus Torvalds 已提交
30 31
{
	struct file *file = area->vm_file;
32
	struct dentry *dentry = file->f_path.dentry;
L
Linus Torvalds 已提交
33 34 35 36 37 38 39 40 41 42
	struct inode *inode = dentry->d_inode;
	struct page* page;
	char *pg_addr;
	unsigned int already_read;
	unsigned int count;
	int bufsize;
	int pos;

	page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages
	           as long as recvmsg and memset works on it */
43 44 45 46
	if (!page) {
		fdata->type = VM_FAULT_OOM;
		return NULL;
	}
L
Linus Torvalds 已提交
47
	pg_addr = kmap(page);
48
	pos = fdata->pgoff << PAGE_SHIFT;
L
Linus Torvalds 已提交
49 50

	count = PAGE_SIZE;
51 52 53
	if (fdata->address + PAGE_SIZE > area->vm_end) {
		WARN_ON(1); /* shouldn't happen? */
		count = area->vm_end - fdata->address;
L
Linus Torvalds 已提交
54 55 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 90 91 92 93 94 95
	}
	/* 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);
	flush_dcache_page(page);
	kunmap(page);

	/*
	 * If I understand ncp_read_kernel() properly, the above always
	 * fetches from the network, here the analogue of disk.
	 * -- wli
	 */
96
	fdata->type = VM_FAULT_MAJOR;
97
	count_vm_event(PGMAJFAULT);
L
Linus Torvalds 已提交
98 99 100 101 102
	return page;
}

static struct vm_operations_struct ncp_file_mmap =
{
103
	.fault = ncp_file_mmap_fault,
L
Linus Torvalds 已提交
104 105 106 107 108 109
};


/* This is used for a general mmap of a ncp file */
int ncp_mmap(struct file *file, struct vm_area_struct *vma)
{
110
	struct inode *inode = file->f_path.dentry->d_inode;
L
Linus Torvalds 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
	
	DPRINTK("ncp_mmap: called\n");

	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;
127
	vma->vm_flags |= VM_CAN_INVALIDATE;
L
Linus Torvalds 已提交
128 129 130
	file_accessed(file);
	return 0;
}
新手
引导
客服 返回
顶部