Hi all,

This is now a conflict between the overlayfs tree and Linus' tree.  (I
restarted my merging after I noticed that Linus merged more stuff.)

On Fri, 15 Jun 2018 10:43:24 +1000 Stephen Rothwell <s...@canb.auug.org.au> 
wrote:
>
> Today's linux-next merge of the y2038 tree got conflicts in:
> 
>   fs/inode.c
>   fs/overlayfs/inode.c
>   fs/overlayfs/overlayfs.h
> 
> between various commits from the overlayfs tree and commits:
> 
>   8efd6894ff08 ("fs: add timespec64_truncate()")
>   95582b008388 ("vfs: change inode times to use struct timespec64")
> 
> from the y2038 tree.
> 
> I fixed it up (I copied the resolutions that used to be in the merge of
> the overlayfs into the y2038 tree - see below) and can carry the fix as
> necessary. This is now fixed as far as linux-next is concerned, but any
> non trivial conflicts should be mentioned to your upstream maintainer
> when your tree is submitted for merging.  You may also want to consider
> cooperating with the maintainer of the conflicting tree to minimise any
> particularly complex conflicts.
> 
> -- 
> Cheers,
> Stephen Rothwell
> 
> diff --cc fs/inode.c
> index 9a6fc2f2d220,9fe1f941be02..55373fcba3a5
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@@ -1635,10 -1681,11 +1635,10 @@@ static int update_time(struct inode *in
>    *  This function automatically handles read only file systems and media,
>    *  as well as the "noatime" flag and inode specific "noatime" markers.
>    */
>  -bool __atime_needs_update(const struct path *path, struct inode *inode,
>  -                      bool rcu)
>  +bool atime_needs_update(const struct path *path, struct inode *inode)
>   {
>       struct vfsmount *mnt = path->mnt;
> -     struct timespec now;
> +     struct timespec64 now;
>   
>       if (inode->i_flags & S_NOATIME)
>               return false;
> @@@ -1661,10 -1708,10 +1661,10 @@@
>   
>       now = current_time(inode);
>   
> -     if (!relatime_need_update(mnt, inode, now))
>  -    if (!relatime_need_update(path, inode, timespec64_to_timespec(now), 
> rcu))
> ++    if (!relatime_need_update(mnt, inode, timespec64_to_timespec(now)))
>               return false;
>   
> -     if (timespec_equal(&inode->i_atime, &now))
> +     if (timespec64_equal(&inode->i_atime, &now))
>               return false;
>   
>       return true;
> @@@ -1674,9 -1721,9 +1674,9 @@@ void touch_atime(const struct path *pat
>   {
>       struct vfsmount *mnt = path->mnt;
>       struct inode *inode = d_inode(path->dentry);
> -     struct timespec now;
> +     struct timespec64 now;
>   
>  -    if (!__atime_needs_update(path, inode, false))
>  +    if (!atime_needs_update(path, inode))
>               return;
>   
>       if (!sb_start_write_trylock(inode->i_sb))
> diff --cc fs/overlayfs/file.c
> index f801e1175a0b,000000000000..c6bce11ac6d3
> mode 100644,000000..100644
> --- a/fs/overlayfs/file.c
> +++ b/fs/overlayfs/file.c
> @@@ -1,508 -1,0 +1,508 @@@
>  +/*
>  + * 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.
>  + */
>  +
>  +#include <linux/cred.h>
>  +#include <linux/file.h>
>  +#include <linux/mount.h>
>  +#include <linux/xattr.h>
>  +#include <linux/uio.h>
>  +#include "overlayfs.h"
>  +
>  +static char ovl_whatisit(struct inode *inode, struct inode *realinode)
>  +{
>  +    if (realinode != ovl_inode_upper(inode))
>  +            return 'l';
>  +    if (ovl_has_upperdata(inode))
>  +            return 'u';
>  +    else
>  +            return 'm';
>  +}
>  +
>  +static struct file *ovl_open_realfile(const struct file *file,
>  +                                  struct inode *realinode)
>  +{
>  +    struct inode *inode = file_inode(file);
>  +    struct file *realfile;
>  +    const struct cred *old_cred;
>  +
>  +    old_cred = ovl_override_creds(inode->i_sb);
>  +    realfile = path_open(&file->f_path, file->f_flags | O_NOATIME,
>  +                         realinode, current_cred(), false);
>  +    revert_creds(old_cred);
>  +
>  +    pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
>  +             file, file, ovl_whatisit(inode, realinode), file->f_flags,
>  +             realfile, IS_ERR(realfile) ? 0 : realfile->f_flags);
>  +
>  +    return realfile;
>  +}
>  +
>  +#define OVL_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
>  +
>  +static int ovl_change_flags(struct file *file, unsigned int flags)
>  +{
>  +    struct inode *inode = file_inode(file);
>  +    int err;
>  +
>  +    /* No atime modificaton on underlying */
>  +    flags |= O_NOATIME;
>  +
>  +    /* If some flag changed that cannot be changed then something's amiss */
>  +    if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
>  +            return -EIO;
>  +
>  +    flags &= OVL_SETFL_MASK;
>  +
>  +    if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
>  +            return -EPERM;
>  +
>  +    if (flags & O_DIRECT) {
>  +            if (!file->f_mapping->a_ops ||
>  +                !file->f_mapping->a_ops->direct_IO)
>  +                    return -EINVAL;
>  +    }
>  +
>  +    if (file->f_op->check_flags) {
>  +            err = file->f_op->check_flags(flags);
>  +            if (err)
>  +                    return err;
>  +    }
>  +
>  +    spin_lock(&file->f_lock);
>  +    file->f_flags = (file->f_flags & ~OVL_SETFL_MASK) | flags;
>  +    spin_unlock(&file->f_lock);
>  +
>  +    return 0;
>  +}
>  +
>  +static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
>  +                           bool allow_meta)
>  +{
>  +    struct inode *inode = file_inode(file);
>  +    struct inode *realinode;
>  +
>  +    real->flags = 0;
>  +    real->file = file->private_data;
>  +
>  +    if (allow_meta)
>  +            realinode = ovl_inode_real(inode);
>  +    else
>  +            realinode = ovl_inode_realdata(inode);
>  +
>  +    /* Has it been copied up since we'd opened it? */
>  +    if (unlikely(file_inode(real->file) != realinode)) {
>  +            real->flags = FDPUT_FPUT;
>  +            real->file = ovl_open_realfile(file, realinode);
>  +
>  +            return PTR_ERR_OR_ZERO(real->file);
>  +    }
>  +
>  +    /* Did the flags change since open? */
>  +    if (unlikely((file->f_flags ^ real->file->f_flags) & ~O_NOATIME))
>  +            return ovl_change_flags(real->file, file->f_flags);
>  +
>  +    return 0;
>  +}
>  +
>  +static int ovl_real_fdget(const struct file *file, struct fd *real)
>  +{
>  +    return ovl_real_fdget_meta(file, real, false);
>  +}
>  +
>  +static int ovl_open(struct inode *inode, struct file *file)
>  +{
>  +    struct dentry *dentry = file_dentry(file);
>  +    struct file *realfile;
>  +    int err;
>  +
>  +    err = ovl_open_maybe_copy_up(dentry, file->f_flags);
>  +    if (err)
>  +            return err;
>  +
>  +    /* No longer need these flags, so don't pass them on to underlying fs */
>  +    file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
>  +
>  +    realfile = ovl_open_realfile(file, ovl_inode_realdata(inode));
>  +    if (IS_ERR(realfile))
>  +            return PTR_ERR(realfile);
>  +
>  +    /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */
>  +    file->f_mapping = realfile->f_mapping;
>  +
>  +    file->private_data = realfile;
>  +
>  +    return 0;
>  +}
>  +
>  +static int ovl_release(struct inode *inode, struct file *file)
>  +{
>  +    fput(file->private_data);
>  +
>  +    return 0;
>  +}
>  +
>  +static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
>  +{
>  +    struct inode *realinode = ovl_inode_real(file_inode(file));
>  +
>  +    return generic_file_llseek_size(file, offset, whence,
>  +                                    realinode->i_sb->s_maxbytes,
>  +                                    i_size_read(realinode));
>  +}
>  +
>  +static void ovl_file_accessed(struct file *file)
>  +{
>  +    struct inode *inode, *upperinode;
>  +
>  +    if (file->f_flags & O_NOATIME)
>  +            return;
>  +
>  +    inode = file_inode(file);
>  +    upperinode = ovl_inode_upper(inode);
>  +
>  +    if (!upperinode)
>  +            return;
>  +
> -     if ((!timespec_equal(&inode->i_mtime, &upperinode->i_mtime) ||
> -          !timespec_equal(&inode->i_ctime, &upperinode->i_ctime))) {
> ++    if ((!timespec64_equal(&inode->i_mtime, &upperinode->i_mtime) ||
> ++         !timespec64_equal(&inode->i_ctime, &upperinode->i_ctime))) {
>  +            inode->i_mtime = upperinode->i_mtime;
>  +            inode->i_ctime = upperinode->i_ctime;
>  +    }
>  +
>  +    touch_atime(&file->f_path);
>  +}
>  +
>  +static rwf_t ovl_iocb_to_rwf(struct kiocb *iocb)
>  +{
>  +    int ifl = iocb->ki_flags;
>  +    rwf_t flags = 0;
>  +
>  +    if (ifl & IOCB_NOWAIT)
>  +            flags |= RWF_NOWAIT;
>  +    if (ifl & IOCB_HIPRI)
>  +            flags |= RWF_HIPRI;
>  +    if (ifl & IOCB_DSYNC)
>  +            flags |= RWF_DSYNC;
>  +    if (ifl & IOCB_SYNC)
>  +            flags |= RWF_SYNC;
>  +
>  +    return flags;
>  +}
>  +
>  +static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
>  +{
>  +    struct file *file = iocb->ki_filp;
>  +    struct fd real;
>  +    const struct cred *old_cred;
>  +    ssize_t ret;
>  +
>  +    if (!iov_iter_count(iter))
>  +            return 0;
>  +
>  +    ret = ovl_real_fdget(file, &real);
>  +    if (ret)
>  +            return ret;
>  +
>  +    old_cred = ovl_override_creds(file_inode(file)->i_sb);
>  +    ret = vfs_iter_read(real.file, iter, &iocb->ki_pos,
>  +                        ovl_iocb_to_rwf(iocb));
>  +    revert_creds(old_cred);
>  +
>  +    ovl_file_accessed(file);
>  +
>  +    fdput(real);
>  +
>  +    return ret;
>  +}
>  +
>  +static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
>  +{
>  +    struct file *file = iocb->ki_filp;
>  +    struct inode *inode = file_inode(file);
>  +    struct fd real;
>  +    const struct cred *old_cred;
>  +    ssize_t ret;
>  +
>  +    if (!iov_iter_count(iter))
>  +            return 0;
>  +
>  +    inode_lock(inode);
>  +    /* Update mode */
>  +    ovl_copyattr(ovl_inode_real(inode), inode);
>  +    ret = file_remove_privs(file);
>  +    if (ret)
>  +            goto out_unlock;
>  +
>  +    ret = ovl_real_fdget(file, &real);
>  +    if (ret)
>  +            goto out_unlock;
>  +
>  +    old_cred = ovl_override_creds(file_inode(file)->i_sb);
>  +    ret = vfs_iter_write(real.file, iter, &iocb->ki_pos,
>  +                         ovl_iocb_to_rwf(iocb));
>  +    revert_creds(old_cred);
>  +
>  +    /* Update size */
>  +    ovl_copyattr(ovl_inode_real(inode), inode);
>  +
>  +    fdput(real);
>  +
>  +out_unlock:
>  +    inode_unlock(inode);
>  +
>  +    return ret;
>  +}
>  +
>  +static int ovl_fsync(struct file *file, loff_t start, loff_t end, int 
> datasync)
>  +{
>  +    struct fd real;
>  +    const struct cred *old_cred;
>  +    int ret;
>  +
>  +    ret = ovl_real_fdget_meta(file, &real, !datasync);
>  +    if (ret)
>  +            return ret;
>  +
>  +    /* Don't sync lower file for fear of receiving EROFS error */
>  +    if (file_inode(real.file) == ovl_inode_upper(file_inode(file))) {
>  +            old_cred = ovl_override_creds(file_inode(file)->i_sb);
>  +            ret = vfs_fsync_range(real.file, start, end, datasync);
>  +            revert_creds(old_cred);
>  +    }
>  +
>  +    fdput(real);
>  +
>  +    return ret;
>  +}
>  +
>  +static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
>  +{
>  +    struct fd real;
>  +    const struct cred *old_cred;
>  +    int ret;
>  +
>  +    ret = ovl_real_fdget(file, &real);
>  +    if (ret)
>  +            return ret;
>  +
>  +    /* transfer ref: */
>  +    fput(vma->vm_file);
>  +    vma->vm_file = get_file(real.file);
>  +    fdput(real);
>  +
>  +    if (!vma->vm_file->f_op->mmap)
>  +            return -ENODEV;
>  +
>  +    old_cred = ovl_override_creds(file_inode(file)->i_sb);
>  +    ret = call_mmap(vma->vm_file, vma);
>  +    revert_creds(old_cred);
>  +
>  +    ovl_file_accessed(file);
>  +
>  +    return ret;
>  +}
>  +
>  +static long ovl_fallocate(struct file *file, int mode, loff_t offset, 
> loff_t len)
>  +{
>  +    struct inode *inode = file_inode(file);
>  +    struct fd real;
>  +    const struct cred *old_cred;
>  +    int ret;
>  +
>  +    ret = ovl_real_fdget(file, &real);
>  +    if (ret)
>  +            return ret;
>  +
>  +    old_cred = ovl_override_creds(file_inode(file)->i_sb);
>  +    ret = vfs_fallocate(real.file, mode, offset, len);
>  +    revert_creds(old_cred);
>  +
>  +    /* Update size */
>  +    ovl_copyattr(ovl_inode_real(inode), inode);
>  +
>  +    fdput(real);
>  +
>  +    return ret;
>  +}
>  +
>  +static long ovl_real_ioctl(struct file *file, unsigned int cmd,
>  +                       unsigned long arg)
>  +{
>  +    struct fd real;
>  +    const struct cred *old_cred;
>  +    long ret;
>  +
>  +    ret = ovl_real_fdget(file, &real);
>  +    if (ret)
>  +            return ret;
>  +
>  +    old_cred = ovl_override_creds(file_inode(file)->i_sb);
>  +    ret = vfs_ioctl(real.file, cmd, arg);
>  +    revert_creds(old_cred);
>  +
>  +    fdput(real);
>  +
>  +    return ret;
>  +}
>  +
>  +static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long 
> arg)
>  +{
>  +    long ret;
>  +    struct inode *inode = file_inode(file);
>  +
>  +    switch (cmd) {
>  +    case FS_IOC_GETFLAGS:
>  +            ret = ovl_real_ioctl(file, cmd, arg);
>  +            break;
>  +
>  +    case FS_IOC_SETFLAGS:
>  +            if (!inode_owner_or_capable(inode))
>  +                    return -EACCES;
>  +
>  +            ret = mnt_want_write_file(file);
>  +            if (ret)
>  +                    return ret;
>  +
>  +            ret = ovl_copy_up_with_data(file_dentry(file));
>  +            if (!ret) {
>  +                    ret = ovl_real_ioctl(file, cmd, arg);
>  +
>  +                    inode_lock(inode);
>  +                    ovl_copyflags(ovl_inode_real(inode), inode);
>  +                    inode_unlock(inode);
>  +            }
>  +
>  +            mnt_drop_write_file(file);
>  +            break;
>  +
>  +    default:
>  +            ret = -ENOTTY;
>  +    }
>  +
>  +    return ret;
>  +}
>  +
>  +static long ovl_compat_ioctl(struct file *file, unsigned int cmd,
>  +                         unsigned long arg)
>  +{
>  +    switch (cmd) {
>  +    case FS_IOC32_GETFLAGS:
>  +            cmd = FS_IOC_GETFLAGS;
>  +            break;
>  +
>  +    case FS_IOC32_SETFLAGS:
>  +            cmd = FS_IOC_SETFLAGS;
>  +            break;
>  +
>  +    default:
>  +            return -ENOIOCTLCMD;
>  +    }
>  +
>  +    return ovl_ioctl(file, cmd, arg);
>  +}
>  +
>  +enum ovl_copyop {
>  +    OVL_COPY,
>  +    OVL_CLONE,
>  +    OVL_DEDUPE,
>  +};
>  +
>  +static s64 ovl_copyfile(struct file *file_in, loff_t pos_in,
>  +                    struct file *file_out, loff_t pos_out,
>  +                    u64 len, unsigned int flags, enum ovl_copyop op)
>  +{
>  +    struct inode *inode_out = file_inode(file_out);
>  +    struct fd real_in, real_out;
>  +    const struct cred *old_cred;
>  +    s64 ret;
>  +
>  +    ret = ovl_real_fdget(file_out, &real_out);
>  +    if (ret)
>  +            return ret;
>  +
>  +    ret = ovl_real_fdget(file_in, &real_in);
>  +    if (ret) {
>  +            fdput(real_out);
>  +            return ret;
>  +    }
>  +
>  +    old_cred = ovl_override_creds(file_inode(file_out)->i_sb);
>  +    switch (op) {
>  +    case OVL_COPY:
>  +            ret = vfs_copy_file_range(real_in.file, pos_in,
>  +                                      real_out.file, pos_out, len, flags);
>  +            break;
>  +
>  +    case OVL_CLONE:
>  +            ret = vfs_clone_file_range(real_in.file, pos_in,
>  +                                       real_out.file, pos_out, len);
>  +            break;
>  +
>  +    case OVL_DEDUPE:
>  +            ret = vfs_dedupe_file_range_one(real_in.file, pos_in,
>  +                                            real_out.file, pos_out, len);
>  +            break;
>  +    }
>  +    revert_creds(old_cred);
>  +
>  +    /* Update size */
>  +    ovl_copyattr(ovl_inode_real(inode_out), inode_out);
>  +
>  +    fdput(real_in);
>  +    fdput(real_out);
>  +
>  +    return ret;
>  +}
>  +
>  +static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in,
>  +                               struct file *file_out, loff_t pos_out,
>  +                               size_t len, unsigned int flags)
>  +{
>  +    return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
>  +                        OVL_COPY);
>  +}
>  +
>  +static int ovl_clone_file_range(struct file *file_in, loff_t pos_in,
>  +                            struct file *file_out, loff_t pos_out, u64 len)
>  +{
>  +    return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0,
>  +                        OVL_CLONE);
>  +}
>  +
>  +static loff_t ovl_dedupe_file_range(struct file *file_in, loff_t pos_in,
>  +                                struct file *file_out, loff_t pos_out,
>  +                                loff_t len)
>  +{
>  +    /*
>  +     * Don't copy up because of a dedupe request, this wouldn't make sense
>  +     * most of the time (data would be duplicated instead of deduplicated).
>  +     */
>  +    if (!ovl_inode_upper(file_inode(file_in)) ||
>  +        !ovl_inode_upper(file_inode(file_out)))
>  +            return -EPERM;
>  +
>  +    return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0,
>  +                        OVL_DEDUPE);
>  +}
>  +
>  +const struct file_operations ovl_file_operations = {
>  +    .open           = ovl_open,
>  +    .release        = ovl_release,
>  +    .llseek         = ovl_llseek,
>  +    .read_iter      = ovl_read_iter,
>  +    .write_iter     = ovl_write_iter,
>  +    .fsync          = ovl_fsync,
>  +    .mmap           = ovl_mmap,
>  +    .fallocate      = ovl_fallocate,
>  +    .unlocked_ioctl = ovl_ioctl,
>  +    .compat_ioctl   = ovl_compat_ioctl,
>  +
>  +    .copy_file_range        = ovl_copy_file_range,
>  +    .clone_file_range       = ovl_clone_file_range,
>  +    .dedupe_file_range      = ovl_dedupe_file_range,
>  +};
> diff --cc fs/overlayfs/inode.c
> index e31d64206a01,d7cca60f28e6..e0bb217c01e2
> --- a/fs/overlayfs/inode.c
> +++ b/fs/overlayfs/inode.c
> @@@ -439,7 -384,39 +439,7 @@@ struct posix_acl *ovl_get_acl(struct in
>       return acl;
>   }
>   
> - int ovl_update_time(struct inode *inode, struct timespec *ts, int flags)
>  -static bool ovl_open_need_copy_up(struct dentry *dentry, int flags)
>  -{
>  -    /* Copy up of disconnected dentry does not set upper alias */
>  -    if (ovl_dentry_upper(dentry) &&
>  -        (ovl_dentry_has_upper_alias(dentry) ||
>  -         (dentry->d_flags & DCACHE_DISCONNECTED)))
>  -            return false;
>  -
>  -    if (special_file(d_inode(dentry)->i_mode))
>  -            return false;
>  -
>  -    if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC))
>  -            return false;
>  -
>  -    return true;
>  -}
>  -
>  -int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
>  -{
>  -    int err = 0;
>  -
>  -    if (ovl_open_need_copy_up(dentry, file_flags)) {
>  -            err = ovl_want_write(dentry);
>  -            if (!err) {
>  -                    err = ovl_copy_up_flags(dentry, file_flags);
>  -                    ovl_drop_write(dentry);
>  -            }
>  -    }
>  -
>  -    return err;
>  -}
>  -
> + int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags)
>   {
>       if (flags & S_ATIME) {
>               struct ovl_fs *ofs = inode->i_sb->s_fs_info;
> diff --cc fs/overlayfs/overlayfs.h
> index ac9fbc3d08ea,9fe10247f9d4..f61839e1054c
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@@ -349,18 -330,10 +349,18 @@@ int ovl_xattr_get(struct dentry *dentry
>                 void *value, size_t size);
>   ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
>   struct posix_acl *ovl_get_acl(struct inode *inode, int type);
> - int ovl_update_time(struct inode *inode, struct timespec *ts, int flags);
>  -int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
> + int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
>   bool ovl_is_private_xattr(const char *name);
>   
>  +struct ovl_inode_params {
>  +    struct inode *newinode;
>  +    struct dentry *upperdentry;
>  +    struct ovl_path *lowerpath;
>  +    struct dentry *index;
>  +    unsigned int numlower;
>  +    char *redirect;
>  +    struct dentry *lowerdata;
>  +};
>   struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t 
> rdev);
>   struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
>                              bool is_upper);



-- 
Cheers,
Stephen Rothwell

Attachment: pgpK33Wcf_1kL.pgp
Description: OpenPGP digital signature

Reply via email to