From f1755e8ad7b3b2a85707740686fdcda4a1a2a31c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 3 Nov 2011 12:35:34 -0700 Subject: [PATCH] 3.1 patches --- ...dd-a-nolock-function-to-w1-interface.patch | 114 +++++++ ...ntral-point-for-calling-w1-interface.patch | 278 ++++++++++++++++++ ...-deadlock-upon-insertion-and-removal.patch | 67 +++++ ...nd_fl-or-immutable_fl-for-new-inodes.patch | 62 ++++ ...h-correct-inode-in-ext4_dx_add_entry.patch | 44 +++ ...k-with-newly-created-directory-inode.patch | 33 +++ ...ty-dir_bh-with-the-correct-directory.patch | 35 +++ ...-race-in-xattr-block-allocation-path.patch | 78 +++++ ...write-stop-started-handle-in-failure.patch | 30 ++ ...se-a-mutex-to-protect-the-radix-tree.patch | 249 ++++++++++++++++ queue-3.1/series | 10 + 11 files changed, 1000 insertions(+) create mode 100644 queue-3.1/drivers-power-ds2780_battery.c-add-a-nolock-function-to-w1-interface.patch create mode 100644 queue-3.1/drivers-power-ds2780_battery.c-create-central-point-for-calling-w1-interface.patch create mode 100644 queue-3.1/drivers-power-ds2780_battery.c-fix-deadlock-upon-insertion-and-removal.patch create mode 100644 queue-3.1/ext2-ext3-ext4-don-t-inherit-append_fl-or-immutable_fl-for-new-inodes.patch create mode 100644 queue-3.1/ext4-call-ext4_handle_dirty_metadata-with-correct-inode-in-ext4_dx_add_entry.patch create mode 100644 queue-3.1/ext4-ext4_mkdir-should-dirty-dir_block-with-newly-created-directory-inode.patch create mode 100644 queue-3.1/ext4-ext4_rename-should-dirty-dir_bh-with-the-correct-directory.patch create mode 100644 queue-3.1/ext4-fix-race-in-xattr-block-allocation-path.patch create mode 100644 queue-3.1/ext4-let-ext4_page_mkwrite-stop-started-handle-in-failure.patch create mode 100644 queue-3.1/hwspinlock-core-use-a-mutex-to-protect-the-radix-tree.patch diff --git a/queue-3.1/drivers-power-ds2780_battery.c-add-a-nolock-function-to-w1-interface.patch b/queue-3.1/drivers-power-ds2780_battery.c-add-a-nolock-function-to-w1-interface.patch new file mode 100644 index 00000000000..122c990d738 --- /dev/null +++ b/queue-3.1/drivers-power-ds2780_battery.c-add-a-nolock-function-to-w1-interface.patch @@ -0,0 +1,114 @@ +From 9fe678fa2feb4aaac0b4220de63e1b7f8ccebae6 Mon Sep 17 00:00:00 2001 +From: Clifton Barnes +Date: Wed, 2 Nov 2011 13:39:52 -0700 +Subject: drivers/power/ds2780_battery.c: add a nolock function to w1 interface + +From: Clifton Barnes + +commit 9fe678fa2feb4aaac0b4220de63e1b7f8ccebae6 upstream. + +Adds a nolock function to the w1 interface to avoid locking the +mutex if needed. + +Signed-off-by: Clifton Barnes +Cc: Evgeniy Polyakov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/w1/slaves/w1_ds2780.c | 48 ++++++++++++++++++++++++++++++------------ + drivers/w1/slaves/w1_ds2780.h | 2 + + 2 files changed, 37 insertions(+), 13 deletions(-) + +--- a/drivers/w1/slaves/w1_ds2780.c ++++ b/drivers/w1/slaves/w1_ds2780.c +@@ -26,20 +26,14 @@ + #include "../w1_family.h" + #include "w1_ds2780.h" + +-int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, +- int io) ++static int w1_ds2780_do_io(struct device *dev, char *buf, int addr, ++ size_t count, int io) + { + struct w1_slave *sl = container_of(dev, struct w1_slave, dev); + +- if (!dev) +- return -ENODEV; +- +- mutex_lock(&sl->master->mutex); ++ if (addr > DS2780_DATA_SIZE || addr < 0) ++ return 0; + +- if (addr > DS2780_DATA_SIZE || addr < 0) { +- count = 0; +- goto out; +- } + count = min_t(int, count, DS2780_DATA_SIZE - addr); + + if (w1_reset_select_slave(sl) == 0) { +@@ -47,7 +41,6 @@ int w1_ds2780_io(struct device *dev, cha + w1_write_8(sl->master, W1_DS2780_WRITE_DATA); + w1_write_8(sl->master, addr); + w1_write_block(sl->master, buf, count); +- /* XXX w1_write_block returns void, not n_written */ + } else { + w1_write_8(sl->master, W1_DS2780_READ_DATA); + w1_write_8(sl->master, addr); +@@ -55,13 +48,42 @@ int w1_ds2780_io(struct device *dev, cha + } + } + +-out: ++ return count; ++} ++ ++int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, ++ int io) ++{ ++ struct w1_slave *sl = container_of(dev, struct w1_slave, dev); ++ int ret; ++ ++ if (!dev) ++ return -ENODEV; ++ ++ mutex_lock(&sl->master->mutex); ++ ++ ret = w1_ds2780_do_io(dev, buf, addr, count, io); ++ + mutex_unlock(&sl->master->mutex); + +- return count; ++ return ret; + } + EXPORT_SYMBOL(w1_ds2780_io); + ++int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, size_t count, ++ int io) ++{ ++ int ret; ++ ++ if (!dev) ++ return -ENODEV; ++ ++ ret = w1_ds2780_do_io(dev, buf, addr, count, io); ++ ++ return ret; ++} ++EXPORT_SYMBOL(w1_ds2780_io_nolock); ++ + int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) + { + struct w1_slave *sl = container_of(dev, struct w1_slave, dev); +--- a/drivers/w1/slaves/w1_ds2780.h ++++ b/drivers/w1/slaves/w1_ds2780.h +@@ -124,6 +124,8 @@ + + extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, + int io); ++extern int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, ++ size_t count, int io); + extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd); + + #endif /* !_W1_DS2780_H */ diff --git a/queue-3.1/drivers-power-ds2780_battery.c-create-central-point-for-calling-w1-interface.patch b/queue-3.1/drivers-power-ds2780_battery.c-create-central-point-for-calling-w1-interface.patch new file mode 100644 index 00000000000..8c5edea7d14 --- /dev/null +++ b/queue-3.1/drivers-power-ds2780_battery.c-create-central-point-for-calling-w1-interface.patch @@ -0,0 +1,278 @@ +From 853eee72f74f449797f0500ea19fc1bf497428d8 Mon Sep 17 00:00:00 2001 +From: Clifton Barnes +Date: Wed, 2 Nov 2011 13:39:50 -0700 +Subject: drivers/power/ds2780_battery.c: create central point for calling w1 interface + +From: Clifton Barnes + +commit 853eee72f74f449797f0500ea19fc1bf497428d8 upstream. + +Simply creates one point to call the w1 interface. + +Signed-off-by: Clifton Barnes +Cc: Evgeniy Polyakov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/power/ds2780_battery.c | 77 ++++++++++++++++++++++------------------- + 1 file changed, 42 insertions(+), 35 deletions(-) + +--- a/drivers/power/ds2780_battery.c ++++ b/drivers/power/ds2780_battery.c +@@ -49,8 +49,8 @@ enum current_types { + static const char model[] = "DS2780"; + static const char manufacturer[] = "Maxim/Dallas"; + +-static inline struct ds2780_device_info *to_ds2780_device_info( +- struct power_supply *psy) ++static inline struct ds2780_device_info * ++to_ds2780_device_info(struct power_supply *psy) + { + return container_of(psy, struct ds2780_device_info, bat); + } +@@ -60,17 +60,25 @@ static inline struct power_supply *to_po + return dev_get_drvdata(dev); + } + +-static inline int ds2780_read8(struct device *dev, u8 *val, int addr) ++static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, ++ char *buf, int addr, size_t count, int io) + { +- return w1_ds2780_io(dev, val, addr, sizeof(u8), 0); ++ return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); + } + +-static int ds2780_read16(struct device *dev, s16 *val, int addr) ++static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val, ++ int addr) ++{ ++ return ds2780_battery_io(dev_info, val, addr, sizeof(u8), 0); ++} ++ ++static int ds2780_read16(struct ds2780_device_info *dev_info, s16 *val, ++ int addr) + { + int ret; + u8 raw[2]; + +- ret = w1_ds2780_io(dev, raw, addr, sizeof(u8) * 2, 0); ++ ret = ds2780_battery_io(dev_info, raw, addr, sizeof(raw), 0); + if (ret < 0) + return ret; + +@@ -79,16 +87,16 @@ static int ds2780_read16(struct device * + return 0; + } + +-static inline int ds2780_read_block(struct device *dev, u8 *val, int addr, +- size_t count) ++static inline int ds2780_read_block(struct ds2780_device_info *dev_info, ++ u8 *val, int addr, size_t count) + { +- return w1_ds2780_io(dev, val, addr, count, 0); ++ return ds2780_battery_io(dev_info, val, addr, count, 0); + } + +-static inline int ds2780_write(struct device *dev, u8 *val, int addr, +- size_t count) ++static inline int ds2780_write(struct ds2780_device_info *dev_info, u8 *val, ++ int addr, size_t count) + { +- return w1_ds2780_io(dev, val, addr, count, 1); ++ return ds2780_battery_io(dev_info, val, addr, count, 1); + } + + static inline int ds2780_store_eeprom(struct device *dev, int addr) +@@ -122,7 +130,7 @@ static int ds2780_set_sense_register(str + { + int ret; + +- ret = ds2780_write(dev_info->w1_dev, &conductance, ++ ret = ds2780_write(dev_info, &conductance, + DS2780_RSNSP_REG, sizeof(u8)); + if (ret < 0) + return ret; +@@ -134,7 +142,7 @@ static int ds2780_set_sense_register(str + static int ds2780_get_rsgain_register(struct ds2780_device_info *dev_info, + u16 *rsgain) + { +- return ds2780_read16(dev_info->w1_dev, rsgain, DS2780_RSGAIN_MSB_REG); ++ return ds2780_read16(dev_info, rsgain, DS2780_RSGAIN_MSB_REG); + } + + /* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */ +@@ -144,8 +152,8 @@ static int ds2780_set_rsgain_register(st + int ret; + u8 raw[] = {rsgain >> 8, rsgain & 0xFF}; + +- ret = ds2780_write(dev_info->w1_dev, raw, +- DS2780_RSGAIN_MSB_REG, sizeof(u8) * 2); ++ ret = ds2780_write(dev_info, raw, ++ DS2780_RSGAIN_MSB_REG, sizeof(raw)); + if (ret < 0) + return ret; + +@@ -167,7 +175,7 @@ static int ds2780_get_voltage(struct ds2 + * Bits 2 - 0 of the voltage value are in bits 7 - 5 of the + * voltage LSB register + */ +- ret = ds2780_read16(dev_info->w1_dev, &voltage_raw, ++ ret = ds2780_read16(dev_info, &voltage_raw, + DS2780_VOLT_MSB_REG); + if (ret < 0) + return ret; +@@ -196,7 +204,7 @@ static int ds2780_get_temperature(struct + * Bits 2 - 0 of the temperature value are in bits 7 - 5 of the + * temperature LSB register + */ +- ret = ds2780_read16(dev_info->w1_dev, &temperature_raw, ++ ret = ds2780_read16(dev_info, &temperature_raw, + DS2780_TEMP_MSB_REG); + if (ret < 0) + return ret; +@@ -222,13 +230,13 @@ static int ds2780_get_current(struct ds2 + * The units of measurement for current are dependent on the value of + * the sense resistor. + */ +- ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG); ++ ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG); + if (ret < 0) + return ret; + + if (sense_res_raw == 0) { + dev_err(dev_info->dev, "sense resistor value is 0\n"); +- return -ENXIO; ++ return -EINVAL; + } + sense_res = 1000 / sense_res_raw; + +@@ -248,7 +256,7 @@ static int ds2780_get_current(struct ds2 + * Bits 7 - 0 of the current value are in bits 7 - 0 of the current + * LSB register + */ +- ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, reg_msb); ++ ret = ds2780_read16(dev_info, ¤t_raw, reg_msb); + if (ret < 0) + return ret; + +@@ -267,7 +275,7 @@ static int ds2780_get_accumulated_curren + * The units of measurement for accumulated current are dependent on + * the value of the sense resistor. + */ +- ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG); ++ ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG); + if (ret < 0) + return ret; + +@@ -285,7 +293,7 @@ static int ds2780_get_accumulated_curren + * Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR + * LSB register + */ +- ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, DS2780_ACR_MSB_REG); ++ ret = ds2780_read16(dev_info, ¤t_raw, DS2780_ACR_MSB_REG); + if (ret < 0) + return ret; + +@@ -299,7 +307,7 @@ static int ds2780_get_capacity(struct ds + int ret; + u8 raw; + +- ret = ds2780_read8(dev_info->w1_dev, &raw, DS2780_RARC_REG); ++ ret = ds2780_read8(dev_info, &raw, DS2780_RARC_REG); + if (ret < 0) + return ret; + +@@ -345,7 +353,7 @@ static int ds2780_get_charge_now(struct + * Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC + * LSB register + */ +- ret = ds2780_read16(dev_info->w1_dev, &charge_raw, DS2780_RAAC_MSB_REG); ++ ret = ds2780_read16(dev_info, &charge_raw, DS2780_RAAC_MSB_REG); + if (ret < 0) + return ret; + +@@ -356,7 +364,7 @@ static int ds2780_get_charge_now(struct + static int ds2780_get_control_register(struct ds2780_device_info *dev_info, + u8 *control_reg) + { +- return ds2780_read8(dev_info->w1_dev, control_reg, DS2780_CONTROL_REG); ++ return ds2780_read8(dev_info, control_reg, DS2780_CONTROL_REG); + } + + static int ds2780_set_control_register(struct ds2780_device_info *dev_info, +@@ -364,7 +372,7 @@ static int ds2780_set_control_register(s + { + int ret; + +- ret = ds2780_write(dev_info->w1_dev, &control_reg, ++ ret = ds2780_write(dev_info, &control_reg, + DS2780_CONTROL_REG, sizeof(u8)); + if (ret < 0) + return ret; +@@ -503,7 +511,7 @@ static ssize_t ds2780_get_sense_resistor + struct power_supply *psy = to_power_supply(dev); + struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); + +- ret = ds2780_read8(dev_info->w1_dev, &sense_resistor, DS2780_RSNSP_REG); ++ ret = ds2780_read8(dev_info, &sense_resistor, DS2780_RSNSP_REG); + if (ret < 0) + return ret; + +@@ -584,7 +592,7 @@ static ssize_t ds2780_get_pio_pin(struct + struct power_supply *psy = to_power_supply(dev); + struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); + +- ret = ds2780_read8(dev_info->w1_dev, &sfr, DS2780_SFR_REG); ++ ret = ds2780_read8(dev_info, &sfr, DS2780_SFR_REG); + if (ret < 0) + return ret; + +@@ -611,7 +619,7 @@ static ssize_t ds2780_set_pio_pin(struct + return -EINVAL; + } + +- ret = ds2780_write(dev_info->w1_dev, &new_setting, ++ ret = ds2780_write(dev_info, &new_setting, + DS2780_SFR_REG, sizeof(u8)); + if (ret < 0) + return ret; +@@ -632,7 +640,7 @@ static ssize_t ds2780_read_param_eeprom_ + DS2780_EEPROM_BLOCK1_END - + DS2780_EEPROM_BLOCK1_START + 1 - off); + +- return ds2780_read_block(dev_info->w1_dev, buf, ++ return ds2780_read_block(dev_info, buf, + DS2780_EEPROM_BLOCK1_START + off, count); + } + +@@ -650,7 +658,7 @@ static ssize_t ds2780_write_param_eeprom + DS2780_EEPROM_BLOCK1_END - + DS2780_EEPROM_BLOCK1_START + 1 - off); + +- ret = ds2780_write(dev_info->w1_dev, buf, ++ ret = ds2780_write(dev_info, buf, + DS2780_EEPROM_BLOCK1_START + off, count); + if (ret < 0) + return ret; +@@ -685,9 +693,8 @@ static ssize_t ds2780_read_user_eeprom_b + DS2780_EEPROM_BLOCK0_END - + DS2780_EEPROM_BLOCK0_START + 1 - off); + +- return ds2780_read_block(dev_info->w1_dev, buf, ++ return ds2780_read_block(dev_info, buf, + DS2780_EEPROM_BLOCK0_START + off, count); +- + } + + static ssize_t ds2780_write_user_eeprom_bin(struct file *filp, +@@ -704,7 +711,7 @@ static ssize_t ds2780_write_user_eeprom_ + DS2780_EEPROM_BLOCK0_END - + DS2780_EEPROM_BLOCK0_START + 1 - off); + +- ret = ds2780_write(dev_info->w1_dev, buf, ++ ret = ds2780_write(dev_info, buf, + DS2780_EEPROM_BLOCK0_START + off, count); + if (ret < 0) + return ret; diff --git a/queue-3.1/drivers-power-ds2780_battery.c-fix-deadlock-upon-insertion-and-removal.patch b/queue-3.1/drivers-power-ds2780_battery.c-fix-deadlock-upon-insertion-and-removal.patch new file mode 100644 index 00000000000..4992566f7d5 --- /dev/null +++ b/queue-3.1/drivers-power-ds2780_battery.c-fix-deadlock-upon-insertion-and-removal.patch @@ -0,0 +1,67 @@ +From 0e053fcbbbc4d945247cb32cad2767b483cb65f8 Mon Sep 17 00:00:00 2001 +From: Clifton Barnes +Date: Wed, 2 Nov 2011 13:39:55 -0700 +Subject: drivers/power/ds2780_battery.c: fix deadlock upon insertion and removal + +From: Clifton Barnes + +commit 0e053fcbbbc4d945247cb32cad2767b483cb65f8 upstream. + +Fixes the deadlock when inserting and removing the ds2780. + +Signed-off-by: Clifton Barnes +Cc: Evgeniy Polyakov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/power/ds2780_battery.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/power/ds2780_battery.c ++++ b/drivers/power/ds2780_battery.c +@@ -39,6 +39,7 @@ struct ds2780_device_info { + struct device *dev; + struct power_supply bat; + struct device *w1_dev; ++ struct task_struct *mutex_holder; + }; + + enum current_types { +@@ -63,6 +64,9 @@ static inline struct power_supply *to_po + static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, + char *buf, int addr, size_t count, int io) + { ++ if (dev_info->mutex_holder == current) ++ return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io); ++ else + return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); + } + +@@ -775,6 +779,7 @@ static int __devinit ds2780_battery_prob + dev_info->bat.properties = ds2780_battery_props; + dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); + dev_info->bat.get_property = ds2780_battery_get_property; ++ dev_info->mutex_holder = current; + + ret = power_supply_register(&pdev->dev, &dev_info->bat); + if (ret) { +@@ -804,6 +809,8 @@ static int __devinit ds2780_battery_prob + goto fail_remove_bin_file; + } + ++ dev_info->mutex_holder = NULL; ++ + return 0; + + fail_remove_bin_file: +@@ -823,6 +830,8 @@ static int __devexit ds2780_battery_remo + { + struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); + ++ dev_info->mutex_holder = current; ++ + /* remove attributes */ + sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); + diff --git a/queue-3.1/ext2-ext3-ext4-don-t-inherit-append_fl-or-immutable_fl-for-new-inodes.patch b/queue-3.1/ext2-ext3-ext4-don-t-inherit-append_fl-or-immutable_fl-for-new-inodes.patch new file mode 100644 index 00000000000..646709e659c --- /dev/null +++ b/queue-3.1/ext2-ext3-ext4-don-t-inherit-append_fl-or-immutable_fl-for-new-inodes.patch @@ -0,0 +1,62 @@ +From 1cd9f0976aa4606db8d6e3dc3edd0aca8019372a Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 31 Aug 2011 11:54:51 -0400 +Subject: ext2,ext3,ext4: don't inherit APPEND_FL or IMMUTABLE_FL for new inodes + +From: Theodore Ts'o + +commit 1cd9f0976aa4606db8d6e3dc3edd0aca8019372a upstream. + +This doesn't make much sense, and it exposes a bug in the kernel where +attempts to create a new file in an append-only directory using +O_CREAT will fail (but still leave a zero-length file). This was +discovered when xfstests #79 was generalized so it could run on all +file systems. + +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ext4.h | 3 +-- + include/linux/ext2_fs.h | 4 ++-- + include/linux/ext3_fs.h | 4 ++-- + 3 files changed, 5 insertions(+), 6 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -358,8 +358,7 @@ struct flex_groups { + + /* Flags that should be inherited by new inodes from their parent. */ + #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\ +- EXT4_SYNC_FL | EXT4_IMMUTABLE_FL | EXT4_APPEND_FL |\ +- EXT4_NODUMP_FL | EXT4_NOATIME_FL |\ ++ EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\ + EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\ + EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL) + +--- a/include/linux/ext2_fs.h ++++ b/include/linux/ext2_fs.h +@@ -197,8 +197,8 @@ struct ext2_group_desc + + /* Flags that should be inherited by new inodes from their parent. */ + #define EXT2_FL_INHERITED (EXT2_SECRM_FL | EXT2_UNRM_FL | EXT2_COMPR_FL |\ +- EXT2_SYNC_FL | EXT2_IMMUTABLE_FL | EXT2_APPEND_FL |\ +- EXT2_NODUMP_FL | EXT2_NOATIME_FL | EXT2_COMPRBLK_FL|\ ++ EXT2_SYNC_FL | EXT2_NODUMP_FL |\ ++ EXT2_NOATIME_FL | EXT2_COMPRBLK_FL |\ + EXT2_NOCOMP_FL | EXT2_JOURNAL_DATA_FL |\ + EXT2_NOTAIL_FL | EXT2_DIRSYNC_FL) + +--- a/include/linux/ext3_fs.h ++++ b/include/linux/ext3_fs.h +@@ -180,8 +180,8 @@ struct ext3_group_desc + + /* Flags that should be inherited by new inodes from their parent. */ + #define EXT3_FL_INHERITED (EXT3_SECRM_FL | EXT3_UNRM_FL | EXT3_COMPR_FL |\ +- EXT3_SYNC_FL | EXT3_IMMUTABLE_FL | EXT3_APPEND_FL |\ +- EXT3_NODUMP_FL | EXT3_NOATIME_FL | EXT3_COMPRBLK_FL|\ ++ EXT3_SYNC_FL | EXT3_NODUMP_FL |\ ++ EXT3_NOATIME_FL | EXT3_COMPRBLK_FL |\ + EXT3_NOCOMPR_FL | EXT3_JOURNAL_DATA_FL |\ + EXT3_NOTAIL_FL | EXT3_DIRSYNC_FL) + diff --git a/queue-3.1/ext4-call-ext4_handle_dirty_metadata-with-correct-inode-in-ext4_dx_add_entry.patch b/queue-3.1/ext4-call-ext4_handle_dirty_metadata-with-correct-inode-in-ext4_dx_add_entry.patch new file mode 100644 index 00000000000..1d12a295d02 --- /dev/null +++ b/queue-3.1/ext4-call-ext4_handle_dirty_metadata-with-correct-inode-in-ext4_dx_add_entry.patch @@ -0,0 +1,44 @@ +From 5930ea643805feb50a2f8383ae12eb6f10935e49 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 31 Aug 2011 12:02:51 -0400 +Subject: ext4: call ext4_handle_dirty_metadata with correct inode in ext4_dx_add_entry + +From: Theodore Ts'o + +commit 5930ea643805feb50a2f8383ae12eb6f10935e49 upstream. + +ext4_dx_add_entry manipulates bh2 and frames[0].bh, which are two buffer_heads +that point to directory blocks assigned to the directory inode. However, the +function calls ext4_handle_dirty_metadata with the inode of the file that's +being added to the directory, not the directory inode itself. Therefore, +correct the code to dirty the directory buffers with the directory inode, not +the file inode. + +Signed-off-by: Darrick J. Wong +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1586,7 +1586,7 @@ static int ext4_dx_add_entry(handle_t *h + dxtrace(dx_show_index("node", frames[1].entries)); + dxtrace(dx_show_index("node", + ((struct dx_node *) bh2->b_data)->entries)); +- err = ext4_handle_dirty_metadata(handle, inode, bh2); ++ err = ext4_handle_dirty_metadata(handle, dir, bh2); + if (err) + goto journal_error; + brelse (bh2); +@@ -1612,7 +1612,7 @@ static int ext4_dx_add_entry(handle_t *h + if (err) + goto journal_error; + } +- err = ext4_handle_dirty_metadata(handle, inode, frames[0].bh); ++ err = ext4_handle_dirty_metadata(handle, dir, frames[0].bh); + if (err) { + ext4_std_error(inode->i_sb, err); + goto cleanup; diff --git a/queue-3.1/ext4-ext4_mkdir-should-dirty-dir_block-with-newly-created-directory-inode.patch b/queue-3.1/ext4-ext4_mkdir-should-dirty-dir_block-with-newly-created-directory-inode.patch new file mode 100644 index 00000000000..441087dd13e --- /dev/null +++ b/queue-3.1/ext4-ext4_mkdir-should-dirty-dir_block-with-newly-created-directory-inode.patch @@ -0,0 +1,33 @@ +From f9287c1f2d329f4d78a3bbc9cf0db0ebae6f146a Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Wed, 31 Aug 2011 12:00:51 -0400 +Subject: ext4: ext4_mkdir should dirty dir_block with newly created directory inode + +From: "Darrick J. Wong" + +commit f9287c1f2d329f4d78a3bbc9cf0db0ebae6f146a upstream. + +ext4_mkdir calls ext4_handle_dirty_metadata with dir_block and the inode "dir". +Unfortunately, dir_block belongs to the newly created directory (which is +"inode"), not the parent directory (which is "dir"). Fix the incorrect +association. + +Signed-off-by: Darrick J. Wong +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1863,7 +1863,7 @@ retry: + ext4_set_de_type(dir->i_sb, de, S_IFDIR); + inode->i_nlink = 2; + BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata"); +- err = ext4_handle_dirty_metadata(handle, dir, dir_block); ++ err = ext4_handle_dirty_metadata(handle, inode, dir_block); + if (err) + goto out_clear_inode; + err = ext4_mark_inode_dirty(handle, inode); diff --git a/queue-3.1/ext4-ext4_rename-should-dirty-dir_bh-with-the-correct-directory.patch b/queue-3.1/ext4-ext4_rename-should-dirty-dir_bh-with-the-correct-directory.patch new file mode 100644 index 00000000000..7307ff96bfd --- /dev/null +++ b/queue-3.1/ext4-ext4_rename-should-dirty-dir_bh-with-the-correct-directory.patch @@ -0,0 +1,35 @@ +From bcaa992975041e40449be8c010c26192b8c8b409 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Wed, 31 Aug 2011 11:58:51 -0400 +Subject: ext4: ext4_rename should dirty dir_bh with the correct directory + +From: "Darrick J. Wong" + +commit bcaa992975041e40449be8c010c26192b8c8b409 upstream. + +When ext4_rename performs a directory rename (move), dir_bh is a +buffer that is modified to update the '..' link in the directory being +moved (old_inode). However, ext4_handle_dirty_metadata is called with +the old parent directory inode (old_dir) and dir_bh, which is +incorrect because dir_bh does not belong to the parent inode. Fix +this error. + +Signed-off-by: Darrick J. Wong +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2530,7 +2530,7 @@ static int ext4_rename(struct inode *old + PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = + cpu_to_le32(new_dir->i_ino); + BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); +- retval = ext4_handle_dirty_metadata(handle, old_dir, dir_bh); ++ retval = ext4_handle_dirty_metadata(handle, old_inode, dir_bh); + if (retval) { + ext4_std_error(old_dir->i_sb, retval); + goto end_rename; diff --git a/queue-3.1/ext4-fix-race-in-xattr-block-allocation-path.patch b/queue-3.1/ext4-fix-race-in-xattr-block-allocation-path.patch new file mode 100644 index 00000000000..67ee218efc5 --- /dev/null +++ b/queue-3.1/ext4-fix-race-in-xattr-block-allocation-path.patch @@ -0,0 +1,78 @@ +From 6d6a435190bdf2e04c9465cde5bdc3ac68cf11a4 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Sat, 29 Oct 2011 10:15:35 -0400 +Subject: ext4: fix race in xattr block allocation path + +From: Eric Sandeen + +commit 6d6a435190bdf2e04c9465cde5bdc3ac68cf11a4 upstream. + +Ceph users reported that when using Ceph on ext4, the filesystem +would often become corrupted, containing inodes with incorrect +i_blocks counters. + +I managed to reproduce this with a very hacked-up "streamtest" +binary from the Ceph tree. + +Ceph is doing a lot of xattr writes, to out-of-inode blocks. +There is also another thread which does sync_file_range and close, +of the same files. The problem appears to happen due to this race: + +sync/flush thread xattr-set thread +----------------- ---------------- + +do_writepages ext4_xattr_set +ext4_da_writepages ext4_xattr_set_handle +mpage_da_map_blocks ext4_xattr_block_set + set DELALLOC_RESERVE + ext4_new_meta_blocks + ext4_mb_new_blocks + if (!i_delalloc_reserved_flag) + vfs_dq_alloc_block +ext4_get_blocks + down_write(i_data_sem) + set i_delalloc_reserved_flag + ... + up_write(i_data_sem) + if (i_delalloc_reserved_flag) + vfs_dq_alloc_block_nofail + + +In other words, the sync/flush thread pops in and sets +i_delalloc_reserved_flag on the inode, which makes the xattr thread +think that it's in a delalloc path in ext4_new_meta_blocks(), +and add the block for a second time, after already having added +it once in the !i_delalloc_reserved_flag case in ext4_mb_new_blocks + +The real problem is that we shouldn't be using the DELALLOC_RESERVED +state flag, and instead we should be passing +EXT4_GET_BLOCKS_DELALLOC_RESERVE down to ext4_map_blocks() instead of +using an inode state flag. We'll fix this for now with using +i_data_sem to prevent this race, but this is really not the right way +to fix things. + +Signed-off-by: Eric Sandeen +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/xattr.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -820,8 +820,14 @@ inserted: + if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) + goal = goal & EXT4_MAX_BLOCK_FILE_PHYS; + ++ /* ++ * take i_data_sem because we will test ++ * i_delalloc_reserved_flag in ext4_mb_new_blocks ++ */ ++ down_read((&EXT4_I(inode)->i_data_sem)); + block = ext4_new_meta_blocks(handle, inode, goal, 0, + NULL, &error); ++ up_read((&EXT4_I(inode)->i_data_sem)); + if (error) + goto cleanup; + diff --git a/queue-3.1/ext4-let-ext4_page_mkwrite-stop-started-handle-in-failure.patch b/queue-3.1/ext4-let-ext4_page_mkwrite-stop-started-handle-in-failure.patch new file mode 100644 index 00000000000..37d7bd4e8ba --- /dev/null +++ b/queue-3.1/ext4-let-ext4_page_mkwrite-stop-started-handle-in-failure.patch @@ -0,0 +1,30 @@ +From fcbb5515825f1bb20b7a6f75ec48bee61416f879 Mon Sep 17 00:00:00 2001 +From: Yongqiang Yang +Date: Wed, 26 Oct 2011 05:00:19 -0400 +Subject: ext4: let ext4_page_mkwrite stop started handle in failure + +From: Yongqiang Yang + +commit fcbb5515825f1bb20b7a6f75ec48bee61416f879 upstream. + +The started journal handle should be stopped in failure case. + +Signed-off-by: Yongqiang Yang +Signed-off-by: "Theodore Ts'o" +Acked-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4416,6 +4416,7 @@ retry_alloc: + PAGE_CACHE_SIZE, NULL, do_journal_get_write_access)) { + unlock_page(page); + ret = VM_FAULT_SIGBUS; ++ ext4_journal_stop(handle); + goto out; + } + ext4_set_inode_state(inode, EXT4_STATE_JDATA); diff --git a/queue-3.1/hwspinlock-core-use-a-mutex-to-protect-the-radix-tree.patch b/queue-3.1/hwspinlock-core-use-a-mutex-to-protect-the-radix-tree.patch new file mode 100644 index 00000000000..99bb8f96862 --- /dev/null +++ b/queue-3.1/hwspinlock-core-use-a-mutex-to-protect-the-radix-tree.patch @@ -0,0 +1,249 @@ +From 93b465c2e186d96fb90012ba0f9372eb9952e732 Mon Sep 17 00:00:00 2001 +From: Juan Gutierrez +Date: Tue, 6 Sep 2011 09:30:16 +0300 +Subject: hwspinlock/core: use a mutex to protect the radix tree + +From: Juan Gutierrez + +commit 93b465c2e186d96fb90012ba0f9372eb9952e732 upstream. + +Since we're using non-atomic radix tree allocations, we +should be protecting the tree using a mutex and not a +spinlock. + +Non-atomic allocations and process context locking is good enough, +as the tree is manipulated only when locks are registered/ +unregistered/requested/freed. + +The locks themselves are still protected by spinlocks of course, +and mutexes are not involved in the locking/unlocking paths. + +Signed-off-by: Juan Gutierrez +[ohad@wizery.com: rewrite the commit log, #include mutex.h, add minor +commentary] +[ohad@wizery.com: update register/unregister parts in hwspinlock.txt] +Signed-off-by: Ohad Ben-Cohen +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/hwspinlock.txt | 18 +++++--------- + drivers/hwspinlock/hwspinlock_core.c | 45 +++++++++++++++-------------------- + 2 files changed, 27 insertions(+), 36 deletions(-) + +--- a/Documentation/hwspinlock.txt ++++ b/Documentation/hwspinlock.txt +@@ -39,23 +39,20 @@ independent, drivers. + in case an unused hwspinlock isn't available. Users of this + API will usually want to communicate the lock's id to the remote core + before it can be used to achieve synchronization. +- Can be called from an atomic context (this function will not sleep) but +- not from within interrupt context. ++ Should be called from a process context (might sleep). + + struct hwspinlock *hwspin_lock_request_specific(unsigned int id); + - assign a specific hwspinlock id and return its address, or NULL + if that hwspinlock is already in use. Usually board code will + be calling this function in order to reserve specific hwspinlock + ids for predefined purposes. +- Can be called from an atomic context (this function will not sleep) but +- not from within interrupt context. ++ Should be called from a process context (might sleep). + + int hwspin_lock_free(struct hwspinlock *hwlock); + - free a previously-assigned hwspinlock; returns 0 on success, or an + appropriate error code on failure (e.g. -EINVAL if the hwspinlock + is already free). +- Can be called from an atomic context (this function will not sleep) but +- not from within interrupt context. ++ Should be called from a process context (might sleep). + + int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout); + - lock a previously-assigned hwspinlock with a timeout limit (specified in +@@ -232,15 +229,14 @@ int hwspinlock_example2(void) + + int hwspin_lock_register(struct hwspinlock *hwlock); + - to be called from the underlying platform-specific implementation, in +- order to register a new hwspinlock instance. Can be called from an atomic +- context (this function will not sleep) but not from within interrupt +- context. Returns 0 on success, or appropriate error code on failure. ++ order to register a new hwspinlock instance. Should be called from ++ a process context (this function might sleep). ++ Returns 0 on success, or appropriate error code on failure. + + struct hwspinlock *hwspin_lock_unregister(unsigned int id); + - to be called from the underlying vendor-specific implementation, in order + to unregister an existing (and unused) hwspinlock instance. +- Can be called from an atomic context (will not sleep) but not from +- within interrupt context. ++ Should be called from a process context (this function might sleep). + Returns the address of hwspinlock on success, or NULL on error (e.g. + if the hwspinlock is sill in use). + +--- a/drivers/hwspinlock/hwspinlock_core.c ++++ b/drivers/hwspinlock/hwspinlock_core.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include "hwspinlock_internal.h" + +@@ -52,10 +53,12 @@ + static RADIX_TREE(hwspinlock_tree, GFP_KERNEL); + + /* +- * Synchronization of access to the tree is achieved using this spinlock, ++ * Synchronization of access to the tree is achieved using this mutex, + * as the radix-tree API requires that users provide all synchronisation. ++ * A mutex is needed because we're using non-atomic radix tree allocations. + */ +-static DEFINE_SPINLOCK(hwspinlock_tree_lock); ++static DEFINE_MUTEX(hwspinlock_tree_lock); ++ + + /** + * __hwspin_trylock() - attempt to lock a specific hwspinlock +@@ -261,8 +264,7 @@ EXPORT_SYMBOL_GPL(__hwspin_unlock); + * This function should be called from the underlying platform-specific + * implementation, to register a new hwspinlock instance. + * +- * Can be called from an atomic context (will not sleep) but not from +- * within interrupt context. ++ * Should be called from a process context (might sleep) + * + * Returns 0 on success, or an appropriate error code on failure + */ +@@ -279,7 +281,7 @@ int hwspin_lock_register(struct hwspinlo + + spin_lock_init(&hwlock->lock); + +- spin_lock(&hwspinlock_tree_lock); ++ mutex_lock(&hwspinlock_tree_lock); + + ret = radix_tree_insert(&hwspinlock_tree, hwlock->id, hwlock); + if (ret) +@@ -293,7 +295,7 @@ int hwspin_lock_register(struct hwspinlo + WARN_ON(tmp != hwlock); + + out: +- spin_unlock(&hwspinlock_tree_lock); ++ mutex_unlock(&hwspinlock_tree_lock); + return ret; + } + EXPORT_SYMBOL_GPL(hwspin_lock_register); +@@ -305,8 +307,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_register); + * This function should be called from the underlying platform-specific + * implementation, to unregister an existing (and unused) hwspinlock. + * +- * Can be called from an atomic context (will not sleep) but not from +- * within interrupt context. ++ * Should be called from a process context (might sleep) + * + * Returns the address of hwspinlock @id on success, or NULL on failure + */ +@@ -315,7 +316,7 @@ struct hwspinlock *hwspin_lock_unregiste + struct hwspinlock *hwlock = NULL; + int ret; + +- spin_lock(&hwspinlock_tree_lock); ++ mutex_lock(&hwspinlock_tree_lock); + + /* make sure the hwspinlock is not in use (tag is set) */ + ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED); +@@ -331,7 +332,7 @@ struct hwspinlock *hwspin_lock_unregiste + } + + out: +- spin_unlock(&hwspinlock_tree_lock); ++ mutex_unlock(&hwspinlock_tree_lock); + return hwlock; + } + EXPORT_SYMBOL_GPL(hwspin_lock_unregister); +@@ -400,9 +401,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_get_id); + * to the remote core before it can be used for synchronization (to get the + * id of a given hwlock, use hwspin_lock_get_id()). + * +- * Can be called from an atomic context (will not sleep) but not from +- * within interrupt context (simply because there is no use case for +- * that yet). ++ * Should be called from a process context (might sleep) + * + * Returns the address of the assigned hwspinlock, or NULL on error + */ +@@ -411,7 +410,7 @@ struct hwspinlock *hwspin_lock_request(v + struct hwspinlock *hwlock; + int ret; + +- spin_lock(&hwspinlock_tree_lock); ++ mutex_lock(&hwspinlock_tree_lock); + + /* look for an unused lock */ + ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock, +@@ -431,7 +430,7 @@ struct hwspinlock *hwspin_lock_request(v + hwlock = NULL; + + out: +- spin_unlock(&hwspinlock_tree_lock); ++ mutex_unlock(&hwspinlock_tree_lock); + return hwlock; + } + EXPORT_SYMBOL_GPL(hwspin_lock_request); +@@ -445,9 +444,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request); + * Usually early board code will be calling this function in order to + * reserve specific hwspinlock ids for predefined purposes. + * +- * Can be called from an atomic context (will not sleep) but not from +- * within interrupt context (simply because there is no use case for +- * that yet). ++ * Should be called from a process context (might sleep) + * + * Returns the address of the assigned hwspinlock, or NULL on error + */ +@@ -456,7 +453,7 @@ struct hwspinlock *hwspin_lock_request_s + struct hwspinlock *hwlock; + int ret; + +- spin_lock(&hwspinlock_tree_lock); ++ mutex_lock(&hwspinlock_tree_lock); + + /* make sure this hwspinlock exists */ + hwlock = radix_tree_lookup(&hwspinlock_tree, id); +@@ -482,7 +479,7 @@ struct hwspinlock *hwspin_lock_request_s + hwlock = NULL; + + out: +- spin_unlock(&hwspinlock_tree_lock); ++ mutex_unlock(&hwspinlock_tree_lock); + return hwlock; + } + EXPORT_SYMBOL_GPL(hwspin_lock_request_specific); +@@ -495,9 +492,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_sp + * Should only be called with an @hwlock that was retrieved from + * an earlier call to omap_hwspin_lock_request{_specific}. + * +- * Can be called from an atomic context (will not sleep) but not from +- * within interrupt context (simply because there is no use case for +- * that yet). ++ * Should be called from a process context (might sleep) + * + * Returns 0 on success, or an appropriate error code on failure + */ +@@ -511,7 +506,7 @@ int hwspin_lock_free(struct hwspinlock * + return -EINVAL; + } + +- spin_lock(&hwspinlock_tree_lock); ++ mutex_lock(&hwspinlock_tree_lock); + + /* make sure the hwspinlock is used */ + ret = radix_tree_tag_get(&hwspinlock_tree, hwlock->id, +@@ -538,7 +533,7 @@ int hwspin_lock_free(struct hwspinlock * + module_put(hwlock->owner); + + out: +- spin_unlock(&hwspinlock_tree_lock); ++ mutex_unlock(&hwspinlock_tree_lock); + return ret; + } + EXPORT_SYMBOL_GPL(hwspin_lock_free); diff --git a/queue-3.1/series b/queue-3.1/series index 66a781bd5f2..8f243a0ff57 100644 --- a/queue-3.1/series +++ b/queue-3.1/series @@ -163,3 +163,13 @@ binfmt_elf-fix-pie-execution-with-randomization-disabled.patch proc-fix-races-against-execve-of-proc-pid-fd.patch alsa-hda-add-missing-static-adc-tables-for-alc269-quirks.patch drivers-net-rionet.c-fix-ethernet-address-macros-for-le-platforms.patch +hwspinlock-core-use-a-mutex-to-protect-the-radix-tree.patch +drivers-power-ds2780_battery.c-create-central-point-for-calling-w1-interface.patch +drivers-power-ds2780_battery.c-add-a-nolock-function-to-w1-interface.patch +drivers-power-ds2780_battery.c-fix-deadlock-upon-insertion-and-removal.patch +ext2-ext3-ext4-don-t-inherit-append_fl-or-immutable_fl-for-new-inodes.patch +ext4-ext4_rename-should-dirty-dir_bh-with-the-correct-directory.patch +ext4-ext4_mkdir-should-dirty-dir_block-with-newly-created-directory-inode.patch +ext4-call-ext4_handle_dirty_metadata-with-correct-inode-in-ext4_dx_add_entry.patch +ext4-let-ext4_page_mkwrite-stop-started-handle-in-failure.patch +ext4-fix-race-in-xattr-block-allocation-path.patch -- 2.47.3