+++ /dev/null
-Index: b/include/linux/blkdev.h
-===================================================================
---- a/include/linux/blkdev.h
-+++ b/include/linux/blkdev.h
-@@ -1026,6 +1026,6 @@ extern int blk_verify_command(unsigned c
- enum blk_default_limits {
-- BLK_MAX_SEGMENTS = 128,
-+ BLK_MAX_SEGMENTS = 256,
- BLK_SAFE_MAX_SECTORS = 255,
-- BLK_DEF_MAX_SECTORS = 1024,
-+ BLK_DEF_MAX_SECTORS = 2048,
- BLK_MAX_SEGMENT_SIZE = 65536,
- BLK_SEG_BOUNDARY_MASK = 0xFFFFFFFFUL,
- };
-Index: linux-2.6.32.x86_64/include/scsi/scsi.h
-===================================================================
---- linux-2.6.32.x86_64.orig/include/scsi/scsi.h 2010-10-26 21:45:52.000000000 +0300
-+++ linux-2.6.32.x86_64/include/scsi/scsi.h 2010-10-29 11:16:35.000000000 +0300
-@@ -19,7 +19,7 @@ struct scsi_cmnd;
- * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order. The
- * minimum value is 32
- */
--#define SCSI_MAX_SG_SEGMENTS 128
-+#define SCSI_MAX_SG_SEGMENTS 256
-
- /*
- * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit
-Index: linux-2.6.32.x86_64/drivers/scsi/isci/init.c
-===================================================================
---- linux-2.6.32.x86_64/drivers/scsi/isci/init.c
-+++ linux-2.6.32.x86_64/drivers/scsi/isci/init.c
-@@ -19,7 +19,7 @@
- .can_queue = ISCI_CAN_QUEUE_VAL,
- .cmd_per_lun = 1,
- .this_id = -1,
-- .sg_tablesize = SG_ALL,
-+ .sg_tablesize = 128,
- .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
- .use_clustering = ENABLE_CLUSTERING,
- .eh_device_reset_handler = sas_eh_device_reset_handler,
+++ /dev/null
-This patch is no longer needed for Lustre. It is only included
-for testing and ease of using the same kernel with older Lustre
-versions. This testing functionality was replaced in Linux 3.0
-by the dm-flakey driver.
-
-This functionality is mainly used during testing, in order to
-simulate a server crash for ldiskfs by discarding all of the
-writes to the filesystem. For recovery testing we could simulate
-this by using a special loopback or DM device that also discards
-writes to the device.
-
-This functionality is also used by target "failback" in order
-to speed up service shutdown and takeover by the other node
-during controlled operation. However, it would also be possible
-to do this by simply allowing all of the in-flight requests to
-complete and then waiting for the service to stop. This will
-also be needed by the DMU-OSD, because discarding of writes on
-a DMU-based target is not safe as it could trigger a storage
-failure if the data is ever read from disk again and the
-checksum does not match that expected by the block pointer.
-
-Index: linux-2.6.32-131.0.15.el6.x86_64/block/blk-core.c
-===================================================================
---- linux-2.6.32-131.0.15.el6.x86_64.orig/block/blk-core.c 2011-05-10 21:38:33.000000000 +0300
-+++ linux-2.6.32-131.0.15.el6.x86_64/block/blk-core.c 2011-05-19 21:01:04.000000000 +0300
-@@ -1416,6 +1416,8 @@ static inline int should_fail_request(st
-
- #endif /* CONFIG_FAIL_MAKE_REQUEST */
-
-+int dev_check_rdonly(struct block_device *bdev);
-+
- /*
- * Check whether this bio extends beyond the end of the device.
- */
-@@ -1517,6 +1519,12 @@ static inline void __generic_make_reques
- goto end_io;
- }
-
-+ /* this is cfs's dev_rdonly check */
-+ if (bio_rw(bio) == WRITE && dev_check_rdonly(bio->bi_bdev)) {
-+ err = 0;
-+ goto end_io;
-+ }
-+
- if (should_fail_request(bio))
- goto end_io;
-
-@@ -2619,6 +2638,99 @@ int kblockd_schedule_work(struct request
- }
- EXPORT_SYMBOL(kblockd_schedule_work);
-
-+ /*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+struct deventry {
-+ dev_t dev;
-+ struct deventry *next;
-+};
-+
-+static struct deventry *devlist = NULL;
-+static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
-+
-+int dev_check_rdonly(struct block_device *bdev)
-+{
-+ struct deventry *cur;
-+
-+ if (!bdev)
-+ return 0;
-+
-+ spin_lock(&devlock);
-+ cur = devlist;
-+ while(cur) {
-+ if (bdev->bd_dev == cur->dev) {
-+ spin_unlock(&devlock);
-+ return 1;
-+ }
-+ cur = cur->next;
-+ }
-+ spin_unlock(&devlock);
-+ return 0;
-+}
-+
-+void dev_set_rdonly(struct block_device *bdev)
-+{
-+ struct deventry *newdev, *cur;
-+
-+ if (!bdev)
-+ return;
-+
-+ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
-+ if (!newdev)
-+ return;
-+
-+ spin_lock(&devlock);
-+ cur = devlist;
-+ while(cur) {
-+ if (bdev->bd_dev == cur->dev) {
-+ spin_unlock(&devlock);
-+ kfree(newdev);
-+ return;
-+ }
-+ cur = cur->next;
-+ }
-+ newdev->dev = bdev->bd_dev;
-+ newdev->next = devlist;
-+ devlist = newdev;
-+ spin_unlock(&devlock);
-+ printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
-+ bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
-+}
-+
-+void dev_clear_rdonly(struct block_device *bdev)
-+{
-+ struct deventry *cur, *last = NULL;
-+
-+ if (!bdev)
-+ return;
-+
-+ spin_lock(&devlock);
-+ cur = devlist;
-+ while(cur) {
-+ if (bdev->bd_dev == cur->dev) {
-+ if (last)
-+ last->next = cur->next;
-+ else
-+ devlist = cur->next;
-+ spin_unlock(&devlock);
-+ kfree(cur);
-+ printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
-+ bdev->bd_disk ? bdev->bd_disk->disk_name :
-+ "unknown block",
-+ bdev->bd_dev);
-+ return;
-+ }
-+ last = cur;
-+ cur = cur->next;
-+ }
-+ spin_unlock(&devlock);
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
- int __init blk_dev_init(void)
- {
- BUILD_BUG_ON(__REQ_NR_BITS > 8 *
-Index: linux-2.6.32-131.0.15.el6.x86_64/fs/block_dev.c
-===================================================================
---- linux-2.6.32-131.0.15.el6.x86_64.orig/fs/block_dev.c 2011-05-10 21:38:29.000000000 +0300
-+++ linux-2.6.32-131.0.15.el6.x86_64/fs/block_dev.c 2011-05-19 21:01:04.000000000 +0300
-@@ -1389,6 +1389,7 @@ static int __blkdev_put(struct block_dev
- if (bdev != bdev->bd_contains)
- victim = bdev->bd_contains;
- bdev->bd_contains = NULL;
-+ dev_clear_rdonly(bdev);
-
- put_disk(disk);
- module_put(owner);
-Index: linux-2.6.32-131.0.15.el6.x86_64/include/linux/fs.h
-===================================================================
---- linux-2.6.32-131.0.15.el6.x86_64.orig/include/linux/fs.h 2011-05-10 21:38:29.000000000 +0300
-+++ linux-2.6.32-131.0.15.el6.x86_64/include/linux/fs.h 2011-05-19 21:01:04.000000000 +0300
-@@ -2244,6 +2244,10 @@ struct bio;
- extern void submit_bio(int, struct bio *);
- extern int bdev_read_only(struct block_device *);
- #endif
-+#define HAVE_CLEAR_RDONLY_ON_PUT
-+extern void dev_set_rdonly(struct block_device *bdev);
-+extern int dev_check_rdonly(struct block_device *bdev);
-+extern void dev_clear_rdonly(struct block_device *bdev);
- extern int set_blocksize(struct block_device *, int);
- extern int sb_set_blocksize(struct super_block *, int);
- extern int sb_min_blocksize(struct super_block *, int);
+++ /dev/null
-diff -ur linux-2.6.32.46-0.orig//block/blk-core.c linux-2.6.32.46-0/block/blk-core.c
---- linux-2.6.32.46-0.orig//block/blk-core.c 2013-04-26 10:23:22.000000000 -0400
-+++ linux-2.6.32.46-0/block/blk-core.c 2013-04-26 10:25:46.000000000 -0400
-@@ -1350,6 +1350,8 @@
-
- #endif /* CONFIG_FAIL_MAKE_REQUEST */
-
-+int dev_check_rdonly(struct block_device *bdev);
-+
- /*
- * Check whether this bio extends beyond the end of the device.
- */
-@@ -1451,6 +1453,12 @@
- if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
- goto end_io;
-
-+ /* this is cfs's dev_rdonly check */
-+ if (bio_rw(bio) == WRITE && dev_check_rdonly(bio->bi_bdev)) {
-+ err = 0;
-+ goto end_io;
-+ }
-+
- if (should_fail_request(bio))
- goto end_io;
-
-@@ -2494,6 +2502,99 @@
- }
- EXPORT_SYMBOL(kblockd_schedule_work);
-
-+ /*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+struct deventry {
-+ dev_t dev;
-+ struct deventry *next;
-+};
-+
-+static struct deventry *devlist = NULL;
-+static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
-+
-+int dev_check_rdonly(struct block_device *bdev)
-+{
-+ struct deventry *cur;
-+
-+ if (!bdev)
-+ return 0;
-+
-+ spin_lock(&devlock);
-+ cur = devlist;
-+ while(cur) {
-+ if (bdev->bd_dev == cur->dev) {
-+ spin_unlock(&devlock);
-+ return 1;
-+ }
-+ cur = cur->next;
-+ }
-+ spin_unlock(&devlock);
-+ return 0;
-+}
-+
-+void dev_set_rdonly(struct block_device *bdev)
-+{
-+ struct deventry *newdev, *cur;
-+
-+ if (!bdev)
-+ return;
-+
-+ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
-+ if (!newdev)
-+ return;
-+
-+ spin_lock(&devlock);
-+ cur = devlist;
-+ while(cur) {
-+ if (bdev->bd_dev == cur->dev) {
-+ spin_unlock(&devlock);
-+ kfree(newdev);
-+ return;
-+ }
-+ cur = cur->next;
-+ }
-+ newdev->dev = bdev->bd_dev;
-+ newdev->next = devlist;
-+ devlist = newdev;
-+ spin_unlock(&devlock);
-+ printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
-+ bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
-+}
-+
-+void dev_clear_rdonly(struct block_device *bdev)
-+{
-+ struct deventry *cur, *last = NULL;
-+
-+ if (!bdev)
-+ return;
-+
-+ spin_lock(&devlock);
-+ cur = devlist;
-+ while(cur) {
-+ if (bdev->bd_dev == cur->dev) {
-+ if (last)
-+ last->next = cur->next;
-+ else
-+ devlist = cur->next;
-+ spin_unlock(&devlock);
-+ kfree(cur);
-+ printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
-+ bdev->bd_disk ? bdev->bd_disk->disk_name :
-+ "unknown block",
-+ bdev->bd_dev);
-+ return;
-+ }
-+ last = cur;
-+ cur = cur->next;
-+ }
-+ spin_unlock(&devlock);
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
- int __init blk_dev_init(void)
- {
- BUILD_BUG_ON(__REQ_NR_BITS > 8 *
-diff -ur linux-2.6.32.46-0.orig//fs/block_dev.c linux-2.6.32.46-0/fs/block_dev.c
---- linux-2.6.32.46-0.orig//fs/block_dev.c 2013-04-26 10:23:31.000000000 -0400
-+++ linux-2.6.32.46-0/fs/block_dev.c 2013-04-26 10:25:46.000000000 -0400
-@@ -1374,6 +1374,7 @@
- if (bdev != bdev->bd_contains)
- victim = bdev->bd_contains;
- bdev->bd_contains = NULL;
-+ dev_clear_rdonly(bdev);
- }
- unlock_kernel();
- mutex_unlock(&bdev->bd_mutex);
-diff -ur linux-2.6.32.46-0.orig//include/linux/fs.h linux-2.6.32.46-0/include/linux/fs.h
---- linux-2.6.32.46-0.orig//include/linux/fs.h 2013-04-26 10:23:39.000000000 -0400
-+++ linux-2.6.32.46-0/include/linux/fs.h 2013-04-26 10:25:46.000000000 -0400
-@@ -2237,6 +2237,10 @@
- extern void submit_bio(int, struct bio *);
- extern int bdev_read_only(struct block_device *);
- #endif
-+#define HAVE_CLEAR_RDONLY_ON_PUT
-+extern void dev_set_rdonly(struct block_device *bdev);
-+extern int dev_check_rdonly(struct block_device *bdev);
-+extern void dev_clear_rdonly(struct block_device *bdev);
- extern int set_blocksize(struct block_device *, int);
- extern int sb_set_blocksize(struct super_block *, int);
- extern int sb_min_blocksize(struct super_block *, int);
+++ /dev/null
---- a/kernel/kallsyms.c.orig 2017-07-12 13:01:00.143416830 -0700
-+++ a/kernel/kallsyms.c 2017-07-12 13:01:40.438112247 -0700
-@@ -181,6 +181,7 @@ unsigned long kallsyms_lookup_name(const
- }
- return module_kallsyms_lookup_name(name);
- }
-+EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
-
- int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
- unsigned long),
+++ /dev/null
-module: Fix a few concurrent module loading races
-
-Concurrently starting multiple OSTs on a single OSS frequently
-triggers 30s deadlocks on module_mutex. This RHEL 6 kernel bug
-applies to any module that results in additional request_module()
-calls in its init callback. In Lustre, at least ptlrpc and libcfs are
-affected. This patch adapts fixes from the following upstream
-commits:
-
- 9bea7f2 module: fix bne2 "gave up waiting for init of module
- libcrc32c"
- be593f4 module: verify_export_symbols under the lock
- 3bafeb6 module: move find_module check to end
- 80a3d1b module: move sysfs exposure to end of load_module
-
-diff -rNup linux-2.6.32-431.20.3.el6.orig/kernel/module.c linux-2.6.32-431.20.3.el6/kernel/module.c
---- linux-2.6.32-431.20.3.el6.orig/kernel/module.c 2014-06-07 05:42:39.000000000 +0800
-+++ linux-2.6.32-431.20.3.el6/kernel/module.c 2014-07-28 00:04:43.000000000 +0800
-@@ -658,6 +658,33 @@ static int already_uses(struct module *a
- }
-
- /* Module a uses b */
-+static int ref_module(struct module *a, struct module *b)
-+{
-+ struct module_use *use;
-+ int err;
-+
-+ if (b == NULL || already_uses(a, b))
-+ return 0;
-+
-+ /* If module isn't available, we fail. */
-+ err = strong_try_module_get(b);
-+ if (err)
-+ return err;
-+
-+ DEBUGP("Allocating new usage for %s.\n", a->name);
-+ use = kmalloc(sizeof(*use), GFP_ATOMIC);
-+ if (!use) {
-+ printk("%s: out of memory loading\n", a->name);
-+ module_put(b);
-+ return -ENOMEM;
-+ }
-+
-+ use->module_which_uses = a;
-+ list_add(&use->list, &b->modules_which_use_me);
-+ return 0;
-+}
-+
-+/* Module a uses b */
- int use_module(struct module *a, struct module *b)
- {
- struct module_use *use;
-@@ -707,7 +734,6 @@ static void module_unload_free(struct mo
- module_put(i);
- list_del(&use->list);
- kfree(use);
-- sysfs_remove_link(i->holders_dir, mod->name);
- /* There can be at most one match. */
- break;
- }
-@@ -962,6 +988,11 @@ static inline void module_unload_free(st
- {
- }
-
-+static inline int ref_module(struct module *a, struct module *b)
-+{
-+ return strong_try_module_get(b);
-+}
-+
- int use_module(struct module *a, struct module *b)
- {
- return strong_try_module_get(b) == 0;
-@@ -1130,24 +1161,60 @@ static inline int same_magic(const char
- static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
- unsigned int versindex,
- const char *name,
-- struct module *mod)
-+ struct module *mod,
-+ char ownername[])
- {
- struct module *owner;
- const struct kernel_symbol *sym;
- const unsigned long *crc;
-+ int err;
-
-+ mutex_lock(&module_mutex);
- sym = find_symbol(name, &owner, &crc,
- !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
-- /* use_module can fail due to OOM,
-- or module initialization or unloading */
-- if (sym) {
-- if (!check_version(sechdrs, versindex, name, mod, crc, owner)
-- || !use_module(mod, owner))
-- sym = NULL;
-+ if (!sym)
-+ goto unlock;
-+
-+ if (!check_version(sechdrs, versindex, name, mod, crc, owner)) {
-+ sym = ERR_PTR(-EINVAL);
-+ goto getname;
- }
-+
-+ err = ref_module(mod, owner);
-+ if (err) {
-+ sym = ERR_PTR(err);
-+ goto getname;
-+ }
-+
-+getname:
-+ /* We must make copy under the lock if we failed to get ref. */
-+ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);
-+unlock:
-+ mutex_unlock(&module_mutex);
- return sym;
- }
-
-+static const struct kernel_symbol *resolve_symbol_wait(Elf_Shdr *sechdrs,
-+ unsigned int versindex,
-+ const char *name,
-+ struct module *mod)
-+{
-+ const struct kernel_symbol *ksym;
-+ char ownername[MODULE_NAME_LEN];
-+
-+ mutex_unlock(&module_mutex);
-+ if (wait_event_interruptible_timeout(module_wq,
-+ !IS_ERR(ksym = resolve_symbol(sechdrs, versindex, name,
-+ mod, ownername)) ||
-+ PTR_ERR(ksym) != -EBUSY,
-+ msecs_to_jiffies(30 * MSEC_PER_SEC)) <= 0) {
-+ printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n",
-+ mod->name, ownername);
-+ }
-+ mutex_lock(&module_mutex);
-+ return ksym;
-+}
-+
- /*
- * /sys/module/foo/sections stuff
- * J. Corbet <corbet@lwn.net>
-@@ -1375,6 +1442,30 @@ static inline void remove_notes_attrs(st
- #endif
-
- #ifdef CONFIG_SYSFS
-+static void add_usage_links(struct module *mod)
-+{
-+#ifdef CONFIG_MODULE_UNLOAD
-+ struct module_use *use;
-+ int nowarn;
-+
-+ list_for_each_entry(use, &mod->modules_which_use_me, list) {
-+ nowarn = sysfs_create_link(use->module_which_uses->holders_dir,
-+ &mod->mkobj.kobj, mod->name);
-+ }
-+#endif
-+}
-+
-+static void del_usage_links(struct module *mod)
-+{
-+#ifdef CONFIG_MODULE_UNLOAD
-+ struct module_use *use;
-+
-+ list_for_each_entry(use, &mod->modules_which_use_me, list)
-+ sysfs_remove_link(use->module_which_uses->holders_dir, mod->name);
-+#endif
-+}
-+
-+
- int module_add_modinfo_attrs(struct module *mod)
- {
- struct module_attribute *attr;
-@@ -1456,6 +1547,10 @@ int mod_sysfs_setup(struct module *mod,
- {
- int err;
-
-+ err = mod_sysfs_init(mod);
-+ if (err)
-+ goto out;
-+
- mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);
- if (!mod->holders_dir) {
- err = -ENOMEM;
-@@ -1470,6 +1565,8 @@ int mod_sysfs_setup(struct module *mod,
- if (err)
- goto out_unreg_param;
-
-+ add_usage_links(mod);
-+
- kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
- return 0;
-
-@@ -1479,6 +1576,7 @@ out_unreg_holders:
- kobject_put(mod->holders_dir);
- out_unreg:
- kobject_put(&mod->mkobj.kobj);
-+out:
- return err;
- }
-
-@@ -1493,10 +1591,15 @@ static void mod_sysfs_fini(struct module
- {
- }
-
-+static void del_usage_links(struct module *mod)
-+{
-+}
-+
- #endif /* CONFIG_SYSFS */
-
- static void mod_kobject_remove(struct module *mod)
- {
-+ del_usage_links(mod);
- module_remove_modinfo_attrs(mod);
- module_param_sysfs_remove(mod);
- kobject_put(mod->mkobj.drivers_dir);
-@@ -1576,6 +1679,8 @@ EXPORT_SYMBOL_GPL(__symbol_get);
- /*
- * Ensure that an exported symbol [global namespace] does not already exist
- * in the kernel or in some other module's exported symbol table.
-+ *
-+ * You must hold the module_mutex.
- */
- static int verify_export_symbols(struct module *mod)
- {
-@@ -1641,21 +1746,23 @@ static int simplify_symbols(Elf_Shdr *se
- break;
-
- case SHN_UNDEF:
-- ksym = resolve_symbol(sechdrs, versindex,
-- strtab + sym[i].st_name, mod);
-+ ksym = resolve_symbol_wait(sechdrs, versindex,
-+ strtab + sym[i].st_name,
-+ mod);
- /* Ok if resolved. */
-- if (ksym) {
-+ if (ksym && !IS_ERR(ksym)) {
- sym[i].st_value = ksym->value;
- break;
- }
-
- /* Ok if weak. */
-- if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
-+ if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
- break;
-
-- printk(KERN_WARNING "%s: Unknown symbol %s\n",
-- mod->name, strtab + sym[i].st_name);
-- ret = -ENOENT;
-+ printk(KERN_WARNING "%s: Unknown symbol %s (err %li)\n",
-+ mod->name, strtab + sym[i].st_name,
-+ PTR_ERR(ksym));
-+ ret = PTR_ERR(ksym) ?: -ENOENT;
- break;
-
- default:
-@@ -2240,11 +2347,6 @@ static noinline struct module *load_modu
- goto free_mod;
- }
-
-- if (find_module(mod->name)) {
-- err = -EEXIST;
-- goto free_mod;
-- }
--
- mod->state = MODULE_STATE_COMING;
-
- /* Allow arches to frob section contents and sizes. */
-@@ -2338,11 +2440,6 @@ static noinline struct module *load_modu
- /* Now we've moved module, initialize linked lists, etc. */
- module_unload_init(mod);
-
-- /* add kobject, so we can reference it. */
-- err = mod_sysfs_init(mod);
-- if (err)
-- goto free_unload;
--
- /* Set up license info based on the info section */
- set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
-
-@@ -2461,11 +2558,6 @@ static noinline struct module *load_modu
- goto cleanup;
- }
-
-- /* Find duplicate symbols */
-- err = verify_export_symbols(mod);
-- if (err < 0)
-- goto cleanup;
--
- /* Set up and sort exception table */
- mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
- sizeof(*mod->extable), &mod->num_exentries);
-@@ -2521,6 +2613,16 @@ static noinline struct module *load_modu
- * function to insert in a way safe to concurrent readers.
- * The mutex protects against concurrent writers.
- */
-+ if (find_module(mod->name)) {
-+ err = -EEXIST;
-+ goto already_exists;
-+ }
-+
-+ /* Find duplicate symbols */
-+ err = verify_export_symbols(mod);
-+ if (err < 0)
-+ goto already_exists;
-+
- list_add_rcu(&mod->list, &modules);
-
- err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
-@@ -2530,6 +2632,7 @@ static noinline struct module *load_modu
- err = mod_sysfs_setup(mod, mod->kp, mod->num_kp);
- if (err < 0)
- goto unlink;
-+
- add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
- add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
-
-@@ -2544,15 +2647,13 @@ static noinline struct module *load_modu
- unlink:
- /* Unlink carefully: kallsyms could be walking list. */
- list_del_rcu(&mod->list);
-+ already_exists:
- synchronize_sched();
- module_arch_cleanup(mod);
- ddebug:
- dynamic_debug_remove(debug);
- cleanup:
- free_modinfo(mod);
-- kobject_del(&mod->mkobj.kobj);
-- kobject_put(&mod->mkobj.kobj);
-- free_unload:
- module_unload_free(mod);
- #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
- percpu_modfree(mod->refptr);
+++ /dev/null
-Increase MAX_SGE for fusion mpt driver.
-
-Index: linux-2.6.32.i386/drivers/message/fusion/Kconfig
-===================================================================
---- linux-2.6.32.i386.orig/drivers/message/fusion/Kconfig 2009-12-03 09:21:21.000000000 +0530
-+++ linux-2.6.32.i386/drivers/message/fusion/Kconfig 2010-03-16 16:45:08.000000000 +0530
-@@ -61,9 +61,9 @@
- LSISAS1078
-
- config FUSION_MAX_SGE
-- int "Maximum number of scatter gather entries (16 - 128)"
-- default "128"
-- range 16 128
-+ int "Maximum number of scatter gather entries (16 - 256)"
-+ default "256"
-+ range 16 256
- help
- This option allows you to specify the maximum number of scatter-
- gather entries per I/O. The driver default is 128, which matches
-Index: linux-2.6.32.i386/drivers/message/fusion/mptbase.h
-===================================================================
---- linux-2.6.32.i386.orig/drivers/message/fusion/mptbase.h 2009-12-03 09:21:21.000000000 +0530
-+++ linux-2.6.32.i386/drivers/message/fusion/mptbase.h 2010-03-16 16:46:54.000000000 +0530
-@@ -165,10 +165,10 @@
- * Set the MAX_SGE value based on user input.
- */
- #ifdef CONFIG_FUSION_MAX_SGE
--#if CONFIG_FUSION_MAX_SGE < 16
-+#if CONFIG_FUSION_MAX_SGE < 16
- #define MPT_SCSI_SG_DEPTH 16
--#elif CONFIG_FUSION_MAX_SGE > 128
--#define MPT_SCSI_SG_DEPTH 128
-+#elif CONFIG_FUSION_MAX_SGE > 256
-+#define MPT_SCSI_SG_DEPTH 256
- #else
- #define MPT_SCSI_SG_DEPTH CONFIG_FUSION_MAX_SGE
- #endif
+++ /dev/null
-commit 1ea06bec78a128adc995ca32bd906a6c9bb9cf91
-Author: Niu Yawei <yawei.niu@gmail.com>
-Date: Wed Jun 4 12:20:30 2014 +0800
-
- quota: avoid unnecessary dqget()/dqput() calls
-
- Avoid unnecessary dqget()/dqput() calls in __dquot_initialize(),
- that will introduce global lock contention otherwise.
-
- Signed-off-by: Lai Siyao <lai.siyao@intel.com>
- Signed-off-by: Niu Yawei <yawei.niu@intel.com>
- Signed-off-by: Jan Kara <jack@suse.cz>
-Index: linux-2.6.32-431.5.1.el6/fs/quota/dquot.c
-===================================================================
---- linux-2.6.32-431.5.1.el6.orig/fs/quota/dquot.c
-+++ linux-2.6.32-431.5.1.el6/fs/quota/dquot.c
-@@ -1230,7 +1230,7 @@ static int info_bdq_free(struct dquot *d
- int dquot_initialize(struct inode *inode, int type)
- {
- unsigned int id = 0;
-- int cnt, ret = 0;
-+ int cnt, ret = 0, init_needed = 0;
- struct dquot *got[MAXQUOTAS] = { NULL, NULL };
- struct super_block *sb = inode->i_sb;
- qsize_t rsv;
-@@ -1244,6 +1244,15 @@ int dquot_initialize(struct inode *inode
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (type != -1 && cnt != type)
- continue;
-+ /*
-+ * The i_dquot should have been initialized in most cases,
-+ * we check it without locking here to avoid unnecessary
-+ * dqget()/dqput() calls.
-+ */
-+ if (inode->i_dquot[cnt])
-+ continue;
-+ init_needed = 1;
-+
- switch (cnt) {
- case USRQUOTA:
- id = inode->i_uid;
-@@ -1255,6 +1264,10 @@ int dquot_initialize(struct inode *inode
- got[cnt] = dqget(sb, id, cnt);
- }
-
-+ /* All required i_dquot has been initialized */
-+ if (!init_needed)
-+ return 0;
-+
- spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode))
- goto out_err;
-@@ -1264,6 +1277,9 @@ int dquot_initialize(struct inode *inode
- /* Avoid races with quotaoff() */
- if (!sb_has_quota_active(sb, cnt))
- continue;
-+ /* We could race with quotaon or dqget() could have failed */
-+ if (!got[cnt])
-+ continue;
- if (!inode->i_dquot[cnt]) {
- inode->i_dquot[cnt] = got[cnt];
- got[cnt] = NULL;
+++ /dev/null
-Remove dqptr_sem (but kept in struct quota_info to keep kernel ABI
-unchanged), and the functionality of this lock is implemented by
-other locks:
-* i_dquot is protected by i_lock, however only this pointer, the
- content of this struct is by dq_data_lock.
-* Q_GETFMT is now protected with dqonoff_mutex instead of dqptr_sem.
-
- fs/quota/dquot.c | 243 +++++++++++++++++++++++++++++------------------------
- fs/quota/quota.c | 6 -
- fs/stat.c | 16 ++-
- fs/super.c | 1
- include/linux/fs.h | 2
- 5 files changed, 154 insertions(+), 114 deletions(-)
-
-Index: linux-2.6.32-358.0.1.el6/fs/quota/dquot.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/quota/dquot.c
-+++ linux-2.6.32-358.0.1.el6/fs/quota/dquot.c
-@@ -83,22 +83,17 @@
- /*
- * There are three quota SMP locks. dq_list_lock protects all lists with quotas
- * and quota formats, dqstats structure containing statistics about the lists
-- * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures and
-- * also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes.
-- * i_blocks and i_bytes updates itself are guarded by i_lock acquired directly
-- * in inode_add_bytes() and inode_sub_bytes(). dq_state_lock protects
-- * modifications of quota state (on quotaon and quotaoff) and readers who care
-- * about latest values take it as well.
-+ * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures.
-+ * dq_state_lock protects modifications of quota state (on quotaon and quotaoff)
-+ * and readers who care about latest values take it as well.
- *
-- * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock,
-+ * The spinlock ordering is hence: i_lock > dq_data_lock > dq_list_lock,
- * dq_list_lock > dq_state_lock
- *
- * Note that some things (eg. sb pointer, type, id) doesn't change during
- * the life of the dquot structure and so needn't to be protected by a lock
- *
-- * Any operation working on dquots via inode pointers must hold dqptr_sem. If
-- * operation is just reading pointers from inode (or not using them at all) the
-- * read lock is enough. If pointers are altered function must hold write lock
-+ * Any operation working on dquots via inode pointers must hold i_lock.
- * (these locking rules also apply for S_NOQUOTA flag in the inode - note that
- * for altering the flag i_mutex is also needed).
- *
-@@ -112,15 +107,8 @@
- * spinlock to internal buffers before writing.
- *
- * Lock ordering (including related VFS locks) is the following:
-- * i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock >
-- * dqio_mutex
-- * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem >
-- * dqptr_sem. But filesystem has to count with the fact that functions such as
-- * dquot_alloc_space() acquire dqptr_sem and they usually have to be called
-- * from inside a transaction to keep filesystem consistency after a crash. Also
-- * filesystems usually want to do some IO on dquot from ->mark_dirty which is
-- * called with dqptr_sem held.
-- * i_mutex on quota files is special (it's below dqio_mutex)
-+ * i_mutex > dqonoff_sem > journal_lock > dquot->dq_lock > dqio_mutex
-+ * i_mutex on quota files is special (it's below dqio_mutex)
- */
-
- static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
-@@ -868,7 +856,6 @@ static inline int dqput_blocks(struct dq
- /*
- * Remove references to dquots from inode and add dquot to list for freeing
- * if we have the last referece to dquot
-- * We can't race with anybody because we hold dqptr_sem for writing...
- */
- static int remove_inode_dquot_ref(struct inode *inode, int type,
- struct list_head *tofree_head)
-@@ -926,10 +913,12 @@ static void remove_dquot_ref(struct supe
- * We have to scan also I_NEW inodes because they can already
- * have quota pointer initialized. Luckily, we need to touch
- * only quota pointers and these have separate locking
-- * (dqptr_sem).
-+ * (i_lock).
- */
-+ spin_lock(&inode->i_lock);
- if (!IS_NOQUOTA(inode))
- remove_inode_dquot_ref(inode, type, tofree_head);
-+ spin_unlock(&inode->i_lock);
- }
- spin_unlock(&inode_lock);
- }
-@@ -940,9 +929,7 @@ static void drop_dquot_ref(struct super_
- LIST_HEAD(tofree_head);
-
- if (sb->dq_op) {
-- down_write(&sb_dqopt(sb)->dqptr_sem);
- remove_dquot_ref(sb, type, &tofree_head);
-- up_write(&sb_dqopt(sb)->dqptr_sem);
- put_dquot_list(&tofree_head);
- }
- }
-@@ -1239,8 +1226,6 @@ static int info_bdq_free(struct dquot *d
-
- /*
- * Initialize quota pointers in inode
-- * We do things in a bit complicated way but by that we avoid calling
-- * dqget() and thus filesystem callbacks under dqptr_sem.
- */
- int dquot_initialize(struct inode *inode, int type)
- {
-@@ -1270,8 +1255,7 @@ int dquot_initialize(struct inode *inode
- got[cnt] = dqget(sb, id, cnt);
- }
-
-- down_write(&sb_dqopt(sb)->dqptr_sem);
-- /* Having dqptr_sem we know NOQUOTA flags can't be altered... */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode))
- goto out_err;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-@@ -1288,12 +1272,16 @@ int dquot_initialize(struct inode *inode
- * did a write before quota was turned on
- */
- rsv = inode_get_rsv_space(inode);
-- if (unlikely(rsv))
-+ if (unlikely(rsv)) {
-+ spin_lock(&dq_data_lock);
- dquot_resv_space(inode->i_dquot[cnt], rsv);
-+ spin_unlock(&dq_data_lock);
-+ }
- }
- }
- out_err:
-- up_write(&sb_dqopt(sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-+
- /* Drop unused references */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- dqput(got[cnt]);
-@@ -1309,12 +1297,12 @@ int dquot_drop(struct inode *inode)
- int cnt;
- struct dquot *put[MAXQUOTAS];
-
-- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- put[cnt] = inode->i_dquot[cnt];
- inode->i_dquot[cnt] = NULL;
- }
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- dqput(put[cnt]);
-@@ -1357,27 +1345,42 @@ static qsize_t *inode_reserved_space(str
- return inode->i_sb->dq_op->get_reserved_space(inode);
- }
-
-+static inline void __inode_add_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ *inode_reserved_space(inode) += number;
-+}
-+
- void inode_add_rsv_space(struct inode *inode, qsize_t number)
- {
- spin_lock(&inode->i_lock);
-- *inode_reserved_space(inode) += number;
-+ __inode_add_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_add_rsv_space);
-
--void inode_claim_rsv_space(struct inode *inode, qsize_t number)
-+static inline void __inode_claim_rsv_space(struct inode *inode, qsize_t number)
- {
-- spin_lock(&inode->i_lock);
- *inode_reserved_space(inode) -= number;
- __inode_add_bytes(inode, number);
-+}
-+
-+void inode_claim_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ spin_lock(&inode->i_lock);
-+ __inode_claim_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_claim_rsv_space);
-
-+static inline void __inode_sub_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ *inode_reserved_space(inode) -= number;
-+}
-+
- void inode_sub_rsv_space(struct inode *inode, qsize_t number)
- {
- spin_lock(&inode->i_lock);
-- *inode_reserved_space(inode) -= number;
-+ __inode_sub_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_sub_rsv_space);
-@@ -1388,9 +1391,8 @@ static qsize_t inode_get_rsv_space(struc
-
- if (!inode->i_sb->dq_op->get_reserved_space)
- return 0;
-- spin_lock(&inode->i_lock);
-+
- ret = *inode_reserved_space(inode);
-- spin_unlock(&inode->i_lock);
- return ret;
- }
-
-@@ -1398,17 +1400,17 @@ static void inode_incr_space(struct inod
- int reserve)
- {
- if (reserve)
-- inode_add_rsv_space(inode, number);
-+ __inode_add_rsv_space(inode, number);
- else
-- inode_add_bytes(inode, number);
-+ __inode_add_bytes(inode, number);
- }
-
- static void inode_decr_space(struct inode *inode, qsize_t number, int reserve)
- {
- if (reserve)
-- inode_sub_rsv_space(inode, number);
-+ __inode_sub_rsv_space(inode, number);
- else
-- inode_sub_bytes(inode, number);
-+ __inode_sub_bytes(inode, number);
- }
-
- /*
-@@ -1430,6 +1432,7 @@ int __dquot_alloc_space(struct inode *in
- struct dquot_warn warn[MAXQUOTAS];
- struct dquot **dquots = inode->i_dquot;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
- int reserve = flags & DQUOT_SPACE_RESERVE;
-
- /*
- * First test before acquiring mutex - solves deadlocks when we
-@@ -1440,48 +1443,53 @@ int __dquot_alloc_space(struct inode *in
- goto out;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
- inode_incr_space(inode, number, reserve);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- goto out;
- }
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- warn[cnt].w_type = QUOTA_NL_NOWARN;
-
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!dquots[cnt])
-+ dquot[cnt] = dquots[cnt];
-+ if (!dquot[cnt])
- continue;
-- if (check_bdq(dquots[cnt], number,
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ if (check_bdq(dquot[cnt], number,
- (flags & DQUOT_SPACE_WARN), &warn[cnt])
- == NO_QUOTA && !(flags & DQUOT_SPACE_NOFAIL)) {
- ret = NO_QUOTA;
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
- goto out_flush_warn;
- }
- }
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!dquots[cnt])
-+ if (!dquot[cnt])
- continue;
- if (reserve)
-- dquot_resv_space(dquots[cnt], number);
-+ dquot_resv_space(dquot[cnt], number);
- else
-- dquot_incr_space(dquots[cnt], number);
-+ dquot_incr_space(dquot[cnt], number);
- }
- inode_incr_space(inode, number, reserve);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-
- if (reserve)
- goto out_flush_warn;
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (dquots[cnt])
-- mark_dquot_dirty(dquots[cnt]);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
- out_flush_warn:
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- flush_warnings(warn);
-+ flush_warnings(warn);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- out:
- return ret;
- }
-@@ -1508,7 +1517,8 @@ int dquot_alloc_inode(const struct inode
- {
- int cnt, ret = NO_QUOTA;
- struct dquot_warn warn[MAXQUOTAS];
- struct dquot * const *dquots = inode->i_dquot;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
-@@ -1515,35 +1525,41 @@ int dquot_alloc_inode(const struct inode
- return QUOTA_OK;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- warn[cnt].w_type = QUOTA_NL_NOWARN;
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+
-+ spin_lock(&((struct inode *)inode)->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
- return QUOTA_OK;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!dquots[cnt])
-+ dquot[cnt] = dquots[cnt];
-+ if (!dquot[cnt])
- continue;
-- if (check_idq(dquots[cnt], number, &warn[cnt])
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ if (check_idq(dquot[cnt], number, &warn[cnt])
- == NO_QUOTA)
- goto warn_put_all;
- }
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!dquots[cnt])
-+ if (!dquot[cnt])
- continue;
-- dquot_incr_inodes(dquots[cnt], number);
-+ dquot_incr_inodes(dquot[cnt], number);
- }
- ret = QUOTA_OK;
- warn_put_all:
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
-+
- if (ret == QUOTA_OK)
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (dquots[cnt])
-- mark_dquot_dirty(dquots[cnt]);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- flush_warnings(warn);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ flush_warnings(warn);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return ret;
- }
- EXPORT_SYMBOL(dquot_alloc_inode);
-@@ -1552,34 +1568,40 @@ int dquot_claim_space(struct inode *inod
- {
- int cnt;
- int ret = QUOTA_OK;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- if (IS_NOQUOTA(inode)) {
- inode_claim_rsv_space(inode, number);
- goto out;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- inode_claim_rsv_space(inode, number);
-+ __inode_claim_rsv_space(inode, number);
-+ spin_unlock(&inode->i_lock);
- goto out;
- }
-
- spin_lock(&dq_data_lock);
- /* Claim reserved quotas to allocated quotas */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (inode->i_dquot[cnt])
-- dquot_claim_reserved_space(inode->i_dquot[cnt],
-- number);
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (dquot[cnt]) {
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ dquot_claim_reserved_space(dquot[cnt], number);
-+ }
- }
- /* Update inode bytes */
-- inode_claim_rsv_space(inode, number);
-+ __inode_claim_rsv_space(inode, number);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-+
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- out:
- return ret;
- }
-@@ -1593,7 +1615,8 @@ int __dquot_free_space(struct inode *ino
- unsigned int cnt;
- struct dquot_warn warn[MAXQUOTAS];
- struct dquot **dquots = inode->i_dquot;
- int reserve = flags & DQUOT_SPACE_RESERVE;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
-@@ -1602,39 +1625,42 @@ out_sub:
- return QUOTA_OK;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- goto out_sub;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- int wtype;
-
- warn[cnt].w_type = QUOTA_NL_NOWARN;
-- if (!dquots[cnt])
-+ dquot[cnt] = dquots[cnt];
-+ if (!dquot[cnt])
- continue;
-- wtype = info_bdq_free(dquots[cnt], number);
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ wtype = info_bdq_free(dquot[cnt], number);
- if (wtype != QUOTA_NL_NOWARN)
-- prepare_warning(&warn[cnt], dquots[cnt], wtype);
-+ prepare_warning(&warn[cnt], dquot[cnt], wtype);
- if (reserve)
-- dquot_free_reserved_space(dquots[cnt], number);
-+ dquot_free_reserved_space(dquot[cnt], number);
- else
-- dquot_decr_space(dquots[cnt], number);
-+ dquot_decr_space(dquot[cnt], number);
- }
- inode_decr_space(inode, number, reserve);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-
- if (reserve)
-- goto out_unlock;
-+ goto out;
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (dquots[cnt])
-- mark_dquot_dirty(dquots[cnt]);
--out_unlock:
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- flush_warnings(warn);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+out:
-+ flush_warnings(warn);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return QUOTA_OK;
- }
-
-@@ -1656,39 +1682,44 @@ int dquot_free_inode(const struct inode
- {
- unsigned int cnt;
- struct dquot_warn warn[MAXQUOTAS];
- struct dquot * const *dquots = inode->i_dquot;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
- if (IS_NOQUOTA(inode))
- return QUOTA_OK;
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&((struct inode *)inode)->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
- return QUOTA_OK;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- int wtype;
-
- warn[cnt].w_type = QUOTA_NL_NOWARN;
-- if (!dquots[cnt])
-+ dquot[cnt] = dquots[cnt];
-+ if (!dquot[cnt])
- continue;
-- wtype = info_idq_free(dquots[cnt], number);
-- if (wtype != QUOTA_NL_NOWARN)
-- prepare_warning(&warn[cnt], dquots[cnt], wtype);
-- dquot_decr_inodes(dquots[cnt], number);
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ wtype = info_idq_free(dquot[cnt], number);
-+ if (wtype != QUOTA_NL_NOWARN)
-+ prepare_warning(&warn[cnt], dquot[cnt], wtype);
-+ dquot_decr_inodes(dquot[cnt], number);
-
- }
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
-+
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (dquots[cnt])
-- mark_dquot_dirty(dquots[cnt]);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- flush_warnings(warn);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ flush_warnings(warn);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return QUOTA_OK;
- }
- EXPORT_SYMBOL(dquot_free_inode);
-@@ -1721,14 +1752,13 @@ int dquot_transfer(struct inode *inode,
- transfer_to[GRPQUOTA] = dqget(inode->i_sb, iattr->ia_gid,
- GRPQUOTA);
-
-- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) { /* File without quota accounting? */
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- goto put_all;
- }
- spin_lock(&dq_data_lock);
-- cur_space = inode_get_bytes(inode);
-+ cur_space = __inode_get_bytes(inode);
- rsv_space = inode_get_rsv_space(inode);
- space = cur_space + rsv_space;
- /* Build the transfer_from list and check the limits */
-@@ -1771,7 +1801,7 @@ int dquot_transfer(struct inode *inode,
- inode->i_dquot[cnt] = transfer_to[cnt];
- }
- spin_unlock(&dq_data_lock);
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-@@ -1795,7 +1825,7 @@ put_all:
- return ret;
- over_quota:
- spin_unlock(&dq_data_lock);
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- /* Clear dquot pointers we don't want to dqput() */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- transfer_from[cnt] = NULL;
-@@ -2047,13 +2077,13 @@ static int vfs_load_quota_inode(struct i
- /* We don't want quota and atime on quota files (deadlocks
- * possible) Also nobody should write to the file - we use
- * special IO operations which ignore the immutable bit. */
-- down_write(&dqopt->dqptr_sem);
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-+ spin_lock(&inode->i_lock);
- oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE |
- S_NOQUOTA);
- inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
-+ spin_unlock(&inode->i_lock);
- mutex_unlock(&inode->i_mutex);
-- up_write(&dqopt->dqptr_sem);
- sb->dq_op->drop(inode);
- }
-
-@@ -2090,14 +2120,14 @@ out_file_init:
- iput(inode);
- out_lock:
- if (oldflags != -1) {
-- down_write(&dqopt->dqptr_sem);
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-+ spin_lock(&inode->i_lock);
- /* Set the flags back (in the case of accidental quotaon()
- * on a wrong file we don't want to mess up the flags) */
- inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
- inode->i_flags |= oldflags;
-+ spin_unlock(&inode->i_lock);
- mutex_unlock(&inode->i_mutex);
-- up_write(&dqopt->dqptr_sem);
- }
- mutex_unlock(&dqopt->dqonoff_mutex);
- out_fmt:
-Index: linux-2.6.32-358.0.1.el6/fs/quota/quota.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/quota/quota.c
-+++ linux-2.6.32-358.0.1.el6/fs/quota/quota.c
-@@ -257,13 +257,13 @@ static int do_quotactl(struct super_bloc
- case Q_GETFMT: {
- __u32 fmt;
-
-- down_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
- if (!sb_has_quota_active(sb, type)) {
-- up_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
- return -ESRCH;
- }
- fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
-- up_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
- if (copy_to_user(addr, &fmt, sizeof(fmt)))
- return -EFAULT;
- return 0;
-Index: linux-2.6.32-358.0.1.el6/fs/stat.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/stat.c
-+++ linux-2.6.32-358.0.1.el6/fs/stat.c
-@@ -422,9 +422,8 @@ void inode_add_bytes(struct inode *inode
-
- EXPORT_SYMBOL(inode_add_bytes);
-
--void inode_sub_bytes(struct inode *inode, loff_t bytes)
-+void __inode_sub_bytes(struct inode *inode, loff_t bytes)
- {
-- spin_lock(&inode->i_lock);
- inode->i_blocks -= bytes >> 9;
- bytes &= 511;
- if (inode->i_bytes < bytes) {
-@@ -432,17 +431,28 @@ void inode_sub_bytes(struct inode *inode
- inode->i_bytes += 512;
- }
- inode->i_bytes -= bytes;
-+}
-+
-+void inode_sub_bytes(struct inode *inode, loff_t bytes)
-+{
-+ spin_lock(&inode->i_lock);
-+ __inode_sub_bytes(inode, bytes);
- spin_unlock(&inode->i_lock);
- }
-
- EXPORT_SYMBOL(inode_sub_bytes);
-
-+loff_t __inode_get_bytes(struct inode *inode)
-+{
-+ return (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
-+}
-+
- loff_t inode_get_bytes(struct inode *inode)
- {
- loff_t ret;
-
- spin_lock(&inode->i_lock);
-- ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
-+ ret = __inode_get_bytes(inode);
- spin_unlock(&inode->i_lock);
- return ret;
- }
-Index: linux-2.6.32-358.0.1.el6/fs/super.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/super.c
-+++ linux-2.6.32-358.0.1.el6/fs/super.c
-@@ -146,7 +146,6 @@ static struct super_block *alloc_super(s
- mutex_init(&s->s_vfs_rename_mutex);
- mutex_init(&s->s_dquot.dqio_mutex);
- mutex_init(&s->s_dquot.dqonoff_mutex);
-- init_rwsem(&s->s_dquot.dqptr_sem);
- init_waitqueue_head(&s->s_wait_unfrozen);
- s->s_maxbytes = MAX_NON_LFS;
- s->dq_op = sb_dquot_ops;
-Index: linux-2.6.32-358.0.1.el6/include/linux/fs.h
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/include/linux/fs.h
-+++ linux-2.6.32-358.0.1.el6/include/linux/fs.h
-@@ -2567,7 +2567,9 @@ extern void generic_fillattr(struct inod
- extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
- void __inode_add_bytes(struct inode *inode, loff_t bytes);
- void inode_add_bytes(struct inode *inode, loff_t bytes);
-+void __inode_sub_bytes(struct inode *inode, loff_t bytes);
- void inode_sub_bytes(struct inode *inode, loff_t bytes);
-+loff_t __inode_get_bytes(struct inode *inode);
- loff_t inode_get_bytes(struct inode *inode);
- void inode_set_bytes(struct inode *inode, loff_t bytes);
-
+++ /dev/null
-diff -urp linux-2.6.32-53.7.orig/fs/quota/dquot.c linux-2.6.32.46-0/fs/quota/dquot.c
---- linux-2.6.32-53.7.orig/fs/quota/dquot.c 2013-04-26 11:56:35.000000000 -0400
-+++ linux-2.6.32-53.7/fs/quota/dquot.c 2013-04-26 12:00:44.000000000 -0400
-@@ -89,22 +89,17 @@
- /*
- * There are three quota SMP locks. dq_list_lock protects all lists with quotas
- * and quota formats, dqstats structure containing statistics about the lists
-- * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures and
-- * also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes.
-- * i_blocks and i_bytes updates itself are guarded by i_lock acquired directly
-- * in inode_add_bytes() and inode_sub_bytes(). dq_state_lock protects
-- * modifications of quota state (on quotaon and quotaoff) and readers who care
-- * about latest values take it as well.
-+ * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures.
-+ * dq_state_lock protects modifications of quota state (on quotaon and quotaoff)
-+ * and readers who care about latest values take it as well.
- *
-- * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock,
-+ * The spinlock ordering is hence: i_lock > dq_data_lock > dq_list_lock,
- * dq_list_lock > dq_state_lock
- *
- * Note that some things (eg. sb pointer, type, id) doesn't change during
- * the life of the dquot structure and so needn't to be protected by a lock
- *
-- * Any operation working on dquots via inode pointers must hold dqptr_sem. If
-- * operation is just reading pointers from inode (or not using them at all) the
-- * read lock is enough. If pointers are altered function must hold write lock
-+ * Any operation working on dquots via inode pointers must hold i_lock.
- * (these locking rules also apply for S_NOQUOTA flag in the inode - note that
- * for altering the flag i_mutex is also needed).
- *
-@@ -118,15 +113,8 @@
- * spinlock to internal buffers before writing.
- *
- * Lock ordering (including related VFS locks) is the following:
-- * i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock >
-- * dqio_mutex
-- * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem >
-- * dqptr_sem. But filesystem has to count with the fact that functions such as
-- * dquot_alloc_space() acquire dqptr_sem and they usually have to be called
-- * from inside a transaction to keep filesystem consistency after a crash. Also
-- * filesystems usually want to do some IO on dquot from ->mark_dirty which is
-- * called with dqptr_sem held.
-- * i_mutex on quota files is special (it's below dqio_mutex)
-+ * i_mutex > dqonoff_sem > journal_lock > dquot->dq_lock > dqio_mutex
-+ * i_mutex on quota files is special (it's below dqio_mutex)
- */
-
- static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
-@@ -867,7 +855,6 @@ static inline int dqput_blocks(struct dq
- /*
- * Remove references to dquots from inode and add dquot to list for freeing
- * if we have the last referece to dquot
-- * We can't race with anybody because we hold dqptr_sem for writing...
- */
- static int remove_inode_dquot_ref(struct inode *inode, int type,
- struct list_head *tofree_head)
-@@ -925,10 +912,12 @@ static void remove_dquot_ref(struct supe
- * We have to scan also I_NEW inodes because they can already
- * have quota pointer initialized. Luckily, we need to touch
- * only quota pointers and these have separate locking
-- * (dqptr_sem).
-+ * (i_lock).
- */
-+ spin_lock(&inode->i_lock);
- if (!IS_NOQUOTA(inode))
- remove_inode_dquot_ref(inode, type, tofree_head);
-+ spin_unlock(&inode->i_lock);
- }
- spin_unlock(&inode_lock);
- }
-@@ -939,9 +928,7 @@ static void drop_dquot_ref(struct super_
- LIST_HEAD(tofree_head);
-
- if (sb->dq_op) {
-- down_write(&sb_dqopt(sb)->dqptr_sem);
- remove_dquot_ref(sb, type, &tofree_head);
-- up_write(&sb_dqopt(sb)->dqptr_sem);
- put_dquot_list(&tofree_head);
- }
- }
-@@ -1303,8 +1290,6 @@ static int info_bdq_free(struct dquot *d
-
- /*
- * Initialize quota pointers in inode
-- * We do things in a bit complicated way but by that we avoid calling
-- * dqget() and thus filesystem callbacks under dqptr_sem.
- */
- int dquot_initialize(struct inode *inode, int type)
- {
-@@ -1334,8 +1319,7 @@ int dquot_initialize(struct inode *inode
- got[cnt] = dqget(sb, id, cnt);
- }
-
-- down_write(&sb_dqopt(sb)->dqptr_sem);
-- /* Having dqptr_sem we know NOQUOTA flags can't be altered... */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode))
- goto out_err;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-@@ -1352,12 +1336,16 @@ int dquot_initialize(struct inode *inode
- * did a write before quota was turned on
- */
- rsv = inode_get_rsv_space(inode);
-- if (unlikely(rsv))
-+ if (unlikely(rsv)) {
-+ spin_lock(&dq_data_lock);
- dquot_resv_space(inode->i_dquot[cnt], rsv);
-+ spin_unlock(&dq_data_lock);
-+ }
- }
- }
- out_err:
-- up_write(&sb_dqopt(sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-+
- /* Drop unused references */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- dqput(got[cnt]);
-@@ -1373,12 +1361,12 @@ int dquot_drop(struct inode *inode)
- int cnt;
- struct dquot *put[MAXQUOTAS];
-
-- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- put[cnt] = inode->i_dquot[cnt];
- inode->i_dquot[cnt] = NULL;
- }
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- dqput(put[cnt]);
-@@ -1421,27 +1409,42 @@ static qsize_t *inode_reserved_space(str
- return inode->i_sb->dq_op->get_reserved_space(inode);
- }
-
-+static inline void __inode_add_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ *inode_reserved_space(inode) += number;
-+}
-+
- void inode_add_rsv_space(struct inode *inode, qsize_t number)
- {
- spin_lock(&inode->i_lock);
-- *inode_reserved_space(inode) += number;
-+ __inode_add_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_add_rsv_space);
-
--void inode_claim_rsv_space(struct inode *inode, qsize_t number)
-+static inline void __inode_claim_rsv_space(struct inode *inode, qsize_t number)
- {
-- spin_lock(&inode->i_lock);
- *inode_reserved_space(inode) -= number;
- __inode_add_bytes(inode, number);
-+}
-+
-+void inode_claim_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ spin_lock(&inode->i_lock);
-+ __inode_claim_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_claim_rsv_space);
-
-+static inline void __inode_sub_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ *inode_reserved_space(inode) -= number;
-+}
-+
- void inode_sub_rsv_space(struct inode *inode, qsize_t number)
- {
- spin_lock(&inode->i_lock);
-- *inode_reserved_space(inode) -= number;
-+ __inode_sub_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_sub_rsv_space);
-@@ -1452,9 +1455,8 @@ static qsize_t inode_get_rsv_space(struc
-
- if (!inode->i_sb->dq_op->get_reserved_space)
- return 0;
-- spin_lock(&inode->i_lock);
-+
- ret = *inode_reserved_space(inode);
-- spin_unlock(&inode->i_lock);
- return ret;
- }
-
-@@ -1462,17 +1464,17 @@ static void inode_incr_space(struct inod
- int reserve)
- {
- if (reserve)
-- inode_add_rsv_space(inode, number);
-+ __inode_add_rsv_space(inode, number);
- else
-- inode_add_bytes(inode, number);
-+ __inode_add_bytes(inode, number);
- }
-
- static void inode_decr_space(struct inode *inode, qsize_t number, int reserve)
- {
- if (reserve)
-- inode_sub_rsv_space(inode, number);
-+ __inode_sub_rsv_space(inode, number);
- else
-- inode_sub_bytes(inode, number);
-+ __inode_sub_bytes(inode, number);
- }
-
- /*
-@@ -1492,6 +1494,7 @@ int __dquot_alloc_space(struct inode *in
- {
- int cnt, ret = QUOTA_OK;
- char warntype[MAXQUOTAS];
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /*
- * First test before acquiring mutex - solves deadlocks when we
-@@ -1502,10 +1505,11 @@ int __dquot_alloc_space(struct inode *in
- goto out;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
- inode_incr_space(inode, number, reserve);
-- goto out_unlock;
-+ spin_unlock(&inode->i_lock);
-+ goto out;
- }
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-@@ -1523,36 +1529,40 @@ int __dquot_alloc_space(struct inode *int inode *in
-
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
-- == NO_QUOTA) {
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ if (check_bdq(dquot[cnt], number, warn, warntype + cnt) ==
-+ NO_QUOTA) {
- ret = NO_QUOTA;
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
- goto out_flush_warn;
- }
- }
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ if (!dquot[cnt])
- continue;
- if (reserve)
-- dquot_resv_space(inode->i_dquot[cnt], number);
-+ dquot_resv_space(dquot[cnt], number);
- else
-- dquot_incr_space(inode->i_dquot[cnt], number);
-+ dquot_incr_space(dquot[cnt], number);
- }
- inode_incr_space(inode, number, reserve);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-
- if (reserve)
- goto out_flush_warn;
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
- out_flush_warn:
-- flush_warnings(inode->i_dquot, warntype);
--out_unlock:
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- out:
- return ret;
- }
-@@ -1566,6 +1573,7 @@ int dquot_alloc_inode(const struct inode
- {
- int cnt, ret = NO_QUOTA;
- char warntype[MAXQUOTAS];
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
-@@ -1573,35 +1581,41 @@ int dquot_alloc_inode(const struct inode
- return QUOTA_OK;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- warntype[cnt] = QUOTA_NL_NOWARN;
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+
-+ spin_lock(&((struct inode *)inode)->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
- return QUOTA_OK;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- if (check_idq(inode->i_dquot[cnt], number, warntype+cnt)
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ if (check_idq(dquot[cnt], number, warntype+cnt)
- == NO_QUOTA)
- goto warn_put_all;
- }
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ if (!dquot[cnt])
- continue;
-- dquot_incr_inodes(inode->i_dquot[cnt], number);
-+ dquot_incr_inodes(dquot[cnt], number);
- }
- ret = QUOTA_OK;
- warn_put_all:
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
-+
- if (ret == QUOTA_OK)
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-- flush_warnings(inode->i_dquot, warntype);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return ret;
- }
- EXPORT_SYMBOL(dquot_alloc_inode);
-@@ -1610,34 +1624,40 @@ int dquot_claim_space(struct inode *inod
- {
- int cnt;
- int ret = QUOTA_OK;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- if (IS_NOQUOTA(inode)) {
- inode_claim_rsv_space(inode, number);
- goto out;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- inode_claim_rsv_space(inode, number);
-+ __inode_claim_rsv_space(inode, number);
-+ spin_unlock(&inode->i_lock);
- goto out;
- }
-
- spin_lock(&dq_data_lock);
- /* Claim reserved quotas to allocated quotas */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (inode->i_dquot[cnt])
-- dquot_claim_reserved_space(inode->i_dquot[cnt],
-- number);
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (dquot[cnt]) {
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ dquot_claim_reserved_space(dquot[cnt], number);
-+ }
- }
- /* Update inode bytes */
-- inode_claim_rsv_space(inode, number);
-+ __inode_claim_rsv_space(inode, number);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-+
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- out:
- return ret;
- }
-@@ -1650,6 +1670,7 @@ int __dquot_free_space(struct inode *ino
- {
- unsigned int cnt;
- char warntype[MAXQUOTAS];
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
-@@ -1659,34 +1680,37 @@ out_sub:
- return QUOTA_OK;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- goto out_sub;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number);
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ warntype[cnt] = info_bdq_free(dquot[cnt], number);
- if (reserve)
-- dquot_free_reserved_space(inode->i_dquot[cnt], number);
-+ dquot_free_reserved_space(dquot[cnt], number);
- else
-- dquot_decr_space(inode->i_dquot[cnt], number);
-+ dquot_decr_space(dquot[cnt], number);
- }
- inode_decr_space(inode, number, reserve);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-
- if (reserve)
-- goto out_unlock;
-+ goto out;
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
--out_unlock:
-- flush_warnings(inode->i_dquot, warntype);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+out:
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return QUOTA_OK;
- }
-
-@@ -1713,32 +1737,37 @@ int dquot_free_inode(const struct inode
- {
- unsigned int cnt;
- char warntype[MAXQUOTAS];
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
- if (IS_NOQUOTA(inode))
- return QUOTA_OK;
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&((struct inode *)inode)->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
- return QUOTA_OK;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- warntype[cnt] = info_idq_free(inode->i_dquot[cnt], number);
-- dquot_decr_inodes(inode->i_dquot[cnt], number);
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ warntype[cnt] = info_idq_free(dquot[cnt], number);
-+ dquot_decr_inodes(dquot[cnt], number);
- }
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
-+
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-- flush_warnings(inode->i_dquot, warntype);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return QUOTA_OK;
- }
- EXPORT_SYMBOL(dquot_free_inode);
-@@ -1778,14 +1807,13 @@ int dquot_transfer(struct inode *inode,
- transfer_to[GRPQUOTA] = dqget(inode->i_sb, iattr->ia_gid,
- GRPQUOTA);
-
-- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) { /* File without quota accounting? */
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- goto put_all;
- }
- spin_lock(&dq_data_lock);
-- cur_space = inode_get_bytes(inode);
-+ cur_space = __inode_get_bytes(inode);
- rsv_space = inode_get_rsv_space(inode);
- space = cur_space + rsv_space;
- /* Build the transfer_from list and check the limits */
-@@ -1828,7 +1856,7 @@ int dquot_transfer(struct inode *inode,
- inode->i_dquot[cnt] = transfer_to[cnt];
- }
- spin_unlock(&dq_data_lock);
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-@@ -1852,7 +1880,7 @@ put_all:
- return ret;
- over_quota:
- spin_unlock(&dq_data_lock);
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- /* Clear dquot pointers we don't want to dqput() */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- transfer_from[cnt] = NULL;
-@@ -2104,13 +2132,13 @@ static int vfs_load_quota_inode(struct i
- /* We don't want quota and atime on quota files (deadlocks
- * possible) Also nobody should write to the file - we use
- * special IO operations which ignore the immutable bit. */
-- down_write(&dqopt->dqptr_sem);
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-+ spin_lock(&inode->i_lock);
- oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE |
- S_NOQUOTA);
- inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
-+ spin_unlock(&inode->i_lock);
- mutex_unlock(&inode->i_mutex);
-- up_write(&dqopt->dqptr_sem);
- sb->dq_op->drop(inode);
- }
-
-@@ -2147,14 +2175,14 @@ out_file_init:
- iput(inode);
- out_lock:
- if (oldflags != -1) {
-- down_write(&dqopt->dqptr_sem);
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-+ spin_lock(&inode->i_lock);
- /* Set the flags back (in the case of accidental quotaon()
- * on a wrong file we don't want to mess up the flags) */
- inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
- inode->i_flags |= oldflags;
-+ spin_unlock(&inode->i_lock);
- mutex_unlock(&inode->i_mutex);
-- up_write(&dqopt->dqptr_sem);
- }
- mutex_unlock(&dqopt->dqonoff_mutex);
- out_fmt:
-diff -urp linux-2.6.32-53.7.orig/fs/quota/quota.c linux-2.6.32.46-0/fs/quota/quota.c
---- linux-2.6.32-53.7.orig/fs/quota/quota.c 2009-12-02 22:51:21.000000000 -0500
-+++ linux-2.6.32-53.7/fs/quota/quota.c 2013-04-26 11:59:22.000000000 -0400
-@@ -255,13 +255,13 @@ static int do_quotactl(struct super_bloc
- case Q_GETFMT: {
- __u32 fmt;
-
-- down_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
- if (!sb_has_quota_active(sb, type)) {
-- up_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
- return -ESRCH;
- }
- fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
-- up_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
- if (copy_to_user(addr, &fmt, sizeof(fmt)))
- return -EFAULT;
- return 0;
-diff -urp linux-2.6.32-53.7.orig/fs/stat.c linux-2.6.32.46-0/fs/stat.c
---- linux-2.6.32-53.7.orig/fs/stat.c 2013-04-26 11:56:28.000000000 -0400
-+++ linux-2.6.32-53.7/fs/stat.c 2013-04-26 11:59:22.000000000 -0400
-@@ -422,9 +422,8 @@ void inode_add_bytes(struct inode *inode
-
- EXPORT_SYMBOL(inode_add_bytes);
-
--void inode_sub_bytes(struct inode *inode, loff_t bytes)
-+void __inode_sub_bytes(struct inode *inode, loff_t bytes)
- {
-- spin_lock(&inode->i_lock);
- inode->i_blocks -= bytes >> 9;
- bytes &= 511;
- if (inode->i_bytes < bytes) {
-@@ -432,17 +431,28 @@ void inode_sub_bytes(struct inode *inode
- inode->i_bytes += 512;
- }
- inode->i_bytes -= bytes;
-+}
-+
-+void inode_sub_bytes(struct inode *inode, loff_t bytes)
-+{
-+ spin_lock(&inode->i_lock);
-+ __inode_sub_bytes(inode, bytes);
- spin_unlock(&inode->i_lock);
- }
-
- EXPORT_SYMBOL(inode_sub_bytes);
-
-+loff_t __inode_get_bytes(struct inode *inode)
-+{
-+ return (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
-+}
-+
- loff_t inode_get_bytes(struct inode *inode)
- {
- loff_t ret;
-
- spin_lock(&inode->i_lock);
-- ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
-+ ret = __inode_get_bytes(inode);
- spin_unlock(&inode->i_lock);
- return ret;
- }
-diff -urp linux-2.6.32-53.7.orig/fs/super.c linux-2.6.32.46-0/fs/super.c
---- linux-2.6.32-53.7.orig/fs/super.c 2013-04-26 11:56:52.000000000 -0400
-+++ linux-2.6.32-53.7/fs/super.c 2013-04-26 11:59:22.000000000 -0400
-@@ -98,7 +98,6 @@ static struct super_block *alloc_super(s
- mutex_init(&s->s_vfs_rename_mutex);
- mutex_init(&s->s_dquot.dqio_mutex);
- mutex_init(&s->s_dquot.dqonoff_mutex);
-- init_rwsem(&s->s_dquot.dqptr_sem);
- init_waitqueue_head(&s->s_wait_unfrozen);
- s->s_maxbytes = MAX_NON_LFS;
- s->dq_op = sb_dquot_ops;
-diff -urp linux-2.6.32-53.7.orig/include/linux/fs.h linux-2.6.32.46-0/include/linux/fs.h
---- linux-2.6.32-53.7.orig/include/linux/fs.h 2013-04-26 11:56:52.000000000 -0400
-+++ linux-2.6.32-53.7/include/linux/fs.h 2013-04-26 11:59:22.000000000 -0400
-@@ -2356,7 +2356,9 @@ extern void generic_fillattr(struct inod
- extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
- void __inode_add_bytes(struct inode *inode, loff_t bytes);
- void inode_add_bytes(struct inode *inode, loff_t bytes);
-+void __inode_sub_bytes(struct inode *inode, loff_t bytes);
- void inode_sub_bytes(struct inode *inode, loff_t bytes);
-+loff_t __inode_get_bytes(struct inode *inode);
- loff_t inode_get_bytes(struct inode *inode);
- void inode_set_bytes(struct inode *inode, loff_t bytes);
-
+++ /dev/null
-Remove dqptr_sem (but kept in struct quota_info to keep kernel ABI
-unchanged), and the functionality of this lock is implemented by
-other locks:
-* i_dquot is protected by i_lock, however only this pointer, the
- content of this struct is by dq_data_lock.
-* Q_GETFMT is now protected with dqonoff_mutex instead of dqptr_sem.
-
- fs/quota/dquot.c | 243 +++++++++++++++++++++++++++++------------------------
- fs/quota/quota.c | 6 -
- fs/stat.c | 16 ++-
- fs/super.c | 1
- include/linux/fs.h | 2
- 5 files changed, 154 insertions(+), 114 deletions(-)
-
-Index: linux-2.6.32-358.0.1.el6/fs/quota/dquot.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/quota/dquot.c
-+++ linux-2.6.32-358.0.1.el6/fs/quota/dquot.c
-@@ -83,22 +83,17 @@
- /*
- * There are three quota SMP locks. dq_list_lock protects all lists with quotas
- * and quota formats, dqstats structure containing statistics about the lists
-- * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures and
-- * also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes.
-- * i_blocks and i_bytes updates itself are guarded by i_lock acquired directly
-- * in inode_add_bytes() and inode_sub_bytes(). dq_state_lock protects
-- * modifications of quota state (on quotaon and quotaoff) and readers who care
-- * about latest values take it as well.
-+ * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures.
-+ * dq_state_lock protects modifications of quota state (on quotaon and quotaoff)
-+ * and readers who care about latest values take it as well.
- *
-- * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock,
-+ * The spinlock ordering is hence: i_lock > dq_data_lock > dq_list_lock,
- * dq_list_lock > dq_state_lock
- *
- * Note that some things (eg. sb pointer, type, id) doesn't change during
- * the life of the dquot structure and so needn't to be protected by a lock
- *
-- * Any operation working on dquots via inode pointers must hold dqptr_sem. If
-- * operation is just reading pointers from inode (or not using them at all) the
-- * read lock is enough. If pointers are altered function must hold write lock
-+ * Any operation working on dquots via inode pointers must hold i_lock.
- * (these locking rules also apply for S_NOQUOTA flag in the inode - note that
- * for altering the flag i_mutex is also needed).
- *
-@@ -112,15 +107,8 @@
- * spinlock to internal buffers before writing.
- *
- * Lock ordering (including related VFS locks) is the following:
-- * i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock >
-- * dqio_mutex
-- * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem >
-- * dqptr_sem. But filesystem has to count with the fact that functions such as
-- * dquot_alloc_space() acquire dqptr_sem and they usually have to be called
-- * from inside a transaction to keep filesystem consistency after a crash. Also
-- * filesystems usually want to do some IO on dquot from ->mark_dirty which is
-- * called with dqptr_sem held.
-- * i_mutex on quota files is special (it's below dqio_mutex)
-+ * i_mutex > dqonoff_sem > journal_lock > dquot->dq_lock > dqio_mutex
-+ * i_mutex on quota files is special (it's below dqio_mutex)
- */
-
- static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
-@@ -868,7 +856,6 @@ static inline int dqput_blocks(struct dq
- /*
- * Remove references to dquots from inode and add dquot to list for freeing
- * if we have the last referece to dquot
-- * We can't race with anybody because we hold dqptr_sem for writing...
- */
- static int remove_inode_dquot_ref(struct inode *inode, int type,
- struct list_head *tofree_head)
-@@ -926,10 +913,12 @@ static void remove_dquot_ref(struct supe
- * We have to scan also I_NEW inodes because they can already
- * have quota pointer initialized. Luckily, we need to touch
- * only quota pointers and these have separate locking
-- * (dqptr_sem).
-+ * (i_lock).
- */
-+ spin_lock(&inode->i_lock);
- if (!IS_NOQUOTA(inode))
- remove_inode_dquot_ref(inode, type, tofree_head);
-+ spin_unlock(&inode->i_lock);
- }
- spin_unlock(&inode_lock);
- }
-@@ -940,9 +929,7 @@ static void drop_dquot_ref(struct super_
- LIST_HEAD(tofree_head);
-
- if (sb->dq_op) {
-- down_write(&sb_dqopt(sb)->dqptr_sem);
- remove_dquot_ref(sb, type, &tofree_head);
-- up_write(&sb_dqopt(sb)->dqptr_sem);
- put_dquot_list(&tofree_head);
- }
- }
-@@ -1239,8 +1226,6 @@ static int info_bdq_free(struct dquot *d
-
- /*
- * Initialize quota pointers in inode
-- * We do things in a bit complicated way but by that we avoid calling
-- * dqget() and thus filesystem callbacks under dqptr_sem.
- */
- int dquot_initialize(struct inode *inode, int type)
- {
-@@ -1270,8 +1255,7 @@ int dquot_initialize(struct inode *inode
- got[cnt] = dqget(sb, id, cnt);
- }
-
-- down_write(&sb_dqopt(sb)->dqptr_sem);
-- /* Having dqptr_sem we know NOQUOTA flags can't be altered... */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode))
- goto out_err;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-@@ -1288,12 +1272,16 @@ int dquot_initialize(struct inode *inode
- * did a write before quota was turned on
- */
- rsv = inode_get_rsv_space(inode);
-- if (unlikely(rsv))
-+ if (unlikely(rsv)) {
-+ spin_lock(&dq_data_lock);
- dquot_resv_space(inode->i_dquot[cnt], rsv);
-+ spin_unlock(&dq_data_lock);
-+ }
- }
- }
- out_err:
-- up_write(&sb_dqopt(sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-+
- /* Drop unused references */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- dqput(got[cnt]);
-@@ -1309,12 +1297,12 @@ int dquot_drop(struct inode *inode)
- int cnt;
- struct dquot *put[MAXQUOTAS];
-
-- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- put[cnt] = inode->i_dquot[cnt];
- inode->i_dquot[cnt] = NULL;
- }
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- dqput(put[cnt]);
-@@ -1357,27 +1345,42 @@ static qsize_t *inode_reserved_space(str
- return inode->i_sb->dq_op->get_reserved_space(inode);
- }
-
-+static inline void __inode_add_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ *inode_reserved_space(inode) += number;
-+}
-+
- void inode_add_rsv_space(struct inode *inode, qsize_t number)
- {
- spin_lock(&inode->i_lock);
-- *inode_reserved_space(inode) += number;
-+ __inode_add_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_add_rsv_space);
-
--void inode_claim_rsv_space(struct inode *inode, qsize_t number)
-+static inline void __inode_claim_rsv_space(struct inode *inode, qsize_t number)
- {
-- spin_lock(&inode->i_lock);
- *inode_reserved_space(inode) -= number;
- __inode_add_bytes(inode, number);
-+}
-+
-+void inode_claim_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ spin_lock(&inode->i_lock);
-+ __inode_claim_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_claim_rsv_space);
-
-+static inline void __inode_sub_rsv_space(struct inode *inode, qsize_t number)
-+{
-+ *inode_reserved_space(inode) -= number;
-+}
-+
- void inode_sub_rsv_space(struct inode *inode, qsize_t number)
- {
- spin_lock(&inode->i_lock);
-- *inode_reserved_space(inode) -= number;
-+ __inode_sub_rsv_space(inode, number);
- spin_unlock(&inode->i_lock);
- }
- EXPORT_SYMBOL(inode_sub_rsv_space);
-@@ -1388,9 +1391,8 @@ static qsize_t inode_get_rsv_space(struc
-
- if (!inode->i_sb->dq_op->get_reserved_space)
- return 0;
-- spin_lock(&inode->i_lock);
-+
- ret = *inode_reserved_space(inode);
-- spin_unlock(&inode->i_lock);
- return ret;
- }
-
-@@ -1398,17 +1400,17 @@ static void inode_incr_space(struct inod
- int reserve)
- {
- if (reserve)
-- inode_add_rsv_space(inode, number);
-+ __inode_add_rsv_space(inode, number);
- else
-- inode_add_bytes(inode, number);
-+ __inode_add_bytes(inode, number);
- }
-
- static void inode_decr_space(struct inode *inode, qsize_t number, int reserve)
- {
- if (reserve)
-- inode_sub_rsv_space(inode, number);
-+ __inode_sub_rsv_space(inode, number);
- else
-- inode_sub_bytes(inode, number);
-+ __inode_sub_bytes(inode, number);
- }
-
- /*
-@@ -1430,6 +1432,7 @@ int __dquot_alloc_space(struct inode *in
- int warn = flags & DQUOT_SPACE_WARN;
- int reserve = flags & DQUOT_SPACE_RESERVE;
- int nofail = flags & DQUOT_SPACE_NOFAIL;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /*
- * First test before acquiring mutex - solves deadlocks when we
-@@ -1440,47 +1443,53 @@ int __dquot_alloc_space(struct inode *in
- goto out;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
- inode_incr_space(inode, number, reserve);
-- goto out_unlock;
-+ spin_unlock(&inode->i_lock);
-+ goto out;
- }
-
-- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- warntype[cnt] = QUOTA_NL_NOWARN;
-+ }
-
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ if (check_bdq(dquot[cnt], number, warn, warntype+cnt)
- == NO_QUOTA && !nofail) {
- ret = NO_QUOTA;
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
- goto out_flush_warn;
- }
- }
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ if (!dquot[cnt])
- continue;
- if (reserve)
-- dquot_resv_space(inode->i_dquot[cnt], number);
-+ dquot_resv_space(dquot[cnt], number);
- else
-- dquot_incr_space(inode->i_dquot[cnt], number);
-+ dquot_incr_space(dquot[cnt], number);
- }
- inode_incr_space(inode, number, reserve);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-
- if (reserve)
- goto out_flush_warn;
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
- out_flush_warn:
-- flush_warnings(inode->i_dquot, warntype);
--out_unlock:
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- out:
- return ret;
- }
-@@ -1508,6 +1517,7 @@ int dquot_alloc_inode(const struct inode
- {
- int cnt, ret = NO_QUOTA;
- char warntype[MAXQUOTAS];
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
-@@ -1515,35 +1525,41 @@ int dquot_alloc_inode(const struct inode
- return QUOTA_OK;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- warntype[cnt] = QUOTA_NL_NOWARN;
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+
-+ spin_lock(&((struct inode *)inode)->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
- return QUOTA_OK;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- if (check_idq(inode->i_dquot[cnt], number, warntype+cnt)
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ if (check_idq(dquot[cnt], number, warntype+cnt)
- == NO_QUOTA)
- goto warn_put_all;
- }
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ if (!dquot[cnt])
- continue;
-- dquot_incr_inodes(inode->i_dquot[cnt], number);
-+ dquot_incr_inodes(dquot[cnt], number);
- }
- ret = QUOTA_OK;
- warn_put_all:
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
-+
- if (ret == QUOTA_OK)
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-- flush_warnings(inode->i_dquot, warntype);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return ret;
- }
- EXPORT_SYMBOL(dquot_alloc_inode);
-@@ -1552,34 +1568,40 @@ int dquot_claim_space(struct inode *inod
- {
- int cnt;
- int ret = QUOTA_OK;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- if (IS_NOQUOTA(inode)) {
- inode_claim_rsv_space(inode, number);
- goto out;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- inode_claim_rsv_space(inode, number);
-+ __inode_claim_rsv_space(inode, number);
-+ spin_unlock(&inode->i_lock);
- goto out;
- }
-
- spin_lock(&dq_data_lock);
- /* Claim reserved quotas to allocated quotas */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (inode->i_dquot[cnt])
-- dquot_claim_reserved_space(inode->i_dquot[cnt],
-- number);
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (dquot[cnt]) {
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ dquot_claim_reserved_space(dquot[cnt], number);
-+ }
- }
- /* Update inode bytes */
-- inode_claim_rsv_space(inode, number);
-+ __inode_claim_rsv_space(inode, number);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-+
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- out:
- return ret;
- }
-@@ -1593,6 +1615,7 @@ int __dquot_free_space(struct inode *ino
- unsigned int cnt;
- char warntype[MAXQUOTAS];
- int reserve = flags & DQUOT_SPACE_RESERVE;
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
-@@ -1602,34 +1625,37 @@ out_sub:
- return QUOTA_OK;
- }
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- goto out_sub;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number);
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ warntype[cnt] = info_bdq_free(dquot[cnt], number);
- if (reserve)
-- dquot_free_reserved_space(inode->i_dquot[cnt], number);
-+ dquot_free_reserved_space(dquot[cnt], number);
- else
-- dquot_decr_space(inode->i_dquot[cnt], number);
-+ dquot_decr_space(dquot[cnt], number);
- }
- inode_decr_space(inode, number, reserve);
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&inode->i_lock);
-
- if (reserve)
-- goto out_unlock;
-+ goto out;
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
--out_unlock:
-- flush_warnings(inode->i_dquot, warntype);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+out:
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return QUOTA_OK;
- }
-
-@@ -1656,32 +1682,37 @@ int dquot_free_inode(const struct inode
- {
- unsigned int cnt;
- char warntype[MAXQUOTAS];
-+ struct dquot *dquot[MAXQUOTAS] = { NULL };
-
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
- if (IS_NOQUOTA(inode))
- return QUOTA_OK;
-
-- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&((struct inode *)inode)->i_lock);
- if (IS_NOQUOTA(inode)) {
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
- return QUOTA_OK;
- }
- spin_lock(&dq_data_lock);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-- if (!inode->i_dquot[cnt])
-+ dquot[cnt] = inode->i_dquot[cnt];
-+ if (!dquot[cnt])
- continue;
-- warntype[cnt] = info_idq_free(inode->i_dquot[cnt], number);
-- dquot_decr_inodes(inode->i_dquot[cnt], number);
-+ atomic_inc(&dquot[cnt]->dq_count);
-+ warntype[cnt] = info_idq_free(dquot[cnt], number);
-+ dquot_decr_inodes(dquot[cnt], number);
- }
- spin_unlock(&dq_data_lock);
-+ spin_unlock(&((struct inode *)inode)->i_lock);
-+
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-- if (inode->i_dquot[cnt])
-- mark_dquot_dirty(inode->i_dquot[cnt]);
-- flush_warnings(inode->i_dquot, warntype);
-- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ if (dquot[cnt])
-+ mark_dquot_dirty(dquot[cnt]);
-+ flush_warnings(dquot, warntype);
-+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+ dqput(dquot[cnt]);
- return QUOTA_OK;
- }
- EXPORT_SYMBOL(dquot_free_inode);
-@@ -1721,14 +1752,13 @@ int dquot_transfer(struct inode *inode,
- transfer_to[GRPQUOTA] = dqget(inode->i_sb, iattr->ia_gid,
- GRPQUOTA);
-
-- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-- /* Now recheck reliably when holding dqptr_sem */
-+ spin_lock(&inode->i_lock);
- if (IS_NOQUOTA(inode)) { /* File without quota accounting? */
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- goto put_all;
- }
- spin_lock(&dq_data_lock);
-- cur_space = inode_get_bytes(inode);
-+ cur_space = __inode_get_bytes(inode);
- rsv_space = inode_get_rsv_space(inode);
- space = cur_space + rsv_space;
- /* Build the transfer_from list and check the limits */
-@@ -1771,7 +1801,7 @@ int dquot_transfer(struct inode *inode,
- inode->i_dquot[cnt] = transfer_to[cnt];
- }
- spin_unlock(&dq_data_lock);
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
-
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-@@ -1795,7 +1825,7 @@ put_all:
- return ret;
- over_quota:
- spin_unlock(&dq_data_lock);
-- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-+ spin_unlock(&inode->i_lock);
- /* Clear dquot pointers we don't want to dqput() */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- transfer_from[cnt] = NULL;
-@@ -2047,13 +2077,13 @@ static int vfs_load_quota_inode(struct i
- /* We don't want quota and atime on quota files (deadlocks
- * possible) Also nobody should write to the file - we use
- * special IO operations which ignore the immutable bit. */
-- down_write(&dqopt->dqptr_sem);
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-+ spin_lock(&inode->i_lock);
- oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE |
- S_NOQUOTA);
- inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
-+ spin_unlock(&inode->i_lock);
- mutex_unlock(&inode->i_mutex);
-- up_write(&dqopt->dqptr_sem);
- sb->dq_op->drop(inode);
- }
-
-@@ -2090,14 +2120,14 @@ out_file_init:
- iput(inode);
- out_lock:
- if (oldflags != -1) {
-- down_write(&dqopt->dqptr_sem);
- mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-+ spin_lock(&inode->i_lock);
- /* Set the flags back (in the case of accidental quotaon()
- * on a wrong file we don't want to mess up the flags) */
- inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
- inode->i_flags |= oldflags;
-+ spin_unlock(&inode->i_lock);
- mutex_unlock(&inode->i_mutex);
-- up_write(&dqopt->dqptr_sem);
- }
- mutex_unlock(&dqopt->dqonoff_mutex);
- out_fmt:
-Index: linux-2.6.32-358.0.1.el6/fs/quota/quota.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/quota/quota.c
-+++ linux-2.6.32-358.0.1.el6/fs/quota/quota.c
-@@ -257,13 +257,13 @@ static int do_quotactl(struct super_bloc
- case Q_GETFMT: {
- __u32 fmt;
-
-- down_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
- if (!sb_has_quota_active(sb, type)) {
-- up_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
- return -ESRCH;
- }
- fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
-- up_read(&sb_dqopt(sb)->dqptr_sem);
-+ mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
- if (copy_to_user(addr, &fmt, sizeof(fmt)))
- return -EFAULT;
- return 0;
-Index: linux-2.6.32-358.0.1.el6/fs/stat.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/stat.c
-+++ linux-2.6.32-358.0.1.el6/fs/stat.c
-@@ -422,9 +422,8 @@ void inode_add_bytes(struct inode *inode
-
- EXPORT_SYMBOL(inode_add_bytes);
-
--void inode_sub_bytes(struct inode *inode, loff_t bytes)
-+void __inode_sub_bytes(struct inode *inode, loff_t bytes)
- {
-- spin_lock(&inode->i_lock);
- inode->i_blocks -= bytes >> 9;
- bytes &= 511;
- if (inode->i_bytes < bytes) {
-@@ -432,17 +431,28 @@ void inode_sub_bytes(struct inode *inode
- inode->i_bytes += 512;
- }
- inode->i_bytes -= bytes;
-+}
-+
-+void inode_sub_bytes(struct inode *inode, loff_t bytes)
-+{
-+ spin_lock(&inode->i_lock);
-+ __inode_sub_bytes(inode, bytes);
- spin_unlock(&inode->i_lock);
- }
-
- EXPORT_SYMBOL(inode_sub_bytes);
-
-+loff_t __inode_get_bytes(struct inode *inode)
-+{
-+ return (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
-+}
-+
- loff_t inode_get_bytes(struct inode *inode)
- {
- loff_t ret;
-
- spin_lock(&inode->i_lock);
-- ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
-+ ret = __inode_get_bytes(inode);
- spin_unlock(&inode->i_lock);
- return ret;
- }
-Index: linux-2.6.32-358.0.1.el6/fs/super.c
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/fs/super.c
-+++ linux-2.6.32-358.0.1.el6/fs/super.c
-@@ -146,7 +146,6 @@ static struct super_block *alloc_super(s
- mutex_init(&s->s_vfs_rename_mutex);
- mutex_init(&s->s_dquot.dqio_mutex);
- mutex_init(&s->s_dquot.dqonoff_mutex);
-- init_rwsem(&s->s_dquot.dqptr_sem);
- init_waitqueue_head(&s->s_wait_unfrozen);
- s->s_maxbytes = MAX_NON_LFS;
- s->dq_op = sb_dquot_ops;
-Index: linux-2.6.32-358.0.1.el6/include/linux/fs.h
-===================================================================
---- linux-2.6.32-358.0.1.el6.orig/include/linux/fs.h
-+++ linux-2.6.32-358.0.1.el6/include/linux/fs.h
-@@ -2567,7 +2567,9 @@ extern void generic_fillattr(struct inod
- extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
- void __inode_add_bytes(struct inode *inode, loff_t bytes);
- void inode_add_bytes(struct inode *inode, loff_t bytes);
-+void __inode_sub_bytes(struct inode *inode, loff_t bytes);
- void inode_sub_bytes(struct inode *inode, loff_t bytes);
-+loff_t __inode_get_bytes(struct inode *inode);
- loff_t inode_get_bytes(struct inode *inode);
- void inode_set_bytes(struct inode *inode, loff_t bytes);
-
+++ /dev/null
-Force MD devices to pass SYNC reads directly to the disk
-instead of handling from cache. This is needed for MMP
-on MD RAID devices, and in theory could be accepted in
-the upstream kernel. Not needed for DMU.
-
-Index: linux-2.6.32-131.0.15.el6.x86_64/drivers/md/raid5.c
-===================================================================
---- linux-2.6.32-131.0.15.el6.x86_64.orig/drivers/md/raid5.c 2011-05-10 21:38:35.000000000 +0300
-+++ linux-2.6.32-131.0.15.el6.x86_64/drivers/md/raid5.c 2011-05-20 08:26:04.000000000 +0300
-@@ -2177,6 +2177,8 @@ static int add_stripe_bio(struct stripe_
- bi->bi_next = *bip;
- *bip = bi;
- raid5_inc_bi_active_stripes(bi);
-+ if (bio_rw_flagged(bi, BIO_RW_SYNCIO) && !forwrite)
-+ clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); /* force to read from disk. */
-
- if (forwrite) {
- /* check if page is covered */
-@@ -4132,6 +4134,9 @@ static int make_request(mddev_t *mddev,
- bio_endio(bi, 0);
- }
-
-+ if (bio_rw_flagged(bi, BIO_RW_SYNCIO))
-+ md_raid5_unplug_device(conf);
-+
- return 0;
- }
-
+++ /dev/null
-Force MD devices to pass SYNC reads directly to the disk
-instead of handling from cache. This is needed for MMP
-on MD RAID devices, and in theory could be accepted in
-the upstream kernel. Not needed for DMU.
-
-Index: linux-2.6.32/drivers/md/raid5.c
-===================================================================
---- linux-2.6.32.orig/drivers/md/raid5.c 2012-06-22 06:09:49.000000000 -0400
-+++ linux-2.6.32/drivers/md/raid5.c 2013-01-25 10:11:10.076431000 -0500
-@@ -2169,6 +2169,9 @@ static int add_stripe_bio(struct stripe_
- bi->bi_next = *bip;
- *bip = bi;
- bi->bi_phys_segments++;
-+ /* force to read from disk. */
-+ if ((bi->bi_rw & REQ_RW_SYNC) && !forwrite)
-+ clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
- spin_unlock_irq(&conf->device_lock);
- spin_unlock(&sh->lock);
-
-@@ -4008,6 +4008,10 @@ static int make_request(mddev_t *mddev,
-
- bio_endio(bi, 0);
- }
-+
-+ if (bi->bi_rw & REQ_RW_SYNC)
-+ md_wakeup_thread(mddev->thread);
-+
- return 0;
- }
-