blob: dae9d23b1519e3f8710f10125a9a0355aa1a6553 [file] [log] [blame]
/*
* Copyright (C) 2017 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#if IS_ENABLED(CONFIG_OVERLAY_FS)
#include <linux/overlay_util.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include "internal.h"
static bool overlay_file_consistent(struct file *file)
{
return d_real_inode(file->f_path.dentry) == file_inode(file);
}
ssize_t overlay_read_iter(struct file *file, struct kiocb *kio,
struct iov_iter *iter)
{
ssize_t ret;
if (likely(overlay_file_consistent(file)))
return file->f_op->read_iter(kio, iter);
file = filp_clone_open(file);
if (IS_ERR(file))
return PTR_ERR(file);
ret = vfs_iter_read(file, iter, &kio->ki_pos);
fput(file);
return ret;
}
EXPORT_SYMBOL(overlay_read_iter);
int overlay_fsync(struct file *file, loff_t start, loff_t end,
int datasync)
{
int ret;
if (likely(overlay_file_consistent(file)))
return file->f_op->fsync(file, start, end, datasync);
file = filp_clone_open(file);
if (IS_ERR(file))
return PTR_ERR(file);
ret = vfs_fsync_range(file, start, end, datasync);
fput(file);
return ret;
}
EXPORT_SYMBOL(overlay_fsync);
int overlay_mmap(struct file *file, struct vm_area_struct *vma)
{
if (unlikely(!overlay_file_consistent(file))) {
file = filp_clone_open(file);
if (IS_ERR(file))
return PTR_ERR(file);
fput(vma->vm_file);
/* transfer ref: */
vma->vm_file = file;
if (!file->f_op->mmap)
return -ENODEV;
}
return file->f_op->mmap(file, vma);
}
EXPORT_SYMBOL(overlay_mmap);
#endif /* IS_ENABLED(CONFIG_OVERLAY_FS) */