]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Sep 2015 03:48:37 +0000 (20:48 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Sep 2015 03:48:37 +0000 (20:48 -0700)
added patches:
btrfs-check-if-previous-transaction-aborted-to-avoid-fs-corruption.patch
media-am437x-vpfe-fix-a-race-condition-during-release.patch
media-am437x-vpfe-requested-frame-size-and-fmt-overwritten-by-current-sensor-setting.patch
nfs-don-t-let-the-ctime-override-attribute-barriers.patch
nfsd-ensure-that-delegation-stateid-hash-references-are-only-put-once.patch
nfsd-ensure-that-the-ol-stateid-hash-reference-is-only-put-once.patch
nfsd-fix-an-fs_layout_types-layout_types-encode-bug.patch
nfsv4-don-t-set-setattr-for-o_rdonly-o_excl.patch
nfsv4-pnfs-ensure-we-don-t-miss-a-file-extension.patch
nfsv4.1-pnfs-fix-borken-function-_same_data_server_addrs_locked.patch
rc-core-fix-remove-uevent-generation.patch
v4l-omap3isp-fix-sub-device-power-management-code.patch

13 files changed:
queue-4.1/btrfs-check-if-previous-transaction-aborted-to-avoid-fs-corruption.patch [new file with mode: 0644]
queue-4.1/media-am437x-vpfe-fix-a-race-condition-during-release.patch [new file with mode: 0644]
queue-4.1/media-am437x-vpfe-requested-frame-size-and-fmt-overwritten-by-current-sensor-setting.patch [new file with mode: 0644]
queue-4.1/nfs-don-t-let-the-ctime-override-attribute-barriers.patch [new file with mode: 0644]
queue-4.1/nfsd-ensure-that-delegation-stateid-hash-references-are-only-put-once.patch [new file with mode: 0644]
queue-4.1/nfsd-ensure-that-the-ol-stateid-hash-reference-is-only-put-once.patch [new file with mode: 0644]
queue-4.1/nfsd-fix-an-fs_layout_types-layout_types-encode-bug.patch [new file with mode: 0644]
queue-4.1/nfsv4-don-t-set-setattr-for-o_rdonly-o_excl.patch [new file with mode: 0644]
queue-4.1/nfsv4-pnfs-ensure-we-don-t-miss-a-file-extension.patch [new file with mode: 0644]
queue-4.1/nfsv4.1-pnfs-fix-borken-function-_same_data_server_addrs_locked.patch [new file with mode: 0644]
queue-4.1/rc-core-fix-remove-uevent-generation.patch [new file with mode: 0644]
queue-4.1/series
queue-4.1/v4l-omap3isp-fix-sub-device-power-management-code.patch [new file with mode: 0644]

diff --git a/queue-4.1/btrfs-check-if-previous-transaction-aborted-to-avoid-fs-corruption.patch b/queue-4.1/btrfs-check-if-previous-transaction-aborted-to-avoid-fs-corruption.patch
new file mode 100644 (file)
index 0000000..837c180
--- /dev/null
@@ -0,0 +1,108 @@
+From 1f9b8c8fbc9a4d029760b16f477b9d15500e3a34 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Wed, 12 Aug 2015 11:54:35 +0100
+Subject: Btrfs: check if previous transaction aborted to avoid fs corruption
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 1f9b8c8fbc9a4d029760b16f477b9d15500e3a34 upstream.
+
+While we are committing a transaction, it's possible the previous one is
+still finishing its commit and therefore we wait for it to finish first.
+However we were not checking if that previous transaction ended up getting
+aborted after we waited for it to commit, so we ended up committing the
+current transaction which can lead to fs corruption because the new
+superblock can point to trees that have had one or more nodes/leafs that
+were never durably persisted.
+The following sequence diagram exemplifies how this is possible:
+
+          CPU 0                                                        CPU 1
+
+  transaction N starts
+
+  (...)
+
+  btrfs_commit_transaction(N)
+
+    cur_trans->state = TRANS_STATE_COMMIT_START;
+    (...)
+    cur_trans->state = TRANS_STATE_COMMIT_DOING;
+    (...)
+
+    cur_trans->state = TRANS_STATE_UNBLOCKED;
+    root->fs_info->running_transaction = NULL;
+
+                                                              btrfs_start_transaction()
+                                                                 --> starts transaction N + 1
+
+    btrfs_write_and_wait_transaction(trans, root);
+      --> starts writing all new or COWed ebs created
+          at transaction N
+
+                                                              creates some new ebs, COWs some
+                                                              existing ebs but doesn't COW or
+                                                              deletes eb X
+
+                                                              btrfs_commit_transaction(N + 1)
+                                                                (...)
+                                                                cur_trans->state = TRANS_STATE_COMMIT_START;
+                                                                (...)
+                                                                wait_for_commit(root, prev_trans);
+                                                                  --> prev_trans == transaction N
+
+    btrfs_write_and_wait_transaction() continues
+    writing ebs
+       --> fails writing eb X, we abort transaction N
+           and set bit BTRFS_FS_STATE_ERROR on
+           fs_info->fs_state, so no new transactions
+           can start after setting that bit
+
+       cleanup_transaction()
+         btrfs_cleanup_one_transaction()
+           wakes up task at CPU 1
+
+                                                                continues, doesn't abort because
+                                                                cur_trans->aborted (transaction N + 1)
+                                                                is zero, and no checks for bit
+                                                                BTRFS_FS_STATE_ERROR in fs_info->fs_state
+                                                                are made
+
+                                                                btrfs_write_and_wait_transaction(trans, root);
+                                                                  --> succeeds, no errors during writeback
+
+                                                                write_ctree_super(trans, root, 0);
+                                                                  --> succeeds
+                                                                  --> we have now a superblock that points us
+                                                                      to some root that uses eb X, which was
+                                                                      never written to disk
+
+In this scenario future attempts to read eb X from disk results in an
+error message like "parent transid verify failed on X wanted Y found Z".
+
+So fix this by aborting the current transaction if after waiting for the
+previous transaction we verify that it was aborted.
+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: Josef Bacik <jbacik@fb.com>
+Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/transaction.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -1875,8 +1875,11 @@ int btrfs_commit_transaction(struct btrf
+                       spin_unlock(&root->fs_info->trans_lock);
+                       wait_for_commit(root, prev_trans);
++                      ret = prev_trans->aborted;
+                       btrfs_put_transaction(prev_trans);
++                      if (ret)
++                              goto cleanup_transaction;
+               } else {
+                       spin_unlock(&root->fs_info->trans_lock);
+               }
diff --git a/queue-4.1/media-am437x-vpfe-fix-a-race-condition-during-release.patch b/queue-4.1/media-am437x-vpfe-fix-a-race-condition-during-release.patch
new file mode 100644 (file)
index 0000000..1032eb8
--- /dev/null
@@ -0,0 +1,53 @@
+From c99235fa3ef833c3c23926085f2bb68851c8460a Mon Sep 17 00:00:00 2001
+From: Benoit Parrot <bparrot@ti.com>
+Date: Wed, 15 Jul 2015 18:00:06 -0300
+Subject: [media] media: am437x-vpfe: Fix a race condition during release
+
+From: Benoit Parrot <bparrot@ti.com>
+
+commit c99235fa3ef833c3c23926085f2bb68851c8460a upstream.
+
+There was a race condition where during cleanup/release operation
+on-going streaming would cause a kernel panic because the hardware
+module was disabled prematurely with IRQ still pending.
+
+Fixes: 417d2e507edc ("[media] media: platform: add VPFE capture driver support for AM437X")
+
+Signed-off-by: Benoit Parrot <bparrot@ti.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/platform/am437x/am437x-vpfe.c |   14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/platform/am437x/am437x-vpfe.c
++++ b/drivers/media/platform/am437x/am437x-vpfe.c
+@@ -1185,14 +1185,24 @@ static int vpfe_initialize_device(struct
+ static int vpfe_release(struct file *file)
+ {
+       struct vpfe_device *vpfe = video_drvdata(file);
++      bool fh_singular;
+       int ret;
+       mutex_lock(&vpfe->lock);
+-      if (v4l2_fh_is_singular_file(file))
+-              vpfe_ccdc_close(&vpfe->ccdc, vpfe->pdev);
++      /* Save the singular status before we call the clean-up helper */
++      fh_singular = v4l2_fh_is_singular_file(file);
++
++      /* the release helper will cleanup any on-going streaming */
+       ret = _vb2_fop_release(file, NULL);
++      /*
++       * If this was the last open file.
++       * Then de-initialize hw module.
++       */
++      if (fh_singular)
++              vpfe_ccdc_close(&vpfe->ccdc, vpfe->pdev);
++
+       mutex_unlock(&vpfe->lock);
+       return ret;
diff --git a/queue-4.1/media-am437x-vpfe-requested-frame-size-and-fmt-overwritten-by-current-sensor-setting.patch b/queue-4.1/media-am437x-vpfe-requested-frame-size-and-fmt-overwritten-by-current-sensor-setting.patch
new file mode 100644 (file)
index 0000000..0ce8166
--- /dev/null
@@ -0,0 +1,36 @@
+From f47c9045643f91e76d8a9030828b9fe1cf4a6bcf Mon Sep 17 00:00:00 2001
+From: Benoit Parrot <bparrot@ti.com>
+Date: Mon, 29 Jun 2015 18:19:06 -0300
+Subject: [media] media: am437x-vpfe: Requested frame size and fmt overwritten by current sensor setting
+
+From: Benoit Parrot <bparrot@ti.com>
+
+commit f47c9045643f91e76d8a9030828b9fe1cf4a6bcf upstream.
+
+Upon a S_FMT the input/requested frame size and pixel format is
+overwritten by the current sub-device settings.
+Fix this so application can actually set the frame size and format.
+
+Fixes: 417d2e507edc ("[media] media: platform: add VPFE capture driver support for AM437X")
+
+Signed-off-by: Benoit Parrot <bparrot@ti.com>
+Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/platform/am437x/am437x-vpfe.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/platform/am437x/am437x-vpfe.c
++++ b/drivers/media/platform/am437x/am437x-vpfe.c
+@@ -1577,7 +1577,7 @@ static int vpfe_s_fmt(struct file *file,
+               return -EBUSY;
+       }
+-      ret = vpfe_try_fmt(file, priv, fmt);
++      ret = vpfe_try_fmt(file, priv, &format);
+       if (ret)
+               return ret;
diff --git a/queue-4.1/nfs-don-t-let-the-ctime-override-attribute-barriers.patch b/queue-4.1/nfs-don-t-let-the-ctime-override-attribute-barriers.patch
new file mode 100644 (file)
index 0000000..8b8de93
--- /dev/null
@@ -0,0 +1,52 @@
+From 7c2dad99d60c86ec686b3bfdcb787c450a7ea89f Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Thu, 6 Aug 2015 12:06:30 -0400
+Subject: NFS: Don't let the ctime override attribute barriers.
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 7c2dad99d60c86ec686b3bfdcb787c450a7ea89f upstream.
+
+Chuck reports seeing cases where a GETATTR that happens to race
+with an asynchronous WRITE is overriding the file size, despite
+the attribute barrier being set by the writeback code.
+
+The culprit turns out to be the check in nfs_ctime_need_update(),
+which sees that the ctime is newer than the cached ctime, and
+assumes that it is safe to override the attribute barrier.
+This patch removes that override, and ensures that attribute
+barriers are always respected.
+
+Reported-by: Chuck Lever <chuck.lever@oracle.com>
+Fixes: a08a8cd375db9 ("NFS: Add attribute update barriers to NFS writebacks")
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/inode.c |    8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -1270,13 +1270,6 @@ static int nfs_check_inode_attributes(st
+       return 0;
+ }
+-static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
+-{
+-      if (!(fattr->valid & NFS_ATTR_FATTR_CTIME))
+-              return 0;
+-      return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0;
+-}
+-
+ static atomic_long_t nfs_attr_generation_counter;
+ static unsigned long nfs_read_attr_generation_counter(void)
+@@ -1425,7 +1418,6 @@ static int nfs_inode_attrs_need_update(c
+       const struct nfs_inode *nfsi = NFS_I(inode);
+       return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 ||
+-              nfs_ctime_need_update(inode, fattr) ||
+               ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
+ }
diff --git a/queue-4.1/nfsd-ensure-that-delegation-stateid-hash-references-are-only-put-once.patch b/queue-4.1/nfsd-ensure-that-delegation-stateid-hash-references-are-only-put-once.patch
new file mode 100644 (file)
index 0000000..7c6d408
--- /dev/null
@@ -0,0 +1,115 @@
+From 3fcbbd244ed1d20dc0eb7d48d729503992fa9b7d Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@poochiereds.net>
+Date: Mon, 24 Aug 2015 12:41:48 -0400
+Subject: nfsd: ensure that delegation stateid hash references are only put once
+
+From: Jeff Layton <jlayton@poochiereds.net>
+
+commit 3fcbbd244ed1d20dc0eb7d48d729503992fa9b7d upstream.
+
+It's possible that a DELEGRETURN could race with (e.g.) client expiry,
+in which case we could end up putting the delegation hash reference more
+than once.
+
+Have unhash_delegation_locked return a bool that indicates whether it
+was already unhashed. In the case of destroy_delegation we only
+conditionally put the hash reference if that returns true.
+
+The other callers of unhash_delegation_locked call it while walking
+list_heads that shouldn't yet be detached. If we find that it doesn't
+return true in those cases, then throw a WARN_ON as that indicates that
+we have a partially hashed delegation, and that something is likely very
+wrong.
+
+Tested-by: Andrew W Elble <aweits@rit.edu>
+Tested-by: Anna Schumaker <Anna.Schumaker@netapp.com>
+Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/nfs4state.c |   26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -777,13 +777,16 @@ hash_delegation_locked(struct nfs4_deleg
+       list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
+ }
+-static void
++static bool
+ unhash_delegation_locked(struct nfs4_delegation *dp)
+ {
+       struct nfs4_file *fp = dp->dl_stid.sc_file;
+       lockdep_assert_held(&state_lock);
++      if (list_empty(&dp->dl_perfile))
++              return false;
++
+       dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID;
+       /* Ensure that deleg break won't try to requeue it */
+       ++dp->dl_time;
+@@ -792,16 +795,21 @@ unhash_delegation_locked(struct nfs4_del
+       list_del_init(&dp->dl_recall_lru);
+       list_del_init(&dp->dl_perfile);
+       spin_unlock(&fp->fi_lock);
++      return true;
+ }
+ static void destroy_delegation(struct nfs4_delegation *dp)
+ {
++      bool unhashed;
++
+       spin_lock(&state_lock);
+-      unhash_delegation_locked(dp);
++      unhashed = unhash_delegation_locked(dp);
+       spin_unlock(&state_lock);
+-      put_clnt_odstate(dp->dl_clnt_odstate);
+-      nfs4_put_deleg_lease(dp->dl_stid.sc_file);
+-      nfs4_put_stid(&dp->dl_stid);
++      if (unhashed) {
++              put_clnt_odstate(dp->dl_clnt_odstate);
++              nfs4_put_deleg_lease(dp->dl_stid.sc_file);
++              nfs4_put_stid(&dp->dl_stid);
++      }
+ }
+ static void revoke_delegation(struct nfs4_delegation *dp)
+@@ -1725,7 +1733,7 @@ __destroy_client(struct nfs4_client *clp
+       spin_lock(&state_lock);
+       while (!list_empty(&clp->cl_delegations)) {
+               dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
+-              unhash_delegation_locked(dp);
++              WARN_ON(!unhash_delegation_locked(dp));
+               list_add(&dp->dl_recall_lru, &reaplist);
+       }
+       spin_unlock(&state_lock);
+@@ -4357,7 +4365,7 @@ nfs4_laundromat(struct nfsd_net *nn)
+                       new_timeo = min(new_timeo, t);
+                       break;
+               }
+-              unhash_delegation_locked(dp);
++              WARN_ON(!unhash_delegation_locked(dp));
+               list_add(&dp->dl_recall_lru, &reaplist);
+       }
+       spin_unlock(&state_lock);
+@@ -6282,7 +6290,7 @@ static u64 nfsd_find_all_delegations(str
+                               continue;
+                       atomic_inc(&clp->cl_refcount);
+-                      unhash_delegation_locked(dp);
++                      WARN_ON(!unhash_delegation_locked(dp));
+                       list_add(&dp->dl_recall_lru, victims);
+               }
+               ++count;
+@@ -6612,7 +6620,7 @@ nfs4_state_shutdown_net(struct net *net)
+       spin_lock(&state_lock);
+       list_for_each_safe(pos, next, &nn->del_recall_lru) {
+               dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+-              unhash_delegation_locked(dp);
++              WARN_ON(!unhash_delegation_locked(dp));
+               list_add(&dp->dl_recall_lru, &reaplist);
+       }
+       spin_unlock(&state_lock);
diff --git a/queue-4.1/nfsd-ensure-that-the-ol-stateid-hash-reference-is-only-put-once.patch b/queue-4.1/nfsd-ensure-that-the-ol-stateid-hash-reference-is-only-put-once.patch
new file mode 100644 (file)
index 0000000..6fcb3bd
--- /dev/null
@@ -0,0 +1,209 @@
+From e85687393f3ee0a77ccca016f903d1558bb69258 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@poochiereds.net>
+Date: Mon, 24 Aug 2015 12:41:47 -0400
+Subject: nfsd: ensure that the ol stateid hash reference is only put once
+
+From: Jeff Layton <jlayton@poochiereds.net>
+
+commit e85687393f3ee0a77ccca016f903d1558bb69258 upstream.
+
+When an open or lock stateid is hashed, we take an extra reference to
+it. When we unhash it, we drop that reference. The code however does
+not properly account for the case where we have two callers concurrently
+trying to unhash the stateid. This can lead to list corruption and the
+hash reference being put more than once.
+
+Fix this by having unhash_ol_stateid use list_del_init on the st_perfile
+list_head, and then testing to see if that list_head is empty before
+releasing the hash reference. This means that some of the unhashing
+wrappers now become bool return functions so we can test to see whether
+the stateid was unhashed before we put the reference.
+
+Reported-by: Andrew W Elble <aweits@rit.edu>
+Tested-by: Andrew W Elble <aweits@rit.edu>
+Reported-by: Anna Schumaker <Anna.Schumaker@netapp.com>
+Tested-by: Anna Schumaker <Anna.Schumaker@netapp.com>
+Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/nfs4state.c |   58 ++++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 36 insertions(+), 22 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1004,16 +1004,20 @@ static void nfs4_put_stateowner(struct n
+       sop->so_ops->so_free(sop);
+ }
+-static void unhash_ol_stateid(struct nfs4_ol_stateid *stp)
++static bool unhash_ol_stateid(struct nfs4_ol_stateid *stp)
+ {
+       struct nfs4_file *fp = stp->st_stid.sc_file;
+       lockdep_assert_held(&stp->st_stateowner->so_client->cl_lock);
++      if (list_empty(&stp->st_perfile))
++              return false;
++
+       spin_lock(&fp->fi_lock);
+-      list_del(&stp->st_perfile);
++      list_del_init(&stp->st_perfile);
+       spin_unlock(&fp->fi_lock);
+       list_del(&stp->st_perstateowner);
++      return true;
+ }
+ static void nfs4_free_ol_stateid(struct nfs4_stid *stid)
+@@ -1063,25 +1067,27 @@ static void put_ol_stateid_locked(struct
+       list_add(&stp->st_locks, reaplist);
+ }
+-static void unhash_lock_stateid(struct nfs4_ol_stateid *stp)
++static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp)
+ {
+       struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner);
+       lockdep_assert_held(&oo->oo_owner.so_client->cl_lock);
+       list_del_init(&stp->st_locks);
+-      unhash_ol_stateid(stp);
+       nfs4_unhash_stid(&stp->st_stid);
++      return unhash_ol_stateid(stp);
+ }
+ static void release_lock_stateid(struct nfs4_ol_stateid *stp)
+ {
+       struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner);
++      bool unhashed;
+       spin_lock(&oo->oo_owner.so_client->cl_lock);
+-      unhash_lock_stateid(stp);
++      unhashed = unhash_lock_stateid(stp);
+       spin_unlock(&oo->oo_owner.so_client->cl_lock);
+-      nfs4_put_stid(&stp->st_stid);
++      if (unhashed)
++              nfs4_put_stid(&stp->st_stid);
+ }
+ static void unhash_lockowner_locked(struct nfs4_lockowner *lo)
+@@ -1129,7 +1135,7 @@ static void release_lockowner(struct nfs
+       while (!list_empty(&lo->lo_owner.so_stateids)) {
+               stp = list_first_entry(&lo->lo_owner.so_stateids,
+                               struct nfs4_ol_stateid, st_perstateowner);
+-              unhash_lock_stateid(stp);
++              WARN_ON(!unhash_lock_stateid(stp));
+               put_ol_stateid_locked(stp, &reaplist);
+       }
+       spin_unlock(&clp->cl_lock);
+@@ -1142,21 +1148,26 @@ static void release_open_stateid_locks(s
+ {
+       struct nfs4_ol_stateid *stp;
++      lockdep_assert_held(&open_stp->st_stid.sc_client->cl_lock);
++
+       while (!list_empty(&open_stp->st_locks)) {
+               stp = list_entry(open_stp->st_locks.next,
+                               struct nfs4_ol_stateid, st_locks);
+-              unhash_lock_stateid(stp);
++              WARN_ON(!unhash_lock_stateid(stp));
+               put_ol_stateid_locked(stp, reaplist);
+       }
+ }
+-static void unhash_open_stateid(struct nfs4_ol_stateid *stp,
++static bool unhash_open_stateid(struct nfs4_ol_stateid *stp,
+                               struct list_head *reaplist)
+ {
++      bool unhashed;
++
+       lockdep_assert_held(&stp->st_stid.sc_client->cl_lock);
+-      unhash_ol_stateid(stp);
++      unhashed = unhash_ol_stateid(stp);
+       release_open_stateid_locks(stp, reaplist);
++      return unhashed;
+ }
+ static void release_open_stateid(struct nfs4_ol_stateid *stp)
+@@ -1164,8 +1175,8 @@ static void release_open_stateid(struct
+       LIST_HEAD(reaplist);
+       spin_lock(&stp->st_stid.sc_client->cl_lock);
+-      unhash_open_stateid(stp, &reaplist);
+-      put_ol_stateid_locked(stp, &reaplist);
++      if (unhash_open_stateid(stp, &reaplist))
++              put_ol_stateid_locked(stp, &reaplist);
+       spin_unlock(&stp->st_stid.sc_client->cl_lock);
+       free_ol_stateid_reaplist(&reaplist);
+ }
+@@ -1210,8 +1221,8 @@ static void release_openowner(struct nfs
+       while (!list_empty(&oo->oo_owner.so_stateids)) {
+               stp = list_first_entry(&oo->oo_owner.so_stateids,
+                               struct nfs4_ol_stateid, st_perstateowner);
+-              unhash_open_stateid(stp, &reaplist);
+-              put_ol_stateid_locked(stp, &reaplist);
++              if (unhash_open_stateid(stp, &reaplist))
++                      put_ol_stateid_locked(stp, &reaplist);
+       }
+       spin_unlock(&clp->cl_lock);
+       free_ol_stateid_reaplist(&reaplist);
+@@ -4714,7 +4725,7 @@ nfsd4_free_stateid(struct svc_rqst *rqst
+               if (check_for_locks(stp->st_stid.sc_file,
+                                   lockowner(stp->st_stateowner)))
+                       break;
+-              unhash_lock_stateid(stp);
++              WARN_ON(!unhash_lock_stateid(stp));
+               spin_unlock(&cl->cl_lock);
+               nfs4_put_stid(s);
+               ret = nfs_ok;
+@@ -4930,20 +4941,23 @@ out:
+ static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s)
+ {
+       struct nfs4_client *clp = s->st_stid.sc_client;
++      bool unhashed;
+       LIST_HEAD(reaplist);
+       s->st_stid.sc_type = NFS4_CLOSED_STID;
+       spin_lock(&clp->cl_lock);
+-      unhash_open_stateid(s, &reaplist);
++      unhashed = unhash_open_stateid(s, &reaplist);
+       if (clp->cl_minorversion) {
+-              put_ol_stateid_locked(s, &reaplist);
++              if (unhashed)
++                      put_ol_stateid_locked(s, &reaplist);
+               spin_unlock(&clp->cl_lock);
+               free_ol_stateid_reaplist(&reaplist);
+       } else {
+               spin_unlock(&clp->cl_lock);
+               free_ol_stateid_reaplist(&reaplist);
+-              move_to_close_lru(s, clp->net);
++              if (unhashed)
++                      move_to_close_lru(s, clp->net);
+       }
+ }
+@@ -5982,7 +5996,7 @@ nfsd_inject_add_lock_to_list(struct nfs4
+ static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max,
+                                   struct list_head *collect,
+-                                  void (*func)(struct nfs4_ol_stateid *))
++                                  bool (*func)(struct nfs4_ol_stateid *))
+ {
+       struct nfs4_openowner *oop;
+       struct nfs4_ol_stateid *stp, *st_next;
+@@ -5996,9 +6010,9 @@ static u64 nfsd_foreach_client_lock(stru
+                       list_for_each_entry_safe(lst, lst_next,
+                                       &stp->st_locks, st_locks) {
+                               if (func) {
+-                                      func(lst);
+-                                      nfsd_inject_add_lock_to_list(lst,
+-                                                              collect);
++                                      if (func(lst))
++                                              nfsd_inject_add_lock_to_list(lst,
++                                                                      collect);
+                               }
+                               ++count;
+                               /*
diff --git a/queue-4.1/nfsd-fix-an-fs_layout_types-layout_types-encode-bug.patch b/queue-4.1/nfsd-fix-an-fs_layout_types-layout_types-encode-bug.patch
new file mode 100644 (file)
index 0000000..2bbeb84
--- /dev/null
@@ -0,0 +1,83 @@
+From 6896f15aabde505b35888039af93d1d182a0108a Mon Sep 17 00:00:00 2001
+From: Kinglong Mee <kinglongmee@gmail.com>
+Date: Thu, 30 Jul 2015 21:52:44 +0800
+Subject: nfsd: Fix an FS_LAYOUT_TYPES/LAYOUT_TYPES encode bug
+
+From: Kinglong Mee <kinglongmee@gmail.com>
+
+commit 6896f15aabde505b35888039af93d1d182a0108a upstream.
+
+Currently we'll respond correctly to a request for either
+FS_LAYOUT_TYPES or LAYOUT_TYPES, but not to a request for both
+attributes simultaneously.
+
+Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/nfs4xdr.c |   45 +++++++++++++++++++++++++++++++--------------
+ 1 file changed, 31 insertions(+), 14 deletions(-)
+
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -2139,6 +2139,27 @@ nfsd4_encode_aclname(struct xdr_stream *
+               return nfsd4_encode_user(xdr, rqstp, ace->who_uid);
+ }
++static inline __be32
++nfsd4_encode_layout_type(struct xdr_stream *xdr, enum pnfs_layouttype layout_type)
++{
++      __be32 *p;
++
++      if (layout_type) {
++              p = xdr_reserve_space(xdr, 8);
++              if (!p)
++                      return nfserr_resource;
++              *p++ = cpu_to_be32(1);
++              *p++ = cpu_to_be32(layout_type);
++      } else {
++              p = xdr_reserve_space(xdr, 4);
++              if (!p)
++                      return nfserr_resource;
++              *p++ = cpu_to_be32(0);
++      }
++
++      return 0;
++}
++
+ #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
+                             FATTR4_WORD0_RDATTR_ERROR)
+ #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
+@@ -2692,20 +2713,16 @@ out_acl:
+               p = xdr_encode_hyper(p, stat.ino);
+       }
+ #ifdef CONFIG_NFSD_PNFS
+-      if ((bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) ||
+-          (bmval2 & FATTR4_WORD2_LAYOUT_TYPES)) {
+-              if (exp->ex_layout_type) {
+-                      p = xdr_reserve_space(xdr, 8);
+-                      if (!p)
+-                              goto out_resource;
+-                      *p++ = cpu_to_be32(1);
+-                      *p++ = cpu_to_be32(exp->ex_layout_type);
+-              } else {
+-                      p = xdr_reserve_space(xdr, 4);
+-                      if (!p)
+-                              goto out_resource;
+-                      *p++ = cpu_to_be32(0);
+-              }
++      if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
++              status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
++              if (status)
++                      goto out;
++      }
++
++      if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
++              status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
++              if (status)
++                      goto out;
+       }
+       if (bmval2 & FATTR4_WORD2_LAYOUT_BLKSIZE) {
diff --git a/queue-4.1/nfsv4-don-t-set-setattr-for-o_rdonly-o_excl.patch b/queue-4.1/nfsv4-don-t-set-setattr-for-o_rdonly-o_excl.patch
new file mode 100644 (file)
index 0000000..6b192cd
--- /dev/null
@@ -0,0 +1,50 @@
+From efcbc04e16dfa95fef76309f89710dd1d99a5453 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.com>
+Date: Thu, 30 Jul 2015 13:00:56 +1000
+Subject: NFSv4: don't set SETATTR for O_RDONLY|O_EXCL
+
+From: NeilBrown <neilb@suse.com>
+
+commit efcbc04e16dfa95fef76309f89710dd1d99a5453 upstream.
+
+It is unusual to combine the open flags O_RDONLY and O_EXCL, but
+it appears that libre-office does just that.
+
+[pid  3250] stat("/home/USER/.config", {st_mode=S_IFDIR|0700, st_size=8192, ...}) = 0
+[pid  3250] open("/home/USER/.config/libreoffice/4-suse/user/extensions/buildid", O_RDONLY|O_EXCL <unfinished ...>
+
+NFSv4 takes O_EXCL as a sign that a setattr command should be sent,
+probably to reset the timestamps.
+
+When it was an O_RDONLY open, the SETATTR command does not
+identify any actual attributes to change.
+If no delegation was provided to the open, the SETATTR uses the
+all-zeros stateid and the request is accepted (at least by the
+Linux NFS server - no harm, no foul).
+
+If a read-delegation was provided, this is used in the SETATTR
+request, and a Netapp filer will justifiably claim
+NFS4ERR_BAD_STATEID, which the Linux client takes as a sign
+to retry - indefinitely.
+
+So only treat O_EXCL specially if O_CREAT was also given.
+
+Signed-off-by: NeilBrown <neilb@suse.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2413,7 +2413,7 @@ static int _nfs4_do_open(struct inode *d
+               goto err_free_label;
+       state = ctx->state;
+-      if ((opendata->o_arg.open_flags & O_EXCL) &&
++      if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) &&
+           (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
+               nfs4_exclusive_attrset(opendata, sattr);
diff --git a/queue-4.1/nfsv4-pnfs-ensure-we-don-t-miss-a-file-extension.patch b/queue-4.1/nfsv4-pnfs-ensure-we-don-t-miss-a-file-extension.patch
new file mode 100644 (file)
index 0000000..43925da
--- /dev/null
@@ -0,0 +1,58 @@
+From 2b83d3de4c18af49800e0b26ae013db4fcf43a4a Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Sun, 5 Jul 2015 20:06:38 -0400
+Subject: NFSv4/pnfs: Ensure we don't miss a file extension
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 2b83d3de4c18af49800e0b26ae013db4fcf43a4a upstream.
+
+pNFS writes don't return attributes, however that doesn't mean that we
+should ignore the fact that they may be extending the file. This patch
+ensures that if a write is seen to extend the file, then we always set
+an attribute barrier, and update the cached file size.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Cc: Peng Tao <tao.peng@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/write.c |   15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -1383,24 +1383,27 @@ static void nfs_writeback_check_extend(s
+ {
+       struct nfs_pgio_args *argp = &hdr->args;
+       struct nfs_pgio_res *resp = &hdr->res;
++      u64 size = argp->offset + resp->count;
+       if (!(fattr->valid & NFS_ATTR_FATTR_SIZE))
++              fattr->size = size;
++      if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode)) {
++              fattr->valid &= ~NFS_ATTR_FATTR_SIZE;
+               return;
+-      if (argp->offset + resp->count != fattr->size)
+-              return;
+-      if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode))
++      }
++      if (size != fattr->size)
+               return;
+       /* Set attribute barrier */
+       nfs_fattr_set_barrier(fattr);
++      /* ...and update size */
++      fattr->valid |= NFS_ATTR_FATTR_SIZE;
+ }
+ void nfs_writeback_update_inode(struct nfs_pgio_header *hdr)
+ {
+-      struct nfs_fattr *fattr = hdr->res.fattr;
++      struct nfs_fattr *fattr = &hdr->fattr;
+       struct inode *inode = hdr->inode;
+-      if (fattr == NULL)
+-              return;
+       spin_lock(&inode->i_lock);
+       nfs_writeback_check_extend(hdr, fattr);
+       nfs_post_op_update_inode_force_wcc_locked(inode, fattr);
diff --git a/queue-4.1/nfsv4.1-pnfs-fix-borken-function-_same_data_server_addrs_locked.patch b/queue-4.1/nfsv4.1-pnfs-fix-borken-function-_same_data_server_addrs_locked.patch
new file mode 100644 (file)
index 0000000..f10a2d4
--- /dev/null
@@ -0,0 +1,69 @@
+From 6f536936b79bd4b5cea8fb0e5b8b0bce8cd1ea4a Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Thu, 13 Aug 2015 10:59:07 -0400
+Subject: NFSv4.1/pNFS: Fix borken function _same_data_server_addrs_locked()
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 6f536936b79bd4b5cea8fb0e5b8b0bce8cd1ea4a upstream.
+
+- Switch back to using list_for_each_entry(). Fixes an incorrect test
+  for list NULL termination.
+- Do not assume that lists are sorted.
+- Finally, consider an existing entry to match if it consists of a subset
+  of the addresses in the new entry.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/pnfs_nfs.c |   31 ++++++++++++++++++-------------
+ 1 file changed, 18 insertions(+), 13 deletions(-)
+
+--- a/fs/nfs/pnfs_nfs.c
++++ b/fs/nfs/pnfs_nfs.c
+@@ -359,26 +359,31 @@ same_sockaddr(struct sockaddr *addr1, st
+       return false;
+ }
++/*
++ * Checks if 'dsaddrs1' contains a subset of 'dsaddrs2'. If it does,
++ * declare a match.
++ */
+ static bool
+ _same_data_server_addrs_locked(const struct list_head *dsaddrs1,
+                              const struct list_head *dsaddrs2)
+ {
+       struct nfs4_pnfs_ds_addr *da1, *da2;
++      struct sockaddr *sa1, *sa2;
++      bool match = false;
+-      /* step through both lists, comparing as we go */
+-      for (da1 = list_first_entry(dsaddrs1, typeof(*da1), da_node),
+-           da2 = list_first_entry(dsaddrs2, typeof(*da2), da_node);
+-           da1 != NULL && da2 != NULL;
+-           da1 = list_entry(da1->da_node.next, typeof(*da1), da_node),
+-           da2 = list_entry(da2->da_node.next, typeof(*da2), da_node)) {
+-              if (!same_sockaddr((struct sockaddr *)&da1->da_addr,
+-                                 (struct sockaddr *)&da2->da_addr))
+-                      return false;
++      list_for_each_entry(da1, dsaddrs1, da_node) {
++              sa1 = (struct sockaddr *)&da1->da_addr;
++              match = false;
++              list_for_each_entry(da2, dsaddrs2, da_node) {
++                      sa2 = (struct sockaddr *)&da2->da_addr;
++                      match = same_sockaddr(sa1, sa2);
++                      if (match)
++                              break;
++              }
++              if (!match)
++                      break;
+       }
+-      if (da1 == NULL && da2 == NULL)
+-              return true;
+-
+-      return false;
++      return match;
+ }
+ /*
diff --git a/queue-4.1/rc-core-fix-remove-uevent-generation.patch b/queue-4.1/rc-core-fix-remove-uevent-generation.patch
new file mode 100644 (file)
index 0000000..e468963
--- /dev/null
@@ -0,0 +1,36 @@
+From a66b0c41ad277ae62a3ae6ac430a71882f899557 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?David=20H=C3=A4rdeman?= <david@hardeman.nu>
+Date: Tue, 19 May 2015 19:03:12 -0300
+Subject: [media] rc-core: fix remove uevent generation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?David=20H=C3=A4rdeman?= <david@hardeman.nu>
+
+commit a66b0c41ad277ae62a3ae6ac430a71882f899557 upstream.
+
+The input_dev is already gone when the rc device is being unregistered
+so checking for its presence only means that no remove uevent will be
+generated.
+
+Signed-off-by: David Härdeman <david@hardeman.nu>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/rc/rc-main.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/media/rc/rc-main.c
++++ b/drivers/media/rc/rc-main.c
+@@ -1191,9 +1191,6 @@ static int rc_dev_uevent(struct device *
+ {
+       struct rc_dev *dev = to_rc_dev(device);
+-      if (!dev || !dev->input_dev)
+-              return -ENODEV;
+-
+       if (dev->rc_map.name)
+               ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
+       if (dev->driver_name)
index 4f38cc02e1d5fba8676d6e54f908510d7a0657e7..d27a27eec9b7c6635ec20e930034c34c3a141bb3 100644 (file)
@@ -45,3 +45,15 @@ add-radeon-suspend-resume-quirk-for-hp-compaq-dc5750.patch
 mm-check-if-section-present-during-memory-block-registering.patch
 x86-mm-initialize-pmd_idx-in-page_table_range_init_count.patch
 mm-make-page-pfmemalloc-check-more-robust.patch
+rc-core-fix-remove-uevent-generation.patch
+v4l-omap3isp-fix-sub-device-power-management-code.patch
+media-am437x-vpfe-requested-frame-size-and-fmt-overwritten-by-current-sensor-setting.patch
+media-am437x-vpfe-fix-a-race-condition-during-release.patch
+btrfs-check-if-previous-transaction-aborted-to-avoid-fs-corruption.patch
+nfsv4-pnfs-ensure-we-don-t-miss-a-file-extension.patch
+nfsd-fix-an-fs_layout_types-layout_types-encode-bug.patch
+nfsd-ensure-that-the-ol-stateid-hash-reference-is-only-put-once.patch
+nfsd-ensure-that-delegation-stateid-hash-references-are-only-put-once.patch
+nfsv4-don-t-set-setattr-for-o_rdonly-o_excl.patch
+nfs-don-t-let-the-ctime-override-attribute-barriers.patch
+nfsv4.1-pnfs-fix-borken-function-_same_data_server_addrs_locked.patch
diff --git a/queue-4.1/v4l-omap3isp-fix-sub-device-power-management-code.patch b/queue-4.1/v4l-omap3isp-fix-sub-device-power-management-code.patch
new file mode 100644 (file)
index 0000000..142b461
--- /dev/null
@@ -0,0 +1,46 @@
+From 9d39f05490115bf145e5ea03c0b7ec9d3d015b01 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@iki.fi>
+Date: Fri, 12 Jun 2015 20:06:23 -0300
+Subject: [media] v4l: omap3isp: Fix sub-device power management code
+
+From: Sakari Ailus <sakari.ailus@iki.fi>
+
+commit 9d39f05490115bf145e5ea03c0b7ec9d3d015b01 upstream.
+
+Commit 813f5c0ac5cc ("media: Change media device link_notify behaviour")
+modified the media controller link setup notification API and updated the
+OMAP3 ISP driver accordingly. As a side effect it introduced a bug by
+turning power on after setting the link instead of before. This results in
+sub-devices not being powered down in some cases when they should be. Fix
+it.
+
+Fixes: 813f5c0ac5cc [media] media: Change media device link_notify behaviour
+
+Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/platform/omap3isp/isp.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/platform/omap3isp/isp.c
++++ b/drivers/media/platform/omap3isp/isp.c
+@@ -829,14 +829,14 @@ static int isp_pipeline_link_notify(stru
+       int ret;
+       if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
+-          !(link->flags & MEDIA_LNK_FL_ENABLED)) {
++          !(flags & MEDIA_LNK_FL_ENABLED)) {
+               /* Powering off entities is assumed to never fail. */
+               isp_pipeline_pm_power(source, -sink_use);
+               isp_pipeline_pm_power(sink, -source_use);
+               return 0;
+       }
+-      if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
++      if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH &&
+               (flags & MEDIA_LNK_FL_ENABLED)) {
+               ret = isp_pipeline_pm_power(source, sink_use);