From: Greg Kroah-Hartman Date: Wed, 5 Mar 2014 18:51:23 +0000 (-0800) Subject: 3.4-stable patches X-Git-Tag: v3.10.33~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ca29d55a50afce4a0d476044d2421f163eef070d;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: cifs-adjust-sequence-number-downward-after-signing-nt_cancel-request.patch cifs-don-t-instantiate-new-dentries-in-readdir-for-inodes-that-need-to-be-revalidated-immediately.patch ext4-fix-possible-use-after-free-with-aio.patch ext4-jbd2-don-t-wait-forever-for-stale-tid-caused-by-wraparound.patch ncpfs-fix-rmdir-returns-device-or-resource-busy.patch ubifs-fix-double-free-of-ubifs_orphan-objects.patch --- diff --git a/queue-3.4/cifs-adjust-sequence-number-downward-after-signing-nt_cancel-request.patch b/queue-3.4/cifs-adjust-sequence-number-downward-after-signing-nt_cancel-request.patch new file mode 100644 index 00000000000..e13dd716300 --- /dev/null +++ b/queue-3.4/cifs-adjust-sequence-number-downward-after-signing-nt_cancel-request.patch @@ -0,0 +1,44 @@ +From f6f82cba2ccbf6a77278c7c3f2e4daf23063944a Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 27 Dec 2012 08:05:03 -0500 +Subject: cifs: adjust sequence number downward after signing NT_CANCEL request + +From: Jeff Layton + +commit 31efee60f489c759c341454d755a9fd13de8c03d upstream. + +When a call goes out, the signing code adjusts the sequence number +upward by two to account for the request and the response. An NT_CANCEL +however doesn't get a response of its own, it just hurries the server +along to get it to respond to the original request more quickly. +Therefore, we must adjust the sequence number back down by one after +signing a NT_CANCEL request. + +Reported-by: Tim Perry +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +[bwh: Backported to 3.2: adjust filename] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/transport.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -511,6 +511,13 @@ send_nt_cancel(struct TCP_Server_Info *s + mutex_unlock(&server->srv_mutex); + return rc; + } ++ ++ /* ++ * The response to this call was already factored into the sequence ++ * number when the call went out, so we must adjust it back downward ++ * after signing here. ++ */ ++ --server->sequence_number; + rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); + mutex_unlock(&server->srv_mutex); + diff --git a/queue-3.4/cifs-don-t-instantiate-new-dentries-in-readdir-for-inodes-that-need-to-be-revalidated-immediately.patch b/queue-3.4/cifs-don-t-instantiate-new-dentries-in-readdir-for-inodes-that-need-to-be-revalidated-immediately.patch new file mode 100644 index 00000000000..666b1edcc20 --- /dev/null +++ b/queue-3.4/cifs-don-t-instantiate-new-dentries-in-readdir-for-inodes-that-need-to-be-revalidated-immediately.patch @@ -0,0 +1,51 @@ +From eb4a22ba43d91d58a35bc4fce11d8e6065bb4e1d Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Wed, 7 Aug 2013 10:29:08 -0400 +Subject: cifs: don't instantiate new dentries in readdir for inodes that need to be revalidated immediately + +From: Jeff Layton + +commit 757c4f6260febff982276818bb946df89c1105aa upstream. + +David reported that commit c2b93e06 (cifs: only set ops for inodes in +I_NEW state) caused a regression with mfsymlinks. Prior to that patch, +if a mfsymlink dentry was instantiated at readdir time, the inode would +get a new set of ops when it was revalidated. After that patch, this +did not occur. + +This patch addresses this by simply skipping instantiating dentries in +the readdir codepath when we know that they will need to be immediately +revalidated. The next attempt to use that dentry will cause a new lookup +to occur (which is basically what we want to happen anyway). + +Cc: "Stefan (metze) Metzmacher" +Cc: Sachin Prabhu +Reported-and-Tested-by: David McBride +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +[bwh: Backported to 3.2: need to return NULL] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/readdir.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -96,6 +96,14 @@ cifs_readdir_lookup(struct dentry *paren + dput(dentry); + } + ++ /* ++ * If we know that the inode will need to be revalidated immediately, ++ * then don't create a new dentry for it. We'll end up doing an on ++ * the wire call either way and this spares us an invalidation. ++ */ ++ if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) ++ return NULL; ++ + dentry = d_alloc(parent, name); + if (dentry == NULL) + return NULL; diff --git a/queue-3.4/ext4-fix-possible-use-after-free-with-aio.patch b/queue-3.4/ext4-fix-possible-use-after-free-with-aio.patch new file mode 100644 index 00000000000..1150c9d2f05 --- /dev/null +++ b/queue-3.4/ext4-fix-possible-use-after-free-with-aio.patch @@ -0,0 +1,62 @@ +From 3e411534ea3be89a7d0ddf4e62e5c5b79d80556a Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 29 Jan 2013 22:48:17 -0500 +Subject: ext4: fix possible use-after-free with AIO + +From: Jan Kara + +commit 091e26dfc156aeb3b73bc5c5f277e433ad39331c upstream. + +Running AIO is pinning inode in memory using file reference. Once AIO +is completed using aio_complete(), file reference is put and inode can +be freed from memory. So we have to be sure that calling aio_complete() +is the last thing we do with the inode. + +Reviewed-by: Carlos Maiolino +Acked-by: Jeff Moyer +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 2 +- + fs/ext4/page-io.c | 9 ++++----- + 2 files changed, 5 insertions(+), 6 deletions(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2800,9 +2800,9 @@ static void ext4_end_io_dio(struct kiocb + if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { + ext4_free_io_end(io_end); + out: ++ inode_dio_done(inode); + if (is_async) + aio_complete(iocb, ret, 0); +- inode_dio_done(inode); + return; + } + +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -107,14 +107,13 @@ int ext4_end_io_nolock(ext4_io_end_t *io + inode->i_ino, offset, size, ret); + } + +- if (io->iocb) +- aio_complete(io->iocb, io->result, 0); +- +- if (io->flag & EXT4_IO_END_DIRECT) +- inode_dio_done(inode); + /* Wake up anyone waiting on unwritten extent conversion */ + if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) + wake_up_all(ext4_ioend_wq(io->inode)); ++ if (io->flag & EXT4_IO_END_DIRECT) ++ inode_dio_done(inode); ++ if (io->iocb) ++ aio_complete(io->iocb, io->result, 0); + return ret; + } + diff --git a/queue-3.4/ext4-jbd2-don-t-wait-forever-for-stale-tid-caused-by-wraparound.patch b/queue-3.4/ext4-jbd2-don-t-wait-forever-for-stale-tid-caused-by-wraparound.patch new file mode 100644 index 00000000000..d12558bdb63 --- /dev/null +++ b/queue-3.4/ext4-jbd2-don-t-wait-forever-for-stale-tid-caused-by-wraparound.patch @@ -0,0 +1,121 @@ +From 164ed4383ca615f9a4f19673ac82372ccf96a33f Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 3 Apr 2013 22:02:52 -0400 +Subject: ext4/jbd2: don't wait (forever) for stale tid caused by wraparound + +From: Theodore Ts'o + +commit d76a3a77113db020d9bb1e894822869410450bd9 upstream. + +In the case where an inode has a very stale transaction id (tid) in +i_datasync_tid or i_sync_tid, it's possible that after a very large +(2**31) number of transactions, that the tid number space might wrap, +causing tid_geq()'s calculations to fail. + +Commit deeeaf13 "jbd2: fix fsync() tid wraparound bug", later modified +by commit e7b04ac0 "jbd2: don't wake kjournald unnecessarily", +attempted to fix this problem, but it only avoided kjournald spinning +forever by fixing the logic in jbd2_log_start_commit(). + +Unfortunately, in the codepaths in fs/ext4/fsync.c and fs/ext4/inode.c +that might call jbd2_log_start_commit() with a stale tid, those +functions will subsequently call jbd2_log_wait_commit() with the same +stale tid, and then wait for a very long time. To fix this, we +replace the calls to jbd2_log_start_commit() and +jbd2_log_wait_commit() with a call to a new function, +jbd2_complete_transaction(), which will correctly handle stale tid's. + +As a bonus, jbd2_complete_transaction() will avoid locking +j_state_lock for writing unless a commit needs to be started. This +should have a small (but probably not measurable) improvement for +ext4's scalability. + +Signed-off-by: "Theodore Ts'o" +Reported-by: Ben Hutchings +Reported-by: George Barnett +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/fsync.c | 3 +-- + fs/ext4/inode.c | 3 +-- + fs/jbd2/journal.c | 31 +++++++++++++++++++++++++++++++ + include/linux/jbd2.h | 1 + + 4 files changed, 34 insertions(+), 4 deletions(-) + +--- a/fs/ext4/fsync.c ++++ b/fs/ext4/fsync.c +@@ -260,8 +260,7 @@ int ext4_sync_file(struct file *file, lo + if (journal->j_flags & JBD2_BARRIER && + !jbd2_trans_will_send_data_barrier(journal, commit_tid)) + needs_barrier = true; +- jbd2_log_start_commit(journal, commit_tid); +- ret = jbd2_log_wait_commit(journal, commit_tid); ++ ret = jbd2_complete_transaction(journal, commit_tid); + if (needs_barrier) + blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + out: +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -149,8 +149,7 @@ void ext4_evict_inode(struct inode *inod + journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; + tid_t commit_tid = EXT4_I(inode)->i_datasync_tid; + +- jbd2_log_start_commit(journal, commit_tid); +- jbd2_log_wait_commit(journal, commit_tid); ++ jbd2_complete_transaction(journal, commit_tid); + filemap_write_and_wait(&inode->i_data); + } + truncate_inode_pages(&inode->i_data, 0); +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -662,6 +662,37 @@ int jbd2_log_wait_commit(journal_t *jour + } + + /* ++ * When this function returns the transaction corresponding to tid ++ * will be completed. If the transaction has currently running, start ++ * committing that transaction before waiting for it to complete. If ++ * the transaction id is stale, it is by definition already completed, ++ * so just return SUCCESS. ++ */ ++int jbd2_complete_transaction(journal_t *journal, tid_t tid) ++{ ++ int need_to_wait = 1; ++ ++ read_lock(&journal->j_state_lock); ++ if (journal->j_running_transaction && ++ journal->j_running_transaction->t_tid == tid) { ++ if (journal->j_commit_request != tid) { ++ /* transaction not yet started, so request it */ ++ read_unlock(&journal->j_state_lock); ++ jbd2_log_start_commit(journal, tid); ++ goto wait_commit; ++ } ++ } else if (!(journal->j_committing_transaction && ++ journal->j_committing_transaction->t_tid == tid)) ++ need_to_wait = 0; ++ read_unlock(&journal->j_state_lock); ++ if (!need_to_wait) ++ return 0; ++wait_commit: ++ return jbd2_log_wait_commit(journal, tid); ++} ++EXPORT_SYMBOL(jbd2_complete_transaction); ++ ++/* + * Log buffer allocation routines: + */ + +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1178,6 +1178,7 @@ int __jbd2_log_start_commit(journal_t *j + int jbd2_journal_start_commit(journal_t *journal, tid_t *tid); + int jbd2_journal_force_commit_nested(journal_t *journal); + int jbd2_log_wait_commit(journal_t *journal, tid_t tid); ++int jbd2_complete_transaction(journal_t *journal, tid_t tid); + int jbd2_log_do_checkpoint(journal_t *journal); + int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid); + diff --git a/queue-3.4/ncpfs-fix-rmdir-returns-device-or-resource-busy.patch b/queue-3.4/ncpfs-fix-rmdir-returns-device-or-resource-busy.patch new file mode 100644 index 00000000000..535dcf9336f --- /dev/null +++ b/queue-3.4/ncpfs-fix-rmdir-returns-device-or-resource-busy.patch @@ -0,0 +1,47 @@ +From 21544884d7d5f8890314271c158926ca0de43719 Mon Sep 17 00:00:00 2001 +From: Dave Chiluk +Date: Tue, 28 May 2013 16:06:08 -0500 +Subject: ncpfs: fix rmdir returns Device or resource busy + +From: Dave Chiluk + +commit 698b8223631472bf982ed570b0812faa61955683 upstream. + +1d2ef5901483004d74947bbf78d5146c24038fe7 caused a regression in ncpfs such that +directories could no longer be removed. This was because ncp_rmdir checked +to see if a dentry could be unhashed before allowing it to be removed. Since +1d2ef5901483004d74947bbf78d5146c24038fe7 introduced a change that incremented +dentry->d_count causing it to always be greater than 1 unhash would always +fail. Thus causing the error path in ncp_rmdir to always be taken. Removing +this error path is safe as unhashing is still accomplished by calls to dput +from vfs_rmdir. + +Signed-off-by: Dave Chiluk +Signed-off-by: Petr Vandrovec +Signed-off-by: Al Viro +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ncpfs/dir.c | 9 --------- + 1 file changed, 9 deletions(-) + +--- a/fs/ncpfs/dir.c ++++ b/fs/ncpfs/dir.c +@@ -1033,15 +1033,6 @@ static int ncp_rmdir(struct inode *dir, + DPRINTK("ncp_rmdir: removing %s/%s\n", + dentry->d_parent->d_name.name, dentry->d_name.name); + +- /* +- * fail with EBUSY if there are still references to this +- * directory. +- */ +- dentry_unhash(dentry); +- error = -EBUSY; +- if (!d_unhashed(dentry)) +- goto out; +- + len = sizeof(__name); + error = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); diff --git a/queue-3.4/series b/queue-3.4/series index 51dcb439192..261f2f05c2e 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -55,3 +55,9 @@ nilfs2-fix-issue-with-race-condition-of-competition-between-segments-for-dirty-b fuse-readdir-check-for-slash-in-names.patch fuse-hotfix-truncate_pagecache-issue.patch libceph-unregister-request-in-__map_request-failed-and-nofail-false.patch +cifs-don-t-instantiate-new-dentries-in-readdir-for-inodes-that-need-to-be-revalidated-immediately.patch +ncpfs-fix-rmdir-returns-device-or-resource-busy.patch +ext4-jbd2-don-t-wait-forever-for-stale-tid-caused-by-wraparound.patch +ubifs-fix-double-free-of-ubifs_orphan-objects.patch +ext4-fix-possible-use-after-free-with-aio.patch +cifs-adjust-sequence-number-downward-after-signing-nt_cancel-request.patch diff --git a/queue-3.4/ubifs-fix-double-free-of-ubifs_orphan-objects.patch b/queue-3.4/ubifs-fix-double-free-of-ubifs_orphan-objects.patch new file mode 100644 index 00000000000..27d08dcbbd7 --- /dev/null +++ b/queue-3.4/ubifs-fix-double-free-of-ubifs_orphan-objects.patch @@ -0,0 +1,81 @@ +From 2ff3ae3932b9ca1152c1835f674048c4cd227db7 Mon Sep 17 00:00:00 2001 +From: Adam Thomas +Date: Sat, 2 Feb 2013 22:35:08 +0000 +Subject: UBIFS: fix double free of ubifs_orphan objects + +From: Adam Thomas + +commit 8afd500cb52a5d00bab4525dd5a560d199f979b9 upstream. + +The last orphan in the dnext list has its dnext set to NULL. Because +of that, ubifs_delete_orphan assumes that it is not on the dnext list +and frees it immediately instead ignoring it as a second delete. The +orphan is later freed again by erase_deleted. + +This change adds an explicit flag to ubifs_orphan indicating whether +it is pending delete. + +Signed-off-by: Adam Thomas +Signed-off-by: Artem Bityutskiy +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/orphan.c | 5 ++++- + fs/ubifs/ubifs.h | 2 ++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/ubifs/orphan.c ++++ b/fs/ubifs/orphan.c +@@ -130,13 +130,14 @@ void ubifs_delete_orphan(struct ubifs_in + else if (inum > o->inum) + p = p->rb_right; + else { +- if (o->dnext) { ++ if (o->del) { + spin_unlock(&c->orphan_lock); + dbg_gen("deleted twice ino %lu", + (unsigned long)inum); + return; + } + if (o->cnext) { ++ o->del = 1; + o->dnext = c->orph_dnext; + c->orph_dnext = o; + spin_unlock(&c->orphan_lock); +@@ -447,6 +448,7 @@ static void erase_deleted(struct ubifs_i + orphan = dnext; + dnext = orphan->dnext; + ubifs_assert(!orphan->new); ++ ubifs_assert(orphan->del); + rb_erase(&orphan->rb, &c->orph_tree); + list_del(&orphan->list); + c->tot_orphans -= 1; +@@ -536,6 +538,7 @@ static int insert_dead_orphan(struct ubi + rb_link_node(&orphan->rb, parent, p); + rb_insert_color(&orphan->rb, &c->orph_tree); + list_add_tail(&orphan->list, &c->orph_list); ++ orphan->del = 1; + orphan->dnext = c->orph_dnext; + c->orph_dnext = orphan; + dbg_mnt("ino %lu, new %d, tot %d", (unsigned long)inum, +--- a/fs/ubifs/ubifs.h ++++ b/fs/ubifs/ubifs.h +@@ -905,6 +905,7 @@ struct ubifs_budget_req { + * @dnext: next orphan to delete + * @inum: inode number + * @new: %1 => added since the last commit, otherwise %0 ++ * @del: %1 => delete pending, otherwise %0 + */ + struct ubifs_orphan { + struct rb_node rb; +@@ -914,6 +915,7 @@ struct ubifs_orphan { + struct ubifs_orphan *dnext; + ino_t inum; + int new; ++ unsigned del:1; + }; + + /**