Commit f4d3935e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fixes from Al Viro.

The most notable fix here is probably the fix for a splice regression
("fix a fencepost error in pipe_advance()") noticed by Alan Wylie.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  fix a fencepost error in pipe_advance()
  coredump: Ensure proper size of sparse core files
  aio: fix lock dep warning
  tmpfs: clear S_ISGID when setting posix ACLs
parents 34241af7 b9dc6f65
...@@ -1085,7 +1085,8 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2) ...@@ -1085,7 +1085,8 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2)
* Tell lockdep we inherited freeze protection from submission * Tell lockdep we inherited freeze protection from submission
* thread. * thread.
*/ */
__sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE); if (S_ISREG(file_inode(file)->i_mode))
__sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
file_end_write(file); file_end_write(file);
} }
...@@ -1525,7 +1526,8 @@ static ssize_t aio_write(struct kiocb *req, struct iocb *iocb, bool vectored, ...@@ -1525,7 +1526,8 @@ static ssize_t aio_write(struct kiocb *req, struct iocb *iocb, bool vectored,
* by telling it the lock got released so that it doesn't * by telling it the lock got released so that it doesn't
* complain about held lock when we return to userspace. * complain about held lock when we return to userspace.
*/ */
__sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE); if (S_ISREG(file_inode(file)->i_mode))
__sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
} }
kfree(iovec); kfree(iovec);
return ret; return ret;
......
...@@ -2298,6 +2298,7 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2298,6 +2298,7 @@ static int elf_core_dump(struct coredump_params *cprm)
goto end_coredump; goto end_coredump;
} }
} }
dump_truncate(cprm);
if (!elf_core_write_extra_data(cprm)) if (!elf_core_write_extra_data(cprm))
goto end_coredump; goto end_coredump;
......
...@@ -833,3 +833,21 @@ int dump_align(struct coredump_params *cprm, int align) ...@@ -833,3 +833,21 @@ int dump_align(struct coredump_params *cprm, int align)
return mod ? dump_skip(cprm, align - mod) : 1; return mod ? dump_skip(cprm, align - mod) : 1;
} }
EXPORT_SYMBOL(dump_align); EXPORT_SYMBOL(dump_align);
/*
* Ensures that file size is big enough to contain the current file
* postion. This prevents gdb from complaining about a truncated file
* if the last "write" to the file was dump_skip.
*/
void dump_truncate(struct coredump_params *cprm)
{
struct file *file = cprm->file;
loff_t offset;
if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
offset = file->f_op->llseek(file, 0, SEEK_CUR);
if (i_size_read(file->f_mapping->host) < offset)
do_truncate(file->f_path.dentry, offset, 0, file);
}
}
EXPORT_SYMBOL(dump_truncate);
...@@ -922,11 +922,10 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type) ...@@ -922,11 +922,10 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
int error; int error;
if (type == ACL_TYPE_ACCESS) { if (type == ACL_TYPE_ACCESS) {
error = posix_acl_equiv_mode(acl, &inode->i_mode); error = posix_acl_update_mode(inode,
if (error < 0) &inode->i_mode, &acl);
return 0; if (error)
if (error == 0) return error;
acl = NULL;
} }
inode->i_ctime = current_time(inode); inode->i_ctime = current_time(inode);
......
...@@ -14,6 +14,7 @@ struct coredump_params; ...@@ -14,6 +14,7 @@ struct coredump_params;
extern int dump_skip(struct coredump_params *cprm, size_t nr); extern int dump_skip(struct coredump_params *cprm, size_t nr);
extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
extern int dump_align(struct coredump_params *cprm, int align); extern int dump_align(struct coredump_params *cprm, int align);
extern void dump_truncate(struct coredump_params *cprm);
#ifdef CONFIG_COREDUMP #ifdef CONFIG_COREDUMP
extern void do_coredump(const siginfo_t *siginfo); extern void do_coredump(const siginfo_t *siginfo);
#else #else
......
...@@ -730,43 +730,50 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, ...@@ -730,43 +730,50 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
} }
EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
static inline void pipe_truncate(struct iov_iter *i)
{
struct pipe_inode_info *pipe = i->pipe;
if (pipe->nrbufs) {
size_t off = i->iov_offset;
int idx = i->idx;
int nrbufs = (idx - pipe->curbuf) & (pipe->buffers - 1);
if (off) {
pipe->bufs[idx].len = off - pipe->bufs[idx].offset;
idx = next_idx(idx, pipe);
nrbufs++;
}
while (pipe->nrbufs > nrbufs) {
pipe_buf_release(pipe, &pipe->bufs[idx]);
idx = next_idx(idx, pipe);
pipe->nrbufs--;
}
}
}
static void pipe_advance(struct iov_iter *i, size_t size) static void pipe_advance(struct iov_iter *i, size_t size)
{ {
struct pipe_inode_info *pipe = i->pipe; struct pipe_inode_info *pipe = i->pipe;
struct pipe_buffer *buf;
int idx = i->idx;
size_t off = i->iov_offset, orig_sz;
if (unlikely(i->count < size)) if (unlikely(i->count < size))
size = i->count; size = i->count;
orig_sz = size;
if (size) { if (size) {
struct pipe_buffer *buf;
size_t off = i->iov_offset, left = size;
int idx = i->idx;
if (off) /* make it relative to the beginning of buffer */ if (off) /* make it relative to the beginning of buffer */
size += off - pipe->bufs[idx].offset; left += off - pipe->bufs[idx].offset;
while (1) { while (1) {
buf = &pipe->bufs[idx]; buf = &pipe->bufs[idx];
if (size <= buf->len) if (left <= buf->len)
break; break;
size -= buf->len; left -= buf->len;
idx = next_idx(idx, pipe); idx = next_idx(idx, pipe);
} }
buf->len = size;
i->idx = idx; i->idx = idx;
off = i->iov_offset = buf->offset + size; i->iov_offset = buf->offset + left;
}
if (off)
idx = next_idx(idx, pipe);
if (pipe->nrbufs) {
int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
/* [curbuf,unused) is in use. Free [idx,unused) */
while (idx != unused) {
pipe_buf_release(pipe, &pipe->bufs[idx]);
idx = next_idx(idx, pipe);
pipe->nrbufs--;
}
} }
i->count -= orig_sz; i->count -= size;
/* ... and discard everything past that point */
pipe_truncate(i);
} }
void iov_iter_advance(struct iov_iter *i, size_t size) void iov_iter_advance(struct iov_iter *i, size_t size)
...@@ -826,6 +833,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction, ...@@ -826,6 +833,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction,
size_t count) size_t count)
{ {
BUG_ON(direction != ITER_PIPE); BUG_ON(direction != ITER_PIPE);
WARN_ON(pipe->nrbufs == pipe->buffers);
i->type = direction; i->type = direction;
i->pipe = pipe; i->pipe = pipe;
i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment