From: Greg Kroah-Hartman Date: Wed, 2 Jul 2014 23:39:09 +0000 (-0700) Subject: 3.15-stable patches X-Git-Tag: v3.4.97~28 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e79e52557d0b629461f0d2fdb17cccf48b85ba96;p=thirdparty%2Fkernel%2Fstable-queue.git 3.15-stable patches added patches: ib-ipath-translate-legacy-diagpkt-into-newer-extended-diagpkt.patch ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_cq.patch ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_srq.patch ib-qib-fix-port-in-pkey-change-event.patch ib-srp-fix-a-sporadic-crash-triggered-by-cable-pulling.patch ib-umad-fix-error-handling.patch ib-umad-fix-use-after-free-on-close.patch nfs-don-t-declare-inode-uptodate-unless-all-attributes-were-checked.patch nfs-fix-cache_validity-check-in-nfs_write_pageuptodate.patch nfs-populate-net-in-mount-data-when-remounting.patch nfs-use-raw_write_seqcount_begin-end-int-nfs4_reclaim_open_state.patch nfsd-getattr-for-fattr4_word0_files_avail-needs-the-statfs-buffer.patch nfsd4-fix-free_stateid-lockowner-leak.patch pnfs-handle-allocation-errors-correctly-in-filelayout_alloc_layout_hdr.patch sunrpc-fix-a-module-reference-leak-in-svc_handle_xprt.patch --- diff --git a/queue-3.15/ib-ipath-translate-legacy-diagpkt-into-newer-extended-diagpkt.patch b/queue-3.15/ib-ipath-translate-legacy-diagpkt-into-newer-extended-diagpkt.patch new file mode 100644 index 00000000000..4587f23228d --- /dev/null +++ b/queue-3.15/ib-ipath-translate-legacy-diagpkt-into-newer-extended-diagpkt.patch @@ -0,0 +1,37 @@ +From 7e6d3e5c70f13874fb06e6b67696ed90ce79bd48 Mon Sep 17 00:00:00 2001 +From: Dennis Dalessandro +Date: Fri, 2 May 2014 11:40:17 -0400 +Subject: IB/ipath: Translate legacy diagpkt into newer extended diagpkt + +From: Dennis Dalessandro + +commit 7e6d3e5c70f13874fb06e6b67696ed90ce79bd48 upstream. + +This patch addresses an issue where the legacy diagpacket is sent in +from the user, but the driver operates on only the extended +diagpkt. This patch specifically initializes the extended diagpkt +based on the legacy packet. + +Reported-by: Rickard Strandqvist +Reviewed-by: Mike Marciniszyn +Signed-off-by: Dennis Dalessandro +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/ipath/ipath_diag.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/infiniband/hw/ipath/ipath_diag.c ++++ b/drivers/infiniband/hw/ipath/ipath_diag.c +@@ -346,6 +346,10 @@ static ssize_t ipath_diagpkt_write(struc + ret = -EFAULT; + goto bail; + } ++ dp.len = odp.len; ++ dp.unit = odp.unit; ++ dp.data = odp.data; ++ dp.pbc_wd = 0; + } else { + ret = -EINVAL; + goto bail; diff --git a/queue-3.15/ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_cq.patch b/queue-3.15/ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_cq.patch new file mode 100644 index 00000000000..005d64972b3 --- /dev/null +++ b/queue-3.15/ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_cq.patch @@ -0,0 +1,113 @@ +From a8237b32a3faab155a5dc8f886452147ce73da3e Mon Sep 17 00:00:00 2001 +From: Yann Droneaud +Date: Mon, 5 May 2014 19:33:21 +0200 +Subject: IB/mlx5: add missing padding at end of struct mlx5_ib_create_cq + +From: Yann Droneaud + +commit a8237b32a3faab155a5dc8f886452147ce73da3e upstream. + +The i386 ABI disagrees with most other ABIs regarding alignment of +data type larger than 4 bytes: on most ABIs a padding must be added at +end of the structures, while it is not required on i386. + +So for most ABI struct mlx5_ib_create_cq get padded to be aligned on a +8 bytes multiple, while for i386, such padding is not added. + +The tool pahole can be used to find such implicit padding: + + $ pahole --anon_include \ + --nested_anon_include \ + --recursive \ + --class_name mlx5_ib_create_cq \ + drivers/infiniband/hw/mlx5/mlx5_ib.o + +Then, structure layout can be compared between i386 and x86_64: + +# +++ obj-i386/drivers/infiniband/hw/mlx5/mlx5_ib.o.pahole.txt 2014-03-28 11:43:07.386413682 +0100 +# --- obj-x86_64/drivers/infiniband/hw/mlx5/mlx5_ib.o.pahole.txt 2014-03-27 13:06:17.788472721 +0100 +# @@ -34,9 +34,8 @@ struct mlx5_ib_create_cq { +# __u64 db_addr; /* 8 8 */ +# __u32 cqe_size; /* 16 4 */ +# +# - /* size: 20, cachelines: 1, members: 3 */ +# - /* last cacheline: 20 bytes */ +# + /* size: 24, cachelines: 1, members: 3 */ +# + /* padding: 4 */ +# + /* last cacheline: 24 bytes */ +# }; + +This ABI disagreement will make an x86_64 kernel try to read past the +buffer provided by an i386 binary. + +When boundary check will be implemented, a x86_64 kernel will refuse +to read past the i386 userspace provided buffer and the uverb will +fail. + +Anyway, if the structure lies in memory on a page boundary and next +page is not mapped, ib_copy_from_udata() will fail when trying to read +the 4 bytes of padding and the uverb will fail. + +This patch makes create_cq_user() takes care of the input data size to +handle the case where no padding is provided. + +This way, x86_64 kernel will be able to handle struct +mlx5_ib_create_cq as sent by unpatched and patched i386 libmlx5. + +Link: http://marc.info/?i=cover.1399309513.git.ydroneaud@opteya.com +Fixes: e126ba97dba9e ("mlx5: Add driver for Mellanox Connect-IB adapter") +Signed-off-by: Yann Droneaud +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx5/cq.c | 13 ++++++++++++- + drivers/infiniband/hw/mlx5/user.h | 1 + + 2 files changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/infiniband/hw/mlx5/cq.c ++++ b/drivers/infiniband/hw/mlx5/cq.c +@@ -32,6 +32,7 @@ + + #include + #include ++#include + #include "mlx5_ib.h" + #include "user.h" + +@@ -602,14 +603,24 @@ static int create_cq_user(struct mlx5_ib + int *cqe_size, int *index, int *inlen) + { + struct mlx5_ib_create_cq ucmd; ++ size_t ucmdlen; + int page_shift; + int npages; + int ncont; + int err; + +- if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) ++ ucmdlen = ++ (udata->inlen - sizeof(struct ib_uverbs_cmd_hdr) < ++ sizeof(ucmd)) ? (sizeof(ucmd) - ++ sizeof(ucmd.reserved)) : sizeof(ucmd); ++ ++ if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) + return -EFAULT; + ++ if (ucmdlen == sizeof(ucmd) && ++ ucmd.reserved != 0) ++ return -EINVAL; ++ + if (ucmd.cqe_size != 64 && ucmd.cqe_size != 128) + return -EINVAL; + +--- a/drivers/infiniband/hw/mlx5/user.h ++++ b/drivers/infiniband/hw/mlx5/user.h +@@ -91,6 +91,7 @@ struct mlx5_ib_create_cq { + __u64 buf_addr; + __u64 db_addr; + __u32 cqe_size; ++ __u32 reserved; /* explicit padding (optional on i386) */ + }; + + struct mlx5_ib_create_cq_resp { diff --git a/queue-3.15/ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_srq.patch b/queue-3.15/ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_srq.patch new file mode 100644 index 00000000000..e1ad97a1ad6 --- /dev/null +++ b/queue-3.15/ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_srq.patch @@ -0,0 +1,117 @@ +From 43bc889380c2ad9aa230eccc03a15cc52cf710d4 Mon Sep 17 00:00:00 2001 +From: Yann Droneaud +Date: Mon, 5 May 2014 19:33:22 +0200 +Subject: IB/mlx5: add missing padding at end of struct mlx5_ib_create_srq + +From: Yann Droneaud + +commit 43bc889380c2ad9aa230eccc03a15cc52cf710d4 upstream. + +The i386 ABI disagrees with most other ABIs regarding alignment of +data type larger than 4 bytes: on most ABIs a padding must be added at +end of the structures, while it is not required on i386. + +So for most ABIs struct mlx5_ib_create_srq gets implicitly padded to be +aligned on a 8 bytes multiple, while for i386, such padding is not +added. + +Tool pahole could be used to find such implicit padding: + + $ pahole --anon_include \ + --nested_anon_include \ + --recursive \ + --class_name mlx5_ib_create_srq \ + drivers/infiniband/hw/mlx5/mlx5_ib.o + +Then, structure layout can be compared between i386 and x86_64: + +# +++ obj-i386/drivers/infiniband/hw/mlx5/mlx5_ib.o.pahole.txt 2014-03-28 11:43:07.386413682 +0100 +# --- obj-x86_64/drivers/infiniband/hw/mlx5/mlx5_ib.o.pahole.txt 2014-03-27 13:06:17.788472721 +0100 +# @@ -69,7 +68,6 @@ struct mlx5_ib_create_srq { +# __u64 db_addr; /* 8 8 */ +# __u32 flags; /* 16 4 */ +# +# - /* size: 20, cachelines: 1, members: 3 */ +# - /* last cacheline: 20 bytes */ +# + /* size: 24, cachelines: 1, members: 3 */ +# + /* padding: 4 */ +# + /* last cacheline: 24 bytes */ +# }; + +ABI disagreement will make an x86_64 kernel try to read past +the buffer provided by an i386 binary. + +When boundary check will be implemented, the x86_64 kernel will +refuse to read past the i386 userspace provided buffer and the +uverb will fail. + +Anyway, if the structure lay in memory on a page boundary and +next page is not mapped, ib_copy_from_udata() will fail and the +uverb will fail. + +This patch makes create_srq_user() takes care of the input +data size to handle the case where no padding was provided. + +This way, x86_64 kernel will be able to handle struct mlx5_ib_create_srq +as sent by unpatched and patched i386 libmlx5. + +Link: http://marc.info/?i=cover.1399309513.git.ydroneaud@opteya.com +Fixes: e126ba97dba9e ("mlx5: Add driver for Mellanox Connect-IB adapter") +Signed-off-by: Yann Droneaud +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx5/srq.c | 14 +++++++++++++- + drivers/infiniband/hw/mlx5/user.h | 1 + + 2 files changed, 14 insertions(+), 1 deletion(-) + +--- a/drivers/infiniband/hw/mlx5/srq.c ++++ b/drivers/infiniband/hw/mlx5/srq.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #include "mlx5_ib.h" + #include "user.h" +@@ -78,16 +79,27 @@ static int create_srq_user(struct ib_pd + { + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct mlx5_ib_create_srq ucmd; ++ size_t ucmdlen; + int err; + int npages; + int page_shift; + int ncont; + u32 offset; + +- if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) { ++ ucmdlen = ++ (udata->inlen - sizeof(struct ib_uverbs_cmd_hdr) < ++ sizeof(ucmd)) ? (sizeof(ucmd) - ++ sizeof(ucmd.reserved)) : sizeof(ucmd); ++ ++ if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) { + mlx5_ib_dbg(dev, "failed copy udata\n"); + return -EFAULT; + } ++ ++ if (ucmdlen == sizeof(ucmd) && ++ ucmd.reserved != 0) ++ return -EINVAL; ++ + srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE); + + srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, buf_size, +--- a/drivers/infiniband/hw/mlx5/user.h ++++ b/drivers/infiniband/hw/mlx5/user.h +@@ -110,6 +110,7 @@ struct mlx5_ib_create_srq { + __u64 buf_addr; + __u64 db_addr; + __u32 flags; ++ __u32 reserved; /* explicit padding (optional on i386) */ + }; + + struct mlx5_ib_create_srq_resp { diff --git a/queue-3.15/ib-qib-fix-port-in-pkey-change-event.patch b/queue-3.15/ib-qib-fix-port-in-pkey-change-event.patch new file mode 100644 index 00000000000..1d043c1e019 --- /dev/null +++ b/queue-3.15/ib-qib-fix-port-in-pkey-change-event.patch @@ -0,0 +1,36 @@ +From 911eccd284d13d78c92ec4f1f1092c03457d732a Mon Sep 17 00:00:00 2001 +From: Mike Marciniszyn +Date: Fri, 2 May 2014 11:28:04 -0400 +Subject: IB/qib: Fix port in pkey change event + +From: Mike Marciniszyn + +commit 911eccd284d13d78c92ec4f1f1092c03457d732a upstream. + +The code used a literal 1 in dispatching an IB_EVENT_PKEY_CHANGE. + +As of the dual port qib QDR card, this is not necessarily correct. + +Change to use the port as specified in the call. + +Reported-by: Alex Estrin +Reviewed-by: Dennis Dalessandro +Signed-off-by: Mike Marciniszyn +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/qib/qib_mad.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/infiniband/hw/qib/qib_mad.c ++++ b/drivers/infiniband/hw/qib/qib_mad.c +@@ -1028,7 +1028,7 @@ static int set_pkeys(struct qib_devdata + + event.event = IB_EVENT_PKEY_CHANGE; + event.device = &dd->verbs_dev.ibdev; +- event.element.port_num = 1; ++ event.element.port_num = port; + ib_dispatch_event(&event); + } + return 0; diff --git a/queue-3.15/ib-srp-fix-a-sporadic-crash-triggered-by-cable-pulling.patch b/queue-3.15/ib-srp-fix-a-sporadic-crash-triggered-by-cable-pulling.patch new file mode 100644 index 00000000000..c23717add08 --- /dev/null +++ b/queue-3.15/ib-srp-fix-a-sporadic-crash-triggered-by-cable-pulling.patch @@ -0,0 +1,42 @@ +From 024ca90151f5e4296d30f72c13ff9a075e23c9ec Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Tue, 20 May 2014 15:03:49 +0200 +Subject: IB/srp: Fix a sporadic crash triggered by cable pulling + +From: Bart Van Assche + +commit 024ca90151f5e4296d30f72c13ff9a075e23c9ec upstream. + +Avoid that the loops that iterate over the request ring can encounter +a pointer to a SCSI command in req->scmnd that is no longer associated +with that request. If the function srp_unmap_data() is invoked twice +for a SCSI command that is not in flight then that would cause +ib_fmr_pool_unmap() to be invoked with an invalid pointer as argument, +resulting in a kernel oops. + +Reported-by: Sagi Grimberg +Reference: http://thread.gmane.org/gmane.linux.drivers.rdma/19068/focus=19069 +Signed-off-by: Bart Van Assche +Reviewed-by: Sagi Grimberg +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/ulp/srp/ib_srp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -1594,6 +1594,12 @@ err_unmap: + err_iu: + srp_put_tx_iu(target, iu, SRP_IU_CMD); + ++ /* ++ * Avoid that the loops that iterate over the request ring can ++ * encounter a dangling SCSI command pointer. ++ */ ++ req->scmnd = NULL; ++ + spin_lock_irqsave(&target->lock, flags); + list_add(&req->list, &target->free_reqs); + diff --git a/queue-3.15/ib-umad-fix-error-handling.patch b/queue-3.15/ib-umad-fix-error-handling.patch new file mode 100644 index 00000000000..3cb4bcdb4af --- /dev/null +++ b/queue-3.15/ib-umad-fix-error-handling.patch @@ -0,0 +1,132 @@ +From 8ec0a0e6b58218bdc1db91dd70ebfcd6ad8dd6cd Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Tue, 20 May 2014 10:33:41 +0200 +Subject: IB/umad: Fix error handling + +From: Bart Van Assche + +commit 8ec0a0e6b58218bdc1db91dd70ebfcd6ad8dd6cd upstream. + +Avoid leaking a kref count in ib_umad_open() if port->ib_dev == NULL +or if nonseekable_open() fails. + +Avoid leaking a kref count, that sm_sem is kept down and also that the +IB_PORT_SM capability mask is not cleared in ib_umad_sm_open() if +nonseekable_open() fails. + +Since container_of() never returns NULL, remove the code that tests +whether container_of() returns NULL. + +Moving the kref_get() call from the start of ib_umad_*open() to the +end is safe since it is the responsibility of the caller of these +functions to ensure that the cdev pointer remains valid until at least +when these functions return. + +Signed-off-by: Bart Van Assche + +[ydroneaud@opteya.com: rework a bit to reduce the amount of code changed] + +Signed-off-by: Yann Droneaud + +[ nonseekable_open() can't actually fail, but.... - Roland ] + +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/core/user_mad.c | 49 ++++++++++++++++++++----------------- + 1 file changed, 27 insertions(+), 22 deletions(-) + +--- a/drivers/infiniband/core/user_mad.c ++++ b/drivers/infiniband/core/user_mad.c +@@ -780,27 +780,19 @@ static int ib_umad_open(struct inode *in + { + struct ib_umad_port *port; + struct ib_umad_file *file; +- int ret; ++ int ret = -ENXIO; + + port = container_of(inode->i_cdev, struct ib_umad_port, cdev); +- if (port) +- kref_get(&port->umad_dev->ref); +- else +- return -ENXIO; + + mutex_lock(&port->file_mutex); + +- if (!port->ib_dev) { +- ret = -ENXIO; ++ if (!port->ib_dev) + goto out; +- } + ++ ret = -ENOMEM; + file = kzalloc(sizeof *file, GFP_KERNEL); +- if (!file) { +- kref_put(&port->umad_dev->ref, ib_umad_release_dev); +- ret = -ENOMEM; ++ if (!file) + goto out; +- } + + mutex_init(&file->mutex); + spin_lock_init(&file->send_lock); +@@ -814,6 +806,13 @@ static int ib_umad_open(struct inode *in + list_add_tail(&file->port_list, &port->file_list); + + ret = nonseekable_open(inode, filp); ++ if (ret) { ++ list_del(&file->port_list); ++ kfree(file); ++ goto out; ++ } ++ ++ kref_get(&port->umad_dev->ref); + + out: + mutex_unlock(&port->file_mutex); +@@ -880,10 +879,6 @@ static int ib_umad_sm_open(struct inode + int ret; + + port = container_of(inode->i_cdev, struct ib_umad_port, sm_cdev); +- if (port) +- kref_get(&port->umad_dev->ref); +- else +- return -ENXIO; + + if (filp->f_flags & O_NONBLOCK) { + if (down_trylock(&port->sm_sem)) { +@@ -898,17 +893,27 @@ static int ib_umad_sm_open(struct inode + } + + ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props); +- if (ret) { +- up(&port->sm_sem); +- goto fail; +- } ++ if (ret) ++ goto err_up_sem; + + filp->private_data = port; + +- return nonseekable_open(inode, filp); ++ ret = nonseekable_open(inode, filp); ++ if (ret) ++ goto err_clr_sm_cap; ++ ++ kref_get(&port->umad_dev->ref); ++ ++ return 0; ++ ++err_clr_sm_cap: ++ swap(props.set_port_cap_mask, props.clr_port_cap_mask); ++ ib_modify_port(port->ib_dev, port->port_num, 0, &props); ++ ++err_up_sem: ++ up(&port->sm_sem); + + fail: +- kref_put(&port->umad_dev->ref, ib_umad_release_dev); + return ret; + } + diff --git a/queue-3.15/ib-umad-fix-use-after-free-on-close.patch b/queue-3.15/ib-umad-fix-use-after-free-on-close.patch new file mode 100644 index 00000000000..3ab0f7f137b --- /dev/null +++ b/queue-3.15/ib-umad-fix-use-after-free-on-close.patch @@ -0,0 +1,165 @@ +From 60e1751cb52cc6d1ae04b6bd3c2b96e770b5823f Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Fri, 6 Jun 2014 18:25:04 +0200 +Subject: IB/umad: Fix use-after-free on close + +From: Bart Van Assche + +commit 60e1751cb52cc6d1ae04b6bd3c2b96e770b5823f upstream. + +Avoid that closing /dev/infiniband/umad or /dev/infiniband/issm +triggers a use-after-free. __fput() invokes f_op->release() before it +invokes cdev_put(). Make sure that the ib_umad_device structure is +freed by the cdev_put() call instead of f_op->release(). This avoids +that changing the port mode from IB into Ethernet and back to IB +followed by restarting opensmd triggers the following kernel oops: + + general protection fault: 0000 [#1] PREEMPT SMP + RIP: 0010:[] [] module_put+0x2c/0x170 + Call Trace: + [] cdev_put+0x20/0x30 + [] __fput+0x1ae/0x1f0 + [] ____fput+0xe/0x10 + [] task_work_run+0xac/0xe0 + [] do_notify_resume+0x9f/0xc0 + [] int_signal+0x12/0x17 + +Reference: https://bugzilla.kernel.org/show_bug.cgi?id=75051 +Signed-off-by: Bart Van Assche +Reviewed-by: Yann Droneaud +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/core/user_mad.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +--- a/drivers/infiniband/core/user_mad.c ++++ b/drivers/infiniband/core/user_mad.c +@@ -98,7 +98,7 @@ struct ib_umad_port { + + struct ib_umad_device { + int start_port, end_port; +- struct kref ref; ++ struct kobject kobj; + struct ib_umad_port port[0]; + }; + +@@ -134,14 +134,18 @@ static DECLARE_BITMAP(dev_map, IB_UMAD_M + static void ib_umad_add_one(struct ib_device *device); + static void ib_umad_remove_one(struct ib_device *device); + +-static void ib_umad_release_dev(struct kref *ref) ++static void ib_umad_release_dev(struct kobject *kobj) + { + struct ib_umad_device *dev = +- container_of(ref, struct ib_umad_device, ref); ++ container_of(kobj, struct ib_umad_device, kobj); + + kfree(dev); + } + ++static struct kobj_type ib_umad_dev_ktype = { ++ .release = ib_umad_release_dev, ++}; ++ + static int hdr_size(struct ib_umad_file *file) + { + return file->use_pkey_index ? sizeof (struct ib_user_mad_hdr) : +@@ -812,7 +816,7 @@ static int ib_umad_open(struct inode *in + goto out; + } + +- kref_get(&port->umad_dev->ref); ++ kobject_get(&port->umad_dev->kobj); + + out: + mutex_unlock(&port->file_mutex); +@@ -851,7 +855,7 @@ static int ib_umad_close(struct inode *i + mutex_unlock(&file->port->file_mutex); + + kfree(file); +- kref_put(&dev->ref, ib_umad_release_dev); ++ kobject_put(&dev->kobj); + + return 0; + } +@@ -902,7 +906,7 @@ static int ib_umad_sm_open(struct inode + if (ret) + goto err_clr_sm_cap; + +- kref_get(&port->umad_dev->ref); ++ kobject_get(&port->umad_dev->kobj); + + return 0; + +@@ -932,7 +936,7 @@ static int ib_umad_sm_close(struct inode + + up(&port->sm_sem); + +- kref_put(&port->umad_dev->ref, ib_umad_release_dev); ++ kobject_put(&port->umad_dev->kobj); + + return ret; + } +@@ -1000,6 +1004,7 @@ static int find_overflow_devnum(void) + } + + static int ib_umad_init_port(struct ib_device *device, int port_num, ++ struct ib_umad_device *umad_dev, + struct ib_umad_port *port) + { + int devnum; +@@ -1032,6 +1037,7 @@ static int ib_umad_init_port(struct ib_d + + cdev_init(&port->cdev, &umad_fops); + port->cdev.owner = THIS_MODULE; ++ port->cdev.kobj.parent = &umad_dev->kobj; + kobject_set_name(&port->cdev.kobj, "umad%d", port->dev_num); + if (cdev_add(&port->cdev, base, 1)) + goto err_cdev; +@@ -1050,6 +1056,7 @@ static int ib_umad_init_port(struct ib_d + base += IB_UMAD_MAX_PORTS; + cdev_init(&port->sm_cdev, &umad_sm_fops); + port->sm_cdev.owner = THIS_MODULE; ++ port->sm_cdev.kobj.parent = &umad_dev->kobj; + kobject_set_name(&port->sm_cdev.kobj, "issm%d", port->dev_num); + if (cdev_add(&port->sm_cdev, base, 1)) + goto err_sm_cdev; +@@ -1143,7 +1150,7 @@ static void ib_umad_add_one(struct ib_de + if (!umad_dev) + return; + +- kref_init(&umad_dev->ref); ++ kobject_init(&umad_dev->kobj, &ib_umad_dev_ktype); + + umad_dev->start_port = s; + umad_dev->end_port = e; +@@ -1151,7 +1158,8 @@ static void ib_umad_add_one(struct ib_de + for (i = s; i <= e; ++i) { + umad_dev->port[i - s].umad_dev = umad_dev; + +- if (ib_umad_init_port(device, i, &umad_dev->port[i - s])) ++ if (ib_umad_init_port(device, i, umad_dev, ++ &umad_dev->port[i - s])) + goto err; + } + +@@ -1163,7 +1171,7 @@ err: + while (--i >= s) + ib_umad_kill_port(&umad_dev->port[i - s]); + +- kref_put(&umad_dev->ref, ib_umad_release_dev); ++ kobject_put(&umad_dev->kobj); + } + + static void ib_umad_remove_one(struct ib_device *device) +@@ -1177,7 +1185,7 @@ static void ib_umad_remove_one(struct ib + for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) + ib_umad_kill_port(&umad_dev->port[i]); + +- kref_put(&umad_dev->ref, ib_umad_release_dev); ++ kobject_put(&umad_dev->kobj); + } + + static char *umad_devnode(struct device *dev, umode_t *mode) diff --git a/queue-3.15/nfs-don-t-declare-inode-uptodate-unless-all-attributes-were-checked.patch b/queue-3.15/nfs-don-t-declare-inode-uptodate-unless-all-attributes-were-checked.patch new file mode 100644 index 00000000000..b058da41669 --- /dev/null +++ b/queue-3.15/nfs-don-t-declare-inode-uptodate-unless-all-attributes-were-checked.patch @@ -0,0 +1,109 @@ +From 43b6535e717d2f656f71d9bd16022136b781c934 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Tue, 15 Apr 2014 10:07:57 -0400 +Subject: NFS: Don't declare inode uptodate unless all attributes were checked + +From: Trond Myklebust + +commit 43b6535e717d2f656f71d9bd16022136b781c934 upstream. + +Fix a bug, whereby nfs_update_inode() was declaring the inode to be +up to date despite not having checked all the attributes. +The bug occurs because the temporary variable in which we cache +the validity information is 'sanitised' before reapplying to +nfsi->cache_validity. + +Reported-by: Kinglong Mee +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/inode.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -1575,18 +1575,20 @@ static int nfs_update_inode(struct inode + inode->i_version = fattr->change_attr; + } + } else if (server->caps & NFS_CAP_CHANGE_ATTR) +- invalid |= save_cache_validity; ++ nfsi->cache_validity |= save_cache_validity; + + if (fattr->valid & NFS_ATTR_FATTR_MTIME) { + memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); + } else if (server->caps & NFS_CAP_MTIME) +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATTR + | NFS_INO_REVAL_FORCED); + + if (fattr->valid & NFS_ATTR_FATTR_CTIME) { + memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); + } else if (server->caps & NFS_CAP_CTIME) +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATTR + | NFS_INO_REVAL_FORCED); + + /* Check if our cached file size is stale */ +@@ -1608,7 +1610,8 @@ static int nfs_update_inode(struct inode + (long long)new_isize); + } + } else +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATTR + | NFS_INO_REVAL_PAGECACHE + | NFS_INO_REVAL_FORCED); + +@@ -1616,7 +1619,8 @@ static int nfs_update_inode(struct inode + if (fattr->valid & NFS_ATTR_FATTR_ATIME) + memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); + else if (server->caps & NFS_CAP_ATIME) +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATIME ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATIME + | NFS_INO_REVAL_FORCED); + + if (fattr->valid & NFS_ATTR_FATTR_MODE) { +@@ -1627,7 +1631,8 @@ static int nfs_update_inode(struct inode + invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; + } + } else if (server->caps & NFS_CAP_MODE) +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATTR + | NFS_INO_INVALID_ACCESS + | NFS_INO_INVALID_ACL + | NFS_INO_REVAL_FORCED); +@@ -1638,7 +1643,8 @@ static int nfs_update_inode(struct inode + inode->i_uid = fattr->uid; + } + } else if (server->caps & NFS_CAP_OWNER) +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATTR + | NFS_INO_INVALID_ACCESS + | NFS_INO_INVALID_ACL + | NFS_INO_REVAL_FORCED); +@@ -1649,7 +1655,8 @@ static int nfs_update_inode(struct inode + inode->i_gid = fattr->gid; + } + } else if (server->caps & NFS_CAP_OWNER_GROUP) +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATTR + | NFS_INO_INVALID_ACCESS + | NFS_INO_INVALID_ACL + | NFS_INO_REVAL_FORCED); +@@ -1662,7 +1669,8 @@ static int nfs_update_inode(struct inode + set_nlink(inode, fattr->nlink); + } + } else if (server->caps & NFS_CAP_NLINK) +- invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR ++ nfsi->cache_validity |= save_cache_validity & ++ (NFS_INO_INVALID_ATTR + | NFS_INO_REVAL_FORCED); + + if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { diff --git a/queue-3.15/nfs-fix-cache_validity-check-in-nfs_write_pageuptodate.patch b/queue-3.15/nfs-fix-cache_validity-check-in-nfs_write_pageuptodate.patch new file mode 100644 index 00000000000..4237c480f23 --- /dev/null +++ b/queue-3.15/nfs-fix-cache_validity-check-in-nfs_write_pageuptodate.patch @@ -0,0 +1,58 @@ +From 18dd78c427513fb0f89365138be66e6ee8700d1b Mon Sep 17 00:00:00 2001 +From: Scott Mayhew +Date: Fri, 20 Jun 2014 08:44:42 -0400 +Subject: nfs: Fix cache_validity check in nfs_write_pageuptodate() + +From: Scott Mayhew + +commit 18dd78c427513fb0f89365138be66e6ee8700d1b upstream. + +NFS_INO_INVALID_DATA cannot be ignored, even if we have a delegation. + +We're still having some problems with data corruption when multiple +clients are appending to a file and those clients are being granted +write delegations on open. + +To reproduce: + +Client A: +vi /mnt/`hostname -s` +while :; do echo "XXXXXXXXXXXXXXX" >>/mnt/file; sleep $(( $RANDOM % 5 )); done + +Client B: +vi /mnt/`hostname -s` +while :; do echo "YYYYYYYYYYYYYYY" >>/mnt/file; sleep $(( $RANDOM % 5 )); done + +What's happening is that in nfs_update_inode() we're recognizing that +the file size has changed and we're setting NFS_INO_INVALID_DATA +accordingly, but then we ignore the cache_validity flags in +nfs_write_pageuptodate() because we have a delegation. As a result, +in nfs_updatepage() we're extending the write to cover the full page +even though we've not read in the data to begin with. + +Signed-off-by: Scott Mayhew +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/write.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -913,12 +913,14 @@ static bool nfs_write_pageuptodate(struc + + if (nfs_have_delegated_attributes(inode)) + goto out; +- if (nfsi->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) ++ if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) + return false; + smp_rmb(); + if (test_bit(NFS_INO_INVALIDATING, &nfsi->flags)) + return false; + out: ++ if (nfsi->cache_validity & NFS_INO_INVALID_DATA) ++ return false; + return PageUptodate(page) != 0; + } + diff --git a/queue-3.15/nfs-populate-net-in-mount-data-when-remounting.patch b/queue-3.15/nfs-populate-net-in-mount-data-when-remounting.patch new file mode 100644 index 00000000000..c97005fe6fa --- /dev/null +++ b/queue-3.15/nfs-populate-net-in-mount-data-when-remounting.patch @@ -0,0 +1,36 @@ +From a914722f333b3359d2f4f12919380a334176bb89 Mon Sep 17 00:00:00 2001 +From: Mateusz Guzik +Date: Tue, 10 Jun 2014 12:44:12 +0200 +Subject: NFS: populate ->net in mount data when remounting + +From: Mateusz Guzik + +commit a914722f333b3359d2f4f12919380a334176bb89 upstream. + +Otherwise the kernel oopses when remounting with IPv6 server because +net is dereferenced in dev_get_by_name. + +Use net ns of current thread so that dev_get_by_name does not operate on +foreign ns. Changing the address is prohibited anyway so this should not +affect anything. + +Signed-off-by: Mateusz Guzik +Cc: linux-nfs@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/super.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/nfs/super.c ++++ b/fs/nfs/super.c +@@ -2248,6 +2248,7 @@ nfs_remount(struct super_block *sb, int + data->nfs_server.addrlen = nfss->nfs_client->cl_addrlen; + data->version = nfsvers; + data->minorversion = nfss->nfs_client->cl_minorversion; ++ data->net = current->nsproxy->net_ns; + memcpy(&data->nfs_server.address, &nfss->nfs_client->cl_addr, + data->nfs_server.addrlen); + diff --git a/queue-3.15/nfs-use-raw_write_seqcount_begin-end-int-nfs4_reclaim_open_state.patch b/queue-3.15/nfs-use-raw_write_seqcount_begin-end-int-nfs4_reclaim_open_state.patch new file mode 100644 index 00000000000..051a6b8c05d --- /dev/null +++ b/queue-3.15/nfs-use-raw_write_seqcount_begin-end-int-nfs4_reclaim_open_state.patch @@ -0,0 +1,48 @@ +From abbec2da13f0e4c5d9b78b7e2c025a3e617228ba Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Thu, 5 Jun 2014 10:42:37 -0400 +Subject: NFS: Use raw_write_seqcount_begin/end int nfs4_reclaim_open_state + +From: Trond Myklebust + +commit abbec2da13f0e4c5d9b78b7e2c025a3e617228ba upstream. + +The addition of lockdep code to write_seqcount_begin/end has lead to +a bunch of false positive claims of ABBA deadlocks with the so_lock +spinlock. Audits show that this simply cannot happen because the +read side code does not spin while holding so_lock. + +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4state.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1456,7 +1456,7 @@ static int nfs4_reclaim_open_state(struc + * server that doesn't support a grace period. + */ + spin_lock(&sp->so_lock); +- write_seqcount_begin(&sp->so_reclaim_seqcount); ++ raw_write_seqcount_begin(&sp->so_reclaim_seqcount); + restart: + list_for_each_entry(state, &sp->so_states, open_states) { + if (!test_and_clear_bit(ops->state_flag_bit, &state->flags)) +@@ -1519,13 +1519,13 @@ restart: + spin_lock(&sp->so_lock); + goto restart; + } +- write_seqcount_end(&sp->so_reclaim_seqcount); ++ raw_write_seqcount_end(&sp->so_reclaim_seqcount); + spin_unlock(&sp->so_lock); + return 0; + out_err: + nfs4_put_open_state(state); + spin_lock(&sp->so_lock); +- write_seqcount_end(&sp->so_reclaim_seqcount); ++ raw_write_seqcount_end(&sp->so_reclaim_seqcount); + spin_unlock(&sp->so_lock); + return status; + } diff --git a/queue-3.15/nfsd-getattr-for-fattr4_word0_files_avail-needs-the-statfs-buffer.patch b/queue-3.15/nfsd-getattr-for-fattr4_word0_files_avail-needs-the-statfs-buffer.patch new file mode 100644 index 00000000000..8e28b8123c4 --- /dev/null +++ b/queue-3.15/nfsd-getattr-for-fattr4_word0_files_avail-needs-the-statfs-buffer.patch @@ -0,0 +1,33 @@ +From 12337901d654415d9f764b5f5ba50052e9700f37 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Wed, 28 May 2014 10:46:13 +0200 +Subject: nfsd: getattr for FATTR4_WORD0_FILES_AVAIL needs the statfs buffer + +From: Christoph Hellwig + +commit 12337901d654415d9f764b5f5ba50052e9700f37 upstream. + +Note nobody's ever noticed because the typical client probably never +requests FILES_AVAIL without also requesting something else on the list. + +Signed-off-by: Christoph Hellwig +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4xdr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -2095,8 +2095,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s + err = vfs_getattr(&path, &stat); + if (err) + goto out_nfserr; +- if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | +- FATTR4_WORD0_MAXNAME)) || ++ if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE | ++ FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) || + (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | + FATTR4_WORD1_SPACE_TOTAL))) { + err = vfs_statfs(&path, &statfs); diff --git a/queue-3.15/nfsd4-fix-free_stateid-lockowner-leak.patch b/queue-3.15/nfsd4-fix-free_stateid-lockowner-leak.patch new file mode 100644 index 00000000000..8b6517c034d --- /dev/null +++ b/queue-3.15/nfsd4-fix-free_stateid-lockowner-leak.patch @@ -0,0 +1,31 @@ +From 48385408b45523d9a432c66292d47ef43efcbb94 Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Tue, 27 May 2014 11:14:26 -0400 +Subject: nfsd4: fix FREE_STATEID lockowner leak + +From: "J. Bruce Fields" + +commit 48385408b45523d9a432c66292d47ef43efcbb94 upstream. + +27b11428b7de ("nfsd4: remove lockowner when removing lock stateid") +introduced a memory leak. + +Reported-by: Jeff Layton +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4state.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -3726,7 +3726,7 @@ nfsd4_free_lock_stateid(struct nfs4_ol_s + * correspondance, and we have to delete the lockowner when we + * delete the lock stateid: + */ +- unhash_lockowner(lo); ++ release_lockowner(lo); + return nfs_ok; + } + diff --git a/queue-3.15/pnfs-handle-allocation-errors-correctly-in-filelayout_alloc_layout_hdr.patch b/queue-3.15/pnfs-handle-allocation-errors-correctly-in-filelayout_alloc_layout_hdr.patch new file mode 100644 index 00000000000..db71e443bf9 --- /dev/null +++ b/queue-3.15/pnfs-handle-allocation-errors-correctly-in-filelayout_alloc_layout_hdr.patch @@ -0,0 +1,30 @@ +From 6df200f5d5191bdde4d2e408215383890f956781 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Thu, 29 May 2014 20:06:55 -0400 +Subject: pNFS: Handle allocation errors correctly in filelayout_alloc_layout_hdr() + +From: Trond Myklebust + +commit 6df200f5d5191bdde4d2e408215383890f956781 upstream. + +Return the NULL pointer when the allocation fails. + +Reported-by: Fengguang Wu +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4filelayout.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/nfs4filelayout.c ++++ b/fs/nfs/nfs4filelayout.c +@@ -1330,7 +1330,7 @@ filelayout_alloc_layout_hdr(struct inode + struct nfs4_filelayout *flo; + + flo = kzalloc(sizeof(*flo), gfp_flags); +- return &flo->generic_hdr; ++ return flo != NULL ? &flo->generic_hdr : NULL; + } + + static void diff --git a/queue-3.15/series b/queue-3.15/series index 16a27c69062..6348b4cadc7 100644 --- a/queue-3.15/series +++ b/queue-3.15/series @@ -23,3 +23,18 @@ watchdog-sp805-set-watchdog_device-timeout-from-set_timeout.patch watchdog-ath79_wdt-avoid-spurious-restarts-on-ar934x.patch watchdog-kempld-wdt-use-the-correct-value-when-configuring-the-prescaler-with-the-watchdog.patch kernel-watchdog.c-remove-preemption-restrictions-when-restarting-lockup-detector.patch +ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_cq.patch +ib-mlx5-add-missing-padding-at-end-of-struct-mlx5_ib_create_srq.patch +ib-qib-fix-port-in-pkey-change-event.patch +ib-ipath-translate-legacy-diagpkt-into-newer-extended-diagpkt.patch +ib-srp-fix-a-sporadic-crash-triggered-by-cable-pulling.patch +ib-umad-fix-error-handling.patch +ib-umad-fix-use-after-free-on-close.patch +sunrpc-fix-a-module-reference-leak-in-svc_handle_xprt.patch +pnfs-handle-allocation-errors-correctly-in-filelayout_alloc_layout_hdr.patch +nfsd4-fix-free_stateid-lockowner-leak.patch +nfsd-getattr-for-fattr4_word0_files_avail-needs-the-statfs-buffer.patch +nfs-don-t-declare-inode-uptodate-unless-all-attributes-were-checked.patch +nfs-use-raw_write_seqcount_begin-end-int-nfs4_reclaim_open_state.patch +nfs-populate-net-in-mount-data-when-remounting.patch +nfs-fix-cache_validity-check-in-nfs_write_pageuptodate.patch diff --git a/queue-3.15/sunrpc-fix-a-module-reference-leak-in-svc_handle_xprt.patch b/queue-3.15/sunrpc-fix-a-module-reference-leak-in-svc_handle_xprt.patch new file mode 100644 index 00000000000..83eb16ed353 --- /dev/null +++ b/queue-3.15/sunrpc-fix-a-module-reference-leak-in-svc_handle_xprt.patch @@ -0,0 +1,30 @@ +From c789102c20bbbdda6831a273e046715be9d6af79 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Sun, 18 May 2014 14:05:22 -0400 +Subject: SUNRPC: Fix a module reference leak in svc_handle_xprt + +From: Trond Myklebust + +commit c789102c20bbbdda6831a273e046715be9d6af79 upstream. + +If the accept() call fails, we need to put the module reference. + +Signed-off-by: Trond Myklebust +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/svc_xprt.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/sunrpc/svc_xprt.c ++++ b/net/sunrpc/svc_xprt.c +@@ -730,6 +730,8 @@ static int svc_handle_xprt(struct svc_rq + newxpt = xprt->xpt_ops->xpo_accept(xprt); + if (newxpt) + svc_add_new_temp_xprt(serv, newxpt); ++ else ++ module_put(xprt->xpt_class->xcl_owner); + } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { + /* XPT_DATA|XPT_DEFERRED case: */ + dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",