From: Greg Kroah-Hartman Date: Sat, 26 Sep 2015 03:48:37 +0000 (-0700) Subject: 4.1-stable patches X-Git-Tag: v4.1.9~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c0f5f476de43fa11c74b6a3a7b8cbe2802878e05;p=thirdparty%2Fkernel%2Fstable-queue.git 4.1-stable patches 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 --- 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 index 00000000000..837c1801d35 --- /dev/null +++ b/queue-4.1/btrfs-check-if-previous-transaction-aborted-to-avoid-fs-corruption.patch @@ -0,0 +1,108 @@ +From 1f9b8c8fbc9a4d029760b16f477b9d15500e3a34 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Wed, 12 Aug 2015 11:54:35 +0100 +Subject: Btrfs: check if previous transaction aborted to avoid fs corruption + +From: Filipe Manana + +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 +Reviewed-by: Josef Bacik +Reviewed-by: Liu Bo +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..1032eb8ff5d --- /dev/null +++ b/queue-4.1/media-am437x-vpfe-fix-a-race-condition-during-release.patch @@ -0,0 +1,53 @@ +From c99235fa3ef833c3c23926085f2bb68851c8460a Mon Sep 17 00:00:00 2001 +From: Benoit Parrot +Date: Wed, 15 Jul 2015 18:00:06 -0300 +Subject: [media] media: am437x-vpfe: Fix a race condition during release + +From: Benoit Parrot + +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 +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0ce81668fba --- /dev/null +++ b/queue-4.1/media-am437x-vpfe-requested-frame-size-and-fmt-overwritten-by-current-sensor-setting.patch @@ -0,0 +1,36 @@ +From f47c9045643f91e76d8a9030828b9fe1cf4a6bcf Mon Sep 17 00:00:00 2001 +From: Benoit Parrot +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 + +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 +Acked-by: Lad, Prabhakar +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..8b8de938438 --- /dev/null +++ b/queue-4.1/nfs-don-t-let-the-ctime-override-attribute-barriers.patch @@ -0,0 +1,52 @@ +From 7c2dad99d60c86ec686b3bfdcb787c450a7ea89f Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Thu, 6 Aug 2015 12:06:30 -0400 +Subject: NFS: Don't let the ctime override attribute barriers. + +From: Trond Myklebust + +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 +Fixes: a08a8cd375db9 ("NFS: Add attribute update barriers to NFS writebacks") +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7c6d408d839 --- /dev/null +++ b/queue-4.1/nfsd-ensure-that-delegation-stateid-hash-references-are-only-put-once.patch @@ -0,0 +1,115 @@ +From 3fcbbd244ed1d20dc0eb7d48d729503992fa9b7d Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Mon, 24 Aug 2015 12:41:48 -0400 +Subject: nfsd: ensure that delegation stateid hash references are only put once + +From: Jeff Layton + +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 +Tested-by: Anna Schumaker +Signed-off-by: Jeff Layton +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6fcb3bd3ce5 --- /dev/null +++ b/queue-4.1/nfsd-ensure-that-the-ol-stateid-hash-reference-is-only-put-once.patch @@ -0,0 +1,209 @@ +From e85687393f3ee0a77ccca016f903d1558bb69258 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +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 + +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 +Tested-by: Andrew W Elble +Reported-by: Anna Schumaker +Tested-by: Anna Schumaker +Signed-off-by: Jeff Layton +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2bbeb843faa --- /dev/null +++ b/queue-4.1/nfsd-fix-an-fs_layout_types-layout_types-encode-bug.patch @@ -0,0 +1,83 @@ +From 6896f15aabde505b35888039af93d1d182a0108a Mon Sep 17 00:00:00 2001 +From: Kinglong Mee +Date: Thu, 30 Jul 2015 21:52:44 +0800 +Subject: nfsd: Fix an FS_LAYOUT_TYPES/LAYOUT_TYPES encode bug + +From: Kinglong Mee + +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6b192cd21ac --- /dev/null +++ b/queue-4.1/nfsv4-don-t-set-setattr-for-o_rdonly-o_excl.patch @@ -0,0 +1,50 @@ +From efcbc04e16dfa95fef76309f89710dd1d99a5453 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Thu, 30 Jul 2015 13:00:56 +1000 +Subject: NFSv4: don't set SETATTR for O_RDONLY|O_EXCL + +From: NeilBrown + +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 + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..43925dafd78 --- /dev/null +++ b/queue-4.1/nfsv4-pnfs-ensure-we-don-t-miss-a-file-extension.patch @@ -0,0 +1,58 @@ +From 2b83d3de4c18af49800e0b26ae013db4fcf43a4a Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Sun, 5 Jul 2015 20:06:38 -0400 +Subject: NFSv4/pnfs: Ensure we don't miss a file extension + +From: Trond Myklebust + +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 +Cc: Peng Tao +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f10a2d46861 --- /dev/null +++ b/queue-4.1/nfsv4.1-pnfs-fix-borken-function-_same_data_server_addrs_locked.patch @@ -0,0 +1,69 @@ +From 6f536936b79bd4b5cea8fb0e5b8b0bce8cd1ea4a Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Thu, 13 Aug 2015 10:59:07 -0400 +Subject: NFSv4.1/pNFS: Fix borken function _same_data_server_addrs_locked() + +From: Trond Myklebust + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..e468963a8b7 --- /dev/null +++ b/queue-4.1/rc-core-fix-remove-uevent-generation.patch @@ -0,0 +1,36 @@ +From a66b0c41ad277ae62a3ae6ac430a71882f899557 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20H=C3=A4rdeman?= +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?= + +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 +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-4.1/series b/queue-4.1/series index 4f38cc02e1d..d27a27eec9b 100644 --- a/queue-4.1/series +++ b/queue-4.1/series @@ -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 index 00000000000..142b461ecdd --- /dev/null +++ b/queue-4.1/v4l-omap3isp-fix-sub-device-power-management-code.patch @@ -0,0 +1,46 @@ +From 9d39f05490115bf145e5ea03c0b7ec9d3d015b01 Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Fri, 12 Jun 2015 20:06:23 -0300 +Subject: [media] v4l: omap3isp: Fix sub-device power management code + +From: Sakari Ailus + +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 +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + 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);