From: Greg Kroah-Hartman Date: Mon, 15 Sep 2014 15:19:22 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.10.55~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b27fcc1c1fcc50504dc259119b39a2be63d2eb23;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch cifs-fix-async-reading-on-reconnects.patch cifs-fix-directory-rename-error.patch cifs-fix-status_cannot_delete-error-mapping-for-smb2.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 cifs-possible-null-ptr-deref-in-smb2_tcon.patch drm-nouveau-bump-version-from-1.1.1-to-1.1.2.patch ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch libceph-add-process_one_ticket-helper.patch libceph-do-not-hard-code-max-auth-ticket-len.patch libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.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 vfs-add-d_is_dir.patch --- diff --git a/queue-3.14/blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch b/queue-3.14/blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch new file mode 100644 index 00000000000..97e8fcce6a1 --- /dev/null +++ b/queue-3.14/blkcg-don-t-call-into-policy-draining-if-root_blkg-is-already-gone.patch @@ -0,0 +1,102 @@ +From 2a1b4cf2331d92bc009bf94fa02a24604cdaf24c Mon Sep 17 00:00:00 2001 +From: Tejun Heo +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 + +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: [] 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:[] [] 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: + [] blkcg_drain_queue+0x1f/0x60 + [] __blk_drain_queue+0x71/0x180 + [] blk_queue_bypass_start+0x6e/0xb0 + [] blkcg_deactivate_policy+0x38/0x120 + [] blk_throtl_exit+0x34/0x50 + [] blkcg_exit_queue+0x35/0x40 + [] blk_release_queue+0x26/0xd0 + [] kobject_cleanup+0x38/0x70 + [] kobject_put+0x28/0x60 + [] blk_put_queue+0x15/0x20 + [] scsi_device_dev_release_usercontext+0x16b/0x1c0 + [] execute_in_process_context+0x89/0xa0 + [] scsi_device_dev_release+0x1c/0x20 + [] device_release+0x32/0xa0 + [] kobject_cleanup+0x38/0x70 + [] kobject_put+0x28/0x60 + [] put_device+0x17/0x20 + [] __scsi_remove_device+0xa9/0xe0 + [] scsi_remove_device+0x2b/0x40 + [] sdev_store_delete+0x27/0x30 + [] dev_attr_store+0x18/0x30 + [] sysfs_kf_write+0x3e/0x50 + [] kernfs_fop_write+0xe7/0x170 + [] vfs_write+0xaf/0x1d0 + [] SyS_write+0x4d/0xc0 + [] 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 +Reported-by: Shirish Pargaonkar +Reported-by: Sasha Levin +Reported-by: Jet Chen +Tested-by: Shirish Pargaonkar +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + block/blk-cgroup.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -866,6 +866,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); + } + diff --git a/queue-3.14/cifs-fix-async-reading-on-reconnects.patch b/queue-3.14/cifs-fix-async-reading-on-reconnects.patch new file mode 100644 index 00000000000..83cf7f4715d --- /dev/null +++ b/queue-3.14/cifs-fix-async-reading-on-reconnects.patch @@ -0,0 +1,51 @@ +From 038bc961c31b070269ecd07349a7ee2e839d4fec Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Fri, 27 Jun 2014 10:33:11 +0400 +Subject: CIFS: Fix async reading on reconnects + +From: Pavel Shilovsky + +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 +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/file.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -2844,7 +2844,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 +@@ -3267,7 +3267,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, diff --git a/queue-3.14/cifs-fix-directory-rename-error.patch b/queue-3.14/cifs-fix-directory-rename-error.patch new file mode 100644 index 00000000000..01daa398a21 --- /dev/null +++ b/queue-3.14/cifs-fix-directory-rename-error.patch @@ -0,0 +1,45 @@ +From a07d322059db66b84c9eb4f98959df468e88b34b Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Fri, 22 Aug 2014 13:32:09 +0400 +Subject: CIFS: Fix directory rename error + +From: Pavel Shilovsky + +commit a07d322059db66b84c9eb4f98959df468e88b34b upstream. + +CIFS servers process nlink counts differently for files and directories. +In cifs_rename() if we the request fails on the existing target, we +try to remove it through cifs_unlink() but this is not what we want +to do for directories. As the result the following sequence of commands + +mkdir {1,2}; mv -T 1 2; rmdir {1,2}; mkdir {1,2}; echo foo > 2/bar + +and XFS test generic/023 fail with -ENOENT error. That's why the second +mkdir reuses the existing inode (target inode of the mv -T command) with +S_DEAD flag. + +Fix this by checking whether the target is directory or not and +calling cifs_rmdir() rather than cifs_unlink() for directories. + +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/inode.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -1706,7 +1706,10 @@ cifs_rename(struct inode *source_dir, st + unlink_target: + /* Try unlinking the target dentry if it's not negative */ + if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { +- tmprc = cifs_unlink(target_dir, target_dentry); ++ if (d_is_dir(target_dentry)) ++ tmprc = cifs_rmdir(target_dir, target_dentry); ++ else ++ tmprc = cifs_unlink(target_dir, target_dentry); + if (tmprc) + goto cifs_rename_exit; + rc = cifs_do_rename(xid, source_dentry, from_name, diff --git a/queue-3.14/cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch b/queue-3.14/cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch new file mode 100644 index 00000000000..41c89d81780 --- /dev/null +++ b/queue-3.14/cifs-fix-status_cannot_delete-error-mapping-for-smb2.patch @@ -0,0 +1,33 @@ +From 21496687a79424572f46a84c690d331055f4866f Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Fri, 18 Jul 2014 18:25:52 +0400 +Subject: CIFS: Fix STATUS_CANNOT_DELETE error mapping for SMB2 + +From: Pavel Shilovsky + +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 +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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"}, diff --git a/queue-3.14/cifs-fix-wrong-directory-attributes-after-rename.patch b/queue-3.14/cifs-fix-wrong-directory-attributes-after-rename.patch new file mode 100644 index 00000000000..2c1651d07a5 --- /dev/null +++ b/queue-3.14/cifs-fix-wrong-directory-attributes-after-rename.patch @@ -0,0 +1,37 @@ +From b46799a8f28c43c5264ac8d8ffa28b311b557e03 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Mon, 18 Aug 2014 20:49:58 +0400 +Subject: CIFS: Fix wrong directory attributes after rename + +From: Pavel Shilovsky + +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 +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/inode.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -1713,6 +1713,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); diff --git a/queue-3.14/cifs-fix-wrong-filename-length-for-smb2.patch b/queue-3.14/cifs-fix-wrong-filename-length-for-smb2.patch new file mode 100644 index 00000000000..137bbb720a1 --- /dev/null +++ b/queue-3.14/cifs-fix-wrong-filename-length-for-smb2.patch @@ -0,0 +1,84 @@ +From 1bbe4997b13de903c421c1cc78440e544b5f9064 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Fri, 22 Aug 2014 13:32:11 +0400 +Subject: CIFS: Fix wrong filename length for SMB2 + +From: Pavel Shilovsky + +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 +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -70,11 +70,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 +@@ -50,7 +50,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 +@@ -131,7 +131,7 @@ smb2_query_path_info(const unsigned int + *adjust_tz = false; + *symlink = 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 +@@ -339,7 +339,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 +@@ -1540,7 +1540,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); + } + diff --git a/queue-3.14/cifs-fix-wrong-restart-readdir-for-smb1.patch b/queue-3.14/cifs-fix-wrong-restart-readdir-for-smb1.patch new file mode 100644 index 00000000000..469ced1e8a7 --- /dev/null +++ b/queue-3.14/cifs-fix-wrong-restart-readdir-for-smb1.patch @@ -0,0 +1,35 @@ +From f736906a7669a77cf8cabdcbcf1dc8cb694e12ef Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Tue, 26 Aug 2014 19:04:44 +0400 +Subject: CIFS: Fix wrong restart readdir for SMB1 + +From: Pavel Shilovsky + +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 +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/readdir.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -596,8 +596,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) { diff --git a/queue-3.14/cifs-possible-null-ptr-deref-in-smb2_tcon.patch b/queue-3.14/cifs-possible-null-ptr-deref-in-smb2_tcon.patch new file mode 100644 index 00000000000..5315e4ba953 --- /dev/null +++ b/queue-3.14/cifs-possible-null-ptr-deref-in-smb2_tcon.patch @@ -0,0 +1,32 @@ +From 18f39e7be0121317550d03e267e3ebd4dbfbb3ce Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Sun, 17 Aug 2014 00:22:24 -0500 +Subject: CIFS: Possible null ptr deref in SMB2_tcon + +From: Steve French + +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 +Reported-by: Raphael Geissert +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2pdu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -916,7 +916,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; + } diff --git a/queue-3.14/drm-nouveau-bump-version-from-1.1.1-to-1.1.2.patch b/queue-3.14/drm-nouveau-bump-version-from-1.1.1-to-1.1.2.patch new file mode 100644 index 00000000000..0e7585f026f --- /dev/null +++ b/queue-3.14/drm-nouveau-bump-version-from-1.1.1-to-1.1.2.patch @@ -0,0 +1,49 @@ +From 7820e5eef0faa4a5e10834296680827f7ce78a89 Mon Sep 17 00:00:00 2001 +From: Mario Kleiner +Date: Wed, 6 Aug 2014 06:09:44 +0200 +Subject: drm/nouveau: Bump version from 1.1.1 to 1.1.2 + +From: Mario Kleiner + +commit 7820e5eef0faa4a5e10834296680827f7ce78a89 upstream. + +Linux 3.16 fixed multiple bugs in kms pageflip completion events +and timestamping, which were originally introduced in Linux 3.13. + +These fixes have been backported to all stable kernels since 3.13. + +However, the userspace nouveau-ddx needs to be aware if it is +running on a kernel on which these bugs are fixed, or not. + +Bump the patchlevel of the drm driver version to signal this, +so backporting this patch to stable 3.13+ kernels will give the +ddx the required info. + +Signed-off-by: Mario Kleiner +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_drm.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_drm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drm.h +@@ -10,7 +10,7 @@ + + #define DRIVER_MAJOR 1 + #define DRIVER_MINOR 1 +-#define DRIVER_PATCHLEVEL 1 ++#define DRIVER_PATCHLEVEL 2 + + /* + * 1.1.1: +@@ -21,6 +21,8 @@ + * to control registers on the MPs to enable performance counters, + * and to control the warp error enable mask (OpenGL requires out of + * bounds access to local memory to be silently ignored / return 0). ++ * 1.1.2: ++ * - fixes multiple bugs in flip completion events and timestamping + */ + + #include diff --git a/queue-3.14/ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch b/queue-3.14/ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch new file mode 100644 index 00000000000..5c1d76f2086 --- /dev/null +++ b/queue-3.14/ib-srp-fix-deadlock-between-host-removal-and-multipathd.patch @@ -0,0 +1,154 @@ +From bcc05910359183b431da92713e98eed478edf83a Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Wed, 9 Jul 2014 15:57:26 +0200 +Subject: IB/srp: Fix deadlock between host removal and multipathd + +From: Bart Van Assche + +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: + [] schedule+0x29/0x70 + [] schedule_timeout+0x10f/0x2a0 + [] msleep+0x2f/0x40 + [] __blk_drain_queue+0x4e/0x180 + [] blk_cleanup_queue+0x225/0x230 + [] __scsi_remove_device+0x62/0xe0 [scsi_mod] + [] scsi_forget_host+0x6f/0x80 [scsi_mod] + [] scsi_remove_host+0x7a/0x130 [scsi_mod] + [] srp_remove_work+0x95/0x180 [ib_srp] + [] process_one_work+0x1ea/0x6c0 + [] worker_thread+0x11b/0x3a0 + [] kthread+0xed/0x110 + [] ret_from_fork+0x7c/0xb0 + multipathd D ffff880096acc460 0 5340 1 0x00000000 + Call Trace: + [] schedule+0x29/0x70 + [] schedule_timeout+0x10f/0x2a0 + [] io_schedule_timeout+0x9b/0xf0 + [] wait_for_completion_io_timeout+0xdc/0x110 + [] blk_execute_rq+0x9b/0x100 + [] sg_io+0x1a5/0x450 + [] scsi_cmd_ioctl+0x2a1/0x430 + [] scsi_cmd_blk_ioctl+0x42/0x50 + [] sd_ioctl+0xbe/0x140 [sd_mod] + [] blkdev_ioctl+0x234/0x840 + [] block_ioctl+0x41/0x50 + [] do_vfs_ioctl+0x300/0x520 + [] SyS_ioctl+0x41/0x80 + [] tracesys+0xd0/0xd5 + +Fix this by scheduling removal work on another workqueue than the +transport layer timers. + +Signed-off-by: Bart Van Assche +Reviewed-by: Sagi Grimberg +Reviewed-by: David Dillow +Cc: Sebastian Parschauer +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -120,6 +120,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", +@@ -539,7 +540,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; + } +@@ -2886,9 +2887,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); + } +@@ -2940,16 +2942,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); +@@ -2957,13 +2965,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) +@@ -2972,6 +2989,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); diff --git a/queue-3.14/libceph-add-process_one_ticket-helper.patch b/queue-3.14/libceph-add-process_one_ticket-helper.patch new file mode 100644 index 00000000000..5c20cb191ae --- /dev/null +++ b/queue-3.14/libceph-add-process_one_ticket-helper.patch @@ -0,0 +1,278 @@ +From 597cda357716a3cf8d994cb11927af917c8d71fa Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Mon, 8 Sep 2014 17:25:34 +0400 +Subject: libceph: add process_one_ticket() helper + +From: Ilya Dryomov + +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 +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-3.14/libceph-do-not-hard-code-max-auth-ticket-len.patch b/queue-3.14/libceph-do-not-hard-code-max-auth-ticket-len.patch new file mode 100644 index 00000000000..75fa81bc23d --- /dev/null +++ b/queue-3.14/libceph-do-not-hard-code-max-auth-ticket-len.patch @@ -0,0 +1,198 @@ +From c27a3e4d667fdcad3db7b104f75659478e0c68d8 Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Tue, 9 Sep 2014 19:39:15 +0400 +Subject: libceph: do not hard code max auth ticket len + +From: Ilya Dryomov + +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 +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman + +--- + 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)) diff --git a/queue-3.14/libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch b/queue-3.14/libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch new file mode 100644 index 00000000000..1179d305161 --- /dev/null +++ b/queue-3.14/libceph-set-last_piece-in-ceph_msg_data_pages_cursor_init.patch @@ -0,0 +1,55 @@ +From 5f740d7e1531099b888410e6bab13f68da9b1a4d Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +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 + +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 +Reviewed-by: Sage Weil +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman + +--- + net/ceph/messenger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -900,7 +900,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 * diff --git a/queue-3.14/mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch b/queue-3.14/mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch new file mode 100644 index 00000000000..a7bd18dc9ff --- /dev/null +++ b/queue-3.14/mtd-ftl-fix-the-double-free-of-the-buffers-allocated-in-build_maps.patch @@ -0,0 +1,98 @@ +From a152056c912db82860a8b4c23d0bd3a5aa89e363 Mon Sep 17 00:00:00 2001 +From: Kevin Hao +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 + +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 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 +Signed-off-by: Brian Norris +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + diff --git a/queue-3.14/mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch b/queue-3.14/mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch new file mode 100644 index 00000000000..311565f885b --- /dev/null +++ b/queue-3.14/mtd-nand-omap-fix-1-bit-hamming-code-scheme-omap_calculate_ecc.patch @@ -0,0 +1,45 @@ +From 40ddbf5069bd4e11447c0088fc75318e0aac53f0 Mon Sep 17 00:00:00 2001 +From: Roger Quadros +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 + +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 +Signed-off-by: Tony Lindgren +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -933,7 +933,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 */ diff --git a/queue-3.14/series b/queue-3.14/series index 28d31d01b03..df1e700a051 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -92,3 +92,19 @@ xfs-quotacheck-leaves-dquot-buffers-without-verifiers.patch xfs-don-t-dirty-buffers-beyond-eof.patch xfs-don-t-zero-partial-page-cache-pages-during-o_direct-writes.patch xfs-don-t-zero-partial-page-cache-pages-during.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 +vfs-add-d_is_dir.patch +cifs-fix-directory-rename-error.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 +drm-nouveau-bump-version-from-1.1.1-to-1.1.2.patch diff --git a/queue-3.14/vfs-add-d_is_dir.patch b/queue-3.14/vfs-add-d_is_dir.patch new file mode 100644 index 00000000000..ea87e26b31e --- /dev/null +++ b/queue-3.14/vfs-add-d_is_dir.patch @@ -0,0 +1,138 @@ +From 44b1d53043c482225196e8a9cd9f35163a1b3336 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Tue, 1 Apr 2014 17:08:41 +0200 +Subject: vfs: add d_is_dir() + +From: Miklos Szeredi + +commit 44b1d53043c482225196e8a9cd9f35163a1b3336 upstream. + +Add d_is_dir(dentry) helper which is analogous to S_ISDIR(). + +To avoid confusion, rename d_is_directory() to d_can_lookup(). + +Signed-off-by: Miklos Szeredi +Reviewed-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/namei.c | 23 +++++++++++------------ + include/linux/dcache.h | 7 ++++++- + 2 files changed, 17 insertions(+), 13 deletions(-) + +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -1797,7 +1797,7 @@ static int link_path_walk(const char *na + if (err) + return err; + } +- if (!d_is_directory(nd->path.dentry)) { ++ if (!d_can_lookup(nd->path.dentry)) { + err = -ENOTDIR; + break; + } +@@ -1818,7 +1818,7 @@ static int path_init(int dfd, const char + struct dentry *root = nd->root.dentry; + struct inode *inode = root->d_inode; + if (*name) { +- if (!d_is_directory(root)) ++ if (!d_can_lookup(root)) + return -ENOTDIR; + retval = inode_permission(inode, MAY_EXEC); + if (retval) +@@ -1874,7 +1874,7 @@ static int path_init(int dfd, const char + dentry = f.file->f_path.dentry; + + if (*name) { +- if (!d_is_directory(dentry)) { ++ if (!d_can_lookup(dentry)) { + fdput(f); + return -ENOTDIR; + } +@@ -1956,7 +1956,7 @@ static int path_lookupat(int dfd, const + err = complete_walk(nd); + + if (!err && nd->flags & LOOKUP_DIRECTORY) { +- if (!d_is_directory(nd->path.dentry)) { ++ if (!d_can_lookup(nd->path.dentry)) { + path_put(&nd->path); + err = -ENOTDIR; + } +@@ -2416,11 +2416,11 @@ static int may_delete(struct inode *dir, + IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) + return -EPERM; + if (isdir) { +- if (!d_is_directory(victim) && !d_is_autodir(victim)) ++ if (!d_is_dir(victim)) + return -ENOTDIR; + if (IS_ROOT(victim)) + return -EBUSY; +- } else if (d_is_directory(victim) || d_is_autodir(victim)) ++ } else if (d_is_dir(victim)) + return -EISDIR; + if (IS_DEADDIR(dir)) + return -ENOENT; +@@ -3018,11 +3018,10 @@ finish_open: + } + audit_inode(name, nd->path.dentry, 0); + error = -EISDIR; +- if ((open_flag & O_CREAT) && +- (d_is_directory(nd->path.dentry) || d_is_autodir(nd->path.dentry))) ++ if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) + goto out; + error = -ENOTDIR; +- if ((nd->flags & LOOKUP_DIRECTORY) && !d_is_directory(nd->path.dentry)) ++ if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry)) + goto out; + if (!S_ISREG(nd->inode->i_mode)) + will_truncate = false; +@@ -3746,7 +3745,7 @@ exit1: + slashes: + if (d_is_negative(dentry)) + error = -ENOENT; +- else if (d_is_directory(dentry) || d_is_autodir(dentry)) ++ else if (d_is_dir(dentry)) + error = -EISDIR; + else + error = -ENOTDIR; +@@ -4125,7 +4124,7 @@ int vfs_rename(struct inode *old_dir, st + struct inode **delegated_inode) + { + int error; +- int is_dir = d_is_directory(old_dentry) || d_is_autodir(old_dentry); ++ int is_dir = d_is_dir(old_dentry); + const unsigned char *old_name; + + if (old_dentry->d_inode == new_dentry->d_inode) +@@ -4218,7 +4217,7 @@ retry_deleg: + if (d_is_negative(old_dentry)) + goto exit4; + /* unless the source is a directory trailing slashes give -ENOTDIR */ +- if (!d_is_directory(old_dentry) && !d_is_autodir(old_dentry)) { ++ if (!d_is_dir(old_dentry)) { + error = -ENOTDIR; + if (oldnd.last.name[oldnd.last.len]) + goto exit4; +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -429,7 +429,7 @@ static inline unsigned __d_entry_type(co + return dentry->d_flags & DCACHE_ENTRY_TYPE; + } + +-static inline bool d_is_directory(const struct dentry *dentry) ++static inline bool d_can_lookup(const struct dentry *dentry) + { + return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; + } +@@ -439,6 +439,11 @@ static inline bool d_is_autodir(const st + return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE; + } + ++static inline bool d_is_dir(const struct dentry *dentry) ++{ ++ return d_can_lookup(dentry) || d_is_autodir(dentry); ++} ++ + static inline bool d_is_symlink(const struct dentry *dentry) + { + return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE;