]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Mar 2014 18:51:23 +0000 (10:51 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Mar 2014 18:51:23 +0000 (10:51 -0800)
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

queue-3.4/cifs-adjust-sequence-number-downward-after-signing-nt_cancel-request.patch [new file with mode: 0644]
queue-3.4/cifs-don-t-instantiate-new-dentries-in-readdir-for-inodes-that-need-to-be-revalidated-immediately.patch [new file with mode: 0644]
queue-3.4/ext4-fix-possible-use-after-free-with-aio.patch [new file with mode: 0644]
queue-3.4/ext4-jbd2-don-t-wait-forever-for-stale-tid-caused-by-wraparound.patch [new file with mode: 0644]
queue-3.4/ncpfs-fix-rmdir-returns-device-or-resource-busy.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/ubifs-fix-double-free-of-ubifs_orphan-objects.patch [new file with mode: 0644]

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 (file)
index 0000000..e13dd71
--- /dev/null
@@ -0,0 +1,44 @@
+From f6f82cba2ccbf6a77278c7c3f2e4daf23063944a Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Thu, 27 Dec 2012 08:05:03 -0500
+Subject: cifs: adjust sequence number downward after signing NT_CANCEL request
+
+From: Jeff Layton <jlayton@redhat.com>
+
+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 <tdparmor-sambabugs@yahoo.com>
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+[bwh: Backported to 3.2: adjust filename]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..666b1ed
--- /dev/null
@@ -0,0 +1,51 @@
+From eb4a22ba43d91d58a35bc4fce11d8e6065bb4e1d Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+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 <jlayton@redhat.com>
+
+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" <metze@samba.org>
+Cc: Sachin Prabhu <sprabhu@redhat.com>
+Reported-and-Tested-by: David McBride <dwm37@cam.ac.uk>
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+[bwh: Backported to 3.2: need to return NULL]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..1150c9d
--- /dev/null
@@ -0,0 +1,62 @@
+From 3e411534ea3be89a7d0ddf4e62e5c5b79d80556a Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 29 Jan 2013 22:48:17 -0500
+Subject: ext4: fix possible use-after-free with AIO
+
+From: Jan Kara <jack@suse.cz>
+
+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 <cmaiolino@redhat.com>
+Acked-by: Jeff Moyer <jmoyer@redhat.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..d12558b
--- /dev/null
@@ -0,0 +1,121 @@
+From 164ed4383ca615f9a4f19673ac82372ccf96a33f Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+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 <tytso@mit.edu>
+
+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" <tytso@mit.edu>
+Reported-by: Ben Hutchings <ben@decadent.org.uk>
+Reported-by: George Barnett <gbarnett@atlassian.com>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..535dcf9
--- /dev/null
@@ -0,0 +1,47 @@
+From 21544884d7d5f8890314271c158926ca0de43719 Mon Sep 17 00:00:00 2001
+From: Dave Chiluk <chiluk@canonical.com>
+Date: Tue, 28 May 2013 16:06:08 -0500
+Subject: ncpfs: fix rmdir returns Device or resource busy
+
+From: Dave Chiluk <chiluk@canonical.com>
+
+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 <chiluk@canonical.com>
+Signed-off-by: Petr Vandrovec <petr@vandrovec.name>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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));
index 51dcb439192b7274ee11331cfd0825dfad44ee47..261f2f05c2ec7da2113438746a33ad347cf243ff 100644 (file)
@@ -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 (file)
index 0000000..27d08dc
--- /dev/null
@@ -0,0 +1,81 @@
+From 2ff3ae3932b9ca1152c1835f674048c4cd227db7 Mon Sep 17 00:00:00 2001
+From: Adam Thomas <adamthomas1111@gmail.com>
+Date: Sat, 2 Feb 2013 22:35:08 +0000
+Subject: UBIFS: fix double free of ubifs_orphan objects
+
+From: Adam Thomas <adamthomas1111@gmail.com>
+
+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 <adamthomas1111@gmail.com>
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
+ };
+ /**