--- /dev/null
+From 2a1b4cf2331d92bc009bf94fa02a24604cdaf24c Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Sat, 5 Jul 2014 18:43:21 -0400
+Subject: blkcg: don't call into policy draining if root_blkg is already gone
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 2a1b4cf2331d92bc009bf94fa02a24604cdaf24c upstream.
+
+While a queue is being destroyed, all the blkgs are destroyed and its
+->root_blkg pointer is set to NULL. If someone else starts to drain
+while the queue is in this state, the following oops happens.
+
+ NULL pointer dereference at 0000000000000028
+ IP: [<ffffffff8144e944>] blk_throtl_drain+0x84/0x230
+ PGD e4a1067 PUD b773067 PMD 0
+ Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
+ Modules linked in: cfq_iosched(-) [last unloaded: cfq_iosched]
+ CPU: 1 PID: 537 Comm: bash Not tainted 3.16.0-rc3-work+ #2
+ Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+ task: ffff88000e222250 ti: ffff88000efd4000 task.ti: ffff88000efd4000
+ RIP: 0010:[<ffffffff8144e944>] [<ffffffff8144e944>] blk_throtl_drain+0x84/0x230
+ RSP: 0018:ffff88000efd7bf0 EFLAGS: 00010046
+ RAX: 0000000000000000 RBX: ffff880015091450 RCX: 0000000000000001
+ RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
+ RBP: ffff88000efd7c10 R08: 0000000000000000 R09: 0000000000000001
+ R10: ffff88000e222250 R11: 0000000000000000 R12: ffff880015091450
+ R13: ffff880015092e00 R14: ffff880015091d70 R15: ffff88001508fc28
+ FS: 00007f1332650740(0000) GS:ffff88001fa80000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+ CR2: 0000000000000028 CR3: 0000000009446000 CR4: 00000000000006e0
+ Stack:
+ ffffffff8144e8f6 ffff880015091450 0000000000000000 ffff880015091d80
+ ffff88000efd7c28 ffffffff8144ae2f ffff880015091450 ffff88000efd7c58
+ ffffffff81427641 ffff880015091450 ffffffff82401f00 ffff880015091450
+ Call Trace:
+ [<ffffffff8144ae2f>] blkcg_drain_queue+0x1f/0x60
+ [<ffffffff81427641>] __blk_drain_queue+0x71/0x180
+ [<ffffffff81429b3e>] blk_queue_bypass_start+0x6e/0xb0
+ [<ffffffff814498b8>] blkcg_deactivate_policy+0x38/0x120
+ [<ffffffff8144ec44>] blk_throtl_exit+0x34/0x50
+ [<ffffffff8144aea5>] blkcg_exit_queue+0x35/0x40
+ [<ffffffff8142d476>] blk_release_queue+0x26/0xd0
+ [<ffffffff81454968>] kobject_cleanup+0x38/0x70
+ [<ffffffff81454848>] kobject_put+0x28/0x60
+ [<ffffffff81427505>] blk_put_queue+0x15/0x20
+ [<ffffffff817d07bb>] scsi_device_dev_release_usercontext+0x16b/0x1c0
+ [<ffffffff810bc339>] execute_in_process_context+0x89/0xa0
+ [<ffffffff817d064c>] scsi_device_dev_release+0x1c/0x20
+ [<ffffffff817930e2>] device_release+0x32/0xa0
+ [<ffffffff81454968>] kobject_cleanup+0x38/0x70
+ [<ffffffff81454848>] kobject_put+0x28/0x60
+ [<ffffffff817934d7>] put_device+0x17/0x20
+ [<ffffffff817d11b9>] __scsi_remove_device+0xa9/0xe0
+ [<ffffffff817d121b>] scsi_remove_device+0x2b/0x40
+ [<ffffffff817d1257>] sdev_store_delete+0x27/0x30
+ [<ffffffff81792ca8>] dev_attr_store+0x18/0x30
+ [<ffffffff8126f75e>] sysfs_kf_write+0x3e/0x50
+ [<ffffffff8126ea87>] kernfs_fop_write+0xe7/0x170
+ [<ffffffff811f5e9f>] vfs_write+0xaf/0x1d0
+ [<ffffffff811f69bd>] SyS_write+0x4d/0xc0
+ [<ffffffff81d24692>] system_call_fastpath+0x16/0x1b
+
+776687bce42b ("block, blk-mq: draining can't be skipped even if
+bypass_depth was non-zero") made it easier to trigger this bug by
+making blk_queue_bypass_start() drain even when it loses the first
+bypass test to blk_cleanup_queue(); however, the bug has always been
+there even before the commit as blk_queue_bypass_start() could race
+against queue destruction, win the initial bypass test but perform the
+actual draining after blk_cleanup_queue() already destroyed all blkgs.
+
+Fix it by skippping calling into policy draining if all the blkgs are
+already gone.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Shirish Pargaonkar <spargaonkar@suse.com>
+Reported-by: Sasha Levin <sasha.levin@oracle.com>
+Reported-by: Jet Chen <jet.chen@intel.com>
+Tested-by: Shirish Pargaonkar <spargaonkar@suse.com>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/blk-cgroup.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -883,6 +883,13 @@ void blkcg_drain_queue(struct request_qu
+ if (!q->root_blkg)
+ return;
+
++ /*
++ * @q could be exiting and already have destroyed all blkgs as
++ * indicated by NULL root_blkg. If so, don't confuse policies.
++ */
++ if (!q->root_blkg)
++ return;
++
+ blk_throtl_drain(q);
+ }
+
--- /dev/null
+From 038bc961c31b070269ecd07349a7ee2e839d4fec Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Fri, 27 Jun 2014 10:33:11 +0400
+Subject: CIFS: Fix async reading on reconnects
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 038bc961c31b070269ecd07349a7ee2e839d4fec upstream.
+
+If we get into read_into_pages() from cifs_readv_receive() and then
+loose a network, we issue cifs_reconnect that moves all mids to
+a private list and issue their callbacks. The callback of the async
+read request sets a mid to retry, frees it and wakes up a process
+that waits on the rdata completion.
+
+After the connection is established we return from read_into_pages()
+with a short read, use the mid that was freed before and try to read
+the remaining data from the a newly created socket. Both actions are
+not what we want to do. In reconnect cases (-EAGAIN) we should not
+mask off the error with a short read but should return the error
+code instead.
+
+Acked-by: Jeff Layton <jlayton@samba.org>
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/file.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -2809,7 +2809,7 @@ cifs_uncached_read_into_pages(struct TCP
+ total_read += result;
+ }
+
+- return total_read > 0 ? total_read : result;
++ return total_read > 0 && result != -EAGAIN ? total_read : result;
+ }
+
+ static ssize_t
+@@ -3232,7 +3232,7 @@ cifs_readpages_read_into_pages(struct TC
+ total_read += result;
+ }
+
+- return total_read > 0 ? total_read : result;
++ return total_read > 0 && result != -EAGAIN ? total_read : result;
+ }
+
+ static int cifs_readpages(struct file *file, struct address_space *mapping,
--- /dev/null
+From 21496687a79424572f46a84c690d331055f4866f Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Fri, 18 Jul 2014 18:25:52 +0400
+Subject: CIFS: Fix STATUS_CANNOT_DELETE error mapping for SMB2
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 21496687a79424572f46a84c690d331055f4866f upstream.
+
+The existing mapping causes unlink() call to return error after delete
+operation. Changing the mapping to -EACCES makes the client process
+the call like CIFS protocol does - reset dos attributes with ATTR_READONLY
+flag masked off and retry the operation.
+
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2maperror.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2maperror.c
++++ b/fs/cifs/smb2maperror.c
+@@ -605,7 +605,7 @@ static const struct status_to_posix_erro
+ {STATUS_MAPPED_FILE_SIZE_ZERO, -EIO, "STATUS_MAPPED_FILE_SIZE_ZERO"},
+ {STATUS_TOO_MANY_OPENED_FILES, -EMFILE, "STATUS_TOO_MANY_OPENED_FILES"},
+ {STATUS_CANCELLED, -EIO, "STATUS_CANCELLED"},
+- {STATUS_CANNOT_DELETE, -EIO, "STATUS_CANNOT_DELETE"},
++ {STATUS_CANNOT_DELETE, -EACCES, "STATUS_CANNOT_DELETE"},
+ {STATUS_INVALID_COMPUTER_NAME, -EIO, "STATUS_INVALID_COMPUTER_NAME"},
+ {STATUS_FILE_DELETED, -EIO, "STATUS_FILE_DELETED"},
+ {STATUS_SPECIAL_ACCOUNT, -EIO, "STATUS_SPECIAL_ACCOUNT"},
--- /dev/null
+From b46799a8f28c43c5264ac8d8ffa28b311b557e03 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Mon, 18 Aug 2014 20:49:58 +0400
+Subject: CIFS: Fix wrong directory attributes after rename
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit b46799a8f28c43c5264ac8d8ffa28b311b557e03 upstream.
+
+When we requests rename we also need to update attributes
+of both source and target parent directories. Not doing it
+causes generic/309 xfstest to fail on SMB2 mounts. Fix this
+by marking these directories for force revalidating.
+
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/inode.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -1647,6 +1647,12 @@ unlink_target:
+ target_dentry, to_name);
+ }
+
++ /* force revalidate to go get info when needed */
++ CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
++
++ source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
++ target_dir->i_mtime = current_fs_time(source_dir->i_sb);
++
+ cifs_rename_exit:
+ kfree(info_buf_source);
+ kfree(from_name);
--- /dev/null
+From 1bbe4997b13de903c421c1cc78440e544b5f9064 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Fri, 22 Aug 2014 13:32:11 +0400
+Subject: CIFS: Fix wrong filename length for SMB2
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 1bbe4997b13de903c421c1cc78440e544b5f9064 upstream.
+
+The existing code uses the old MAX_NAME constant. This causes
+XFS test generic/013 to fail. Fix it by replacing MAX_NAME with
+PATH_MAX that SMB1 uses. Also remove an unused MAX_NAME constant
+definition.
+
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsglob.h | 5 -----
+ fs/cifs/smb2file.c | 2 +-
+ fs/cifs/smb2inode.c | 2 +-
+ fs/cifs/smb2ops.c | 2 +-
+ fs/cifs/smb2pdu.c | 2 +-
+ 5 files changed, 4 insertions(+), 9 deletions(-)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -74,11 +74,6 @@
+ #define SERVER_NAME_LENGTH 40
+ #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
+
+-/* used to define string lengths for reversing unicode strings */
+-/* (256+1)*2 = 514 */
+-/* (max path length + 1 for null) * 2 for unicode */
+-#define MAX_NAME 514
+-
+ /* SMB echo "timeout" -- FIXME: tunable? */
+ #define SMB_ECHO_INTERVAL (60 * HZ)
+
+--- a/fs/cifs/smb2file.c
++++ b/fs/cifs/smb2file.c
+@@ -73,7 +73,7 @@ smb2_open_file(const unsigned int xid, s
+ goto out;
+ }
+
+- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+ GFP_KERNEL);
+ if (smb2_data == NULL) {
+ rc = -ENOMEM;
+--- a/fs/cifs/smb2inode.c
++++ b/fs/cifs/smb2inode.c
+@@ -123,7 +123,7 @@ smb2_query_path_info(const unsigned int
+
+ *adjust_tz = false;
+
+- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+ GFP_KERNEL);
+ if (smb2_data == NULL)
+ return -ENOMEM;
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -243,7 +243,7 @@ smb2_query_file_info(const unsigned int
+ int rc;
+ struct smb2_file_all_info *smb2_data;
+
+- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+ GFP_KERNEL);
+ if (smb2_data == NULL)
+ return -ENOMEM;
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1204,7 +1204,7 @@ SMB2_query_info(const unsigned int xid,
+ {
+ return query_info(xid, tcon, persistent_fid, volatile_fid,
+ FILE_ALL_INFORMATION,
+- sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
++ sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+ sizeof(struct smb2_file_all_info), data);
+ }
+
--- /dev/null
+From f736906a7669a77cf8cabdcbcf1dc8cb694e12ef Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Tue, 26 Aug 2014 19:04:44 +0400
+Subject: CIFS: Fix wrong restart readdir for SMB1
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit f736906a7669a77cf8cabdcbcf1dc8cb694e12ef upstream.
+
+The existing code calls server->ops->close() that is not
+right. This causes XFS test generic/310 to fail. Fix this
+by using server->ops->closedir() function.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/readdir.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -585,8 +585,8 @@ find_cifs_entry(const unsigned int xid,
+ if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
+ cfile->invalidHandle = true;
+ spin_unlock(&cifs_file_list_lock);
+- if (server->ops->close)
+- server->ops->close(xid, tcon, &cfile->fid);
++ if (server->ops->close_dir)
++ server->ops->close_dir(xid, tcon, &cfile->fid);
+ } else
+ spin_unlock(&cifs_file_list_lock);
+ if (cfile->srch_inf.ntwrk_buf_start) {
--- /dev/null
+From 18f39e7be0121317550d03e267e3ebd4dbfbb3ce Mon Sep 17 00:00:00 2001
+From: Steve French <smfrench@gmail.com>
+Date: Sun, 17 Aug 2014 00:22:24 -0500
+Subject: CIFS: Possible null ptr deref in SMB2_tcon
+
+From: Steve French <smfrench@gmail.com>
+
+commit 18f39e7be0121317550d03e267e3ebd4dbfbb3ce upstream.
+
+As Raphael Geissert pointed out, tcon_error_exit can dereference tcon
+and there is one path in which tcon can be null.
+
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reported-by: Raphael Geissert <geissert@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2pdu.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -809,7 +809,8 @@ tcon_exit:
+ tcon_error_exit:
+ if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
+ cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
+- tcon->bad_network_name = true;
++ if (tcon)
++ tcon->bad_network_name = true;
+ }
+ goto tcon_exit;
+ }
--- /dev/null
+From bcc05910359183b431da92713e98eed478edf83a Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bvanassche@acm.org>
+Date: Wed, 9 Jul 2014 15:57:26 +0200
+Subject: IB/srp: Fix deadlock between host removal and multipathd
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+commit bcc05910359183b431da92713e98eed478edf83a upstream.
+
+If scsi_remove_host() is invoked after a SCSI device has been blocked,
+if the fast_io_fail_tmo or dev_loss_tmo work gets scheduled on the
+workqueue executing srp_remove_work() and if an I/O request is
+scheduled after the SCSI device had been blocked by e.g. multipathd
+then the following deadlock can occur:
+
+ kworker/6:1 D ffff880831f3c460 0 195 2 0x00000000
+ Call Trace:
+ [<ffffffff814aafd9>] schedule+0x29/0x70
+ [<ffffffff814aa0ef>] schedule_timeout+0x10f/0x2a0
+ [<ffffffff8105af6f>] msleep+0x2f/0x40
+ [<ffffffff8123b0ae>] __blk_drain_queue+0x4e/0x180
+ [<ffffffff8123d2d5>] blk_cleanup_queue+0x225/0x230
+ [<ffffffffa0010732>] __scsi_remove_device+0x62/0xe0 [scsi_mod]
+ [<ffffffffa000ed2f>] scsi_forget_host+0x6f/0x80 [scsi_mod]
+ [<ffffffffa0002eba>] scsi_remove_host+0x7a/0x130 [scsi_mod]
+ [<ffffffffa07cf5c5>] srp_remove_work+0x95/0x180 [ib_srp]
+ [<ffffffff8106d7aa>] process_one_work+0x1ea/0x6c0
+ [<ffffffff8106dd9b>] worker_thread+0x11b/0x3a0
+ [<ffffffff810758bd>] kthread+0xed/0x110
+ [<ffffffff814b972c>] ret_from_fork+0x7c/0xb0
+ multipathd D ffff880096acc460 0 5340 1 0x00000000
+ Call Trace:
+ [<ffffffff814aafd9>] schedule+0x29/0x70
+ [<ffffffff814aa0ef>] schedule_timeout+0x10f/0x2a0
+ [<ffffffff814ab79b>] io_schedule_timeout+0x9b/0xf0
+ [<ffffffff814abe1c>] wait_for_completion_io_timeout+0xdc/0x110
+ [<ffffffff81244b9b>] blk_execute_rq+0x9b/0x100
+ [<ffffffff8124f665>] sg_io+0x1a5/0x450
+ [<ffffffff8124fd21>] scsi_cmd_ioctl+0x2a1/0x430
+ [<ffffffff8124fef2>] scsi_cmd_blk_ioctl+0x42/0x50
+ [<ffffffffa00ec97e>] sd_ioctl+0xbe/0x140 [sd_mod]
+ [<ffffffff8124bd04>] blkdev_ioctl+0x234/0x840
+ [<ffffffff811cb491>] block_ioctl+0x41/0x50
+ [<ffffffff811a0df0>] do_vfs_ioctl+0x300/0x520
+ [<ffffffff811a1051>] SyS_ioctl+0x41/0x80
+ [<ffffffff814b9962>] tracesys+0xd0/0xd5
+
+Fix this by scheduling removal work on another workqueue than the
+transport layer timers.
+
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
+Reviewed-by: David Dillow <dave@thedillows.org>
+Cc: Sebastian Parschauer <sebastian.riemer@profitbricks.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srp/ib_srp.c | 38 ++++++++++++++++++++++++++----------
+ 1 file changed, 28 insertions(+), 10 deletions(-)
+
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -93,6 +93,7 @@ static void srp_send_completion(struct i
+ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
+
+ static struct scsi_transport_template *ib_srp_transport_template;
++static struct workqueue_struct *srp_remove_wq;
+
+ static struct ib_client srp_client = {
+ .name = "srp",
+@@ -456,7 +457,7 @@ static bool srp_queue_remove_work(struct
+ spin_unlock_irq(&target->lock);
+
+ if (changed)
+- queue_work(system_long_wq, &target->remove_work);
++ queue_work(srp_remove_wq, &target->remove_work);
+
+ return changed;
+ }
+@@ -2530,9 +2531,10 @@ static void srp_remove_one(struct ib_dev
+ spin_unlock(&host->target_lock);
+
+ /*
+- * Wait for target port removal tasks.
++ * Wait for tl_err and target port removal tasks.
+ */
+ flush_workqueue(system_long_wq);
++ flush_workqueue(srp_remove_wq);
+
+ kfree(host);
+ }
+@@ -2577,16 +2579,22 @@ static int __init srp_init_module(void)
+ indirect_sg_entries = cmd_sg_entries;
+ }
+
++ srp_remove_wq = create_workqueue("srp_remove");
++ if (IS_ERR(srp_remove_wq)) {
++ ret = PTR_ERR(srp_remove_wq);
++ goto out;
++ }
++
++ ret = -ENOMEM;
+ ib_srp_transport_template =
+ srp_attach_transport(&ib_srp_transport_functions);
+ if (!ib_srp_transport_template)
+- return -ENOMEM;
++ goto destroy_wq;
+
+ ret = class_register(&srp_class);
+ if (ret) {
+ pr_err("couldn't register class infiniband_srp\n");
+- srp_release_transport(ib_srp_transport_template);
+- return ret;
++ goto release_tr;
+ }
+
+ ib_sa_register_client(&srp_sa_client);
+@@ -2594,13 +2602,22 @@ static int __init srp_init_module(void)
+ ret = ib_register_client(&srp_client);
+ if (ret) {
+ pr_err("couldn't register IB client\n");
+- srp_release_transport(ib_srp_transport_template);
+- ib_sa_unregister_client(&srp_sa_client);
+- class_unregister(&srp_class);
+- return ret;
++ goto unreg_sa;
+ }
+
+- return 0;
++out:
++ return ret;
++
++unreg_sa:
++ ib_sa_unregister_client(&srp_sa_client);
++ class_unregister(&srp_class);
++
++release_tr:
++ srp_release_transport(ib_srp_transport_template);
++
++destroy_wq:
++ destroy_workqueue(srp_remove_wq);
++ goto out;
+ }
+
+ static void __exit srp_cleanup_module(void)
+@@ -2609,6 +2626,7 @@ static void __exit srp_cleanup_module(vo
+ ib_sa_unregister_client(&srp_sa_client);
+ class_unregister(&srp_class);
+ srp_release_transport(ib_srp_transport_template);
++ destroy_workqueue(srp_remove_wq);
+ }
+
+ module_init(srp_init_module);
--- /dev/null
+From 597cda357716a3cf8d994cb11927af917c8d71fa Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+Date: Mon, 8 Sep 2014 17:25:34 +0400
+Subject: libceph: add process_one_ticket() helper
+
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+
+commit 597cda357716a3cf8d994cb11927af917c8d71fa upstream.
+
+Add a helper for processing individual cephx auth tickets. Needed for
+the next commit, which deals with allocating ticket buffers. (Most of
+the diff here is whitespace - view with git diff -b).
+
+Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c | 228 +++++++++++++++++++++++++++++-------------------------
+ 1 file changed, 124 insertions(+), 104 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -129,17 +129,131 @@ static void remove_ticket_handler(struct
+ kfree(th);
+ }
+
++static int process_one_ticket(struct ceph_auth_client *ac,
++ struct ceph_crypto_key *secret,
++ void **p, void *end,
++ void *dbuf, void *ticket_buf)
++{
++ struct ceph_x_info *xi = ac->private;
++ int type;
++ u8 tkt_struct_v, blob_struct_v;
++ struct ceph_x_ticket_handler *th;
++ void *dp, *dend;
++ int dlen;
++ char is_enc;
++ struct timespec validity;
++ struct ceph_crypto_key old_key;
++ void *tp, *tpend;
++ struct ceph_timespec new_validity;
++ struct ceph_crypto_key new_session_key;
++ struct ceph_buffer *new_ticket_blob;
++ unsigned long new_expires, new_renew_after;
++ u64 new_secret_id;
++ int ret;
++
++ ceph_decode_need(p, end, sizeof(u32) + 1, bad);
++
++ type = ceph_decode_32(p);
++ dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
++
++ tkt_struct_v = ceph_decode_8(p);
++ if (tkt_struct_v != 1)
++ goto bad;
++
++ th = get_ticket_handler(ac, type);
++ if (IS_ERR(th)) {
++ ret = PTR_ERR(th);
++ goto out;
++ }
++
++ /* blob for me */
++ dlen = ceph_x_decrypt(secret, p, end, dbuf,
++ TEMP_TICKET_BUF_LEN);
++ if (dlen <= 0) {
++ ret = dlen;
++ goto out;
++ }
++ dout(" decrypted %d bytes\n", dlen);
++ dp = dbuf;
++ dend = dp + dlen;
++
++ tkt_struct_v = ceph_decode_8(&dp);
++ if (tkt_struct_v != 1)
++ goto bad;
++
++ memcpy(&old_key, &th->session_key, sizeof(old_key));
++ ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
++ if (ret)
++ goto out;
++
++ ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
++ ceph_decode_timespec(&validity, &new_validity);
++ new_expires = get_seconds() + validity.tv_sec;
++ new_renew_after = new_expires - (validity.tv_sec / 4);
++ dout(" expires=%lu renew_after=%lu\n", new_expires,
++ new_renew_after);
++
++ /* ticket blob for service */
++ ceph_decode_8_safe(p, end, is_enc, bad);
++ tp = ticket_buf;
++ if (is_enc) {
++ /* encrypted */
++ dout(" encrypted ticket\n");
++ dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
++ TEMP_TICKET_BUF_LEN);
++ if (dlen < 0) {
++ ret = dlen;
++ goto out;
++ }
++ dlen = ceph_decode_32(&tp);
++ } else {
++ /* unencrypted */
++ ceph_decode_32_safe(p, end, dlen, bad);
++ ceph_decode_need(p, end, dlen, bad);
++ ceph_decode_copy(p, ticket_buf, dlen);
++ }
++ tpend = tp + dlen;
++ dout(" ticket blob is %d bytes\n", dlen);
++ ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
++ blob_struct_v = ceph_decode_8(&tp);
++ new_secret_id = ceph_decode_64(&tp);
++ ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
++ if (ret)
++ goto out;
++
++ /* all is well, update our ticket */
++ ceph_crypto_key_destroy(&th->session_key);
++ if (th->ticket_blob)
++ ceph_buffer_put(th->ticket_blob);
++ th->session_key = new_session_key;
++ th->ticket_blob = new_ticket_blob;
++ th->validity = new_validity;
++ th->secret_id = new_secret_id;
++ th->expires = new_expires;
++ th->renew_after = new_renew_after;
++ dout(" got ticket service %d (%s) secret_id %lld len %d\n",
++ type, ceph_entity_type_name(type), th->secret_id,
++ (int)th->ticket_blob->vec.iov_len);
++ xi->have_keys |= th->service;
++
++out:
++ return ret;
++
++bad:
++ ret = -EINVAL;
++ goto out;
++}
++
+ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
+ struct ceph_crypto_key *secret,
+ void *buf, void *end)
+ {
+- struct ceph_x_info *xi = ac->private;
+- int num;
+ void *p = buf;
+- int ret;
+ char *dbuf;
+ char *ticket_buf;
+ u8 reply_struct_v;
++ u32 num;
++ int ret;
+
+ dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+ if (!dbuf)
+@@ -150,112 +264,18 @@ static int ceph_x_proc_ticket_reply(stru
+ if (!ticket_buf)
+ goto out_dbuf;
+
+- ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
+- reply_struct_v = ceph_decode_8(&p);
++ ceph_decode_8_safe(&p, end, reply_struct_v, bad);
+ if (reply_struct_v != 1)
+- goto bad;
+- num = ceph_decode_32(&p);
+- dout("%d tickets\n", num);
+- while (num--) {
+- int type;
+- u8 tkt_struct_v, blob_struct_v;
+- struct ceph_x_ticket_handler *th;
+- void *dp, *dend;
+- int dlen;
+- char is_enc;
+- struct timespec validity;
+- struct ceph_crypto_key old_key;
+- void *tp, *tpend;
+- struct ceph_timespec new_validity;
+- struct ceph_crypto_key new_session_key;
+- struct ceph_buffer *new_ticket_blob;
+- unsigned long new_expires, new_renew_after;
+- u64 new_secret_id;
+-
+- ceph_decode_need(&p, end, sizeof(u32) + 1, bad);
+-
+- type = ceph_decode_32(&p);
+- dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
+-
+- tkt_struct_v = ceph_decode_8(&p);
+- if (tkt_struct_v != 1)
+- goto bad;
+-
+- th = get_ticket_handler(ac, type);
+- if (IS_ERR(th)) {
+- ret = PTR_ERR(th);
+- goto out;
+- }
+-
+- /* blob for me */
+- dlen = ceph_x_decrypt(secret, &p, end, dbuf,
+- TEMP_TICKET_BUF_LEN);
+- if (dlen <= 0) {
+- ret = dlen;
+- goto out;
+- }
+- dout(" decrypted %d bytes\n", dlen);
+- dend = dbuf + dlen;
+- dp = dbuf;
+-
+- tkt_struct_v = ceph_decode_8(&dp);
+- if (tkt_struct_v != 1)
+- goto bad;
++ return -EINVAL;
+
+- memcpy(&old_key, &th->session_key, sizeof(old_key));
+- ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
+- if (ret)
+- goto out;
++ ceph_decode_32_safe(&p, end, num, bad);
++ dout("%d tickets\n", num);
+
+- ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
+- ceph_decode_timespec(&validity, &new_validity);
+- new_expires = get_seconds() + validity.tv_sec;
+- new_renew_after = new_expires - (validity.tv_sec / 4);
+- dout(" expires=%lu renew_after=%lu\n", new_expires,
+- new_renew_after);
+-
+- /* ticket blob for service */
+- ceph_decode_8_safe(&p, end, is_enc, bad);
+- tp = ticket_buf;
+- if (is_enc) {
+- /* encrypted */
+- dout(" encrypted ticket\n");
+- dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf,
+- TEMP_TICKET_BUF_LEN);
+- if (dlen < 0) {
+- ret = dlen;
+- goto out;
+- }
+- dlen = ceph_decode_32(&tp);
+- } else {
+- /* unencrypted */
+- ceph_decode_32_safe(&p, end, dlen, bad);
+- ceph_decode_need(&p, end, dlen, bad);
+- ceph_decode_copy(&p, ticket_buf, dlen);
+- }
+- tpend = tp + dlen;
+- dout(" ticket blob is %d bytes\n", dlen);
+- ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
+- blob_struct_v = ceph_decode_8(&tp);
+- new_secret_id = ceph_decode_64(&tp);
+- ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
++ while (num--) {
++ ret = process_one_ticket(ac, secret, &p, end,
++ dbuf, ticket_buf);
+ if (ret)
+ goto out;
+-
+- /* all is well, update our ticket */
+- ceph_crypto_key_destroy(&th->session_key);
+- if (th->ticket_blob)
+- ceph_buffer_put(th->ticket_blob);
+- th->session_key = new_session_key;
+- th->ticket_blob = new_ticket_blob;
+- th->validity = new_validity;
+- th->secret_id = new_secret_id;
+- th->expires = new_expires;
+- th->renew_after = new_renew_after;
+- dout(" got ticket service %d (%s) secret_id %lld len %d\n",
+- type, ceph_entity_type_name(type), th->secret_id,
+- (int)th->ticket_blob->vec.iov_len);
+- xi->have_keys |= th->service;
+ }
+
+ ret = 0;
--- /dev/null
+From c27a3e4d667fdcad3db7b104f75659478e0c68d8 Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+Date: Tue, 9 Sep 2014 19:39:15 +0400
+Subject: libceph: do not hard code max auth ticket len
+
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+
+commit c27a3e4d667fdcad3db7b104f75659478e0c68d8 upstream.
+
+We hard code cephx auth ticket buffer size to 256 bytes. This isn't
+enough for any moderate setups and, in case tickets themselves are not
+encrypted, leads to buffer overflows (ceph_x_decrypt() errors out, but
+ceph_decode_copy() doesn't - it's just a memcpy() wrapper). Since the
+buffer is allocated dynamically anyway, allocated it a bit later, at
+the point where we know how much is going to be needed.
+
+Fixes: http://tracker.ceph.com/issues/8979
+
+Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/auth_x.c | 64 ++++++++++++++++++++++++------------------------------
+ 1 file changed, 29 insertions(+), 35 deletions(-)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -13,8 +13,6 @@
+ #include "auth_x.h"
+ #include "auth_x_protocol.h"
+
+-#define TEMP_TICKET_BUF_LEN 256
+-
+ static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
+
+ static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
+@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_cr
+ }
+
+ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
+- void **p, void *end, void *obuf, size_t olen)
++ void **p, void *end, void **obuf, size_t olen)
+ {
+ struct ceph_x_encrypt_header head;
+ size_t head_len = sizeof(head);
+@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_cr
+ return -EINVAL;
+
+ dout("ceph_x_decrypt len %d\n", len);
+- ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
+- *p, len);
++ if (*obuf == NULL) {
++ *obuf = kmalloc(len, GFP_NOFS);
++ if (!*obuf)
++ return -ENOMEM;
++ olen = len;
++ }
++
++ ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
+ if (ret)
+ return ret;
+ if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
+@@ -131,18 +135,19 @@ static void remove_ticket_handler(struct
+
+ static int process_one_ticket(struct ceph_auth_client *ac,
+ struct ceph_crypto_key *secret,
+- void **p, void *end,
+- void *dbuf, void *ticket_buf)
++ void **p, void *end)
+ {
+ struct ceph_x_info *xi = ac->private;
+ int type;
+ u8 tkt_struct_v, blob_struct_v;
+ struct ceph_x_ticket_handler *th;
++ void *dbuf = NULL;
+ void *dp, *dend;
+ int dlen;
+ char is_enc;
+ struct timespec validity;
+ struct ceph_crypto_key old_key;
++ void *ticket_buf = NULL;
+ void *tp, *tpend;
+ struct ceph_timespec new_validity;
+ struct ceph_crypto_key new_session_key;
+@@ -167,8 +172,7 @@ static int process_one_ticket(struct cep
+ }
+
+ /* blob for me */
+- dlen = ceph_x_decrypt(secret, p, end, dbuf,
+- TEMP_TICKET_BUF_LEN);
++ dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
+ if (dlen <= 0) {
+ ret = dlen;
+ goto out;
+@@ -195,20 +199,25 @@ static int process_one_ticket(struct cep
+
+ /* ticket blob for service */
+ ceph_decode_8_safe(p, end, is_enc, bad);
+- tp = ticket_buf;
+ if (is_enc) {
+ /* encrypted */
+ dout(" encrypted ticket\n");
+- dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
+- TEMP_TICKET_BUF_LEN);
++ dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
+ if (dlen < 0) {
+ ret = dlen;
+ goto out;
+ }
++ tp = ticket_buf;
+ dlen = ceph_decode_32(&tp);
+ } else {
+ /* unencrypted */
+ ceph_decode_32_safe(p, end, dlen, bad);
++ ticket_buf = kmalloc(dlen, GFP_NOFS);
++ if (!ticket_buf) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ tp = ticket_buf;
+ ceph_decode_need(p, end, dlen, bad);
+ ceph_decode_copy(p, ticket_buf, dlen);
+ }
+@@ -237,6 +246,8 @@ static int process_one_ticket(struct cep
+ xi->have_keys |= th->service;
+
+ out:
++ kfree(ticket_buf);
++ kfree(dbuf);
+ return ret;
+
+ bad:
+@@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(stru
+ void *buf, void *end)
+ {
+ void *p = buf;
+- char *dbuf;
+- char *ticket_buf;
+ u8 reply_struct_v;
+ u32 num;
+ int ret;
+
+- dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+- if (!dbuf)
+- return -ENOMEM;
+-
+- ret = -ENOMEM;
+- ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+- if (!ticket_buf)
+- goto out_dbuf;
+-
+ ceph_decode_8_safe(&p, end, reply_struct_v, bad);
+ if (reply_struct_v != 1)
+ return -EINVAL;
+@@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(stru
+ dout("%d tickets\n", num);
+
+ while (num--) {
+- ret = process_one_ticket(ac, secret, &p, end,
+- dbuf, ticket_buf);
++ ret = process_one_ticket(ac, secret, &p, end);
+ if (ret)
+- goto out;
++ return ret;
+ }
+
+- ret = 0;
+-out:
+- kfree(ticket_buf);
+-out_dbuf:
+- kfree(dbuf);
+- return ret;
++ return 0;
+
+ bad:
+- ret = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
+@@ -603,13 +596,14 @@ static int ceph_x_verify_authorizer_repl
+ struct ceph_x_ticket_handler *th;
+ int ret = 0;
+ struct ceph_x_authorize_reply reply;
++ void *preply = &reply;
+ void *p = au->reply_buf;
+ void *end = p + sizeof(au->reply_buf);
+
+ th = get_ticket_handler(ac, au->service);
+ if (IS_ERR(th))
+ return PTR_ERR(th);
+- ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
++ ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply));
+ if (ret < 0)
+ return ret;
+ if (ret != sizeof(reply))
--- /dev/null
+From 5f740d7e1531099b888410e6bab13f68da9b1a4d Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+Date: Fri, 8 Aug 2014 12:43:39 +0400
+Subject: libceph: set last_piece in ceph_msg_data_pages_cursor_init()
+ correctly
+
+From: Ilya Dryomov <ilya.dryomov@inktank.com>
+
+commit 5f740d7e1531099b888410e6bab13f68da9b1a4d upstream.
+
+Determining ->last_piece based on the value of ->page_offset + length
+is incorrect because length here is the length of the entire message.
+->last_piece set to false even if page array data item length is <=
+PAGE_SIZE, which results in invalid length passed to
+ceph_tcp_{send,recv}page() and causes various asserts to fire.
+
+ # cat pages-cursor-init.sh
+ #!/bin/bash
+ rbd create --size 10 --image-format 2 foo
+ FOO_DEV=$(rbd map foo)
+ dd if=/dev/urandom of=$FOO_DEV bs=1M &>/dev/null
+ rbd snap create foo@snap
+ rbd snap protect foo@snap
+ rbd clone foo@snap bar
+ # rbd_resize calls librbd rbd_resize(), size is in bytes
+ ./rbd_resize bar $(((4 << 20) + 512))
+ rbd resize --size 10 bar
+ BAR_DEV=$(rbd map bar)
+ # trigger a 512-byte copyup -- 512-byte page array data item
+ dd if=/dev/urandom of=$BAR_DEV bs=1M count=1 seek=5
+
+The problem exists only in ceph_msg_data_pages_cursor_init(),
+ceph_msg_data_pages_advance() does the right thing. The size_t cast is
+unnecessary.
+
+Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
+Reviewed-by: Sage Weil <sage@redhat.com>
+Reviewed-by: Alex Elder <elder@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/messenger.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -904,7 +904,7 @@ static void ceph_msg_data_pages_cursor_i
+ BUG_ON(page_count > (int)USHRT_MAX);
+ cursor->page_count = (unsigned short)page_count;
+ BUG_ON(length > SIZE_MAX - cursor->page_offset);
+- cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE;
++ cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE;
+ }
+
+ static struct page *
--- /dev/null
+From a152056c912db82860a8b4c23d0bd3a5aa89e363 Mon Sep 17 00:00:00 2001
+From: Kevin Hao <haokexin@gmail.com>
+Date: Thu, 3 Jul 2014 10:35:26 +0800
+Subject: mtd/ftl: fix the double free of the buffers allocated in build_maps()
+
+From: Kevin Hao <haokexin@gmail.com>
+
+commit a152056c912db82860a8b4c23d0bd3a5aa89e363 upstream.
+
+I got the following panic on my fsl p5020ds board.
+
+ Unable to handle kernel paging request for data at address 0x7375627379737465
+ Faulting instruction address: 0xc000000000100778
+ Oops: Kernel access of bad area, sig: 11 [#1]
+ SMP NR_CPUS=24 CoreNet Generic
+ Modules linked in:
+ CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.15.0-next-20140613 #145
+ task: c0000000fe080000 ti: c0000000fe088000 task.ti: c0000000fe088000
+ NIP: c000000000100778 LR: c00000000010073c CTR: 0000000000000000
+ REGS: c0000000fe08aa00 TRAP: 0300 Not tainted (3.15.0-next-20140613)
+ MSR: 0000000080029000 <CE,EE,ME> CR: 24ad2e24 XER: 00000000
+ DEAR: 7375627379737465 ESR: 0000000000000000 SOFTE: 1
+ GPR00: c0000000000c99b0 c0000000fe08ac80 c0000000009598e0 c0000000fe001d80
+ GPR04: 00000000000000d0 0000000000000913 c000000007902b20 0000000000000000
+ GPR08: c0000000feaae888 0000000000000000 0000000007091000 0000000000200200
+ GPR12: 0000000028ad2e28 c00000000fff4000 c0000000007abe08 0000000000000000
+ GPR16: c0000000007ab160 c0000000007aaf98 c00000000060ba68 c0000000007abda8
+ GPR20: c0000000007abde8 c0000000feaea6f8 c0000000feaea708 c0000000007abd10
+ GPR24: c000000000989370 c0000000008c6228 00000000000041ed c0000000fe00a400
+ GPR28: c00000000017c1cc 00000000000000d0 7375627379737465 c0000000fe001d80
+ NIP [c000000000100778] .__kmalloc_track_caller+0x70/0x168
+ LR [c00000000010073c] .__kmalloc_track_caller+0x34/0x168
+ Call Trace:
+ [c0000000fe08ac80] [c00000000087e6b8] uevent_sock_list+0x0/0x10 (unreliable)
+ [c0000000fe08ad20] [c0000000000c99b0] .kstrdup+0x44/0x90
+ [c0000000fe08adc0] [c00000000017c1cc] .__kernfs_new_node+0x4c/0x130
+ [c0000000fe08ae70] [c00000000017d7e4] .kernfs_new_node+0x2c/0x64
+ [c0000000fe08aef0] [c00000000017db00] .kernfs_create_dir_ns+0x34/0xc8
+ [c0000000fe08af80] [c00000000018067c] .sysfs_create_dir_ns+0x58/0xcc
+ [c0000000fe08b010] [c0000000002c711c] .kobject_add_internal+0xc8/0x384
+ [c0000000fe08b0b0] [c0000000002c7644] .kobject_add+0x64/0xc8
+ [c0000000fe08b140] [c000000000355ebc] .device_add+0x11c/0x654
+ [c0000000fe08b200] [c0000000002b5988] .add_disk+0x20c/0x4b4
+ [c0000000fe08b2c0] [c0000000003a21d4] .add_mtd_blktrans_dev+0x340/0x514
+ [c0000000fe08b350] [c0000000003a3410] .mtdblock_add_mtd+0x74/0xb4
+ [c0000000fe08b3e0] [c0000000003a32cc] .blktrans_notify_add+0x64/0x94
+ [c0000000fe08b470] [c00000000039b5b4] .add_mtd_device+0x1d4/0x368
+ [c0000000fe08b520] [c00000000039b830] .mtd_device_parse_register+0xe8/0x104
+ [c0000000fe08b5c0] [c0000000003b8408] .of_flash_probe+0x72c/0x734
+ [c0000000fe08b750] [c00000000035ba40] .platform_drv_probe+0x38/0x84
+ [c0000000fe08b7d0] [c0000000003599a4] .really_probe+0xa4/0x29c
+ [c0000000fe08b870] [c000000000359d3c] .__driver_attach+0x100/0x104
+ [c0000000fe08b900] [c00000000035746c] .bus_for_each_dev+0x84/0xe4
+ [c0000000fe08b9a0] [c0000000003593c0] .driver_attach+0x24/0x38
+ [c0000000fe08ba10] [c000000000358f24] .bus_add_driver+0x1c8/0x2ac
+ [c0000000fe08bab0] [c00000000035a3a4] .driver_register+0x8c/0x158
+ [c0000000fe08bb30] [c00000000035b9f4] .__platform_driver_register+0x6c/0x80
+ [c0000000fe08bba0] [c00000000084e080] .of_flash_driver_init+0x1c/0x30
+ [c0000000fe08bc10] [c000000000001864] .do_one_initcall+0xbc/0x238
+ [c0000000fe08bd00] [c00000000082cdc0] .kernel_init_freeable+0x188/0x268
+ [c0000000fe08bdb0] [c0000000000020a0] .kernel_init+0x1c/0xf7c
+ [c0000000fe08be30] [c000000000000884] .ret_from_kernel_thread+0x58/0xd4
+ Instruction dump:
+ 41bd0010 480000c8 4bf04eb5 60000000 e94d0028 e93f0000 7cc95214 e8a60008
+ 7fc9502a 2fbe0000 419e00c8 e93f0022 <7f7e482a> 39200000 88ed06b2 992d06b2
+ ---[ end trace b4c9a94804a42d40 ]---
+
+It seems that the corrupted partition header on my mtd device triggers
+a bug in the ftl. In function build_maps() it will allocate the buffers
+needed by the mtd partition, but if something goes wrong such as kmalloc
+failure, mtd read error or invalid partition header parameter, it will
+free all allocated buffers and then return non-zero. In my case, it
+seems that partition header parameter 'NumTransferUnits' is invalid.
+
+And the ftl_freepart() is a function which free all the partition
+buffers allocated by build_maps(). Given the build_maps() is a self
+cleaning function, so there is no need to invoke this function even
+if build_maps() return with error. Otherwise it will causes the
+buffers to be freed twice and then weird things would happen.
+
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mtd/ftl.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/mtd/ftl.c
++++ b/drivers/mtd/ftl.c
+@@ -1075,7 +1075,6 @@ static void ftl_add_mtd(struct mtd_blktr
+ return;
+ }
+
+- ftl_freepart(partition);
+ kfree(partition);
+ }
+
--- /dev/null
+From 40ddbf5069bd4e11447c0088fc75318e0aac53f0 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 25 Aug 2014 16:15:33 -0700
+Subject: mtd: nand: omap: Fix 1-bit Hamming code scheme, omap_calculate_ecc()
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit 40ddbf5069bd4e11447c0088fc75318e0aac53f0 upstream.
+
+commit 65b97cf6b8de introduced in v3.7 caused a regression
+by using a reversed CS_MASK thus causing omap_calculate_ecc to
+always fail. As the NAND base driver never checks for .calculate()'s
+return value, the zeroed ECC values are used as is without showing
+any error to the user. However, this won't work and the NAND device
+won't be guarded by any error code.
+
+Fix the issue by using the correct mask.
+
+Code was tested on omap3beagle using the following procedure
+- flash the primary bootloader (MLO) from the kernel to the first
+NAND partition using nandwrite.
+- boot the board from NAND. This utilizes OMAP ROM loader that
+relies on 1-bit Hamming code ECC.
+
+Fixes: 65b97cf6b8de (mtd: nand: omap2: handle nand on gpmc)
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mtd/nand/omap2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/omap2.c
++++ b/drivers/mtd/nand/omap2.c
+@@ -948,7 +948,7 @@ static int omap_calculate_ecc(struct mtd
+ u32 val;
+
+ val = readl(info->reg.gpmc_ecc_config);
+- if (((val >> ECC_CONFIG_CS_SHIFT) & ~CS_MASK) != info->gpmc_cs)
++ if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs)
+ return -EINVAL;
+
+ /* read ecc result */
xfs-don-t-zero-partial-page-cache-pages-during-o_direct-writes.patch
xfs-don-t-zero-partial-page-cache-pages-during.patch
md-raid1-raid10-always-abort-recover-on-write-error.patch
+libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch
+libceph-add-process_one_ticket-helper.patch
+libceph-do-not-hard-code-max-auth-ticket-len.patch
+cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch
+cifs-fix-async-reading-on-reconnects.patch
+cifs-possible-null-ptr-deref-in-smb2_tcon.patch
+cifs-fix-wrong-directory-attributes-after-rename.patch
+cifs-fix-wrong-filename-length-for-smb2.patch
+cifs-fix-wrong-restart-readdir-for-smb1.patch
+mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch
+mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch
+blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch
+ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch