- struct lu_env *env;
- struct cl_io *io;
- struct vvp_io *vio = NULL;
- unsigned long ra_flags;
- struct cl_env_nest nest;
- int result;
- int fault_ret = 0;
- ENTRY;
-
- result = ll_fault_io_init(vma, &env, &nest, vmf->pgoff, &ra_flags);
- if (env == NULL)
- RETURN(VM_FAULT_ERROR);
-
- io = &ccc_env_info(env)->cti_io;
- if (result < 0)
- goto out_err;
-
- vio = vvp_env_io(env);
-
- vio->u.fault.ft_vma = vma;
- vio->u.fault.fault.ft_vmf = vmf;
+ struct lu_env *env;
+ struct cl_io *io;
+ struct vvp_io *vio = NULL;
+ struct page *vmpage;
+ unsigned long ra_flags;
+ int result = 0;
+ int fault_ret = 0;
+ __u16 refcheck;
+ ENTRY;
+
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
+
+ if (ll_sbi_has_fast_read(ll_i2sbi(file_inode(vma->vm_file)))) {
+ /* do fast fault */
+ ll_cl_add(vma->vm_file, env, NULL, LCC_MMAP);
+ fault_ret = ll_filemap_fault(vma, vmf);
+ ll_cl_remove(vma->vm_file, env);
+
+ /* - If there is no error, then the page was found in cache and
+ * uptodate;
+ * - If VM_FAULT_RETRY is set, the page existed but failed to
+ * lock. It will return to kernel and retry;
+ * - Otherwise, it should try normal fault under DLM lock. */
+ if ((fault_ret & VM_FAULT_RETRY) ||
+ !(fault_ret & VM_FAULT_ERROR))
+ GOTO(out, result = 0);
+
+ fault_ret = 0;
+ }
+
+ io = ll_fault_io_init(env, vma, vmf->pgoff, &ra_flags);
+ if (IS_ERR(io))
+ GOTO(out, result = PTR_ERR(io));
+
+ result = io->ci_result;
+ if (result == 0) {
+ vio = vvp_env_io(env);
+ vio->u.fault.ft_vma = vma;
+ vio->u.fault.ft_vmpage = NULL;
+ vio->u.fault.ft_vmf = vmf;
+ vio->u.fault.ft_flags = 0;
+ vio->u.fault.ft_flags_valid = 0;
+
+ /* May call ll_readpage() */
+ ll_cl_add(vma->vm_file, env, io, LCC_MMAP);
+
+ result = cl_io_loop(env, io);
+
+ ll_cl_remove(vma->vm_file, env);
+
+ /* ft_flags are only valid if we reached
+ * the call to filemap_fault */
+ if (vio->u.fault.ft_flags_valid)
+ fault_ret = vio->u.fault.ft_flags;
+
+ vmpage = vio->u.fault.ft_vmpage;
+ if (result != 0 && vmpage != NULL) {
+ put_page(vmpage);
+ vmf->page = NULL;
+ }
+ }
+ cl_io_fini(env, io);