From: Greg Kroah-Hartman Date: Thu, 18 Aug 2016 13:09:47 +0000 (+0200) Subject: 3.14-stable patches X-Git-Tag: v3.14.77~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4552862b88344a9a9b7dd43dd0cb9dae586872d2;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: input-i8042-break-load-dependency-between-atkbd-psmouse-and-i8042.patch pci-mark-atheros-ar9485-and-qca9882-to-avoid-bus-reset.patch target-fix-max_unmap_lba_count-calc-overflow.patch target-fix-race-between-iscsi-target-connection-shutdown-abort_task.patch ubi-fix-race-condition-between-ubi-device-creation-and-udev.patch ubi-make-volume-resize-power-cut-aware.patch --- diff --git a/queue-3.14/ib-mlx5-fix-entries-checks-in-mlx5_ib_create_cq.patch b/queue-3.14/ib-mlx5-fix-entries-checks-in-mlx5_ib_create_cq.patch deleted file mode 100644 index dfbdb5bda85..00000000000 --- a/queue-3.14/ib-mlx5-fix-entries-checks-in-mlx5_ib_create_cq.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 9ea578528656e191c1097798a771ff08bab6f323 Mon Sep 17 00:00:00 2001 -From: Noa Osherovich -Date: Sat, 4 Jun 2016 15:15:34 +0300 -Subject: IB/mlx5: Fix entries checks in mlx5_ib_create_cq - -From: Noa Osherovich - -commit 9ea578528656e191c1097798a771ff08bab6f323 upstream. - -Number of entries shouldn't be greater than the device's max -capability. This should be checked before rounding the entries number -to power of two. - -Fixes: 51ee86a4af639 ('IB/mlx5: Fix check of number of entries...') -Signed-off-by: Majd Dibbiny -Signed-off-by: Noa Osherovich -Signed-off-by: Leon Romanovsky -Reviewed-by: Sagi Grimberg -Signed-off-by: Doug Ledford -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/infiniband/hw/mlx5/cq.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/infiniband/hw/mlx5/cq.c -+++ b/drivers/infiniband/hw/mlx5/cq.c -@@ -686,7 +686,8 @@ struct ib_cq *mlx5_ib_create_cq(struct i - int eqn; - int err; - -- if (entries < 0) -+ if (entries < 0 || -+ (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)))) - return ERR_PTR(-EINVAL); - - entries = roundup_pow_of_two(entries + 1); diff --git a/queue-3.14/input-i8042-break-load-dependency-between-atkbd-psmouse-and-i8042.patch b/queue-3.14/input-i8042-break-load-dependency-between-atkbd-psmouse-and-i8042.patch new file mode 100644 index 00000000000..3b32c4b6492 --- /dev/null +++ b/queue-3.14/input-i8042-break-load-dependency-between-atkbd-psmouse-and-i8042.patch @@ -0,0 +1,168 @@ +From 4097461897df91041382ff6fcd2bfa7ee6b2448c Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Mon, 25 Jul 2016 11:36:54 -0700 +Subject: Input: i8042 - break load dependency between atkbd/psmouse and i8042 + +From: Dmitry Torokhov + +commit 4097461897df91041382ff6fcd2bfa7ee6b2448c upstream. + +As explained in 1407814240-4275-1-git-send-email-decui@microsoft.com we +have a hard load dependency between i8042 and atkbd which prevents +keyboard from working on Gen2 Hyper-V VMs. + +> hyperv_keyboard invokes serio_interrupt(), which needs a valid serio +> driver like atkbd.c. atkbd.c depends on libps2.c because it invokes +> ps2_command(). libps2.c depends on i8042.c because it invokes +> i8042_check_port_owner(). As a result, hyperv_keyboard actually +> depends on i8042.c. +> +> For a Generation 2 Hyper-V VM (meaning no i8042 device emulated), if a +> Linux VM (like Arch Linux) happens to configure CONFIG_SERIO_I8042=m +> rather than =y, atkbd.ko can't load because i8042.ko can't load(due to +> no i8042 device emulated) and finally hyperv_keyboard can't work and +> the user can't input: https://bugs.archlinux.org/task/39820 +> (Ubuntu/RHEL/SUSE aren't affected since they use CONFIG_SERIO_I8042=y) + +To break the dependency we move away from using i8042_check_port_owner() +and instead allow serio port owner specify a mutex that clients should use +to serialize PS/2 command stream. + +Reported-by: Mark Laws +Tested-by: Mark Laws +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/serio/i8042.c | 16 +--------------- + drivers/input/serio/libps2.c | 10 ++++------ + include/linux/i8042.h | 6 ------ + include/linux/serio.h | 24 +++++++++++++++++++----- + 4 files changed, 24 insertions(+), 32 deletions(-) + +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -1230,6 +1230,7 @@ static int __init i8042_create_kbd_port( + serio->start = i8042_start; + serio->stop = i8042_stop; + serio->close = i8042_port_close; ++ serio->ps2_cmd_mutex = &i8042_mutex; + serio->port_data = port; + serio->dev.parent = &i8042_platform_device->dev; + strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); +@@ -1321,21 +1322,6 @@ static void i8042_unregister_ports(void) + } + } + +-/* +- * Checks whether port belongs to i8042 controller. +- */ +-bool i8042_check_port_owner(const struct serio *port) +-{ +- int i; +- +- for (i = 0; i < I8042_NUM_PORTS; i++) +- if (i8042_ports[i].serio == port) +- return true; +- +- return false; +-} +-EXPORT_SYMBOL(i8042_check_port_owner); +- + static void i8042_free_irqs(void) + { + if (i8042_aux_irq_registered) +--- a/drivers/input/serio/libps2.c ++++ b/drivers/input/serio/libps2.c +@@ -56,19 +56,17 @@ EXPORT_SYMBOL(ps2_sendbyte); + + void ps2_begin_command(struct ps2dev *ps2dev) + { +- mutex_lock(&ps2dev->cmd_mutex); ++ struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; + +- if (i8042_check_port_owner(ps2dev->serio)) +- i8042_lock_chip(); ++ mutex_lock(m); + } + EXPORT_SYMBOL(ps2_begin_command); + + void ps2_end_command(struct ps2dev *ps2dev) + { +- if (i8042_check_port_owner(ps2dev->serio)) +- i8042_unlock_chip(); ++ struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; + +- mutex_unlock(&ps2dev->cmd_mutex); ++ mutex_unlock(m); + } + EXPORT_SYMBOL(ps2_end_command); + +--- a/include/linux/i8042.h ++++ b/include/linux/i8042.h +@@ -62,7 +62,6 @@ struct serio; + void i8042_lock_chip(void); + void i8042_unlock_chip(void); + int i8042_command(unsigned char *param, int command); +-bool i8042_check_port_owner(const struct serio *); + int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *serio)); + int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, +@@ -83,11 +82,6 @@ static inline int i8042_command(unsigned + return -ENODEV; + } + +-static inline bool i8042_check_port_owner(const struct serio *serio) +-{ +- return false; +-} +- + static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *serio)) + { +--- a/include/linux/serio.h ++++ b/include/linux/serio.h +@@ -29,7 +29,8 @@ struct serio { + + struct serio_device_id id; + +- spinlock_t lock; /* protects critical sections from port's interrupt handler */ ++ /* Protects critical sections from port's interrupt handler */ ++ spinlock_t lock; + + int (*write)(struct serio *, unsigned char); + int (*open)(struct serio *); +@@ -38,16 +39,29 @@ struct serio { + void (*stop)(struct serio *); + + struct serio *parent; +- struct list_head child_node; /* Entry in parent->children list */ ++ /* Entry in parent->children list */ ++ struct list_head child_node; + struct list_head children; +- unsigned int depth; /* level of nesting in serio hierarchy */ ++ /* Level of nesting in serio hierarchy */ ++ unsigned int depth; + +- struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */ +- struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */ ++ /* ++ * serio->drv is accessed from interrupt handlers; when modifying ++ * caller should acquire serio->drv_mutex and serio->lock. ++ */ ++ struct serio_driver *drv; ++ /* Protects serio->drv so attributes can pin current driver */ ++ struct mutex drv_mutex; + + struct device dev; + + struct list_head node; ++ ++ /* ++ * For use by PS/2 layer when several ports share hardware and ++ * may get indigestion when exposed to concurrent access (i8042). ++ */ ++ struct mutex *ps2_cmd_mutex; + }; + #define to_serio_port(d) container_of(d, struct serio, dev) + diff --git a/queue-3.14/pci-mark-atheros-ar9485-and-qca9882-to-avoid-bus-reset.patch b/queue-3.14/pci-mark-atheros-ar9485-and-qca9882-to-avoid-bus-reset.patch new file mode 100644 index 00000000000..7d48e568bc9 --- /dev/null +++ b/queue-3.14/pci-mark-atheros-ar9485-and-qca9882-to-avoid-bus-reset.patch @@ -0,0 +1,43 @@ +From 9ac0108c2bac3f1d0255f64fb89fc27e71131b24 Mon Sep 17 00:00:00 2001 +From: Chris Blake +Date: Mon, 30 May 2016 07:26:37 -0500 +Subject: PCI: Mark Atheros AR9485 and QCA9882 to avoid bus reset + +From: Chris Blake + +commit 9ac0108c2bac3f1d0255f64fb89fc27e71131b24 upstream. + +Similar to the AR93xx series, the AR94xx and the Qualcomm QCA988x also have +the same quirk for the Bus Reset. + +Fixes: c3e59ee4e766 ("PCI: Mark Atheros AR93xx to avoid bus reset") +Signed-off-by: Chris Blake +Signed-off-by: Bjorn Helgaas +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/quirks.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -3017,13 +3017,15 @@ static void quirk_no_bus_reset(struct pc + } + + /* +- * Atheros AR93xx chips do not behave after a bus reset. The device will +- * throw a Link Down error on AER-capable systems and regardless of AER, +- * config space of the device is never accessible again and typically +- * causes the system to hang or reset when access is attempted. ++ * Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset. ++ * The device will throw a Link Down error on AER-capable systems and ++ * regardless of AER, config space of the device is never accessible again ++ * and typically causes the system to hang or reset when access is attempted. + * http://www.spinics.net/lists/linux-pci/msg34797.html + */ + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); + + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, + struct pci_fixup *end) diff --git a/queue-3.14/series b/queue-3.14/series index d8a135a9bd8..ff57805b8a5 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -31,8 +31,13 @@ balloon-check-the-number-of-available-pages-in-leak-balloon.patch ftrace-recordmcount-work-around-for-addition-of-metag-magic-but-not-relocations.patch metag-fix-__cmpxchg_u32-asm-constraint-for-cmp.patch ib-mlx5-fix-modify_qp-command-input-structure.patch -ib-mlx5-fix-entries-checks-in-mlx5_ib_create_cq.patch ib-mlx5-fix-returned-values-of-query-qp.patch ib-mlx5-fix-post-send-fence-logic.patch ib-ipoib-don-t-update-neigh-validity-for-unresolved-entries.patch ib-mlx4-fix-the-sq-size-of-an-rc-qp.patch +ubi-make-volume-resize-power-cut-aware.patch +ubi-fix-race-condition-between-ubi-device-creation-and-udev.patch +target-fix-race-between-iscsi-target-connection-shutdown-abort_task.patch +target-fix-max_unmap_lba_count-calc-overflow.patch +input-i8042-break-load-dependency-between-atkbd-psmouse-and-i8042.patch +pci-mark-atheros-ar9485-and-qca9882-to-avoid-bus-reset.patch diff --git a/queue-3.14/target-fix-max_unmap_lba_count-calc-overflow.patch b/queue-3.14/target-fix-max_unmap_lba_count-calc-overflow.patch new file mode 100644 index 00000000000..ef76c42b1df --- /dev/null +++ b/queue-3.14/target-fix-max_unmap_lba_count-calc-overflow.patch @@ -0,0 +1,92 @@ +From ea263c7fada4af8ec7fe5fcfd6e7d7705a89351b Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Thu, 2 Jun 2016 20:12:37 -0500 +Subject: target: Fix max_unmap_lba_count calc overflow + +From: Mike Christie + +commit ea263c7fada4af8ec7fe5fcfd6e7d7705a89351b upstream. + +max_discard_sectors only 32bits, and some non scsi backend +devices will set this to the max 0xffffffff, so we can end up +overflowing during the max_unmap_lba_count calculation. + +This fixes a regression caused by my patch: + +commit 8a9ebe717a133ba7bc90b06047f43cc6b8bcb8b3 +Author: Mike Christie +Date: Mon Jan 18 14:09:27 2016 -0600 + + target: Fix WRITE_SAME/DISCARD conversion to linux 512b sectors + +which can result in extra discards being sent to due the overflow +causing max_unmap_lba_count to be smaller than what the backing +device can actually support. + +Signed-off-by: Mike Christie +Reviewed-by: Bart Van Assche +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_device.c | 8 +++++--- + drivers/target/target_core_file.c | 3 +-- + drivers/target/target_core_iblock.c | 3 +-- + include/target/target_core_backend.h | 2 +- + 4 files changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1583,13 +1583,15 @@ struct se_device *target_alloc_device(st + * in ATA and we need to set TPE=1 + */ + bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, +- struct request_queue *q, int block_size) ++ struct request_queue *q) + { ++ int block_size = queue_logical_block_size(q); ++ + if (!blk_queue_discard(q)) + return false; + +- attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) / +- block_size; ++ attrib->max_unmap_lba_count = ++ q->limits.max_discard_sectors >> (ilog2(block_size) - 9); + /* + * Currently hardcoded to 1 in Linux/SCSI code.. + */ +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -165,8 +165,7 @@ static int fd_configure_device(struct se + dev_size, div_u64(dev_size, fd_dev->fd_block_size), + fd_dev->fd_block_size); + +- if (target_configure_unmap_from_queue(&dev->dev_attrib, q, +- fd_dev->fd_block_size)) ++ if (target_configure_unmap_from_queue(&dev->dev_attrib, q)) + pr_debug("IFILE: BLOCK Discard support available," + " disabled by default\n"); + /* +--- a/drivers/target/target_core_iblock.c ++++ b/drivers/target/target_core_iblock.c +@@ -126,8 +126,7 @@ static int iblock_configure_device(struc + dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); + dev->dev_attrib.hw_queue_depth = q->nr_requests; + +- if (target_configure_unmap_from_queue(&dev->dev_attrib, q, +- dev->dev_attrib.hw_block_size)) ++ if (target_configure_unmap_from_queue(&dev->dev_attrib, q)) + pr_debug("IBLOCK: BLOCK Discard support available," + " disabled by default\n"); + +--- a/include/target/target_core_backend.h ++++ b/include/target/target_core_backend.h +@@ -96,6 +96,6 @@ void array_free(void *array, int n); + + sector_t target_to_linux_sector(struct se_device *dev, sector_t lb); + bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, +- struct request_queue *q, int block_size); ++ struct request_queue *q); + + #endif /* TARGET_CORE_BACKEND_H */ diff --git a/queue-3.14/target-fix-race-between-iscsi-target-connection-shutdown-abort_task.patch b/queue-3.14/target-fix-race-between-iscsi-target-connection-shutdown-abort_task.patch new file mode 100644 index 00000000000..6a44d47655d --- /dev/null +++ b/queue-3.14/target-fix-race-between-iscsi-target-connection-shutdown-abort_task.patch @@ -0,0 +1,105 @@ +From 064cdd2d91c2805d788876082f31cc63506f22c3 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Thu, 2 Jun 2016 14:56:45 -0700 +Subject: target: Fix race between iscsi-target connection shutdown + ABORT_TASK + +From: Nicholas Bellinger + +commit 064cdd2d91c2805d788876082f31cc63506f22c3 upstream. + +This patch fixes a race in iscsit_release_commands_from_conn() -> +iscsit_free_cmd() -> transport_generic_free_cmd() + wait_for_tasks=1, +where CMD_T_FABRIC_STOP could end up being set after the final +kref_put() is called from core_tmr_abort_task() context. + +This results in transport_generic_free_cmd() blocking indefinately +on se_cmd->cmd_wait_comp, because the target_release_cmd_kref() +check for CMD_T_FABRIC_STOP returns false. + +To address this bug, make iscsit_release_commands_from_conn() +do list_splice and set CMD_T_FABRIC_STOP early while holding +iscsi_conn->cmd_lock. Also make iscsit_aborted_task() only +remove iscsi_cmd_t if CMD_T_FABRIC_STOP has not already been +set. + +Finally in target_release_cmd_kref(), only honor fabric_stop +if CMD_T_ABORTED has been set. + +Cc: Mike Christie +Cc: Quinn Tran +Cc: Himanshu Madhani +Cc: Christoph Hellwig +Cc: Hannes Reinecke +Tested-by: Nicholas Bellinger +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 22 ++++++++++++++++------ + drivers/target/target_core_transport.c | 3 ++- + 2 files changed, 18 insertions(+), 7 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -505,7 +505,8 @@ static void iscsit_aborted_task(struct i + bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD); + + spin_lock_bh(&conn->cmd_lock); +- if (!list_empty(&cmd->i_conn_node)) ++ if (!list_empty(&cmd->i_conn_node) && ++ !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP)) + list_del_init(&cmd->i_conn_node); + spin_unlock_bh(&conn->cmd_lock); + +@@ -4160,6 +4161,7 @@ transport_err: + + static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) + { ++ LIST_HEAD(tmp_list); + struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL; + struct iscsi_session *sess = conn->sess; + /* +@@ -4168,18 +4170,26 @@ static void iscsit_release_commands_from + * has been reset -> returned sleeping pre-handler state. + */ + spin_lock_bh(&conn->cmd_lock); +- list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) { ++ list_splice_init(&conn->conn_cmd_list, &tmp_list); + ++ list_for_each_entry(cmd, &tmp_list, i_conn_node) { ++ struct se_cmd *se_cmd = &cmd->se_cmd; ++ ++ if (se_cmd->se_tfo != NULL) { ++ spin_lock(&se_cmd->t_state_lock); ++ se_cmd->transport_state |= CMD_T_FABRIC_STOP; ++ spin_unlock(&se_cmd->t_state_lock); ++ } ++ } ++ spin_unlock_bh(&conn->cmd_lock); ++ ++ list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) { + list_del_init(&cmd->i_conn_node); +- spin_unlock_bh(&conn->cmd_lock); + + iscsit_increment_maxcmdsn(cmd, sess); +- + iscsit_free_cmd(cmd, true); + +- spin_lock_bh(&conn->cmd_lock); + } +- spin_unlock_bh(&conn->cmd_lock); + } + + static void iscsit_stop_timers_for_cmds( +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -2407,7 +2407,8 @@ static void target_release_cmd_kref(stru + } + + spin_lock(&se_cmd->t_state_lock); +- fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP); ++ fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) && ++ (se_cmd->transport_state & CMD_T_ABORTED); + spin_unlock(&se_cmd->t_state_lock); + + if (se_cmd->cmd_wait_set || fabric_stop) { diff --git a/queue-3.14/ubi-fix-race-condition-between-ubi-device-creation-and-udev.patch b/queue-3.14/ubi-fix-race-condition-between-ubi-device-creation-and-udev.patch new file mode 100644 index 00000000000..a2210d1dfd1 --- /dev/null +++ b/queue-3.14/ubi-fix-race-condition-between-ubi-device-creation-and-udev.patch @@ -0,0 +1,50 @@ +From 714fb87e8bc05ff78255afc0dca981e8c5242785 Mon Sep 17 00:00:00 2001 +From: Iosif Harutyunov +Date: Fri, 22 Jul 2016 23:22:42 +0000 +Subject: ubi: Fix race condition between ubi device creation and udev + +From: Iosif Harutyunov + +commit 714fb87e8bc05ff78255afc0dca981e8c5242785 upstream. + +Install the UBI device object before we arm sysfs. +Otherwise udev tries to read sysfs attributes before UBI is ready and +udev rules will not match. + +Signed-off-by: Iosif Harutyunov +[rw: massaged commit message] +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/ubi/build.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -999,6 +999,9 @@ int ubi_attach_mtd_dev(struct mtd_info * + goto out_detach; + } + ++ /* Make device "available" before it becomes accessible via sysfs */ ++ ubi_devices[ubi_num] = ubi; ++ + err = uif_init(ubi, &ref); + if (err) + goto out_detach; +@@ -1043,7 +1046,6 @@ int ubi_attach_mtd_dev(struct mtd_info * + wake_up_process(ubi->bgt_thread); + spin_unlock(&ubi->wl_lock); + +- ubi_devices[ubi_num] = ubi; + ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL); + return ubi_num; + +@@ -1054,6 +1056,7 @@ out_uif: + ubi_assert(ref); + uif_close(ubi); + out_detach: ++ ubi_devices[ubi_num] = NULL; + ubi_wl_close(ubi); + ubi_free_internal_volumes(ubi); + vfree(ubi->vtbl); diff --git a/queue-3.14/ubi-make-volume-resize-power-cut-aware.patch b/queue-3.14/ubi-make-volume-resize-power-cut-aware.patch new file mode 100644 index 00000000000..a8de3579092 --- /dev/null +++ b/queue-3.14/ubi-make-volume-resize-power-cut-aware.patch @@ -0,0 +1,69 @@ +From 4946784bd3924b1374f05eebff2fd68660bae866 Mon Sep 17 00:00:00 2001 +From: Richard Weinberger +Date: Thu, 23 Jun 2016 19:30:38 +0200 +Subject: ubi: Make volume resize power cut aware + +From: Richard Weinberger + +commit 4946784bd3924b1374f05eebff2fd68660bae866 upstream. + +When the volume resize operation shrinks a volume, +LEBs will be unmapped. Since unmapping will not erase these +LEBs immediately we have to wait for that operation to finish. +Otherwise in case of a power cut right after writing the new +volume table the UBI attach process can find more LEBs than the +volume table knows. This will render the UBI image unattachable. + +Fix this issue by waiting for erase to complete and write the new +volume table afterward. + +Reported-by: Boris Brezillon +Reviewed-by: Boris Brezillon +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/ubi/vmt.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +--- a/drivers/mtd/ubi/vmt.c ++++ b/drivers/mtd/ubi/vmt.c +@@ -534,13 +534,6 @@ int ubi_resize_volume(struct ubi_volume_ + spin_unlock(&ubi->volumes_lock); + } + +- /* Change volume table record */ +- vtbl_rec = ubi->vtbl[vol_id]; +- vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); +- err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); +- if (err) +- goto out_acc; +- + if (pebs < 0) { + for (i = 0; i < -pebs; i++) { + err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i); +@@ -558,6 +551,24 @@ int ubi_resize_volume(struct ubi_volume_ + spin_unlock(&ubi->volumes_lock); + } + ++ /* ++ * When we shrink a volume we have to flush all pending (erase) work. ++ * Otherwise it can happen that upon next attach UBI finds a LEB with ++ * lnum > highest_lnum and refuses to attach. ++ */ ++ if (pebs < 0) { ++ err = ubi_wl_flush(ubi, vol_id, UBI_ALL); ++ if (err) ++ goto out_acc; ++ } ++ ++ /* Change volume table record */ ++ vtbl_rec = ubi->vtbl[vol_id]; ++ vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); ++ err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); ++ if (err) ++ goto out_acc; ++ + vol->reserved_pebs = reserved_pebs; + if (vol->vol_type == UBI_DYNAMIC_VOLUME) { + vol->used_ebs = reserved_pebs;