]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 26 Jul 2019 13:23:19 +0000 (15:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 26 Jul 2019 13:23:19 +0000 (15:23 +0200)
added patches:
dma-buf-balance-refcount-inbalance.patch
dma-buf-discard-old-fence_excl-on-retrying-get_fences_rcu-for-realloc.patch
ext4-allow-directory-holes.patch
ext4-don-t-allow-any-modifications-to-an-immutable-file.patch
ext4-enforce-the-immutable-flag-on-open-files.patch
ext4-use-jbd2_inode-dirty-range-scoping.patch
jbd2-introduce-jbd2_inode-dirty-range-scoping.patch
mips-lb60-fix-pin-mappings.patch
mm-add-filemap_fdatawait_range_keep_errors.patch
perf-core-fix-exclusive-events-grouping.patch

queue-4.14/dma-buf-balance-refcount-inbalance.patch [new file with mode: 0644]
queue-4.14/dma-buf-discard-old-fence_excl-on-retrying-get_fences_rcu-for-realloc.patch [new file with mode: 0644]
queue-4.14/ext4-allow-directory-holes.patch [new file with mode: 0644]
queue-4.14/ext4-don-t-allow-any-modifications-to-an-immutable-file.patch [new file with mode: 0644]
queue-4.14/ext4-enforce-the-immutable-flag-on-open-files.patch [new file with mode: 0644]
queue-4.14/ext4-use-jbd2_inode-dirty-range-scoping.patch [new file with mode: 0644]
queue-4.14/jbd2-introduce-jbd2_inode-dirty-range-scoping.patch [new file with mode: 0644]
queue-4.14/mips-lb60-fix-pin-mappings.patch [new file with mode: 0644]
queue-4.14/mm-add-filemap_fdatawait_range_keep_errors.patch [new file with mode: 0644]
queue-4.14/perf-core-fix-exclusive-events-grouping.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/dma-buf-balance-refcount-inbalance.patch b/queue-4.14/dma-buf-balance-refcount-inbalance.patch
new file mode 100644 (file)
index 0000000..1771ed5
--- /dev/null
@@ -0,0 +1,42 @@
+From 5e383a9798990c69fc759a4930de224bb497e62c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Glisse?= <jglisse@redhat.com>
+Date: Thu, 6 Dec 2018 11:18:40 -0500
+Subject: dma-buf: balance refcount inbalance
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jérôme Glisse <jglisse@redhat.com>
+
+commit 5e383a9798990c69fc759a4930de224bb497e62c upstream.
+
+The debugfs take reference on fence without dropping them.
+
+Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: linux-media@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: linaro-mm-sig@lists.linaro.org
+Cc: Stéphane Marchesin <marcheu@chromium.org>
+Cc: stable@vger.kernel.org
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20181206161840.6578-1-jglisse@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/dma-buf.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/dma-buf/dma-buf.c
++++ b/drivers/dma-buf/dma-buf.c
+@@ -1115,6 +1115,7 @@ static int dma_buf_debug_show(struct seq
+                                  fence->ops->get_driver_name(fence),
+                                  fence->ops->get_timeline_name(fence),
+                                  dma_fence_is_signaled(fence) ? "" : "un");
++                      dma_fence_put(fence);
+               }
+               rcu_read_unlock();
diff --git a/queue-4.14/dma-buf-discard-old-fence_excl-on-retrying-get_fences_rcu-for-realloc.patch b/queue-4.14/dma-buf-discard-old-fence_excl-on-retrying-get_fences_rcu-for-realloc.patch
new file mode 100644 (file)
index 0000000..d407032
--- /dev/null
@@ -0,0 +1,45 @@
+From f5b07b04e5f090a85d1e96938520f2b2b58e4a8e Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Tue, 4 Jun 2019 13:53:23 +0100
+Subject: dma-buf: Discard old fence_excl on retrying get_fences_rcu for realloc
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit f5b07b04e5f090a85d1e96938520f2b2b58e4a8e upstream.
+
+If we have to drop the seqcount & rcu lock to perform a krealloc, we
+have to restart the loop. In doing so, be careful not to lose track of
+the already acquired exclusive fence.
+
+Fixes: fedf54132d24 ("dma-buf: Restart reservation_object_get_fences_rcu() after writes")
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: Sumit Semwal <sumit.semwal@linaro.org>
+Cc: stable@vger.kernel.org #v4.10
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190604125323.21396-1-chris@chris-wilson.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/reservation.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/dma-buf/reservation.c
++++ b/drivers/dma-buf/reservation.c
+@@ -394,6 +394,10 @@ int reservation_object_get_fences_rcu(st
+                                          GFP_NOWAIT | __GFP_NOWARN);
+                       if (!nshared) {
+                               rcu_read_unlock();
++
++                              dma_fence_put(fence_excl);
++                              fence_excl = NULL;
++
+                               nshared = krealloc(shared, sz, GFP_KERNEL);
+                               if (nshared) {
+                                       shared = nshared;
diff --git a/queue-4.14/ext4-allow-directory-holes.patch b/queue-4.14/ext4-allow-directory-holes.patch
new file mode 100644 (file)
index 0000000..f2f41f9
--- /dev/null
@@ -0,0 +1,198 @@
+From 4e19d6b65fb4fc42e352ce9883649e049da14743 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Thu, 20 Jun 2019 21:19:02 -0400
+Subject: ext4: allow directory holes
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 4e19d6b65fb4fc42e352ce9883649e049da14743 upstream.
+
+The largedir feature was intended to allow ext4 directories to have
+unmapped directory blocks (e.g., directory holes).  And so the
+released e2fsprogs no longer enforces this for largedir file systems;
+however, the corresponding change to the kernel-side code was not made.
+
+This commit fixes this oversight.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/dir.c   |   19 +++++++++----------
+ fs/ext4/namei.c |   45 +++++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 46 insertions(+), 18 deletions(-)
+
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -107,7 +107,6 @@ static int ext4_readdir(struct file *fil
+       struct inode *inode = file_inode(file);
+       struct super_block *sb = inode->i_sb;
+       struct buffer_head *bh = NULL;
+-      int dir_has_error = 0;
+       struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
+       if (ext4_encrypted_inode(inode)) {
+@@ -143,8 +142,6 @@ static int ext4_readdir(struct file *fil
+                       return err;
+       }
+-      offset = ctx->pos & (sb->s_blocksize - 1);
+-
+       while (ctx->pos < inode->i_size) {
+               struct ext4_map_blocks map;
+@@ -153,9 +150,18 @@ static int ext4_readdir(struct file *fil
+                       goto errout;
+               }
+               cond_resched();
++              offset = ctx->pos & (sb->s_blocksize - 1);
+               map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
+               map.m_len = 1;
+               err = ext4_map_blocks(NULL, inode, &map, 0);
++              if (err == 0) {
++                      /* m_len should never be zero but let's avoid
++                       * an infinite loop if it somehow is */
++                      if (map.m_len == 0)
++                              map.m_len = 1;
++                      ctx->pos += map.m_len * sb->s_blocksize;
++                      continue;
++              }
+               if (err > 0) {
+                       pgoff_t index = map.m_pblk >>
+                                       (PAGE_SHIFT - inode->i_blkbits);
+@@ -174,13 +180,6 @@ static int ext4_readdir(struct file *fil
+               }
+               if (!bh) {
+-                      if (!dir_has_error) {
+-                              EXT4_ERROR_FILE(file, 0,
+-                                              "directory contains a "
+-                                              "hole at offset %llu",
+-                                         (unsigned long long) ctx->pos);
+-                              dir_has_error = 1;
+-                      }
+                       /* corrupt size?  Maybe no more blocks to read */
+                       if (ctx->pos > inode->i_blocks << 9)
+                               break;
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -80,8 +80,18 @@ static struct buffer_head *ext4_append(h
+ static int ext4_dx_csum_verify(struct inode *inode,
+                              struct ext4_dir_entry *dirent);
++/*
++ * Hints to ext4_read_dirblock regarding whether we expect a directory
++ * block being read to be an index block, or a block containing
++ * directory entries (and if the latter, whether it was found via a
++ * logical block in an htree index block).  This is used to control
++ * what sort of sanity checkinig ext4_read_dirblock() will do on the
++ * directory block read from the storage device.  EITHER will means
++ * the caller doesn't know what kind of directory block will be read,
++ * so no specific verification will be done.
++ */
+ typedef enum {
+-      EITHER, INDEX, DIRENT
++      EITHER, INDEX, DIRENT, DIRENT_HTREE
+ } dirblock_type_t;
+ #define ext4_read_dirblock(inode, block, type) \
+@@ -107,11 +117,14 @@ static struct buffer_head *__ext4_read_d
+               return bh;
+       }
+-      if (!bh) {
++      if (!bh && (type == INDEX || type == DIRENT_HTREE)) {
+               ext4_error_inode(inode, func, line, block,
+-                               "Directory hole found");
++                               "Directory hole found for htree %s block",
++                               (type == INDEX) ? "index" : "leaf");
+               return ERR_PTR(-EFSCORRUPTED);
+       }
++      if (!bh)
++              return NULL;
+       dirent = (struct ext4_dir_entry *) bh->b_data;
+       /* Determine whether or not we have an index block */
+       if (is_dx(inode)) {
+@@ -978,7 +991,7 @@ static int htree_dirblock_to_tree(struct
+       dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
+                                                       (unsigned long)block));
+-      bh = ext4_read_dirblock(dir, block, DIRENT);
++      bh = ext4_read_dirblock(dir, block, DIRENT_HTREE);
+       if (IS_ERR(bh))
+               return PTR_ERR(bh);
+@@ -1508,7 +1521,7 @@ static struct buffer_head * ext4_dx_find
+               return (struct buffer_head *) frame;
+       do {
+               block = dx_get_block(frame->at);
+-              bh = ext4_read_dirblock(dir, block, DIRENT);
++              bh = ext4_read_dirblock(dir, block, DIRENT_HTREE);
+               if (IS_ERR(bh))
+                       goto errout;
+@@ -2088,6 +2101,11 @@ static int ext4_add_entry(handle_t *hand
+       blocks = dir->i_size >> sb->s_blocksize_bits;
+       for (block = 0; block < blocks; block++) {
+               bh = ext4_read_dirblock(dir, block, DIRENT);
++              if (bh == NULL) {
++                      bh = ext4_bread(handle, dir, block,
++                                      EXT4_GET_BLOCKS_CREATE);
++                      goto add_to_new_block;
++              }
+               if (IS_ERR(bh)) {
+                       retval = PTR_ERR(bh);
+                       bh = NULL;
+@@ -2108,6 +2126,7 @@ static int ext4_add_entry(handle_t *hand
+               brelse(bh);
+       }
+       bh = ext4_append(handle, dir, &block);
++add_to_new_block:
+       if (IS_ERR(bh)) {
+               retval = PTR_ERR(bh);
+               bh = NULL;
+@@ -2152,7 +2171,7 @@ again:
+               return PTR_ERR(frame);
+       entries = frame->entries;
+       at = frame->at;
+-      bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
++      bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT_HTREE);
+       if (IS_ERR(bh)) {
+               err = PTR_ERR(bh);
+               bh = NULL;
+@@ -2700,7 +2719,10 @@ bool ext4_empty_dir(struct inode *inode)
+               EXT4_ERROR_INODE(inode, "invalid size");
+               return true;
+       }
+-      bh = ext4_read_dirblock(inode, 0, EITHER);
++      /* The first directory block must not be a hole,
++       * so treat it as DIRENT_HTREE
++       */
++      bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
+       if (IS_ERR(bh))
+               return true;
+@@ -2722,6 +2744,10 @@ bool ext4_empty_dir(struct inode *inode)
+                       brelse(bh);
+                       lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
+                       bh = ext4_read_dirblock(inode, lblock, EITHER);
++                      if (bh == NULL) {
++                              offset += sb->s_blocksize;
++                              continue;
++                      }
+                       if (IS_ERR(bh))
+                               return true;
+                       de = (struct ext4_dir_entry_2 *) bh->b_data;
+@@ -3292,7 +3318,10 @@ static struct buffer_head *ext4_get_firs
+       struct buffer_head *bh;
+       if (!ext4_has_inline_data(inode)) {
+-              bh = ext4_read_dirblock(inode, 0, EITHER);
++              /* The first directory block must not be a hole, so
++               * treat it as DIRENT_HTREE
++               */
++              bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
+               if (IS_ERR(bh)) {
+                       *retval = PTR_ERR(bh);
+                       return NULL;
diff --git a/queue-4.14/ext4-don-t-allow-any-modifications-to-an-immutable-file.patch b/queue-4.14/ext4-don-t-allow-any-modifications-to-an-immutable-file.patch
new file mode 100644 (file)
index 0000000..0d76a49
--- /dev/null
@@ -0,0 +1,98 @@
+From 2e53840362771c73eb0a5ff71611507e64e8eecd Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <darrick.wong@oracle.com>
+Date: Sun, 9 Jun 2019 21:41:41 -0400
+Subject: ext4: don't allow any modifications to an immutable file
+
+From: Darrick J. Wong <darrick.wong@oracle.com>
+
+commit 2e53840362771c73eb0a5ff71611507e64e8eecd upstream.
+
+Don't allow any modifications to a file that's marked immutable, which
+means that we have to flush all the writable pages to make the readonly
+and we have to check the setattr/setflags parameters more closely.
+
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ioctl.c |   46 +++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 45 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -210,6 +210,29 @@ static int uuid_is_zero(__u8 u[16])
+ }
+ #endif
++/*
++ * If immutable is set and we are not clearing it, we're not allowed to change
++ * anything else in the inode.  Don't error out if we're only trying to set
++ * immutable on an immutable file.
++ */
++static int ext4_ioctl_check_immutable(struct inode *inode, __u32 new_projid,
++                                    unsigned int flags)
++{
++      struct ext4_inode_info *ei = EXT4_I(inode);
++      unsigned int oldflags = ei->i_flags;
++
++      if (!(oldflags & EXT4_IMMUTABLE_FL) || !(flags & EXT4_IMMUTABLE_FL))
++              return 0;
++
++      if ((oldflags & ~EXT4_IMMUTABLE_FL) != (flags & ~EXT4_IMMUTABLE_FL))
++              return -EPERM;
++      if (ext4_has_feature_project(inode->i_sb) &&
++          __kprojid_val(ei->i_projid) != new_projid)
++              return -EPERM;
++
++      return 0;
++}
++
+ static int ext4_ioctl_setflags(struct inode *inode,
+                              unsigned int flags)
+ {
+@@ -263,6 +286,20 @@ static int ext4_ioctl_setflags(struct in
+                       goto flags_out;
+       }
++      /*
++       * Wait for all pending directio and then flush all the dirty pages
++       * for this file.  The flush marks all the pages readonly, so any
++       * subsequent attempt to write to the file (particularly mmap pages)
++       * will come through the filesystem and fail.
++       */
++      if (S_ISREG(inode->i_mode) && !IS_IMMUTABLE(inode) &&
++          (flags & EXT4_IMMUTABLE_FL)) {
++              inode_dio_wait(inode);
++              err = filemap_write_and_wait(inode->i_mapping);
++              if (err)
++                      goto flags_out;
++      }
++
+       handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
+       if (IS_ERR(handle)) {
+               err = PTR_ERR(handle);
+@@ -653,7 +690,11 @@ long ext4_ioctl(struct file *filp, unsig
+                       return err;
+               inode_lock(inode);
+-              err = ext4_ioctl_setflags(inode, flags);
++              err = ext4_ioctl_check_immutable(inode,
++                              from_kprojid(&init_user_ns, ei->i_projid),
++                              flags);
++              if (!err)
++                      err = ext4_ioctl_setflags(inode, flags);
+               inode_unlock(inode);
+               mnt_drop_write_file(filp);
+               return err;
+@@ -1061,6 +1102,9 @@ resizefs_out:
+                       goto out;
+               flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) |
+                        (flags & EXT4_FL_XFLAG_VISIBLE);
++              err = ext4_ioctl_check_immutable(inode, fa.fsx_projid, flags);
++              if (err)
++                      goto out;
+               err = ext4_ioctl_setflags(inode, flags);
+               if (err)
+                       goto out;
diff --git a/queue-4.14/ext4-enforce-the-immutable-flag-on-open-files.patch b/queue-4.14/ext4-enforce-the-immutable-flag-on-open-files.patch
new file mode 100644 (file)
index 0000000..326fa80
--- /dev/null
@@ -0,0 +1,70 @@
+From 02b016ca7f99229ae6227e7b2fc950c4e140d74a Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sun, 9 Jun 2019 22:04:33 -0400
+Subject: ext4: enforce the immutable flag on open files
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 02b016ca7f99229ae6227e7b2fc950c4e140d74a upstream.
+
+According to the chattr man page, "a file with the 'i' attribute
+cannot be modified..."  Historically, this was only enforced when the
+file was opened, per the rest of the description, "... and the file
+can not be opened in write mode".
+
+There is general agreement that we should standardize all file systems
+to prevent modifications even for files that were opened at the time
+the immutable flag is set.  Eventually, a change to enforce this at
+the VFS layer should be landing in mainline.  Until then, enforce this
+at the ext4 level to prevent xfstests generic/553 from failing.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: "Darrick J. Wong" <darrick.wong@oracle.com>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/file.c  |    4 ++++
+ fs/ext4/inode.c |   11 +++++++++++
+ 2 files changed, 15 insertions(+)
+
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -163,6 +163,10 @@ static ssize_t ext4_write_checks(struct
+       ret = generic_write_checks(iocb, from);
+       if (ret <= 0)
+               return ret;
++
++      if (unlikely(IS_IMMUTABLE(inode)))
++              return -EPERM;
++
+       /*
+        * If we have encountered a bitmap-format file, the size limit
+        * is smaller than s_maxbytes, which is for extent-mapped files.
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5341,6 +5341,14 @@ int ext4_setattr(struct dentry *dentry,
+       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
+               return -EIO;
++      if (unlikely(IS_IMMUTABLE(inode)))
++              return -EPERM;
++
++      if (unlikely(IS_APPEND(inode) &&
++                   (ia_valid & (ATTR_MODE | ATTR_UID |
++                                ATTR_GID | ATTR_TIMES_SET))))
++              return -EPERM;
++
+       error = setattr_prepare(dentry, attr);
+       if (error)
+               return error;
+@@ -6045,6 +6053,9 @@ int ext4_page_mkwrite(struct vm_fault *v
+       get_block_t *get_block;
+       int retries = 0;
++      if (unlikely(IS_IMMUTABLE(inode)))
++              return VM_FAULT_SIGBUS;
++
+       sb_start_pagefault(inode->i_sb);
+       file_update_time(vma->vm_file);
diff --git a/queue-4.14/ext4-use-jbd2_inode-dirty-range-scoping.patch b/queue-4.14/ext4-use-jbd2_inode-dirty-range-scoping.patch
new file mode 100644 (file)
index 0000000..8e1d683
--- /dev/null
@@ -0,0 +1,96 @@
+From 73131fbb003b3691cfcf9656f234b00da497fcd6 Mon Sep 17 00:00:00 2001
+From: Ross Zwisler <zwisler@chromium.org>
+Date: Thu, 20 Jun 2019 17:26:26 -0400
+Subject: ext4: use jbd2_inode dirty range scoping
+
+From: Ross Zwisler <zwisler@chromium.org>
+
+commit 73131fbb003b3691cfcf9656f234b00da497fcd6 upstream.
+
+Use the newly introduced jbd2_inode dirty range scoping to prevent us
+from waiting forever when trying to complete a journal transaction.
+
+Signed-off-by: Ross Zwisler <zwisler@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4_jbd2.h   |   12 ++++++------
+ fs/ext4/inode.c       |   13 ++++++++++---
+ fs/ext4/move_extent.c |    3 ++-
+ 3 files changed, 18 insertions(+), 10 deletions(-)
+
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -364,20 +364,20 @@ static inline int ext4_journal_force_com
+ }
+ static inline int ext4_jbd2_inode_add_write(handle_t *handle,
+-                                          struct inode *inode)
++              struct inode *inode, loff_t start_byte, loff_t length)
+ {
+       if (ext4_handle_valid(handle))
+-              return jbd2_journal_inode_add_write(handle,
+-                                                  EXT4_I(inode)->jinode);
++              return jbd2_journal_inode_ranged_write(handle,
++                              EXT4_I(inode)->jinode, start_byte, length);
+       return 0;
+ }
+ static inline int ext4_jbd2_inode_add_wait(handle_t *handle,
+-                                         struct inode *inode)
++              struct inode *inode, loff_t start_byte, loff_t length)
+ {
+       if (ext4_handle_valid(handle))
+-              return jbd2_journal_inode_add_wait(handle,
+-                                                 EXT4_I(inode)->jinode);
++              return jbd2_journal_inode_ranged_wait(handle,
++                              EXT4_I(inode)->jinode, start_byte, length);
+       return 0;
+ }
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -728,10 +728,16 @@ out_sem:
+                   !(flags & EXT4_GET_BLOCKS_ZERO) &&
+                   !ext4_is_quota_file(inode) &&
+                   ext4_should_order_data(inode)) {
++                      loff_t start_byte =
++                              (loff_t)map->m_lblk << inode->i_blkbits;
++                      loff_t length = (loff_t)map->m_len << inode->i_blkbits;
++
+                       if (flags & EXT4_GET_BLOCKS_IO_SUBMIT)
+-                              ret = ext4_jbd2_inode_add_wait(handle, inode);
++                              ret = ext4_jbd2_inode_add_wait(handle, inode,
++                                              start_byte, length);
+                       else
+-                              ret = ext4_jbd2_inode_add_write(handle, inode);
++                              ret = ext4_jbd2_inode_add_write(handle, inode,
++                                              start_byte, length);
+                       if (ret)
+                               return ret;
+               }
+@@ -4004,7 +4010,8 @@ static int __ext4_block_zero_page_range(
+               err = 0;
+               mark_buffer_dirty(bh);
+               if (ext4_should_order_data(inode))
+-                      err = ext4_jbd2_inode_add_write(handle, inode);
++                      err = ext4_jbd2_inode_add_write(handle, inode, from,
++                                      length);
+       }
+ unlock:
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -400,7 +400,8 @@ data_copy:
+       /* Even in case of data=writeback it is reasonable to pin
+        * inode to transaction, to prevent unexpected data loss */
+-      *err = ext4_jbd2_inode_add_write(handle, orig_inode);
++      *err = ext4_jbd2_inode_add_write(handle, orig_inode,
++                      (loff_t)orig_page_offset << PAGE_SHIFT, replaced_size);
+ unlock_pages:
+       unlock_page(pagep[0]);
diff --git a/queue-4.14/jbd2-introduce-jbd2_inode-dirty-range-scoping.patch b/queue-4.14/jbd2-introduce-jbd2_inode-dirty-range-scoping.patch
new file mode 100644 (file)
index 0000000..637da55
--- /dev/null
@@ -0,0 +1,251 @@
+From 6ba0e7dc64a5adcda2fbe65adc466891795d639e Mon Sep 17 00:00:00 2001
+From: Ross Zwisler <zwisler@chromium.org>
+Date: Thu, 20 Jun 2019 17:24:56 -0400
+Subject: jbd2: introduce jbd2_inode dirty range scoping
+
+From: Ross Zwisler <zwisler@chromium.org>
+
+commit 6ba0e7dc64a5adcda2fbe65adc466891795d639e upstream.
+
+Currently both journal_submit_inode_data_buffers() and
+journal_finish_inode_data_buffers() operate on the entire address space
+of each of the inodes associated with a given journal entry.  The
+consequence of this is that if we have an inode where we are constantly
+appending dirty pages we can end up waiting for an indefinite amount of
+time in journal_finish_inode_data_buffers() while we wait for all the
+pages under writeback to be written out.
+
+The easiest way to cause this type of workload is do just dd from
+/dev/zero to a file until it fills the entire filesystem.  This can
+cause journal_finish_inode_data_buffers() to wait for the duration of
+the entire dd operation.
+
+We can improve this situation by scoping each of the inode dirty ranges
+associated with a given transaction.  We do this via the jbd2_inode
+structure so that the scoping is contained within jbd2 and so that it
+follows the lifetime and locking rules for that structure.
+
+This allows us to limit the writeback & wait in
+journal_submit_inode_data_buffers() and
+journal_finish_inode_data_buffers() respectively to the dirty range for
+a given struct jdb2_inode, keeping us from waiting forever if the inode
+in question is still being appended to.
+
+Signed-off-by: Ross Zwisler <zwisler@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/jbd2/commit.c      |   23 +++++++++++++++++------
+ fs/jbd2/journal.c     |    4 ++++
+ fs/jbd2/transaction.c |   49 ++++++++++++++++++++++++++++---------------------
+ include/linux/jbd2.h  |   22 ++++++++++++++++++++++
+ 4 files changed, 71 insertions(+), 27 deletions(-)
+
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -189,14 +189,15 @@ static int journal_wait_on_commit_record
+  * use writepages() because with dealyed allocation we may be doing
+  * block allocation in writepages().
+  */
+-static int journal_submit_inode_data_buffers(struct address_space *mapping)
++static int journal_submit_inode_data_buffers(struct address_space *mapping,
++              loff_t dirty_start, loff_t dirty_end)
+ {
+       int ret;
+       struct writeback_control wbc = {
+               .sync_mode =  WB_SYNC_ALL,
+               .nr_to_write = mapping->nrpages * 2,
+-              .range_start = 0,
+-              .range_end = i_size_read(mapping->host),
++              .range_start = dirty_start,
++              .range_end = dirty_end,
+       };
+       ret = generic_writepages(mapping, &wbc);
+@@ -220,6 +221,9 @@ static int journal_submit_data_buffers(j
+       spin_lock(&journal->j_list_lock);
+       list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) {
++              loff_t dirty_start = jinode->i_dirty_start;
++              loff_t dirty_end = jinode->i_dirty_end;
++
+               if (!(jinode->i_flags & JI_WRITE_DATA))
+                       continue;
+               mapping = jinode->i_vfs_inode->i_mapping;
+@@ -232,7 +236,8 @@ static int journal_submit_data_buffers(j
+                * only allocated blocks here.
+                */
+               trace_jbd2_submit_inode_data(jinode->i_vfs_inode);
+-              err = journal_submit_inode_data_buffers(mapping);
++              err = journal_submit_inode_data_buffers(mapping, dirty_start,
++                              dirty_end);
+               if (!ret)
+                       ret = err;
+               spin_lock(&journal->j_list_lock);
+@@ -259,12 +264,16 @@ static int journal_finish_inode_data_buf
+       /* For locking, see the comment in journal_submit_data_buffers() */
+       spin_lock(&journal->j_list_lock);
+       list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) {
++              loff_t dirty_start = jinode->i_dirty_start;
++              loff_t dirty_end = jinode->i_dirty_end;
++
+               if (!(jinode->i_flags & JI_WAIT_DATA))
+                       continue;
+               jinode->i_flags |= JI_COMMIT_RUNNING;
+               spin_unlock(&journal->j_list_lock);
+-              err = filemap_fdatawait_keep_errors(
+-                              jinode->i_vfs_inode->i_mapping);
++              err = filemap_fdatawait_range_keep_errors(
++                              jinode->i_vfs_inode->i_mapping, dirty_start,
++                              dirty_end);
+               if (!ret)
+                       ret = err;
+               spin_lock(&journal->j_list_lock);
+@@ -284,6 +293,8 @@ static int journal_finish_inode_data_buf
+                               &jinode->i_transaction->t_inode_list);
+               } else {
+                       jinode->i_transaction = NULL;
++                      jinode->i_dirty_start = 0;
++                      jinode->i_dirty_end = 0;
+               }
+       }
+       spin_unlock(&journal->j_list_lock);
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -97,6 +97,8 @@ EXPORT_SYMBOL(jbd2_journal_try_to_free_b
+ EXPORT_SYMBOL(jbd2_journal_force_commit);
+ EXPORT_SYMBOL(jbd2_journal_inode_add_write);
+ EXPORT_SYMBOL(jbd2_journal_inode_add_wait);
++EXPORT_SYMBOL(jbd2_journal_inode_ranged_write);
++EXPORT_SYMBOL(jbd2_journal_inode_ranged_wait);
+ EXPORT_SYMBOL(jbd2_journal_init_jbd_inode);
+ EXPORT_SYMBOL(jbd2_journal_release_jbd_inode);
+ EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);
+@@ -2581,6 +2583,8 @@ void jbd2_journal_init_jbd_inode(struct
+       jinode->i_next_transaction = NULL;
+       jinode->i_vfs_inode = inode;
+       jinode->i_flags = 0;
++      jinode->i_dirty_start = 0;
++      jinode->i_dirty_end = 0;
+       INIT_LIST_HEAD(&jinode->i_list);
+ }
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -2503,7 +2503,7 @@ void jbd2_journal_refile_buffer(journal_
+  * File inode in the inode list of the handle's transaction
+  */
+ static int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode,
+-                                 unsigned long flags)
++              unsigned long flags, loff_t start_byte, loff_t end_byte)
+ {
+       transaction_t *transaction = handle->h_transaction;
+       journal_t *journal;
+@@ -2515,26 +2515,17 @@ static int jbd2_journal_file_inode(handl
+       jbd_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino,
+                       transaction->t_tid);
+-      /*
+-       * First check whether inode isn't already on the transaction's
+-       * lists without taking the lock. Note that this check is safe
+-       * without the lock as we cannot race with somebody removing inode
+-       * from the transaction. The reason is that we remove inode from the
+-       * transaction only in journal_release_jbd_inode() and when we commit
+-       * the transaction. We are guarded from the first case by holding
+-       * a reference to the inode. We are safe against the second case
+-       * because if jinode->i_transaction == transaction, commit code
+-       * cannot touch the transaction because we hold reference to it,
+-       * and if jinode->i_next_transaction == transaction, commit code
+-       * will only file the inode where we want it.
+-       */
+-      if ((jinode->i_transaction == transaction ||
+-          jinode->i_next_transaction == transaction) &&
+-          (jinode->i_flags & flags) == flags)
+-              return 0;
+-
+       spin_lock(&journal->j_list_lock);
+       jinode->i_flags |= flags;
++
++      if (jinode->i_dirty_end) {
++              jinode->i_dirty_start = min(jinode->i_dirty_start, start_byte);
++              jinode->i_dirty_end = max(jinode->i_dirty_end, end_byte);
++      } else {
++              jinode->i_dirty_start = start_byte;
++              jinode->i_dirty_end = end_byte;
++      }
++
+       /* Is inode already attached where we need it? */
+       if (jinode->i_transaction == transaction ||
+           jinode->i_next_transaction == transaction)
+@@ -2569,12 +2560,28 @@ done:
+ int jbd2_journal_inode_add_write(handle_t *handle, struct jbd2_inode *jinode)
+ {
+       return jbd2_journal_file_inode(handle, jinode,
+-                                     JI_WRITE_DATA | JI_WAIT_DATA);
++                      JI_WRITE_DATA | JI_WAIT_DATA, 0, LLONG_MAX);
+ }
+ int jbd2_journal_inode_add_wait(handle_t *handle, struct jbd2_inode *jinode)
+ {
+-      return jbd2_journal_file_inode(handle, jinode, JI_WAIT_DATA);
++      return jbd2_journal_file_inode(handle, jinode, JI_WAIT_DATA, 0,
++                      LLONG_MAX);
++}
++
++int jbd2_journal_inode_ranged_write(handle_t *handle,
++              struct jbd2_inode *jinode, loff_t start_byte, loff_t length)
++{
++      return jbd2_journal_file_inode(handle, jinode,
++                      JI_WRITE_DATA | JI_WAIT_DATA, start_byte,
++                      start_byte + length - 1);
++}
++
++int jbd2_journal_inode_ranged_wait(handle_t *handle, struct jbd2_inode *jinode,
++              loff_t start_byte, loff_t length)
++{
++      return jbd2_journal_file_inode(handle, jinode, JI_WAIT_DATA,
++                      start_byte, start_byte + length - 1);
+ }
+ /*
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -454,6 +454,22 @@ struct jbd2_inode {
+        * @i_flags: Flags of inode [j_list_lock]
+        */
+       unsigned long i_flags;
++
++      /**
++       * @i_dirty_start:
++       *
++       * Offset in bytes where the dirty range for this inode starts.
++       * [j_list_lock]
++       */
++      loff_t i_dirty_start;
++
++      /**
++       * @i_dirty_end:
++       *
++       * Inclusive offset in bytes where the dirty range for this inode
++       * ends. [j_list_lock]
++       */
++      loff_t i_dirty_end;
+ };
+ struct jbd2_revoke_table_s;
+@@ -1399,6 +1415,12 @@ extern int         jbd2_journal_force_commit(
+ extern int       jbd2_journal_force_commit_nested(journal_t *);
+ extern int       jbd2_journal_inode_add_write(handle_t *handle, struct jbd2_inode *inode);
+ extern int       jbd2_journal_inode_add_wait(handle_t *handle, struct jbd2_inode *inode);
++extern int       jbd2_journal_inode_ranged_write(handle_t *handle,
++                      struct jbd2_inode *inode, loff_t start_byte,
++                      loff_t length);
++extern int       jbd2_journal_inode_ranged_wait(handle_t *handle,
++                      struct jbd2_inode *inode, loff_t start_byte,
++                      loff_t length);
+ extern int       jbd2_journal_begin_ordered_truncate(journal_t *journal,
+                               struct jbd2_inode *inode, loff_t new_size);
+ extern void      jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode);
diff --git a/queue-4.14/mips-lb60-fix-pin-mappings.patch b/queue-4.14/mips-lb60-fix-pin-mappings.patch
new file mode 100644 (file)
index 0000000..6bf246d
--- /dev/null
@@ -0,0 +1,68 @@
+From 1323c3b72a987de57141cabc44bf9cd83656bc70 Mon Sep 17 00:00:00 2001
+From: Paul Cercueil <paul@crapouillou.net>
+Date: Tue, 4 Jun 2019 18:33:11 +0200
+Subject: MIPS: lb60: Fix pin mappings
+
+From: Paul Cercueil <paul@crapouillou.net>
+
+commit 1323c3b72a987de57141cabc44bf9cd83656bc70 upstream.
+
+The pin mappings introduced in commit 636f8ba67fb6
+("MIPS: JZ4740: Qi LB60: Add pinctrl configuration for several drivers")
+are completely wrong. The pinctrl driver name is incorrect, and the
+function and group fields are swapped.
+
+Fixes: 636f8ba67fb6 ("MIPS: JZ4740: Qi LB60: Add pinctrl configuration for several drivers")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Paul Cercueil <paul@crapouillou.net>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Paul Burton <paul.burton@mips.com>
+Cc: Ralf Baechle <ralf@linux-mips.org>
+Cc: James Hogan <jhogan@kernel.org>
+Cc: od@zcrc.me
+Cc: linux-mips@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/mips/jz4740/board-qi_lb60.c |   16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/arch/mips/jz4740/board-qi_lb60.c
++++ b/arch/mips/jz4740/board-qi_lb60.c
+@@ -456,27 +456,27 @@ static unsigned long pin_cfg_bias_disabl
+ static struct pinctrl_map pin_map[] __initdata = {
+       /* NAND pin configuration */
+       PIN_MAP_MUX_GROUP_DEFAULT("jz4740-nand",
+-                      "10010000.jz4740-pinctrl", "nand", "nand-cs1"),
++                      "10010000.pin-controller", "nand-cs1", "nand"),
+       /* fbdev pin configuration */
+       PIN_MAP_MUX_GROUP("jz4740-fb", PINCTRL_STATE_DEFAULT,
+-                      "10010000.jz4740-pinctrl", "lcd", "lcd-8bit"),
++                      "10010000.pin-controller", "lcd-8bit", "lcd"),
+       PIN_MAP_MUX_GROUP("jz4740-fb", PINCTRL_STATE_SLEEP,
+-                      "10010000.jz4740-pinctrl", "lcd", "lcd-no-pins"),
++                      "10010000.pin-controller", "lcd-no-pins", "lcd"),
+       /* MMC pin configuration */
+       PIN_MAP_MUX_GROUP_DEFAULT("jz4740-mmc.0",
+-                      "10010000.jz4740-pinctrl", "mmc", "mmc-1bit"),
++                      "10010000.pin-controller", "mmc-1bit", "mmc"),
+       PIN_MAP_MUX_GROUP_DEFAULT("jz4740-mmc.0",
+-                      "10010000.jz4740-pinctrl", "mmc", "mmc-4bit"),
++                      "10010000.pin-controller", "mmc-4bit", "mmc"),
+       PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0",
+-                      "10010000.jz4740-pinctrl", "PD0", pin_cfg_bias_disable),
++                      "10010000.pin-controller", "PD0", pin_cfg_bias_disable),
+       PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0",
+-                      "10010000.jz4740-pinctrl", "PD2", pin_cfg_bias_disable),
++                      "10010000.pin-controller", "PD2", pin_cfg_bias_disable),
+       /* PWM pin configuration */
+       PIN_MAP_MUX_GROUP_DEFAULT("jz4740-pwm",
+-                      "10010000.jz4740-pinctrl", "pwm4", "pwm4"),
++                      "10010000.pin-controller", "pwm4", "pwm4"),
+ };
diff --git a/queue-4.14/mm-add-filemap_fdatawait_range_keep_errors.patch b/queue-4.14/mm-add-filemap_fdatawait_range_keep_errors.patch
new file mode 100644 (file)
index 0000000..03be9d5
--- /dev/null
@@ -0,0 +1,67 @@
+From aa0bfcd939c30617385ffa28682c062d78050eba Mon Sep 17 00:00:00 2001
+From: Ross Zwisler <zwisler@chromium.org>
+Date: Thu, 20 Jun 2019 17:05:37 -0400
+Subject: mm: add filemap_fdatawait_range_keep_errors()
+
+From: Ross Zwisler <zwisler@chromium.org>
+
+commit aa0bfcd939c30617385ffa28682c062d78050eba upstream.
+
+In the spirit of filemap_fdatawait_range() and
+filemap_fdatawait_keep_errors(), introduce
+filemap_fdatawait_range_keep_errors() which both takes a range upon
+which to wait and does not clear errors from the address space.
+
+Signed-off-by: Ross Zwisler <zwisler@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/fs.h |    2 ++
+ mm/filemap.c       |   22 ++++++++++++++++++++++
+ 2 files changed, 24 insertions(+)
+
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2580,6 +2580,8 @@ extern int filemap_flush(struct address_
+ extern int filemap_fdatawait_keep_errors(struct address_space *mapping);
+ extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
+                                  loff_t lend);
++extern int filemap_fdatawait_range_keep_errors(struct address_space *mapping,
++              loff_t start_byte, loff_t end_byte);
+ static inline int filemap_fdatawait(struct address_space *mapping)
+ {
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -464,6 +464,28 @@ int filemap_fdatawait_range(struct addre
+ EXPORT_SYMBOL(filemap_fdatawait_range);
+ /**
++ * filemap_fdatawait_range_keep_errors - wait for writeback to complete
++ * @mapping:          address space structure to wait for
++ * @start_byte:               offset in bytes where the range starts
++ * @end_byte:         offset in bytes where the range ends (inclusive)
++ *
++ * Walk the list of under-writeback pages of the given address space in the
++ * given range and wait for all of them.  Unlike filemap_fdatawait_range(),
++ * this function does not clear error status of the address space.
++ *
++ * Use this function if callers don't handle errors themselves.  Expected
++ * call sites are system-wide / filesystem-wide data flushers: e.g. sync(2),
++ * fsfreeze(8)
++ */
++int filemap_fdatawait_range_keep_errors(struct address_space *mapping,
++              loff_t start_byte, loff_t end_byte)
++{
++      __filemap_fdatawait_range(mapping, start_byte, end_byte);
++      return filemap_check_and_keep_errors(mapping);
++}
++EXPORT_SYMBOL(filemap_fdatawait_range_keep_errors);
++
++/**
+  * file_fdatawait_range - wait for writeback to complete
+  * @file:             file pointing to address space structure to wait for
+  * @start_byte:               offset in bytes where the range starts
diff --git a/queue-4.14/perf-core-fix-exclusive-events-grouping.patch b/queue-4.14/perf-core-fix-exclusive-events-grouping.patch
new file mode 100644 (file)
index 0000000..46a7dab
--- /dev/null
@@ -0,0 +1,171 @@
+From 8a58ddae23796c733c5dfbd717538d89d036c5bd Mon Sep 17 00:00:00 2001
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Date: Mon, 1 Jul 2019 14:07:55 +0300
+Subject: perf/core: Fix exclusive events' grouping
+
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+
+commit 8a58ddae23796c733c5dfbd717538d89d036c5bd upstream.
+
+So far, we tried to disallow grouping exclusive events for the fear of
+complications they would cause with moving between contexts. Specifically,
+moving a software group to a hardware context would violate the exclusivity
+rules if both groups contain matching exclusive events.
+
+This attempt was, however, unsuccessful: the check that we have in the
+perf_event_open() syscall is both wrong (looks at wrong PMU) and
+insufficient (group leader may still be exclusive), as can be illustrated
+by running:
+
+  $ perf record -e '{intel_pt//,cycles}' uname
+  $ perf record -e '{cycles,intel_pt//}' uname
+
+ultimately successfully.
+
+Furthermore, we are completely free to trigger the exclusivity violation
+by:
+
+   perf -e '{cycles,intel_pt//}' -e '{intel_pt//,instructions}'
+
+even though the helpful perf record will not allow that, the ABI will.
+
+The warning later in the perf_event_open() path will also not trigger, because
+it's also wrong.
+
+Fix all this by validating the original group before moving, getting rid
+of broken safeguards and placing a useful one to perf_install_in_context().
+
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: <stable@vger.kernel.org>
+Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Stephane Eranian <eranian@google.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Vince Weaver <vincent.weaver@maine.edu>
+Cc: mathieu.poirier@linaro.org
+Cc: will.deacon@arm.com
+Fixes: bed5b25ad9c8a ("perf: Add a pmu capability for "exclusive" events")
+Link: https://lkml.kernel.org/r/20190701110755.24646-1-alexander.shishkin@linux.intel.com
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/perf_event.h |    5 +++++
+ kernel/events/core.c       |   34 ++++++++++++++++++++++------------
+ 2 files changed, 27 insertions(+), 12 deletions(-)
+
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -1017,6 +1017,11 @@ static inline int is_software_event(stru
+       return event->event_caps & PERF_EV_CAP_SOFTWARE;
+ }
++static inline int is_exclusive_pmu(struct pmu *pmu)
++{
++      return pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE;
++}
++
+ extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX];
+ extern void ___perf_sw_event(u32, u64, struct pt_regs *, u64);
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -2442,6 +2442,9 @@ unlock:
+       return ret;
+ }
++static bool exclusive_event_installable(struct perf_event *event,
++                                      struct perf_event_context *ctx);
++
+ /*
+  * Attach a performance event to a context.
+  *
+@@ -2456,6 +2459,8 @@ perf_install_in_context(struct perf_even
+       lockdep_assert_held(&ctx->mutex);
++      WARN_ON_ONCE(!exclusive_event_installable(event, ctx));
++
+       if (event->cpu != -1)
+               event->cpu = cpu;
+@@ -4132,7 +4137,7 @@ static int exclusive_event_init(struct p
+ {
+       struct pmu *pmu = event->pmu;
+-      if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
++      if (!is_exclusive_pmu(pmu))
+               return 0;
+       /*
+@@ -4163,7 +4168,7 @@ static void exclusive_event_destroy(stru
+ {
+       struct pmu *pmu = event->pmu;
+-      if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
++      if (!is_exclusive_pmu(pmu))
+               return;
+       /* see comment in exclusive_event_init() */
+@@ -4183,14 +4188,15 @@ static bool exclusive_event_match(struct
+       return false;
+ }
+-/* Called under the same ctx::mutex as perf_install_in_context() */
+ static bool exclusive_event_installable(struct perf_event *event,
+                                       struct perf_event_context *ctx)
+ {
+       struct perf_event *iter_event;
+       struct pmu *pmu = event->pmu;
+-      if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
++      lockdep_assert_held(&ctx->mutex);
++
++      if (!is_exclusive_pmu(pmu))
+               return true;
+       list_for_each_entry(iter_event, &ctx->event_list, event_entry) {
+@@ -10155,11 +10161,6 @@ SYSCALL_DEFINE5(perf_event_open,
+               goto err_alloc;
+       }
+-      if ((pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE) && group_leader) {
+-              err = -EBUSY;
+-              goto err_context;
+-      }
+-
+       /*
+        * Look up the group leader (we will attach this event to it):
+        */
+@@ -10247,6 +10248,18 @@ SYSCALL_DEFINE5(perf_event_open,
+                               move_group = 0;
+                       }
+               }
++
++              /*
++               * Failure to create exclusive events returns -EBUSY.
++               */
++              err = -EBUSY;
++              if (!exclusive_event_installable(group_leader, ctx))
++                      goto err_locked;
++
++              for_each_sibling_event(sibling, group_leader) {
++                      if (!exclusive_event_installable(sibling, ctx))
++                              goto err_locked;
++              }
+       } else {
+               mutex_lock(&ctx->mutex);
+       }
+@@ -10283,9 +10296,6 @@ SYSCALL_DEFINE5(perf_event_open,
+        * because we need to serialize with concurrent event creation.
+        */
+       if (!exclusive_event_installable(event, ctx)) {
+-              /* exclusive and group stuff are assumed mutually exclusive */
+-              WARN_ON_ONCE(move_group);
+-
+               err = -EBUSY;
+               goto err_locked;
+       }
index fb181016dc3a52d6b32198678532343f9caabbab..80fb9c80db67a033450e82395c7a8e55e85ee448 100644 (file)
@@ -203,3 +203,13 @@ tcp-reset-bytes_acked-and-bytes_received-when-disconnecting.patch
 net-bridge-mcast-fix-stale-nsrcs-pointer-in-igmp3-mld2-report-handling.patch
 net-bridge-mcast-fix-stale-ipv6-hdr-pointer-when-handling-v6-query.patch
 net-bridge-stp-don-t-cache-eth-dest-pointer-before-skb-pull.patch
+dma-buf-balance-refcount-inbalance.patch
+dma-buf-discard-old-fence_excl-on-retrying-get_fences_rcu-for-realloc.patch
+mips-lb60-fix-pin-mappings.patch
+perf-core-fix-exclusive-events-grouping.patch
+ext4-don-t-allow-any-modifications-to-an-immutable-file.patch
+ext4-enforce-the-immutable-flag-on-open-files.patch
+mm-add-filemap_fdatawait_range_keep_errors.patch
+jbd2-introduce-jbd2_inode-dirty-range-scoping.patch
+ext4-use-jbd2_inode-dirty-range-scoping.patch
+ext4-allow-directory-holes.patch