Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Linus Torvalds committed Jan 15, 2017
2 parents 34241af + b9dc6f6 commit f4d3935
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 30 deletions.
6 changes: 4 additions & 2 deletions fs/aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1085,7 +1085,8 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2)
* Tell lockdep we inherited freeze protection from submission
* 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);
}

Expand Down Expand Up @@ -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
* 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);
return ret;
Expand Down
1 change: 1 addition & 0 deletions fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2298,6 +2298,7 @@ static int elf_core_dump(struct coredump_params *cprm)
goto end_coredump;
}
}
dump_truncate(cprm);

if (!elf_core_write_extra_data(cprm))
goto end_coredump;
Expand Down
18 changes: 18 additions & 0 deletions fs/coredump.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,3 +833,21 @@ int dump_align(struct coredump_params *cprm, int align)
return mod ? dump_skip(cprm, align - mod) : 1;
}
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);
9 changes: 4 additions & 5 deletions fs/posix_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -922,11 +922,10 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
int error;

if (type == ACL_TYPE_ACCESS) {
error = posix_acl_equiv_mode(acl, &inode->i_mode);
if (error < 0)
return 0;
if (error == 0)
acl = NULL;
error = posix_acl_update_mode(inode,
&inode->i_mode, &acl);
if (error)
return error;
}

inode->i_ctime = current_time(inode);
Expand Down
1 change: 1 addition & 0 deletions include/linux/coredump.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct coredump_params;
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_align(struct coredump_params *cprm, int align);
extern void dump_truncate(struct coredump_params *cprm);
#ifdef CONFIG_COREDUMP
extern void do_coredump(const siginfo_t *siginfo);
#else
Expand Down
54 changes: 31 additions & 23 deletions lib/iov_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,43 +730,50 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
}
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)
{
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))
size = i->count;
orig_sz = 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 */
size += off - pipe->bufs[idx].offset;
left += off - pipe->bufs[idx].offset;
while (1) {
buf = &pipe->bufs[idx];
if (size <= buf->len)
if (left <= buf->len)
break;
size -= buf->len;
left -= buf->len;
idx = next_idx(idx, pipe);
}
buf->len = size;
i->idx = idx;
off = i->iov_offset = buf->offset + size;
}
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->iov_offset = buf->offset + left;
}
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)
Expand Down Expand Up @@ -826,6 +833,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction,
size_t count)
{
BUG_ON(direction != ITER_PIPE);
WARN_ON(pipe->nrbufs == pipe->buffers);
i->type = direction;
i->pipe = pipe;
i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
Expand Down

0 comments on commit f4d3935

Please sign in to comment.