VM area marked with VM_WRITE means that pages may be written, but
mmap page write may never happen.
It should delay layout write until the actual modification on the
file happen in ->page_mkwrite().
Otherwise, it will trigger panic for PCC-RO sanity-pcc test_21f().
Fixes:
f2d1c4ee4 ("LU-14647 flr: mmap write/punch does not stale other mirrors")
Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I1cbfef8a4ed7e2c718324fd8a21bafd6157b5f0c
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/44483
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
return io->ci_type == CIT_FAULT && io->u.ci_fault.ft_mkwrite;
}
-static inline int cl_io_is_fault_writable(const struct cl_io *io)
-{
- return io->ci_type == CIT_FAULT && io->u.ci_fault.ft_writable;
-}
-
/**
* True, iff \a io is a truncate(2).
*/
* \param env - corespondent lu_env to processing
* \param vma - virtual memory area addressed to page fault
* \param index - page index corespondent to fault.
+ * \param mkwrite - whether it is mmap write.
*
* \return error codes from cl_io_init.
*/
static struct cl_io *
-ll_fault_io_init(struct lu_env *env, struct vm_area_struct *vma, pgoff_t index)
+ll_fault_io_init(struct lu_env *env, struct vm_area_struct *vma,
+ pgoff_t index, bool mkwrite)
{
struct file *file = vma->vm_file;
struct inode *inode = file_inode(file);
fio->ft_index = index;
fio->ft_executable = vma->vm_flags & VM_EXEC;
+ if (mkwrite) {
+ fio->ft_mkwrite = 1;
+ fio->ft_writable = 1;
+ }
+
CDEBUG(D_MMAP,
DFID": vma=%p start=%#lx end=%#lx vm_flags=%#lx idx=%lu\n",
PFID(&ll_i2info(inode)->lli_fid), vma, vma->vm_start,
else if (vma->vm_flags & VM_RAND_READ)
io->ci_rand_read = 1;
- if (vma->vm_flags & VM_WRITE)
- fio->ft_writable = 1;
-
rc = cl_io_init(env, io, CIT_FAULT, io->ci_obj);
if (rc == 0) {
struct vvp_io *vio = vvp_env_io(env);
if (IS_ERR(env))
RETURN(PTR_ERR(env));
- io = ll_fault_io_init(env, vma, vmpage->index);
+ io = ll_fault_io_init(env, vma, vmpage->index, true);
if (IS_ERR(io))
GOTO(out, result = PTR_ERR(io));
if (result < 0)
GOTO(out_io, result);
- io->u.ci_fault.ft_mkwrite = 1;
- io->u.ci_fault.ft_writable = 1;
-
vio = vvp_env_io(env);
vio->u.fault.ft_vma = vma;
vio->u.fault.ft_vmpage = vmpage;
fault_ret = 0;
}
- io = ll_fault_io_init(env, vma, vmf->pgoff);
+ io = ll_fault_io_init(env, vma, vmf->pgoff, false);
if (IS_ERR(io))
GOTO(out, result = PTR_ERR(io));
io->ci_need_write_intent = 0;
LASSERT(io->ci_type == CIT_WRITE || cl_io_is_fallocate(io) ||
- cl_io_is_trunc(io) || cl_io_is_mkwrite(io) ||
- cl_io_is_fault_writable(io));
+ cl_io_is_trunc(io) || cl_io_is_mkwrite(io));
CDEBUG(D_VFSTRACE, DFID" write layout, type %u "DEXT"\n",
PFID(lu_object_fid(&obj->co_lu)), io->ci_type,
io->ci_need_write_intent = 0;
if (!(io->ci_type == CIT_WRITE || cl_io_is_mkwrite(io) ||
- cl_io_is_fallocate(io) || cl_io_is_trunc(io) ||
- cl_io_is_fault_writable(io)))
+ cl_io_is_fallocate(io) || cl_io_is_trunc(io)))
RETURN(0);
/*
/* check if it needs to instantiate layout */
if (!(io->ci_type == CIT_WRITE || cl_io_is_mkwrite(io) ||
cl_io_is_fallocate(io) ||
- (cl_io_is_trunc(io) && io->u.ci_setattr.sa_attr.lvb_size > 0)) ||
- cl_io_is_fault_writable(io))
+ (cl_io_is_trunc(io) && io->u.ci_setattr.sa_attr.lvb_size > 0)))
GOTO(out, result = 0);
/*
return -EINVAL;
for (i = 0; i < paths.gl_pathc; i++) {
- FILE *f = fopen(paths.gl_pathv[i], "r");
+ FILE *f = fopen(paths.gl_pathv[i], "r+");
if (!f) {
rc = -errno;
return rc;
}
+static int mmap_tst10(char *mnt)
+{
+ char *buf = MAP_FAILED;
+ char *buffer[256];
+ struct stat st1, st2;
+ long off;
+ int fd = -1;
+ int rc = 0;
+
+ /* cancel unused locks */
+ rc = cancel_lru_locks("osc");
+ if (rc)
+ goto out;
+
+ fd = open(mmap_sanity, O_RDONLY);
+ if (fd == -1) {
+ perror("open");
+ rc = -errno;
+ goto out;
+ }
+
+ if (fstat(fd, &st1) != 0) {
+ perror("fstat");
+ rc = -errno;
+ goto out;
+ }
+
+ sleep(1);
+
+ buf = mmap(NULL, st1.st_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_NORESERVE, fd, 0);
+ if (buf == MAP_FAILED) {
+ perror("mmap");
+ rc = -errno;
+ goto out;
+ }
+
+ /* read some data */
+ for (off = 0; off + 256 <= st1.st_size; off += 256)
+ memcpy(buffer, off + buf, 256);
+
+ if (fstat(fd, &st2) != 0) {
+ perror("fstat");
+ rc = -errno;
+ goto out;
+ }
+
+ if (st1.st_mtime != st2.st_mtime) {
+ fprintf(stderr, "before mmap read mtime(%ld) != after mtime=(%ld)\n",
+ st1.st_mtime, st2.st_mtime);
+ rc = -EINVAL;
+ goto out;
+ }
+out:
+ if (buf != MAP_FAILED)
+ munmap(buf, st1.st_size);
+ if (fd != -1)
+ close(fd);
+ return rc;
+}
+
static int remote_tst(int tc, char *mnt)
{
int rc = 0;
.node_cnt = 1
},
{
+ .tc = 10,
+ .desc = "mmap test10: mtime not change for readonly mmap access",
+ .test_fn = mmap_tst10,
+ .node_cnt = 1
+ },
+ {
.tc = 0
}
};