[go: nahoru, domu]

1d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/*
2d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * GPL HEADER START
3d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
4d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
6d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * This program is free software; you can redistribute it and/or modify
7d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * it under the terms of the GNU General Public License version 2 only,
8d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * as published by the Free Software Foundation.
9d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
10d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * This program is distributed in the hope that it will be useful, but
11d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * WITHOUT ANY WARRANTY; without even the implied warranty of
12d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * General Public License version 2 for more details (a copy is included
14d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * in the LICENSE file that accompanied this code).
15d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
16d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * You should have received a copy of the GNU General Public License
17d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * version 2 along with this program; If not, see
18d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
20d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * CA 95054 USA or visit www.sun.com if you need additional information or
22d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * have any questions.
23d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
24d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * GPL HEADER END
25d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao */
26d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/*
27d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
28d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * Use is subject to license terms.
29d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
30d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * Copyright (c) 2011, 2012, Intel Corporation.
31d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao */
32d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/*
33d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * This file is part of Lustre, http://www.lustre.org/
34d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * Lustre is a trademark of Sun Microsystems, Inc.
35d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao */
36d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
37d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/kernel.h>
38d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/mm.h>
39d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/string.h>
40d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/stat.h>
41d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/errno.h>
42d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/unistd.h>
43d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <asm/uaccess.h>
44d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
45d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/fs.h>
46d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include <linux/pagemap.h>
47d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
48d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#define DEBUG_SUBSYSTEM S_LLITE
49d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
5067a235f5e5893bc7dc86cf0e867fdb3f9041df18Greg Kroah-Hartman#include "../include/lustre_lite.h"
51d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao#include "llite_internal.h"
5267a235f5e5893bc7dc86cf0e867fdb3f9041df18Greg Kroah-Hartman#include "../include/linux/lustre_compat25.h"
53d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
542d95f10e50da3eadd3f0a54f8b4b03db37ce879cJohn L. Hammondstatic const struct vm_operations_struct ll_file_vm_ops;
55d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
56d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taovoid policy_from_vma(ldlm_policy_data_t *policy,
57d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			    struct vm_area_struct *vma, unsigned long addr,
58d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			    size_t count)
59d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
60d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	policy->l_extent.start = ((addr - vma->vm_start) & CFS_PAGE_MASK) +
61d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao				 (vma->vm_pgoff << PAGE_CACHE_SHIFT);
62d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	policy->l_extent.end = (policy->l_extent.start + count - 1) |
63d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			       ~CFS_PAGE_MASK;
64d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
65d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
66d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taostruct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr,
67d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			       size_t count)
68d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
69d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct vm_area_struct *vma, *ret = NULL;
70d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
71d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	/* mmap_sem must have been held by caller. */
72d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(!down_write_trylock(&mm->mmap_sem));
73d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
74a58a38ac0d94ccafdc1ae3c0ece750cbb9ca34c9Greg Donald	for (vma = find_vma(mm, addr);
75d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	    vma != NULL && vma->vm_start < (addr + count); vma = vma->vm_next) {
76d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		if (vma->vm_ops && vma->vm_ops == &ll_file_vm_ops &&
77d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		    vma->vm_flags & VM_SHARED) {
78d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			ret = vma;
79d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			break;
80d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		}
81d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
820a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman	return ret;
83d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
84d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
85d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/**
86d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * API independent part for page fault initialization.
87d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \param vma - virtual memory area addressed to page fault
88d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \param env - corespondent lu_env to processing
89d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \param nest - nested level
90d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \param index - page index corespondent to fault.
91d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \parm ra_flags - vma readahead flags.
92d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
93d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \return allocated and initialized env for fault operation.
94d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \retval EINVAL if env can't allocated
95d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \return other error codes from cl_io_init.
96d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao */
972d95f10e50da3eadd3f0a54f8b4b03db37ce879cJohn L. Hammondstatic struct cl_io *
982d95f10e50da3eadd3f0a54f8b4b03db37ce879cJohn L. Hammondll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret,
992d95f10e50da3eadd3f0a54f8b4b03db37ce879cJohn L. Hammond		 struct cl_env_nest *nest, pgoff_t index,
1002d95f10e50da3eadd3f0a54f8b4b03db37ce879cJohn L. Hammond		 unsigned long *ra_flags)
101d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
1028a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	struct file	       *file = vma->vm_file;
1038a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	struct inode	       *inode = file->f_dentry->d_inode;
1048a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	struct cl_io	       *io;
1058a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	struct cl_fault_io     *fio;
1068a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	struct lu_env	       *env;
1078a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	int			rc;
108d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
109d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	*env_ret = NULL;
110d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (ll_file_nolock(file))
1110a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman		return ERR_PTR(-EOPNOTSUPP);
112d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
113d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	/*
114d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * page fault can be called when lustre IO is
115d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * already active for the current thread, e.g., when doing read/write
116d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * against user level buffer mapped from Lustre buffer. To avoid
117d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * stomping on existing context, optionally force an allocation of a new
118d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * one.
119d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 */
120d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	env = cl_env_nested_get(nest);
121d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (IS_ERR(env))
1220a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman		 return ERR_PTR(-EINVAL);
123d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
124d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	*env_ret = env;
125d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
126d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	io = ccc_env_thread_io(env);
127d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	io->ci_obj = ll_i2info(inode)->lli_clob;
128d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(io->ci_obj != NULL);
129d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
130d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	fio = &io->u.ci_fault;
131d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	fio->ft_index      = index;
132d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	fio->ft_executable = vma->vm_flags&VM_EXEC;
133d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
134d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	/*
135d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * disable VM_SEQ_READ and use VM_RAND_READ to make sure that
136d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * the kernel will not read other pages not covered by ldlm in
137d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * filemap_nopage. we do our readahead in ll_readpage.
138d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 */
139d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (ra_flags != NULL)
140d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		*ra_flags = vma->vm_flags & (VM_RAND_READ|VM_SEQ_READ);
141d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	vma->vm_flags &= ~VM_SEQ_READ;
142d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	vma->vm_flags |= VM_RAND_READ;
143d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
144d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	CDEBUG(D_MMAP, "vm_flags: %lx (%lu %d)\n", vma->vm_flags,
145d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	       fio->ft_index, fio->ft_executable);
146d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
1478a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	rc = cl_io_init(env, io, CIT_FAULT, io->ci_obj);
1488a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	if (rc == 0) {
149d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		struct ccc_io *cio = ccc_env_io(env);
150d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
151d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
152d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		LASSERT(cio->cui_cl.cis_io == io);
153d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
1548a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond		/* mmap lock must be MANDATORY it has to cache
1558a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond		 * pages. */
156d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		io->ci_lockreq = CILR_MANDATORY;
1578a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond		cio->cui_fd = fd;
1588a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	} else {
1598a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond		LASSERT(rc < 0);
1608a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond		cl_io_fini(env, io);
1618a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond		cl_env_nested_put(nest, env);
1628a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond		io = ERR_PTR(rc);
163d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
164d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
165d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	return io;
166d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
167d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
168d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/* Sharing code of page_mkwrite method for rhel5 and rhel6 */
169d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taostatic int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage,
170d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			    bool *retry)
171d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
172d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct lu_env	   *env;
173d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct cl_io	    *io;
174d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct vvp_io	   *vio;
175d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct cl_env_nest       nest;
176d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int		      result;
177d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	sigset_t	     set;
178d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct inode	     *inode;
179d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct ll_inode_info     *lli;
180d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
181d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(vmpage != NULL);
182d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
183d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	io = ll_fault_io_init(vma, &env,  &nest, vmpage->index, NULL);
18434e1f2bb1e7ab87c2b950189f7ccae57a72f25a8Julia Lawall	if (IS_ERR(io)) {
18534e1f2bb1e7ab87c2b950189f7ccae57a72f25a8Julia Lawall		result = PTR_ERR(io);
18634e1f2bb1e7ab87c2b950189f7ccae57a72f25a8Julia Lawall		goto out;
18734e1f2bb1e7ab87c2b950189f7ccae57a72f25a8Julia Lawall	}
188d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
189d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	result = io->ci_result;
190d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (result < 0)
19134e1f2bb1e7ab87c2b950189f7ccae57a72f25a8Julia Lawall		goto out_io;
192d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
193d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	io->u.ci_fault.ft_mkwrite = 1;
194d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	io->u.ci_fault.ft_writable = 1;
195d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
196d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	vio = vvp_env_io(env);
197d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	vio->u.fault.ft_vma    = vma;
198d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	vio->u.fault.ft_vmpage = vmpage;
199d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
200d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM));
201d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
202d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	/* we grab lli_trunc_sem to exclude truncate case.
203d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * Otherwise, we could add dirty pages into osc cache
204d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * while truncate is on-going. */
205d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	inode = ccc_object_inode(io->ci_obj);
206d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	lli = ll_i2info(inode);
207d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	down_read(&lli->lli_trunc_sem);
208d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
209d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	result = cl_io_loop(env, io);
210d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
211d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	up_read(&lli->lli_trunc_sem);
212d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
213d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	cfs_restore_sigs(set);
214d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
215d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (result == 0) {
216d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		struct inode *inode = vma->vm_file->f_dentry->d_inode;
217d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		struct ll_inode_info *lli = ll_i2info(inode);
218d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
219d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		lock_page(vmpage);
220d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		if (vmpage->mapping == NULL) {
221d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			unlock_page(vmpage);
222d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
223d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			/* page was truncated and lock was cancelled, return
224d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			 * ENODATA so that VM_FAULT_NOPAGE will be returned
225d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			 * to handle_mm_fault(). */
226d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			if (result == 0)
227d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao				result = -ENODATA;
228d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		} else if (!PageDirty(vmpage)) {
229d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			/* race, the page has been cleaned by ptlrpcd after
230d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			 * it was unlocked, it has to be added into dirty
231d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			 * cache again otherwise this soon-to-dirty page won't
232d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			 * consume any grants, even worse if this page is being
233d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			 * transferred because it will break RPC checksum.
234d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			 */
235d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			unlock_page(vmpage);
236d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
237d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			CDEBUG(D_MMAP, "Race on page_mkwrite %p/%lu, page has "
238d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			       "been written out, retry.\n",
239d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			       vmpage, vmpage->index);
240d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
241d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			*retry = true;
242d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			result = -EAGAIN;
243d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		}
244d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
245d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		if (result == 0) {
246d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			spin_lock(&lli->lli_lock);
247d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			lli->lli_flags |= LLIF_DATA_MODIFIED;
248d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			spin_unlock(&lli->lli_lock);
249d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		}
250d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
251d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
2528a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammondout_io:
253d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	cl_io_fini(env, io);
254d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	cl_env_nested_put(&nest, env);
2558a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammondout:
256d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	CDEBUG(D_MMAP, "%s mkwrite with %d\n", current->comm, result);
257d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(ergo(result == 0, PageLocked(vmpage)));
2588a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond
2598a48df7080b2fa0aed2b8df74437a39217c1eb8cJohn L. Hammond	return result;
260d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
261d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
262d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
263d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
264d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taostatic inline int to_fault_error(int result)
265d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
266a58a38ac0d94ccafdc1ae3c0ece750cbb9ca34c9Greg Donald	switch (result) {
267d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case 0:
268d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_LOCKED;
269d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
270d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case -EFAULT:
271d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_NOPAGE;
272d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
273d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case -ENOMEM:
274d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_OOM;
275d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
276d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	default:
277d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_SIGBUS;
278d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
279d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
280d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	return result;
281d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
282d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
283d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/**
284d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * Lustre implementation of a vm_operations_struct::fault() method, called by
285d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * VM to server page fault (both in kernel and user space).
286d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
287d0a0acc3ccf5a45c976fe94b15a1f9e9c4c78414Masanari Iida * \param vma - is virtual area struct related to page fault
288d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \param vmf - structure which describe type and address where hit fault
289d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *
290d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \return allocated and filled _locked_ page for address
291d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \retval VM_FAULT_ERROR on general error
292d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * \retval NOPAGE_OOM not have memory for allocate new page
293d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao */
294d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taostatic int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
295d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
296d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct lu_env	   *env;
297d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct cl_io	    *io;
298d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct vvp_io	   *vio = NULL;
299d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct page	     *vmpage;
300d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	unsigned long	    ra_flags;
301d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct cl_env_nest       nest;
302d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int		      result;
303d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int		      fault_ret = 0;
304d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
305d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	io = ll_fault_io_init(vma, &env,  &nest, vmf->pgoff, &ra_flags);
306d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (IS_ERR(io))
3070a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman		return to_fault_error(PTR_ERR(io));
308d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
309d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	result = io->ci_result;
310d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (result == 0) {
311d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		vio = vvp_env_io(env);
312d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		vio->u.fault.ft_vma       = vma;
313d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		vio->u.fault.ft_vmpage    = NULL;
314d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		vio->u.fault.fault.ft_vmf = vmf;
3156aa5107281ea065b9a7818a1c640e022d41a421bPaul Cassella		vio->u.fault.fault.ft_flags = 0;
3166aa5107281ea065b9a7818a1c640e022d41a421bPaul Cassella		vio->u.fault.fault.ft_flags_valid = 0;
317d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
318d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = cl_io_loop(env, io);
319d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
3206aa5107281ea065b9a7818a1c640e022d41a421bPaul Cassella		/* ft_flags are only valid if we reached
3216aa5107281ea065b9a7818a1c640e022d41a421bPaul Cassella		 * the call to filemap_fault */
3226aa5107281ea065b9a7818a1c640e022d41a421bPaul Cassella		if (vio->u.fault.fault.ft_flags_valid)
3236aa5107281ea065b9a7818a1c640e022d41a421bPaul Cassella			fault_ret = vio->u.fault.fault.ft_flags;
3246aa5107281ea065b9a7818a1c640e022d41a421bPaul Cassella
325d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		vmpage = vio->u.fault.ft_vmpage;
326d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		if (result != 0 && vmpage != NULL) {
327d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			page_cache_release(vmpage);
328d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			vmf->page = NULL;
329d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		}
330d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
331d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	cl_io_fini(env, io);
332d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	cl_env_nested_put(&nest, env);
333d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
334d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	vma->vm_flags |= ra_flags;
335d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (result != 0 && !(fault_ret & VM_FAULT_RETRY))
336d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		fault_ret |= to_fault_error(result);
337d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
338d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	CDEBUG(D_MMAP, "%s fault %d/%d\n",
339d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	       current->comm, fault_ret, result);
3400a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman	return fault_ret;
341d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
342d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
343d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taostatic int ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
344d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
345d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int count = 0;
346d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	bool printed = false;
347d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int result;
348d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	sigset_t set;
349d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
350d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	/* Only SIGKILL and SIGTERM is allowed for fault/nopage/mkwrite
351d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * so that it can be killed by admin but not cause segfault by
352d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	 * other signals. */
353d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM));
354d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
355d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taorestart:
356d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	result = ll_fault0(vma, vmf);
357d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(!(result & VM_FAULT_LOCKED));
358d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (result == 0) {
359d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		struct page *vmpage = vmf->page;
360d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
361d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		/* check if this page has been truncated */
362d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		lock_page(vmpage);
363d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		if (unlikely(vmpage->mapping == NULL)) { /* unlucky */
364d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			unlock_page(vmpage);
365d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			page_cache_release(vmpage);
366d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			vmf->page = NULL;
367d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
368d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			if (!printed && ++count > 16) {
369d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao				CWARN("the page is under heavy contention,"
370d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao				      "maybe your app(%s) needs revising :-)\n",
371d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao				      current->comm);
372d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao				printed = true;
373d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			}
374d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
375d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			goto restart;
376d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		}
377d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
37834d1f637cbf04eb88db10605338ccc6f8e9dedb8Georgiana Rodica Chelu		result = VM_FAULT_LOCKED;
379d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
380d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	cfs_restore_sigs(set);
381d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	return result;
382d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
383d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
384d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taostatic int ll_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
385d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
386d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int count = 0;
387d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	bool printed = false;
388d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	bool retry;
389d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int result;
390d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
391d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	do {
392d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		retry = false;
393d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = ll_page_mkwrite0(vma, vmf->page, &retry);
394d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
395d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		if (!printed && ++count > 16) {
396d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			CWARN("app(%s): the page %lu of file %lu is under heavy"
397d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			      " contention.\n",
398d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			      current->comm, vmf->pgoff,
399d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			      vma->vm_file->f_dentry->d_inode->i_ino);
400d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao			printed = true;
401d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		}
402d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	} while (retry);
403d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
404a58a38ac0d94ccafdc1ae3c0ece750cbb9ca34c9Greg Donald	switch (result) {
405d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case 0:
406d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		LASSERT(PageLocked(vmf->page));
407d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_LOCKED;
408d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
409d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case -ENODATA:
410d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case -EFAULT:
411d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_NOPAGE;
412d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
413d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case -ENOMEM:
414d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_OOM;
415d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
416d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	case -EAGAIN:
417d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_RETRY;
418d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
419d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	default:
420d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		result = VM_FAULT_SIGBUS;
421d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		break;
422d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
423d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
424d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	return result;
425d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
426d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
427d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/**
428d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *  To avoid cancel the locks covering mmapped region for lock cache pressure,
429d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao *  we track the mapped vma count in ccc_object::cob_mmap_cnt.
430d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao */
431aff9d8e80489e2abe446094680009f6a23e8e6d7Greg Donaldstatic void ll_vm_open(struct vm_area_struct *vma)
432d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
433d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct inode *inode    = vma->vm_file->f_dentry->d_inode;
434d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct ccc_object *vob = cl_inode2ccc(inode);
435d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
436d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(vma->vm_file);
437d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0);
438d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	atomic_inc(&vob->cob_mmap_cnt);
439d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
440d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
441d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/**
442d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * Dual to ll_vm_open().
443d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao */
444d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taostatic void ll_vm_close(struct vm_area_struct *vma)
445d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
446d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct inode      *inode = vma->vm_file->f_dentry->d_inode;
447d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct ccc_object *vob   = cl_inode2ccc(inode);
448d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
449d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(vma->vm_file);
450d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	atomic_dec(&vob->cob_mmap_cnt);
451d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0);
452d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
453d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
454d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao/* XXX put nice comment here.  talk about __free_pte -> dirty pages and
455d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao * nopage's reference passing to the pte */
456d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Taoint ll_teardown_mmaps(struct address_space *mapping, __u64 first, __u64 last)
457d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
458d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int rc = -ENOENT;
459d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
460b0f5aad587ea1fc3563d056609ee54a961ee1256Greg Kroah-Hartman	LASSERTF(last > first, "last %llu first %llu\n", last, first);
461d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (mapping_mapped(mapping)) {
462d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		rc = 0;
463d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		unmap_mapping_range(mapping, first + PAGE_CACHE_SIZE - 1,
464d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao				    last - first + 1, 0);
465d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
466d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
4670a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman	return rc;
468d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
469d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
4702d95f10e50da3eadd3f0a54f8b4b03db37ce879cJohn L. Hammondstatic const struct vm_operations_struct ll_file_vm_ops = {
471d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	.fault			= ll_fault,
472d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	.page_mkwrite		= ll_page_mkwrite,
473d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	.open			= ll_vm_open,
474d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	.close			= ll_vm_close,
475d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao};
476d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
477aff9d8e80489e2abe446094680009f6a23e8e6d7Greg Donaldint ll_file_mmap(struct file *file, struct vm_area_struct *vma)
478d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao{
479d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	struct inode *inode = file->f_dentry->d_inode;
480d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	int rc;
481d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
482d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (ll_file_nolock(file))
4830a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman		return -EOPNOTSUPP;
484d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
485d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_MAP, 1);
486d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	rc = generic_file_mmap(file, vma);
487d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	if (rc == 0) {
488d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		vma->vm_ops = &ll_file_vm_ops;
489d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		vma->vm_ops->open(vma);
490d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		/* update the inode's size and mtime */
491d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao		rc = ll_glimpse_size(inode);
492d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao	}
493d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao
4940a3bdb00710bf253ba8ba8f645645f22297c7a04Greg Kroah-Hartman	return rc;
495d7e09d0397e84eefbabfd9cb353221f3c6448d83Peng Tao}
496