* Lustre is a trademark of Sun Microsystems, Inc.
*/
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/version.h>
-#include <asm/uaccess.h>
-
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/pagemap.h>
#define DEBUG_SUBSYSTEM S_LLITE
int result;
__u16 refcheck;
sigset_t set;
- struct inode *inode;
+ struct inode *inode = NULL;
struct ll_inode_info *lli;
ENTRY;
CDEBUG(D_MMAP, "%s mkwrite with %d\n", current->comm, result);
LASSERT(ergo(result == 0, PageLocked(vmpage)));
+ /* if page has been unmapped, presumably due to lock reclaim for
+ * concurrent usage, add some delay before retrying to prevent
+ * entering live-lock situation with competitors
+ */
+ if (result == -ENODATA && inode != NULL) {
+ CDEBUG(D_MMAP, "delaying new page-fault for inode %p to "
+ "prevent live-lock\n", inode);
+ msleep(10);
+ }
+
return result;
}
case 0:
result = VM_FAULT_LOCKED;
break;
- case -EFAULT:
- result = VM_FAULT_NOPAGE;
- break;
case -ENOMEM:
result = VM_FAULT_OOM;
break;
* \retval VM_FAULT_ERROR on general error
* \retval NOPAGE_OOM not have memory for allocate new page
*/
-static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
+static vm_fault_t ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct lu_env *env;
struct cl_io *io;
}
#ifdef HAVE_VM_OPS_USE_VM_FAULT_ONLY
-static int ll_fault(struct vm_fault *vmf)
+static vm_fault_t ll_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
#else
-static int ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+static vm_fault_t ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
#endif
int count = 0;
bool printed = false;
- int result;
+ bool cached;
+ vm_fault_t result;
sigset_t set;
+ ll_stats_ops_tally(ll_i2sbi(file_inode(vma->vm_file)),
+ LPROC_LL_FAULT, 1);
+
+ result = pcc_fault(vma, vmf, &cached);
+ if (cached)
+ return result;
+
/* Only SIGKILL and SIGTERM is allowed for fault/nopage/mkwrite
* so that it can be killed by admin but not cause segfault by
* other signals. */
set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM));
- ll_stats_ops_tally(ll_i2sbi(file_inode(vma->vm_file)),
- LPROC_LL_FAULT, 1);
-
+ /* make sure offset is not a negative number */
+ if (vmf->pgoff > (MAX_LFS_FILESIZE >> PAGE_SHIFT))
+ return VM_FAULT_SIGBUS;
restart:
result = ll_fault0(vma, vmf);
- if (!(result & (VM_FAULT_RETRY | VM_FAULT_ERROR | VM_FAULT_LOCKED))) {
+ if (vmf->page &&
+ !(result & (VM_FAULT_RETRY | VM_FAULT_ERROR | VM_FAULT_LOCKED))) {
struct page *vmpage = vmf->page;
/* check if this page has been truncated */
}
#ifdef HAVE_VM_OPS_USE_VM_FAULT_ONLY
-static int ll_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t ll_page_mkwrite(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
#else
-static int ll_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+static vm_fault_t ll_page_mkwrite(struct vm_area_struct *vma,
+ struct vm_fault *vmf)
{
#endif
int count = 0;
bool printed = false;
bool retry;
- int result;
+ bool cached;
+ vm_fault_t result;
ll_stats_ops_tally(ll_i2sbi(file_inode(vma->vm_file)),
LPROC_LL_MKWRITE, 1);
+ result = pcc_page_mkwrite(vma, vmf, &cached);
+ if (cached)
+ return result;
+
file_update_time(vma->vm_file);
do {
retry = false;
ENTRY;
LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0);
atomic_inc(&vob->vob_mmap_cnt);
+ pcc_vm_open(vma);
EXIT;
}
ENTRY;
atomic_dec(&vob->vob_mmap_cnt);
LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0);
+ pcc_vm_close(vma);
EXIT;
}
if (mapping_mapped(mapping)) {
rc = 0;
unmap_mapping_range(mapping, first + PAGE_SIZE - 1,
- last - first + 1, 0);
+ last - first + 1, 1);
}
RETURN(rc);
int ll_file_mmap(struct file *file, struct vm_area_struct * vma)
{
struct inode *inode = file_inode(file);
+ bool cached;
int rc;
+
ENTRY;
if (ll_file_nolock(file))
RETURN(-EOPNOTSUPP);
+ rc = pcc_file_mmap(file, vma, &cached);
+ if (cached && rc != 0)
+ RETURN(rc);
+
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_MAP, 1);
rc = generic_file_mmap(file, vma);
if (rc == 0) {
- vma->vm_ops = &ll_file_vm_ops;
+ vma->vm_ops = &ll_file_vm_ops;
vma->vm_ops->open(vma);
/* update the inode's size and mtime */
- rc = ll_glimpse_size(inode);
+ if (!cached)
+ rc = ll_glimpse_size(inode);
}
RETURN(rc);