[incremental to the previous] Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- fs/overlayfs/file.c | 113 +++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 58 deletions(-) diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index a0ab981b13d9..e10a009d32e7 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -268,6 +268,15 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) &ctx); } +static ssize_t ovl_write_locked(struct kiocb *iocb, struct iov_iter *iter, int ifl, + struct backing_file_ctx *ctx) +{ + CLASS(fd_real, real)(ctx->user_file); + if (fd_empty(real)) + return fd_err(real); + return backing_file_write_iter(fd_file(real), iter, iocb, ifl, ctx); +} + static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) { struct file *file = iocb->ki_filp; @@ -287,14 +296,6 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) /* Update mode */ ovl_copyattr(inode); - { - - CLASS(fd_real, real)(file); - if (fd_empty(real)) { - ret = fd_err(real); - goto out_unlock; - } - if (!ovl_should_sync(OVL_FS(inode->i_sb))) ifl &= ~(IOCB_DSYNC | IOCB_SYNC); @@ -303,11 +304,8 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) * this property in case it is set by the issuer. */ ifl &= ~IOCB_DIO_CALLER_COMP; - ret = backing_file_write_iter(fd_file(real), iter, iocb, ifl, &ctx); - - } + ret = ovl_write_locked(iocb, iter, ifl, &ctx); -out_unlock: inode_unlock(inode); return ret; @@ -331,6 +329,16 @@ static ssize_t ovl_splice_read(struct file *in, loff_t *ppos, &ctx); } +static ssize_t ovl_splice_locked(struct pipe_inode_info *pipe, + loff_t *ppos, size_t len, unsigned int flags, + struct backing_file_ctx *ctx) +{ + CLASS(fd_real, real)(ctx->user_file); + if (fd_empty(real)) + return fd_err(real); + return backing_file_splice_write(pipe, fd_file(real), ppos, len, flags, ctx); +} + /* * Calling iter_file_splice_write() directly from overlay's f_op may deadlock * due to lock order inversion between pipe->mutex in iter_file_splice_write() @@ -353,19 +361,7 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out, inode_lock(inode); /* Update mode */ ovl_copyattr(inode); - - { - - CLASS(fd_real, real)(out); - if (fd_empty(real)) { - ret = fd_err(real); - goto out_unlock; - } - - ret = backing_file_splice_write(pipe, fd_file(real), ppos, len, flags, &ctx); - - } -out_unlock: + ret = ovl_splice_locked(pipe, ppos, len, flags, &ctx); inode_unlock(inode); return ret; @@ -409,25 +405,14 @@ static int ovl_mmap(struct file *file, struct vm_area_struct *vma) return backing_file_mmap(realfile, vma, &ctx); } -static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len) +static long ovl_fallocate_locked(struct file *file, int mode, loff_t offset, loff_t len) { - struct inode *inode = file_inode(file); const struct cred *old_cred; int ret; - inode_lock(inode); - /* Update mode */ - ovl_copyattr(inode); - ret = file_remove_privs(file); - if (ret) - goto out_unlock; - { - CLASS(fd_real, real)(file); - if (fd_empty(real)) { - ret = fd_err(real); - goto out_unlock; - } + if (fd_empty(real)) + return fd_err(real); old_cred = ovl_override_creds(file_inode(file)->i_sb); ret = vfs_fallocate(fd_file(real), mode, offset, len); @@ -435,9 +420,20 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len /* Update size */ ovl_file_modified(file); + return ret; +} - } -out_unlock: +static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len) +{ + struct inode *inode = file_inode(file); + int ret; + + inode_lock(inode); + /* Update mode */ + ovl_copyattr(inode); + ret = file_remove_privs(file); + if (!ret) + ret = ovl_fallocate_locked(file, mode, offset, len); inode_unlock(inode); return ret; @@ -465,36 +461,28 @@ enum ovl_copyop { OVL_DEDUPE, }; -static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, +static loff_t ovl_copyfile_locked(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t len, unsigned int flags, enum ovl_copyop op) { - struct inode *inode_out = file_inode(file_out); const struct cred *old_cred; loff_t ret; - inode_lock(inode_out); if (op != OVL_DEDUPE) { /* Update mode */ - ovl_copyattr(inode_out); + ovl_copyattr(file_inode(file_out)); ret = file_remove_privs(file_out); if (ret) - goto out_unlock; + return ret; } - { - CLASS(fd_real, real_out)(file_out); - if (fd_empty(real_out)) { - ret = fd_err(real_out); - goto out_unlock; - } + if (fd_empty(real_out)) + return fd_err(real_out); CLASS(fd_real, real_in)(file_in); - if (fd_empty(real_in)) { - ret = fd_err(real_in); - goto out_unlock; - } + if (fd_empty(real_in)) + return fd_err(real_in); old_cred = ovl_override_creds(file_inode(file_out)->i_sb); switch (op) { @@ -518,10 +506,19 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, /* Update size */ ovl_file_modified(file_out); + return ret; +} - } +static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + loff_t len, unsigned int flags, enum ovl_copyop op) +{ + struct inode *inode_out = file_inode(file_out); + loff_t ret; -out_unlock: + inode_lock(inode_out); + ret = ovl_copyfile_locked(file_in, pos_in, file_out, pos_out, + len, flags, op); inode_unlock(inode_out); return ret; -- 2.39.5