Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2019 20:27:20 +0000 (13:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2019 20:27:20 +0000 (13:27 -0700)
Pull misc vfs updates from Al Viro:
 "Assorted fixes (really no common topic here)"

* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  vfs: Make __vfs_write() static
  vfs: fix preadv64v2 and pwritev64v2 compat syscalls with offset == -1
  pipe: stop using ->can_merge
  splice: don't merge into linked buffers
  fs: move generic stat response attr handling to vfs_getattr_nosec
  orangefs: don't reinitialize result_mask in ->getattr
  fs/devpts: always delete dcache dentry-s in dput()

fs/devpts/inode.c
fs/orangefs/inode.c
fs/pipe.c
fs/read_write.c
fs/splice.c
fs/stat.c
include/linux/pipe_fs_i.h
kernel/relay.c
kernel/trace/trace.c
net/smc/smc_rx.c

index c53814539070d5ac5d2196e2f4b7383055e11dd1..553a3f3300ae5ef584bc2e3c30bd49f4923ab3ed 100644 (file)
@@ -455,6 +455,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
        s->s_blocksize_bits = 10;
        s->s_magic = DEVPTS_SUPER_MAGIC;
        s->s_op = &devpts_sops;
+       s->s_d_op = &simple_dentry_operations;
        s->s_time_gran = 1;
 
        error = -ENOMEM;
index f038235c64bdf6d840f0d37fde29818ffa5c6e65..c3334eca18c7e95358224c4ecaec73b2d123152d 100644 (file)
@@ -261,11 +261,8 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
                generic_fillattr(inode, stat);
 
                /* override block size reported to stat */
-               if (request_mask & STATX_SIZE)
-                       stat->result_mask = STATX_BASIC_STATS;
-               else
-                       stat->result_mask = STATX_BASIC_STATS &
-                           ~STATX_SIZE;
+               if (!(request_mask & STATX_SIZE))
+                       stat->result_mask &= ~STATX_SIZE;
 
                stat->attributes_mask = STATX_ATTR_IMMUTABLE |
                    STATX_ATTR_APPEND;
index 51d5fd8840abd895b7d39c8ca0c22770615bfa7b..070aad543382a4e30aa0bd5eef94b5dabba7219d 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -225,8 +225,15 @@ void generic_pipe_buf_release(struct pipe_inode_info *pipe,
 }
 EXPORT_SYMBOL(generic_pipe_buf_release);
 
+/* New data written to a pipe may be appended to a buffer with this type. */
 static const struct pipe_buf_operations anon_pipe_buf_ops = {
-       .can_merge = 1,
+       .confirm = generic_pipe_buf_confirm,
+       .release = anon_pipe_buf_release,
+       .steal = anon_pipe_buf_steal,
+       .get = generic_pipe_buf_get,
+};
+
+static const struct pipe_buf_operations anon_pipe_buf_nomerge_ops = {
        .confirm = generic_pipe_buf_confirm,
        .release = anon_pipe_buf_release,
        .steal = anon_pipe_buf_steal,
@@ -234,13 +241,32 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
 };
 
 static const struct pipe_buf_operations packet_pipe_buf_ops = {
-       .can_merge = 0,
        .confirm = generic_pipe_buf_confirm,
        .release = anon_pipe_buf_release,
        .steal = anon_pipe_buf_steal,
        .get = generic_pipe_buf_get,
 };
 
+/**
+ * pipe_buf_mark_unmergeable - mark a &struct pipe_buffer as unmergeable
+ * @buf:       the buffer to mark
+ *
+ * Description:
+ *     This function ensures that no future writes will be merged into the
+ *     given &struct pipe_buffer. This is necessary when multiple pipe buffers
+ *     share the same backing page.
+ */
+void pipe_buf_mark_unmergeable(struct pipe_buffer *buf)
+{
+       if (buf->ops == &anon_pipe_buf_ops)
+               buf->ops = &anon_pipe_buf_nomerge_ops;
+}
+
+static bool pipe_buf_can_merge(struct pipe_buffer *buf)
+{
+       return buf->ops == &anon_pipe_buf_ops;
+}
+
 static ssize_t
 pipe_read(struct kiocb *iocb, struct iov_iter *to)
 {
@@ -378,7 +404,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
                struct pipe_buffer *buf = pipe->bufs + lastbuf;
                int offset = buf->offset + buf->len;
 
-               if (buf->ops->can_merge && offset + chars <= PAGE_SIZE) {
+               if (pipe_buf_can_merge(buf) && offset + chars <= PAGE_SIZE) {
                        ret = pipe_buf_confirm(pipe, buf);
                        if (ret)
                                goto out;
index 30df848b7451468649d86ed9080b99df9fbf99cb..177ccc3d405a33b425998e400b105418d8f537a4 100644 (file)
@@ -478,8 +478,8 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
        return ret;
 }
 
-ssize_t __vfs_write(struct file *file, const char __user *p, size_t count,
-                   loff_t *pos)
+static ssize_t __vfs_write(struct file *file, const char __user *p,
+                          size_t count, loff_t *pos)
 {
        if (file->f_op->write)
                return file->f_op->write(file, p, count, pos);
@@ -1238,6 +1238,9 @@ COMPAT_SYSCALL_DEFINE5(preadv64v2, unsigned long, fd,
                const struct compat_iovec __user *,vec,
                unsigned long, vlen, loff_t, pos, rwf_t, flags)
 {
+       if (pos == -1)
+               return do_compat_readv(fd, vec, vlen, flags);
+
        return do_compat_preadv64(fd, vec, vlen, pos, flags);
 }
 #endif
@@ -1344,6 +1347,9 @@ COMPAT_SYSCALL_DEFINE5(pwritev64v2, unsigned long, fd,
                const struct compat_iovec __user *,vec,
                unsigned long, vlen, loff_t, pos, rwf_t, flags)
 {
+       if (pos == -1)
+               return do_compat_writev(fd, vec, vlen, flags);
+
        return do_compat_pwritev64(fd, vec, vlen, pos, flags);
 }
 #endif
index 6489fb9436e4a88880d939e21db903b5f2d0ccfe..3ee7e82df48f2b14d09ddd3b4877879e90f8c418 100644 (file)
@@ -138,7 +138,6 @@ error:
 }
 
 const struct pipe_buf_operations page_cache_pipe_buf_ops = {
-       .can_merge = 0,
        .confirm = page_cache_pipe_buf_confirm,
        .release = page_cache_pipe_buf_release,
        .steal = page_cache_pipe_buf_steal,
@@ -156,7 +155,6 @@ static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
 }
 
 static const struct pipe_buf_operations user_page_pipe_buf_ops = {
-       .can_merge = 0,
        .confirm = generic_pipe_buf_confirm,
        .release = page_cache_pipe_buf_release,
        .steal = user_page_pipe_buf_steal,
@@ -326,7 +324,6 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
 EXPORT_SYMBOL(generic_file_splice_read);
 
 const struct pipe_buf_operations default_pipe_buf_ops = {
-       .can_merge = 0,
        .confirm = generic_pipe_buf_confirm,
        .release = generic_pipe_buf_release,
        .steal = generic_pipe_buf_steal,
@@ -341,7 +338,6 @@ static int generic_pipe_buf_nosteal(struct pipe_inode_info *pipe,
 
 /* Pipe buffer operations for a socket and similar. */
 const struct pipe_buf_operations nosteal_pipe_buf_ops = {
-       .can_merge = 0,
        .confirm = generic_pipe_buf_confirm,
        .release = generic_pipe_buf_release,
        .steal = generic_pipe_buf_nosteal,
@@ -1606,6 +1602,8 @@ retry:
                         */
                        obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
 
+                       pipe_buf_mark_unmergeable(obuf);
+
                        obuf->len = len;
                        opipe->nrbufs++;
                        ibuf->offset += obuf->len;
@@ -1680,6 +1678,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
                 */
                obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
 
+               pipe_buf_mark_unmergeable(obuf);
+
                if (obuf->len > len)
                        obuf->len = len;
 
index adbfcd86c81b7761e6534f9cfb82f725568f0614..c38e4c2e1221cdca2cd4178e9266b14e9cf52cbb 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -45,11 +45,6 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
        stat->ctime = inode->i_ctime;
        stat->blksize = i_blocksize(inode);
        stat->blocks = inode->i_blocks;
-
-       if (IS_NOATIME(inode))
-               stat->result_mask &= ~STATX_ATIME;
-       if (IS_AUTOMOUNT(inode))
-               stat->attributes |= STATX_ATTR_AUTOMOUNT;
 }
 EXPORT_SYMBOL(generic_fillattr);
 
@@ -75,6 +70,13 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
        stat->result_mask |= STATX_BASIC_STATS;
        request_mask &= STATX_ALL;
        query_flags &= KSTAT_QUERY_FLAGS;
+
+       /* allow the fs to override these if it really wants to */
+       if (IS_NOATIME(inode))
+               stat->result_mask &= ~STATX_ATIME;
+       if (IS_AUTOMOUNT(inode))
+               stat->attributes |= STATX_ATTR_AUTOMOUNT;
+
        if (inode->i_op->getattr)
                return inode->i_op->getattr(path, stat, request_mask,
                                            query_flags);
index 5a3bb3b7c9ad3fb287e3133d81cd52b0def6bdde..787d224ff43e1fc72ceed0164bf26a4f2fa08794 100644 (file)
@@ -73,13 +73,6 @@ struct pipe_inode_info {
  * in fs/pipe.c for the pipe and generic variants of these hooks.
  */
 struct pipe_buf_operations {
-       /*
-        * This is set to 1, if the generic pipe read/write may coalesce
-        * data into an existing buffer. If this is set to 0, a new pipe
-        * page segment is always used for new data.
-        */
-       int can_merge;
-
        /*
         * ->confirm() verifies that the data in the pipe buffer is there
         * and that the contents are good. If the pages in the pipe belong
@@ -182,6 +175,7 @@ void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
 int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
 int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
 void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *);
+void pipe_buf_mark_unmergeable(struct pipe_buffer *buf);
 
 extern const struct pipe_buf_operations nosteal_pipe_buf_ops;
 
index 9e0f52375487d7be47ee4c265ee0cbd5227186d0..ade14fb7ce2e60cc676f7807daa0302ce24e7b79 100644 (file)
@@ -1177,7 +1177,6 @@ static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
 }
 
 static const struct pipe_buf_operations relay_pipe_buf_ops = {
-       .can_merge = 0,
        .confirm = generic_pipe_buf_confirm,
        .release = relay_pipe_buf_release,
        .steal = generic_pipe_buf_steal,
index d7325eb1bc83585fb0b0cac0827ab94d1c7f1735..94ffc1c559d51613fd92c226a61aeb6051148aa7 100644 (file)
@@ -6023,7 +6023,6 @@ static void tracing_spd_release_pipe(struct splice_pipe_desc *spd,
 }
 
 static const struct pipe_buf_operations tracing_pipe_buf_ops = {
-       .can_merge              = 0,
        .confirm                = generic_pipe_buf_confirm,
        .release                = generic_pipe_buf_release,
        .steal                  = generic_pipe_buf_steal,
@@ -7050,7 +7049,6 @@ static void buffer_pipe_buf_get(struct pipe_inode_info *pipe,
 
 /* Pipe buffer operations for a buffer. */
 static const struct pipe_buf_operations buffer_pipe_buf_ops = {
-       .can_merge              = 0,
        .confirm                = generic_pipe_buf_confirm,
        .release                = buffer_pipe_buf_release,
        .steal                  = generic_pipe_buf_steal,
index bbcf0fe4ae10f631a84a2379d1c075f087db7037..413a6abf227ef13dacc8c6c20ccb92aa953a1bf0 100644 (file)
@@ -136,7 +136,6 @@ static int smc_rx_pipe_buf_nosteal(struct pipe_inode_info *pipe,
 }
 
 static const struct pipe_buf_operations smc_pipe_ops = {
-       .can_merge = 0,
        .confirm = generic_pipe_buf_confirm,
        .release = smc_rx_pipe_buf_release,
        .steal = smc_rx_pipe_buf_nosteal,